Root/target/linux/generic/patches-3.6/441-block2mtd_refresh.patch

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

Archive Download this file



interactive