441-block2mtd_refresh.patch 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. --- a/drivers/mtd/devices/block2mtd.c
  2. +++ b/drivers/mtd/devices/block2mtd.c
  3. @@ -30,6 +30,8 @@ struct block2mtd_dev {
  4. struct block_device *blkdev;
  5. struct mtd_info mtd;
  6. struct mutex write_mutex;
  7. + rwlock_t bdev_mutex;
  8. + char devname[0];
  9. };
  10. @@ -82,6 +84,12 @@ static int block2mtd_erase(struct mtd_in
  11. size_t len = instr->len;
  12. int err;
  13. + read_lock(&dev->bdev_mutex);
  14. + if (!dev->blkdev) {
  15. + err = -EINVAL;
  16. + goto done;
  17. + }
  18. +
  19. instr->state = MTD_ERASING;
  20. mutex_lock(&dev->write_mutex);
  21. err = _block2mtd_erase(dev, from, len);
  22. @@ -93,6 +101,10 @@ static int block2mtd_erase(struct mtd_in
  23. instr->state = MTD_ERASE_DONE;
  24. mtd_erase_callback(instr);
  25. +
  26. +done:
  27. + read_unlock(&dev->bdev_mutex);
  28. +
  29. return err;
  30. }
  31. @@ -104,10 +116,14 @@ static int block2mtd_read(struct mtd_inf
  32. struct page *page;
  33. int index = from >> PAGE_SHIFT;
  34. int offset = from & (PAGE_SIZE-1);
  35. - int cpylen;
  36. + int cpylen, err = 0;
  37. +
  38. + read_lock(&dev->bdev_mutex);
  39. + if (!dev->blkdev || (from > mtd->size)) {
  40. + err = -EINVAL;
  41. + goto done;
  42. + }
  43. - if (from > mtd->size)
  44. - return -EINVAL;
  45. if (from + len > mtd->size)
  46. len = mtd->size - from;
  47. @@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf
  48. len = len - cpylen;
  49. page = page_read(dev->blkdev->bd_inode->i_mapping, index);
  50. - if (!page)
  51. - return -ENOMEM;
  52. - if (IS_ERR(page))
  53. - return PTR_ERR(page);
  54. + if (!page) {
  55. + err = -ENOMEM;
  56. + goto done;
  57. + }
  58. + if (IS_ERR(page)) {
  59. + err = PTR_ERR(page);
  60. + goto done;
  61. + }
  62. memcpy(buf, page_address(page) + offset, cpylen);
  63. page_cache_release(page);
  64. @@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf
  65. offset = 0;
  66. index++;
  67. }
  68. - return 0;
  69. +
  70. +done:
  71. + read_unlock(&dev->bdev_mutex);
  72. + return err;
  73. }
  74. @@ -188,12 +211,22 @@ static int block2mtd_write(struct mtd_in
  75. size_t *retlen, const u_char *buf)
  76. {
  77. struct block2mtd_dev *dev = mtd->priv;
  78. - int err;
  79. + int err = 0;
  80. +
  81. + read_lock(&dev->bdev_mutex);
  82. + if (!dev->blkdev) {
  83. + err = -EINVAL;
  84. + goto done;
  85. + }
  86. if (!len)
  87. - return 0;
  88. - if (to >= mtd->size)
  89. - return -ENOSPC;
  90. + goto done;
  91. +
  92. + if (to >= mtd->size) {
  93. + err = -ENOSPC;
  94. + goto done;
  95. + }
  96. +
  97. if (to + len > mtd->size)
  98. len = mtd->size - to;
  99. @@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in
  100. mutex_unlock(&dev->write_mutex);
  101. if (err > 0)
  102. err = 0;
  103. +
  104. +done:
  105. + read_unlock(&dev->bdev_mutex);
  106. return err;
  107. }
  108. @@ -210,33 +246,110 @@ static int block2mtd_write(struct mtd_in
  109. static void block2mtd_sync(struct mtd_info *mtd)
  110. {
  111. struct block2mtd_dev *dev = mtd->priv;
  112. + read_lock(&dev->bdev_mutex);
  113. + if (dev->blkdev)
  114. sync_blockdev(dev->blkdev);
  115. + read_unlock(&dev->bdev_mutex);
  116. +
  117. return;
  118. }
  119. +static int _open_bdev(struct block2mtd_dev *dev)
  120. +{
  121. + const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
  122. + struct block_device *bdev;
  123. +
  124. + /* Get a handle on the device */
  125. + bdev = blkdev_get_by_path(dev->devname, mode, dev);
  126. +#ifndef MODULE
  127. + if (IS_ERR(bdev)) {
  128. + dev_t devt;
  129. +
  130. + /* We might not have rootfs mounted at this point. Try
  131. + to resolve the device name by other means. */
  132. +
  133. + devt = name_to_dev_t(dev->devname);
  134. + if (devt)
  135. + bdev = blkdev_get_by_dev(devt, mode, dev);
  136. + }
  137. +#endif
  138. +
  139. + if (IS_ERR(bdev)) {
  140. + ERROR("error: cannot open device %s", dev->devname);
  141. + return 1;
  142. + }
  143. + dev->blkdev = bdev;
  144. +
  145. + if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
  146. + ERROR("attempting to use an MTD device as a block device");
  147. + return 1;
  148. + }
  149. +
  150. + return 0;
  151. +}
  152. +
  153. +static void _close_bdev(struct block2mtd_dev *dev)
  154. +{
  155. + struct block_device *bdev;
  156. +
  157. + if (!dev->blkdev)
  158. + return;
  159. +
  160. + bdev = dev->blkdev;
  161. + invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
  162. + blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
  163. + dev->blkdev = NULL;
  164. +}
  165. +
  166. static void block2mtd_free_device(struct block2mtd_dev *dev)
  167. {
  168. if (!dev)
  169. return;
  170. kfree(dev->mtd.name);
  171. -
  172. - if (dev->blkdev) {
  173. - invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
  174. - 0, -1);
  175. - blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
  176. - }
  177. -
  178. + _close_bdev(dev);
  179. kfree(dev);
  180. }
  181. -/* FIXME: ensure that mtd->size % erase_size == 0 */
  182. -static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
  183. +static int block2mtd_refresh(struct mtd_info *mtd)
  184. {
  185. - const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
  186. + struct block2mtd_dev *dev = mtd->priv;
  187. struct block_device *bdev;
  188. + dev_t devt;
  189. + int err = 0;
  190. +
  191. + /* no other mtd function can run at this point */
  192. + write_lock(&dev->bdev_mutex);
  193. +
  194. + /* get the device number for the whole disk */
  195. + devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
  196. +
  197. + /* close the old block device */
  198. + _close_bdev(dev);
  199. +
  200. + /* open the whole disk, issue a partition rescan, then */
  201. + bdev = blkdev_get_by_dev(devt, FMODE_WRITE | FMODE_READ, mtd);
  202. + if (!bdev || !bdev->bd_disk)
  203. + err = -EINVAL;
  204. +#ifndef CONFIG_MTD_BLOCK2MTD_MODULE
  205. + else
  206. + err = rescan_partitions(bdev->bd_disk, bdev);
  207. +#endif
  208. + if (bdev)
  209. + blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
  210. +
  211. + /* try to open the partition block device again */
  212. + _open_bdev(dev);
  213. + write_unlock(&dev->bdev_mutex);
  214. +
  215. + return err;
  216. +}
  217. +
  218. +/* FIXME: ensure that mtd->size % erase_size == 0 */
  219. +static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
  220. +{
  221. struct block2mtd_dev *dev;
  222. struct mtd_partition *part;
  223. char *name;
  224. @@ -244,36 +357,17 @@ static struct block2mtd_dev *add_device(
  225. if (!devname)
  226. return NULL;
  227. - dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
  228. + dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
  229. if (!dev)
  230. return NULL;
  231. - /* Get a handle on the device */
  232. - bdev = blkdev_get_by_path(devname, mode, dev);
  233. -#ifndef MODULE
  234. - if (IS_ERR(bdev)) {
  235. -
  236. - /* We might not have rootfs mounted at this point. Try
  237. - to resolve the device name by other means. */
  238. + strcpy(dev->devname, devname);
  239. - dev_t devt = name_to_dev_t(devname);
  240. - if (devt)
  241. - bdev = blkdev_get_by_dev(devt, mode, dev);
  242. - }
  243. -#endif
  244. -
  245. - if (IS_ERR(bdev)) {
  246. - ERROR("error: cannot open device %s", devname);
  247. + if (_open_bdev(dev))
  248. goto devinit_err;
  249. - }
  250. - dev->blkdev = bdev;
  251. -
  252. - if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
  253. - ERROR("attempting to use an MTD device as a block device");
  254. - goto devinit_err;
  255. - }
  256. mutex_init(&dev->write_mutex);
  257. + rwlock_init(&dev->bdev_mutex);
  258. /* Setup the MTD structure */
  259. /* make the name contain the block device in */
  260. @@ -299,6 +393,7 @@ static struct block2mtd_dev *add_device(
  261. dev->mtd.read = block2mtd_read;
  262. dev->mtd.priv = dev;
  263. dev->mtd.owner = THIS_MODULE;
  264. + dev->mtd.refresh_device = block2mtd_refresh;
  265. part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
  266. part->name = name;