Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * faulty.c : Multiple Devices driver for Linux
0004  *
0005  * Copyright (C) 2004 Neil Brown
0006  *
0007  * fautly-device-simulator personality for md
0008  */
0009 
0010 
0011 /*
0012  * The "faulty" personality causes some requests to fail.
0013  *
0014  * Possible failure modes are:
0015  *   reads fail "randomly" but succeed on retry
0016  *   writes fail "randomly" but succeed on retry
0017  *   reads for some address fail and then persist until a write
0018  *   reads for some address fail and then persist irrespective of write
0019  *   writes for some address fail and persist
0020  *   all writes fail
0021  *
0022  * Different modes can be active at a time, but only
0023  * one can be set at array creation.  Others can be added later.
0024  * A mode can be one-shot or recurrent with the recurrence being
0025  * once in every N requests.
0026  * The bottom 5 bits of the "layout" indicate the mode.  The
0027  * remainder indicate a period, or 0 for one-shot.
0028  *
0029  * There is an implementation limit on the number of concurrently
0030  * persisting-faulty blocks. When a new fault is requested that would
0031  * exceed the limit, it is ignored.
0032  * All current faults can be clear using a layout of "0".
0033  *
0034  * Requests are always sent to the device.  If they are to fail,
0035  * we clone the bio and insert a new b_end_io into the chain.
0036  */
0037 
0038 #define WriteTransient  0
0039 #define ReadTransient   1
0040 #define WritePersistent 2
0041 #define ReadPersistent  3
0042 #define WriteAll    4 /* doesn't go to device */
0043 #define ReadFixable 5
0044 #define Modes   6
0045 
0046 #define ClearErrors 31
0047 #define ClearFaults 30
0048 
0049 #define AllPersist  100 /* internal use only */
0050 #define NoPersist   101
0051 
0052 #define ModeMask    0x1f
0053 #define ModeShift   5
0054 
0055 #define MaxFault    50
0056 #include <linux/blkdev.h>
0057 #include <linux/module.h>
0058 #include <linux/raid/md_u.h>
0059 #include <linux/slab.h>
0060 #include "md.h"
0061 #include <linux/seq_file.h>
0062 
0063 
0064 static void faulty_fail(struct bio *bio)
0065 {
0066     struct bio *b = bio->bi_private;
0067 
0068     b->bi_iter.bi_size = bio->bi_iter.bi_size;
0069     b->bi_iter.bi_sector = bio->bi_iter.bi_sector;
0070 
0071     bio_put(bio);
0072 
0073     bio_io_error(b);
0074 }
0075 
0076 struct faulty_conf {
0077     int period[Modes];
0078     atomic_t counters[Modes];
0079     sector_t faults[MaxFault];
0080     int modes[MaxFault];
0081     int nfaults;
0082     struct md_rdev *rdev;
0083 };
0084 
0085 static int check_mode(struct faulty_conf *conf, int mode)
0086 {
0087     if (conf->period[mode] == 0 &&
0088         atomic_read(&conf->counters[mode]) <= 0)
0089         return 0; /* no failure, no decrement */
0090 
0091 
0092     if (atomic_dec_and_test(&conf->counters[mode])) {
0093         if (conf->period[mode])
0094             atomic_set(&conf->counters[mode], conf->period[mode]);
0095         return 1;
0096     }
0097     return 0;
0098 }
0099 
0100 static int check_sector(struct faulty_conf *conf, sector_t start, sector_t end, int dir)
0101 {
0102     /* If we find a ReadFixable sector, we fix it ... */
0103     int i;
0104     for (i=0; i<conf->nfaults; i++)
0105         if (conf->faults[i] >= start &&
0106             conf->faults[i] < end) {
0107             /* found it ... */
0108             switch (conf->modes[i] * 2 + dir) {
0109             case WritePersistent*2+WRITE: return 1;
0110             case ReadPersistent*2+READ: return 1;
0111             case ReadFixable*2+READ: return 1;
0112             case ReadFixable*2+WRITE:
0113                 conf->modes[i] = NoPersist;
0114                 return 0;
0115             case AllPersist*2+READ:
0116             case AllPersist*2+WRITE: return 1;
0117             default:
0118                 return 0;
0119             }
0120         }
0121     return 0;
0122 }
0123 
0124 static void add_sector(struct faulty_conf *conf, sector_t start, int mode)
0125 {
0126     int i;
0127     int n = conf->nfaults;
0128     for (i=0; i<conf->nfaults; i++)
0129         if (conf->faults[i] == start) {
0130             switch(mode) {
0131             case NoPersist: conf->modes[i] = mode; return;
0132             case WritePersistent:
0133                 if (conf->modes[i] == ReadPersistent ||
0134                     conf->modes[i] == ReadFixable)
0135                     conf->modes[i] = AllPersist;
0136                 else
0137                     conf->modes[i] = WritePersistent;
0138                 return;
0139             case ReadPersistent:
0140                 if (conf->modes[i] == WritePersistent)
0141                     conf->modes[i] = AllPersist;
0142                 else
0143                     conf->modes[i] = ReadPersistent;
0144                 return;
0145             case ReadFixable:
0146                 if (conf->modes[i] == WritePersistent ||
0147                     conf->modes[i] == ReadPersistent)
0148                     conf->modes[i] = AllPersist;
0149                 else
0150                     conf->modes[i] = ReadFixable;
0151                 return;
0152             }
0153         } else if (conf->modes[i] == NoPersist)
0154             n = i;
0155 
0156     if (n >= MaxFault)
0157         return;
0158     conf->faults[n] = start;
0159     conf->modes[n] = mode;
0160     if (conf->nfaults == n)
0161         conf->nfaults = n+1;
0162 }
0163 
0164 static bool faulty_make_request(struct mddev *mddev, struct bio *bio)
0165 {
0166     struct faulty_conf *conf = mddev->private;
0167     int failit = 0;
0168 
0169     if (bio_data_dir(bio) == WRITE) {
0170         /* write request */
0171         if (atomic_read(&conf->counters[WriteAll])) {
0172             /* special case - don't decrement, don't submit_bio_noacct,
0173              * just fail immediately
0174              */
0175             bio_io_error(bio);
0176             return true;
0177         }
0178 
0179         if (check_sector(conf, bio->bi_iter.bi_sector,
0180                  bio_end_sector(bio), WRITE))
0181             failit = 1;
0182         if (check_mode(conf, WritePersistent)) {
0183             add_sector(conf, bio->bi_iter.bi_sector,
0184                    WritePersistent);
0185             failit = 1;
0186         }
0187         if (check_mode(conf, WriteTransient))
0188             failit = 1;
0189     } else {
0190         /* read request */
0191         if (check_sector(conf, bio->bi_iter.bi_sector,
0192                  bio_end_sector(bio), READ))
0193             failit = 1;
0194         if (check_mode(conf, ReadTransient))
0195             failit = 1;
0196         if (check_mode(conf, ReadPersistent)) {
0197             add_sector(conf, bio->bi_iter.bi_sector,
0198                    ReadPersistent);
0199             failit = 1;
0200         }
0201         if (check_mode(conf, ReadFixable)) {
0202             add_sector(conf, bio->bi_iter.bi_sector,
0203                    ReadFixable);
0204             failit = 1;
0205         }
0206     }
0207     if (failit) {
0208         struct bio *b = bio_alloc_clone(conf->rdev->bdev, bio, GFP_NOIO,
0209                         &mddev->bio_set);
0210 
0211         b->bi_private = bio;
0212         b->bi_end_io = faulty_fail;
0213         bio = b;
0214     } else
0215         bio_set_dev(bio, conf->rdev->bdev);
0216 
0217     submit_bio_noacct(bio);
0218     return true;
0219 }
0220 
0221 static void faulty_status(struct seq_file *seq, struct mddev *mddev)
0222 {
0223     struct faulty_conf *conf = mddev->private;
0224     int n;
0225 
0226     if ((n=atomic_read(&conf->counters[WriteTransient])) != 0)
0227         seq_printf(seq, " WriteTransient=%d(%d)",
0228                n, conf->period[WriteTransient]);
0229 
0230     if ((n=atomic_read(&conf->counters[ReadTransient])) != 0)
0231         seq_printf(seq, " ReadTransient=%d(%d)",
0232                n, conf->period[ReadTransient]);
0233 
0234     if ((n=atomic_read(&conf->counters[WritePersistent])) != 0)
0235         seq_printf(seq, " WritePersistent=%d(%d)",
0236                n, conf->period[WritePersistent]);
0237 
0238     if ((n=atomic_read(&conf->counters[ReadPersistent])) != 0)
0239         seq_printf(seq, " ReadPersistent=%d(%d)",
0240                n, conf->period[ReadPersistent]);
0241 
0242 
0243     if ((n=atomic_read(&conf->counters[ReadFixable])) != 0)
0244         seq_printf(seq, " ReadFixable=%d(%d)",
0245                n, conf->period[ReadFixable]);
0246 
0247     if ((n=atomic_read(&conf->counters[WriteAll])) != 0)
0248         seq_printf(seq, " WriteAll");
0249 
0250     seq_printf(seq, " nfaults=%d", conf->nfaults);
0251 }
0252 
0253 
0254 static int faulty_reshape(struct mddev *mddev)
0255 {
0256     int mode = mddev->new_layout & ModeMask;
0257     int count = mddev->new_layout >> ModeShift;
0258     struct faulty_conf *conf = mddev->private;
0259 
0260     if (mddev->new_layout < 0)
0261         return 0;
0262 
0263     /* new layout */
0264     if (mode == ClearFaults)
0265         conf->nfaults = 0;
0266     else if (mode == ClearErrors) {
0267         int i;
0268         for (i=0 ; i < Modes ; i++) {
0269             conf->period[i] = 0;
0270             atomic_set(&conf->counters[i], 0);
0271         }
0272     } else if (mode < Modes) {
0273         conf->period[mode] = count;
0274         if (!count) count++;
0275         atomic_set(&conf->counters[mode], count);
0276     } else
0277         return -EINVAL;
0278     mddev->new_layout = -1;
0279     mddev->layout = -1; /* makes sure further changes come through */
0280     return 0;
0281 }
0282 
0283 static sector_t faulty_size(struct mddev *mddev, sector_t sectors, int raid_disks)
0284 {
0285     WARN_ONCE(raid_disks,
0286           "%s does not support generic reshape\n", __func__);
0287 
0288     if (sectors == 0)
0289         return mddev->dev_sectors;
0290 
0291     return sectors;
0292 }
0293 
0294 static int faulty_run(struct mddev *mddev)
0295 {
0296     struct md_rdev *rdev;
0297     int i;
0298     struct faulty_conf *conf;
0299 
0300     if (md_check_no_bitmap(mddev))
0301         return -EINVAL;
0302 
0303     conf = kmalloc(sizeof(*conf), GFP_KERNEL);
0304     if (!conf)
0305         return -ENOMEM;
0306 
0307     for (i=0; i<Modes; i++) {
0308         atomic_set(&conf->counters[i], 0);
0309         conf->period[i] = 0;
0310     }
0311     conf->nfaults = 0;
0312 
0313     rdev_for_each(rdev, mddev) {
0314         conf->rdev = rdev;
0315         disk_stack_limits(mddev->gendisk, rdev->bdev,
0316                   rdev->data_offset << 9);
0317     }
0318 
0319     md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
0320     mddev->private = conf;
0321 
0322     faulty_reshape(mddev);
0323 
0324     return 0;
0325 }
0326 
0327 static void faulty_free(struct mddev *mddev, void *priv)
0328 {
0329     struct faulty_conf *conf = priv;
0330 
0331     kfree(conf);
0332 }
0333 
0334 static struct md_personality faulty_personality =
0335 {
0336     .name       = "faulty",
0337     .level      = LEVEL_FAULTY,
0338     .owner      = THIS_MODULE,
0339     .make_request   = faulty_make_request,
0340     .run        = faulty_run,
0341     .free       = faulty_free,
0342     .status     = faulty_status,
0343     .check_reshape  = faulty_reshape,
0344     .size       = faulty_size,
0345 };
0346 
0347 static int __init raid_init(void)
0348 {
0349     return register_md_personality(&faulty_personality);
0350 }
0351 
0352 static void raid_exit(void)
0353 {
0354     unregister_md_personality(&faulty_personality);
0355 }
0356 
0357 module_init(raid_init);
0358 module_exit(raid_exit);
0359 MODULE_LICENSE("GPL");
0360 MODULE_DESCRIPTION("Fault injection personality for MD (deprecated)");
0361 MODULE_ALIAS("md-personality-10"); /* faulty */
0362 MODULE_ALIAS("md-faulty");
0363 MODULE_ALIAS("md-level--5");