0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/blkdev.h>
0013 #include <linux/raid/md_u.h>
0014 #include <linux/seq_file.h>
0015 #include <linux/module.h>
0016 #include <linux/slab.h>
0017 #include <trace/events/block.h>
0018 #include "md.h"
0019 #include "md-linear.h"
0020
0021
0022
0023
0024 static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector)
0025 {
0026 int lo, mid, hi;
0027 struct linear_conf *conf;
0028
0029 lo = 0;
0030 hi = mddev->raid_disks - 1;
0031 conf = mddev->private;
0032
0033
0034
0035
0036
0037 while (hi > lo) {
0038
0039 mid = (hi + lo) / 2;
0040 if (sector < conf->disks[mid].end_sector)
0041 hi = mid;
0042 else
0043 lo = mid + 1;
0044 }
0045
0046 return conf->disks + lo;
0047 }
0048
0049 static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disks)
0050 {
0051 struct linear_conf *conf;
0052 sector_t array_sectors;
0053
0054 conf = mddev->private;
0055 WARN_ONCE(sectors || raid_disks,
0056 "%s does not support generic reshape\n", __func__);
0057 array_sectors = conf->array_sectors;
0058
0059 return array_sectors;
0060 }
0061
0062 static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
0063 {
0064 struct linear_conf *conf;
0065 struct md_rdev *rdev;
0066 int i, cnt;
0067
0068 conf = kzalloc(struct_size(conf, disks, raid_disks), GFP_KERNEL);
0069 if (!conf)
0070 return NULL;
0071
0072 cnt = 0;
0073 conf->array_sectors = 0;
0074
0075 rdev_for_each(rdev, mddev) {
0076 int j = rdev->raid_disk;
0077 struct dev_info *disk = conf->disks + j;
0078 sector_t sectors;
0079
0080 if (j < 0 || j >= raid_disks || disk->rdev) {
0081 pr_warn("md/linear:%s: disk numbering problem. Aborting!\n",
0082 mdname(mddev));
0083 goto out;
0084 }
0085
0086 disk->rdev = rdev;
0087 if (mddev->chunk_sectors) {
0088 sectors = rdev->sectors;
0089 sector_div(sectors, mddev->chunk_sectors);
0090 rdev->sectors = sectors * mddev->chunk_sectors;
0091 }
0092
0093 disk_stack_limits(mddev->gendisk, rdev->bdev,
0094 rdev->data_offset << 9);
0095
0096 conf->array_sectors += rdev->sectors;
0097 cnt++;
0098 }
0099 if (cnt != raid_disks) {
0100 pr_warn("md/linear:%s: not enough drives present. Aborting!\n",
0101 mdname(mddev));
0102 goto out;
0103 }
0104
0105
0106
0107
0108 conf->disks[0].end_sector = conf->disks[0].rdev->sectors;
0109
0110 for (i = 1; i < raid_disks; i++)
0111 conf->disks[i].end_sector =
0112 conf->disks[i-1].end_sector +
0113 conf->disks[i].rdev->sectors;
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 conf->raid_disks = raid_disks;
0127
0128 return conf;
0129
0130 out:
0131 kfree(conf);
0132 return NULL;
0133 }
0134
0135 static int linear_run (struct mddev *mddev)
0136 {
0137 struct linear_conf *conf;
0138 int ret;
0139
0140 if (md_check_no_bitmap(mddev))
0141 return -EINVAL;
0142 conf = linear_conf(mddev, mddev->raid_disks);
0143
0144 if (!conf)
0145 return 1;
0146 mddev->private = conf;
0147 md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
0148
0149 ret = md_integrity_register(mddev);
0150 if (ret) {
0151 kfree(conf);
0152 mddev->private = NULL;
0153 }
0154 return ret;
0155 }
0156
0157 static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
0158 {
0159
0160
0161
0162
0163
0164
0165
0166
0167 struct linear_conf *newconf, *oldconf;
0168
0169 if (rdev->saved_raid_disk != mddev->raid_disks)
0170 return -EINVAL;
0171
0172 rdev->raid_disk = rdev->saved_raid_disk;
0173 rdev->saved_raid_disk = -1;
0174
0175 newconf = linear_conf(mddev,mddev->raid_disks+1);
0176
0177 if (!newconf)
0178 return -ENOMEM;
0179
0180
0181
0182
0183
0184
0185
0186 mddev_suspend(mddev);
0187 oldconf = rcu_dereference_protected(mddev->private,
0188 lockdep_is_held(&mddev->reconfig_mutex));
0189 mddev->raid_disks++;
0190 WARN_ONCE(mddev->raid_disks != newconf->raid_disks,
0191 "copied raid_disks doesn't match mddev->raid_disks");
0192 rcu_assign_pointer(mddev->private, newconf);
0193 md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
0194 set_capacity_and_notify(mddev->gendisk, mddev->array_sectors);
0195 mddev_resume(mddev);
0196 kfree_rcu(oldconf, rcu);
0197 return 0;
0198 }
0199
0200 static void linear_free(struct mddev *mddev, void *priv)
0201 {
0202 struct linear_conf *conf = priv;
0203
0204 kfree(conf);
0205 }
0206
0207 static bool linear_make_request(struct mddev *mddev, struct bio *bio)
0208 {
0209 struct dev_info *tmp_dev;
0210 sector_t start_sector, end_sector, data_offset;
0211 sector_t bio_sector = bio->bi_iter.bi_sector;
0212
0213 if (unlikely(bio->bi_opf & REQ_PREFLUSH)
0214 && md_flush_request(mddev, bio))
0215 return true;
0216
0217 tmp_dev = which_dev(mddev, bio_sector);
0218 start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
0219 end_sector = tmp_dev->end_sector;
0220 data_offset = tmp_dev->rdev->data_offset;
0221
0222 if (unlikely(bio_sector >= end_sector ||
0223 bio_sector < start_sector))
0224 goto out_of_bounds;
0225
0226 if (unlikely(is_mddev_broken(tmp_dev->rdev, "linear"))) {
0227 bio_io_error(bio);
0228 return true;
0229 }
0230
0231 if (unlikely(bio_end_sector(bio) > end_sector)) {
0232
0233 struct bio *split = bio_split(bio, end_sector - bio_sector,
0234 GFP_NOIO, &mddev->bio_set);
0235 bio_chain(split, bio);
0236 submit_bio_noacct(bio);
0237 bio = split;
0238 }
0239
0240 bio_set_dev(bio, tmp_dev->rdev->bdev);
0241 bio->bi_iter.bi_sector = bio->bi_iter.bi_sector -
0242 start_sector + data_offset;
0243
0244 if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
0245 !bdev_max_discard_sectors(bio->bi_bdev))) {
0246
0247 bio_endio(bio);
0248 } else {
0249 if (mddev->gendisk)
0250 trace_block_bio_remap(bio, disk_devt(mddev->gendisk),
0251 bio_sector);
0252 mddev_check_write_zeroes(mddev, bio);
0253 submit_bio_noacct(bio);
0254 }
0255 return true;
0256
0257 out_of_bounds:
0258 pr_err("md/linear:%s: make_request: Sector %llu out of bounds on dev %pg: %llu sectors, offset %llu\n",
0259 mdname(mddev),
0260 (unsigned long long)bio->bi_iter.bi_sector,
0261 tmp_dev->rdev->bdev,
0262 (unsigned long long)tmp_dev->rdev->sectors,
0263 (unsigned long long)start_sector);
0264 bio_io_error(bio);
0265 return true;
0266 }
0267
0268 static void linear_status (struct seq_file *seq, struct mddev *mddev)
0269 {
0270 seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
0271 }
0272
0273 static void linear_quiesce(struct mddev *mddev, int state)
0274 {
0275 }
0276
0277 static struct md_personality linear_personality =
0278 {
0279 .name = "linear",
0280 .level = LEVEL_LINEAR,
0281 .owner = THIS_MODULE,
0282 .make_request = linear_make_request,
0283 .run = linear_run,
0284 .free = linear_free,
0285 .status = linear_status,
0286 .hot_add_disk = linear_add,
0287 .size = linear_size,
0288 .quiesce = linear_quiesce,
0289 };
0290
0291 static int __init linear_init (void)
0292 {
0293 return register_md_personality (&linear_personality);
0294 }
0295
0296 static void linear_exit (void)
0297 {
0298 unregister_md_personality (&linear_personality);
0299 }
0300
0301 module_init(linear_init);
0302 module_exit(linear_exit);
0303 MODULE_LICENSE("GPL");
0304 MODULE_DESCRIPTION("Linear device concatenation personality for MD (deprecated)");
0305 MODULE_ALIAS("md-personality-1");
0306 MODULE_ALIAS("md-linear");
0307 MODULE_ALIAS("md-level--1");