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;
6 struct mutex write_mutex;
12 @@ -82,6 +84,12 @@ static int block2mtd_erase(struct mtd_in
13 size_t len = instr->len;
16 + read_lock(&dev->bdev_mutex);
22 instr->state = MTD_ERASING;
23 mutex_lock(&dev->write_mutex);
24 err = _block2mtd_erase(dev, from, len);
25 @@ -93,6 +101,10 @@ static int block2mtd_erase(struct mtd_in
26 instr->state = MTD_ERASE_DONE;
28 mtd_erase_callback(instr);
31 + read_unlock(&dev->bdev_mutex);
36 @@ -104,10 +116,14 @@ static int block2mtd_read(struct mtd_inf
38 int index = from >> PAGE_SHIFT;
39 int offset = from & (PAGE_SIZE-1);
41 + int cpylen, err = 0;
43 + read_lock(&dev->bdev_mutex);
44 + if (!dev->blkdev || (from > mtd->size)) {
49 - if (from > mtd->size)
51 if (from + len > mtd->size)
52 len = mtd->size - from;
54 @@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf
57 page = page_read(dev->blkdev->bd_inode->i_mapping, index);
61 - return PTR_ERR(page);
67 + err = PTR_ERR(page);
71 memcpy(buf, page_address(page) + offset, cpylen);
72 page_cache_release(page);
73 @@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf
80 + read_unlock(&dev->bdev_mutex);
85 @@ -188,12 +211,22 @@ static int block2mtd_write(struct mtd_in
86 size_t *retlen, const u_char *buf)
88 struct block2mtd_dev *dev = mtd->priv;
92 + read_lock(&dev->bdev_mutex);
100 - if (to >= mtd->size)
104 + if (to >= mtd->size) {
109 if (to + len > mtd->size)
110 len = mtd->size - to;
112 @@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in
113 mutex_unlock(&dev->write_mutex);
118 + read_unlock(&dev->bdev_mutex);
122 @@ -210,52 +246,29 @@ static int block2mtd_write(struct mtd_in
123 static void block2mtd_sync(struct mtd_info *mtd)
125 struct block2mtd_dev *dev = mtd->priv;
126 - sync_blockdev(dev->blkdev);
131 -static void block2mtd_free_device(struct block2mtd_dev *dev)
136 - kfree(dev->mtd.name);
139 - invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
141 - close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
143 + read_lock(&dev->bdev_mutex);
145 + sync_blockdev(dev->blkdev);
146 + read_unlock(&dev->bdev_mutex);
153 -/* FIXME: ensure that mtd->size % erase_size == 0 */
154 -static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
155 +static int _open_bdev(struct block2mtd_dev *dev)
157 struct block_device *bdev;
158 - struct block2mtd_dev *dev;
159 - struct mtd_partition *part;
165 - dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
169 /* Get a handle on the device */
170 - bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);
171 + bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL);
175 /* We might not have rootfs mounted at this point. Try
176 to resolve the device name by other means. */
178 - dev_t devt = name_to_dev_t(devname);
179 + dev_t devt = name_to_dev_t(dev->devname);
181 bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
183 @@ -263,17 +276,98 @@ static struct block2mtd_dev *add_device(
187 - ERROR("error: cannot open device %s", devname);
189 + ERROR("error: cannot open device %s", dev->devname);
194 if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
195 ERROR("attempting to use an MTD device as a block device");
203 +static void _close_bdev(struct block2mtd_dev *dev)
205 + struct block_device *bdev;
210 + bdev = dev->blkdev;
211 + invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
212 + close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
213 + dev->blkdev = NULL;
216 +static void block2mtd_free_device(struct block2mtd_dev *dev)
221 + kfree(dev->mtd.name);
227 +static int block2mtd_refresh(struct mtd_info *mtd)
229 + struct block2mtd_dev *dev = mtd->priv;
230 + struct block_device *bdev;
234 + /* no other mtd function can run at this point */
235 + write_lock(&dev->bdev_mutex);
237 + /* get the device number for the whole disk */
238 + devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
240 + /* close the old block device */
243 + /* open the whole disk, issue a partition rescan, then */
244 + bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
245 + if (!bdev || !bdev->bd_disk)
247 +#ifndef CONFIG_MTD_BLOCK2MTD_MODULE
249 + err = rescan_partitions(bdev->bd_disk, bdev);
252 + close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
254 + /* try to open the partition block device again */
256 + write_unlock(&dev->bdev_mutex);
261 +/* FIXME: ensure that mtd->size % erase_size == 0 */
262 +static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
264 + struct block2mtd_dev *dev;
265 + struct mtd_partition *part;
271 + dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
275 + strcpy(dev->devname, devname);
277 + if (_open_bdev(dev))
280 mutex_init(&dev->write_mutex);
281 + rwlock_init(&dev->bdev_mutex);
283 /* Setup the MTD structure */
284 /* make the name contain the block device in */
285 @@ -298,6 +392,7 @@ static struct block2mtd_dev *add_device(
286 dev->mtd.read = block2mtd_read;
288 dev->mtd.owner = THIS_MODULE;
289 + dev->mtd.refresh_device = block2mtd_refresh;
291 part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
292 part->name = dev->mtd.name;