dm-linear.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Copyright (C) 2001-2003 Sistina Software (UK) Limited.
  3. *
  4. * This file is released under the GPL.
  5. */
  6. #include "dm.h"
  7. #include <linux/module.h>
  8. #include <linux/init.h>
  9. #include <linux/blkdev.h>
  10. #include <linux/bio.h>
  11. #include <linux/slab.h>
  12. #include <linux/device-mapper.h>
  13. #define DM_MSG_PREFIX "linear"
  14. /*
  15. * Linear: maps a linear range of a device.
  16. */
  17. struct linear_c {
  18. struct dm_dev *dev;
  19. sector_t start;
  20. };
  21. /*
  22. * Construct a linear mapping: <dev_path> <offset>
  23. */
  24. static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
  25. {
  26. struct linear_c *lc;
  27. unsigned long long tmp;
  28. if (argc != 2) {
  29. ti->error = "Invalid argument count";
  30. return -EINVAL;
  31. }
  32. lc = kmalloc(sizeof(*lc), GFP_KERNEL);
  33. if (lc == NULL) {
  34. ti->error = "dm-linear: Cannot allocate linear context";
  35. return -ENOMEM;
  36. }
  37. if (sscanf(argv[1], "%llu", &tmp) != 1) {
  38. ti->error = "dm-linear: Invalid device sector";
  39. goto bad;
  40. }
  41. lc->start = tmp;
  42. if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) {
  43. ti->error = "dm-linear: Device lookup failed";
  44. goto bad;
  45. }
  46. ti->num_flush_requests = 1;
  47. ti->private = lc;
  48. return 0;
  49. bad:
  50. kfree(lc);
  51. return -EINVAL;
  52. }
  53. static void linear_dtr(struct dm_target *ti)
  54. {
  55. struct linear_c *lc = (struct linear_c *) ti->private;
  56. dm_put_device(ti, lc->dev);
  57. kfree(lc);
  58. }
  59. static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
  60. {
  61. struct linear_c *lc = ti->private;
  62. return lc->start + (bi_sector - ti->begin);
  63. }
  64. static void linear_map_bio(struct dm_target *ti, struct bio *bio)
  65. {
  66. struct linear_c *lc = ti->private;
  67. bio->bi_bdev = lc->dev->bdev;
  68. if (bio_sectors(bio))
  69. bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
  70. }
  71. static int linear_map(struct dm_target *ti, struct bio *bio,
  72. union map_info *map_context)
  73. {
  74. linear_map_bio(ti, bio);
  75. return DM_MAPIO_REMAPPED;
  76. }
  77. static int linear_status(struct dm_target *ti, status_type_t type,
  78. char *result, unsigned int maxlen)
  79. {
  80. struct linear_c *lc = (struct linear_c *) ti->private;
  81. switch (type) {
  82. case STATUSTYPE_INFO:
  83. result[0] = '\0';
  84. break;
  85. case STATUSTYPE_TABLE:
  86. snprintf(result, maxlen, "%s %llu", lc->dev->name,
  87. (unsigned long long)lc->start);
  88. break;
  89. }
  90. return 0;
  91. }
  92. static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
  93. unsigned long arg)
  94. {
  95. struct linear_c *lc = (struct linear_c *) ti->private;
  96. return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg);
  97. }
  98. static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
  99. struct bio_vec *biovec, int max_size)
  100. {
  101. struct linear_c *lc = ti->private;
  102. struct request_queue *q = bdev_get_queue(lc->dev->bdev);
  103. if (!q->merge_bvec_fn)
  104. return max_size;
  105. bvm->bi_bdev = lc->dev->bdev;
  106. bvm->bi_sector = linear_map_sector(ti, bvm->bi_sector);
  107. return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
  108. }
  109. static int linear_iterate_devices(struct dm_target *ti,
  110. iterate_devices_callout_fn fn, void *data)
  111. {
  112. struct linear_c *lc = ti->private;
  113. return fn(ti, lc->dev, lc->start, ti->len, data);
  114. }
  115. static struct target_type linear_target = {
  116. .name = "linear",
  117. .version = {1, 1, 0},
  118. .module = THIS_MODULE,
  119. .ctr = linear_ctr,
  120. .dtr = linear_dtr,
  121. .map = linear_map,
  122. .status = linear_status,
  123. .ioctl = linear_ioctl,
  124. .merge = linear_merge,
  125. .iterate_devices = linear_iterate_devices,
  126. };
  127. int __init dm_linear_init(void)
  128. {
  129. int r = dm_register_target(&linear_target);
  130. if (r < 0)
  131. DMERR("register failed %d", r);
  132. return r;
  133. }
  134. void dm_linear_exit(void)
  135. {
  136. dm_unregister_target(&linear_target);
  137. }