1 /* 2 * Copyright (C) 2005-2007 Red Hat GmbH 3 * 4 * A target that delays reads and/or writes and can send 5 * them to different devices. 6 * 7 * This file is released under the GPL. 8 */ 9 10 #include <linux/module.h> 11 #include <linux/init.h> 12 #include <linux/blkdev.h> 13 #include <linux/bio.h> 14 #include <linux/slab.h> 15 16 #include <linux/device-mapper.h> 17 18 #define DM_MSG_PREFIX "delay" 19 20 struct delay_c { 21 struct timer_list delay_timer; 22 struct mutex timer_lock; 23 struct workqueue_struct *kdelayd_wq; 24 struct work_struct flush_expired_bios; 25 struct list_head delayed_bios; 26 atomic_t may_delay; 27 28 struct dm_dev *dev_read; 29 sector_t start_read; 30 unsigned read_delay; 31 unsigned reads; 32 33 struct dm_dev *dev_write; 34 sector_t start_write; 35 unsigned write_delay; 36 unsigned writes; 37 }; 38 39 struct dm_delay_info { 40 struct delay_c *context; 41 struct list_head list; 42 unsigned long expires; 43 }; 44 45 static DEFINE_MUTEX(delayed_bios_lock); 46 47 static void handle_delayed_timer(unsigned long data) 48 { 49 struct delay_c *dc = (struct delay_c *)data; 50 51 queue_work(dc->kdelayd_wq, &dc->flush_expired_bios); 52 } 53 54 static void queue_timeout(struct delay_c *dc, unsigned long expires) 55 { 56 mutex_lock(&dc->timer_lock); 57 58 if (!timer_pending(&dc->delay_timer) || expires < dc->delay_timer.expires) 59 mod_timer(&dc->delay_timer, expires); 60 61 mutex_unlock(&dc->timer_lock); 62 } 63 64 static void flush_bios(struct bio *bio) 65 { 66 struct bio *n; 67 68 while (bio) { 69 n = bio->bi_next; 70 bio->bi_next = NULL; 71 generic_make_request(bio); 72 bio = n; 73 } 74 } 75 76 static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all) 77 { 78 struct dm_delay_info *delayed, *next; 79 unsigned long next_expires = 0; 80 int start_timer = 0; 81 struct bio_list flush_bios = { }; 82 83 mutex_lock(&delayed_bios_lock); 84 list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) { 85 if (flush_all || time_after_eq(jiffies, delayed->expires)) { 86 struct bio *bio = dm_bio_from_per_bio_data(delayed, 87 sizeof(struct dm_delay_info)); 88 list_del(&delayed->list); 89 bio_list_add(&flush_bios, bio); 90 if ((bio_data_dir(bio) == WRITE)) 91 delayed->context->writes--; 92 else 93 delayed->context->reads--; 94 continue; 95 } 96 97 if (!start_timer) { 98 start_timer = 1; 99 next_expires = delayed->expires; 100 } else 101 next_expires = min(next_expires, delayed->expires); 102 } 103 104 mutex_unlock(&delayed_bios_lock); 105 106 if (start_timer) 107 queue_timeout(dc, next_expires); 108 109 return bio_list_get(&flush_bios); 110 } 111 112 static void flush_expired_bios(struct work_struct *work) 113 { 114 struct delay_c *dc; 115 116 dc = container_of(work, struct delay_c, flush_expired_bios); 117 flush_bios(flush_delayed_bios(dc, 0)); 118 } 119 120 /* 121 * Mapping parameters: 122 * <device> <offset> <delay> [<write_device> <write_offset> <write_delay>] 123 * 124 * With separate write parameters, the first set is only used for reads. 125 * Delays are specified in milliseconds. 126 */ 127 static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) 128 { 129 struct delay_c *dc; 130 unsigned long long tmpll; 131 char dummy; 132 133 if (argc != 3 && argc != 6) { 134 ti->error = "requires exactly 3 or 6 arguments"; 135 return -EINVAL; 136 } 137 138 dc = kmalloc(sizeof(*dc), GFP_KERNEL); 139 if (!dc) { 140 ti->error = "Cannot allocate context"; 141 return -ENOMEM; 142 } 143 144 dc->reads = dc->writes = 0; 145 146 if (sscanf(argv[1], "%llu%c", &tmpll, &dummy) != 1) { 147 ti->error = "Invalid device sector"; 148 goto bad; 149 } 150 dc->start_read = tmpll; 151 152 if (sscanf(argv[2], "%u%c", &dc->read_delay, &dummy) != 1) { 153 ti->error = "Invalid delay"; 154 goto bad; 155 } 156 157 if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), 158 &dc->dev_read)) { 159 ti->error = "Device lookup failed"; 160 goto bad; 161 } 162 163 dc->dev_write = NULL; 164 if (argc == 3) 165 goto out; 166 167 if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1) { 168 ti->error = "Invalid write device sector"; 169 goto bad_dev_read; 170 } 171 dc->start_write = tmpll; 172 173 if (sscanf(argv[5], "%u%c", &dc->write_delay, &dummy) != 1) { 174 ti->error = "Invalid write delay"; 175 goto bad_dev_read; 176 } 177 178 if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), 179 &dc->dev_write)) { 180 ti->error = "Write device lookup failed"; 181 goto bad_dev_read; 182 } 183 184 out: 185 dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); 186 if (!dc->kdelayd_wq) { 187 DMERR("Couldn't start kdelayd"); 188 goto bad_queue; 189 } 190 191 setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc); 192 193 INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); 194 INIT_LIST_HEAD(&dc->delayed_bios); 195 mutex_init(&dc->timer_lock); 196 atomic_set(&dc->may_delay, 1); 197 198 ti->num_flush_bios = 1; 199 ti->num_discard_bios = 1; 200 ti->per_bio_data_size = sizeof(struct dm_delay_info); 201 ti->private = dc; 202 return 0; 203 204 bad_queue: 205 if (dc->dev_write) 206 dm_put_device(ti, dc->dev_write); 207 bad_dev_read: 208 dm_put_device(ti, dc->dev_read); 209 bad: 210 kfree(dc); 211 return -EINVAL; 212 } 213 214 static void delay_dtr(struct dm_target *ti) 215 { 216 struct delay_c *dc = ti->private; 217 218 destroy_workqueue(dc->kdelayd_wq); 219 220 dm_put_device(ti, dc->dev_read); 221 222 if (dc->dev_write) 223 dm_put_device(ti, dc->dev_write); 224 225 kfree(dc); 226 } 227 228 static int delay_bio(struct delay_c *dc, int delay, struct bio *bio) 229 { 230 struct dm_delay_info *delayed; 231 unsigned long expires = 0; 232 233 if (!delay || !atomic_read(&dc->may_delay)) 234 return 1; 235 236 delayed = dm_per_bio_data(bio, sizeof(struct dm_delay_info)); 237 238 delayed->context = dc; 239 delayed->expires = expires = jiffies + msecs_to_jiffies(delay); 240 241 mutex_lock(&delayed_bios_lock); 242 243 if (bio_data_dir(bio) == WRITE) 244 dc->writes++; 245 else 246 dc->reads++; 247 248 list_add_tail(&delayed->list, &dc->delayed_bios); 249 250 mutex_unlock(&delayed_bios_lock); 251 252 queue_timeout(dc, expires); 253 254 return 0; 255 } 256 257 static void delay_presuspend(struct dm_target *ti) 258 { 259 struct delay_c *dc = ti->private; 260 261 atomic_set(&dc->may_delay, 0); 262 del_timer_sync(&dc->delay_timer); 263 flush_bios(flush_delayed_bios(dc, 1)); 264 } 265 266 static void delay_resume(struct dm_target *ti) 267 { 268 struct delay_c *dc = ti->private; 269 270 atomic_set(&dc->may_delay, 1); 271 } 272 273 static int delay_map(struct dm_target *ti, struct bio *bio) 274 { 275 struct delay_c *dc = ti->private; 276 277 if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) { 278 bio->bi_bdev = dc->dev_write->bdev; 279 if (bio_sectors(bio)) 280 bio->bi_iter.bi_sector = dc->start_write + 281 dm_target_offset(ti, bio->bi_iter.bi_sector); 282 283 return delay_bio(dc, dc->write_delay, bio); 284 } 285 286 bio->bi_bdev = dc->dev_read->bdev; 287 bio->bi_iter.bi_sector = dc->start_read + 288 dm_target_offset(ti, bio->bi_iter.bi_sector); 289 290 return delay_bio(dc, dc->read_delay, bio); 291 } 292 293 static void delay_status(struct dm_target *ti, status_type_t type, 294 unsigned status_flags, char *result, unsigned maxlen) 295 { 296 struct delay_c *dc = ti->private; 297 int sz = 0; 298 299 switch (type) { 300 case STATUSTYPE_INFO: 301 DMEMIT("%u %u", dc->reads, dc->writes); 302 break; 303 304 case STATUSTYPE_TABLE: 305 DMEMIT("%s %llu %u", dc->dev_read->name, 306 (unsigned long long) dc->start_read, 307 dc->read_delay); 308 if (dc->dev_write) 309 DMEMIT(" %s %llu %u", dc->dev_write->name, 310 (unsigned long long) dc->start_write, 311 dc->write_delay); 312 break; 313 } 314 } 315 316 static int delay_iterate_devices(struct dm_target *ti, 317 iterate_devices_callout_fn fn, void *data) 318 { 319 struct delay_c *dc = ti->private; 320 int ret = 0; 321 322 ret = fn(ti, dc->dev_read, dc->start_read, ti->len, data); 323 if (ret) 324 goto out; 325 326 if (dc->dev_write) 327 ret = fn(ti, dc->dev_write, dc->start_write, ti->len, data); 328 329 out: 330 return ret; 331 } 332 333 static struct target_type delay_target = { 334 .name = "delay", 335 .version = {1, 2, 1}, 336 .module = THIS_MODULE, 337 .ctr = delay_ctr, 338 .dtr = delay_dtr, 339 .map = delay_map, 340 .presuspend = delay_presuspend, 341 .resume = delay_resume, 342 .status = delay_status, 343 .iterate_devices = delay_iterate_devices, 344 }; 345 346 static int __init dm_delay_init(void) 347 { 348 int r; 349 350 r = dm_register_target(&delay_target); 351 if (r < 0) { 352 DMERR("register failed %d", r); 353 goto bad_register; 354 } 355 356 return 0; 357 358 bad_register: 359 return r; 360 } 361 362 static void __exit dm_delay_exit(void) 363 { 364 dm_unregister_target(&delay_target); 365 } 366 367 /* Module hooks */ 368 module_init(dm_delay_init); 369 module_exit(dm_delay_exit); 370 371 MODULE_DESCRIPTION(DM_NAME " delay target"); 372 MODULE_AUTHOR("Heinz Mauelshagen <mauelshagen@redhat.com>"); 373 MODULE_LICENSE("GPL"); 374