add 3.7-rc6 support (patch 820 still has to be fixed)
[openwrt/staging/wigyori.git] / target / linux / generic / patches-3.7 / 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;