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

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

Archive Download this file



interactive