aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/kapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/kapi.c')
-rw-r--r--drivers/mtd/ubi/kapi.c177
1 files changed, 116 insertions, 61 deletions
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 03c774f41549..a70d58823f8d 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -30,23 +30,27 @@
30 * @ubi_num: UBI device number 30 * @ubi_num: UBI device number
31 * @di: the information is stored here 31 * @di: the information is stored here
32 * 32 *
33 * This function returns %0 in case of success and a %-ENODEV if there is no 33 * This function returns %0 in case of success, %-EINVAL if the UBI device
34 * such UBI device. 34 * number is invalid, and %-ENODEV if there is no such UBI device.
35 */ 35 */
36int ubi_get_device_info(int ubi_num, struct ubi_device_info *di) 36int ubi_get_device_info(int ubi_num, struct ubi_device_info *di)
37{ 37{
38 const struct ubi_device *ubi; 38 struct ubi_device *ubi;
39
40 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
41 return -EINVAL;
39 42
40 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || 43 ubi = ubi_get_device(ubi_num);
41 !ubi_devices[ubi_num]) 44 if (!ubi)
42 return -ENODEV; 45 return -ENODEV;
43 46
44 ubi = ubi_devices[ubi_num];
45 di->ubi_num = ubi->ubi_num; 47 di->ubi_num = ubi->ubi_num;
46 di->leb_size = ubi->leb_size; 48 di->leb_size = ubi->leb_size;
47 di->min_io_size = ubi->min_io_size; 49 di->min_io_size = ubi->min_io_size;
48 di->ro_mode = ubi->ro_mode; 50 di->ro_mode = ubi->ro_mode;
49 di->cdev = MKDEV(ubi->major, 0); 51 di->cdev = ubi->cdev.dev;
52
53 ubi_put_device(ubi);
50 return 0; 54 return 0;
51} 55}
52EXPORT_SYMBOL_GPL(ubi_get_device_info); 56EXPORT_SYMBOL_GPL(ubi_get_device_info);
@@ -73,7 +77,7 @@ void ubi_get_volume_info(struct ubi_volume_desc *desc,
73 vi->usable_leb_size = vol->usable_leb_size; 77 vi->usable_leb_size = vol->usable_leb_size;
74 vi->name_len = vol->name_len; 78 vi->name_len = vol->name_len;
75 vi->name = vol->name; 79 vi->name = vol->name;
76 vi->cdev = MKDEV(ubi->major, vi->vol_id + 1); 80 vi->cdev = vol->cdev.dev;
77} 81}
78EXPORT_SYMBOL_GPL(ubi_get_volume_info); 82EXPORT_SYMBOL_GPL(ubi_get_volume_info);
79 83
@@ -104,37 +108,39 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
104 108
105 dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode); 109 dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode);
106 110
107 err = -ENODEV; 111 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
108 if (ubi_num < 0) 112 return ERR_PTR(-EINVAL);
109 return ERR_PTR(err);
110
111 ubi = ubi_devices[ubi_num];
112
113 if (!try_module_get(THIS_MODULE))
114 return ERR_PTR(err);
115
116 if (ubi_num >= UBI_MAX_DEVICES || !ubi)
117 goto out_put;
118 113
119 err = -EINVAL;
120 if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
121 goto out_put;
122 if (mode != UBI_READONLY && mode != UBI_READWRITE && 114 if (mode != UBI_READONLY && mode != UBI_READWRITE &&
123 mode != UBI_EXCLUSIVE) 115 mode != UBI_EXCLUSIVE)
124 goto out_put; 116 return ERR_PTR(-EINVAL);
117
118 /*
119 * First of all, we have to get the UBI device to prevent its removal.
120 */
121 ubi = ubi_get_device(ubi_num);
122 if (!ubi)
123 return ERR_PTR(-ENODEV);
124
125 if (vol_id < 0 || vol_id >= ubi->vtbl_slots) {
126 err = -EINVAL;
127 goto out_put_ubi;
128 }
125 129
126 desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL); 130 desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL);
127 if (!desc) { 131 if (!desc) {
128 err = -ENOMEM; 132 err = -ENOMEM;
129 goto out_put; 133 goto out_put_ubi;
130 } 134 }
131 135
136 err = -ENODEV;
137 if (!try_module_get(THIS_MODULE))
138 goto out_free;
139
132 spin_lock(&ubi->volumes_lock); 140 spin_lock(&ubi->volumes_lock);
133 vol = ubi->volumes[vol_id]; 141 vol = ubi->volumes[vol_id];
134 if (!vol) { 142 if (!vol)
135 err = -ENODEV;
136 goto out_unlock; 143 goto out_unlock;
137 }
138 144
139 err = -EBUSY; 145 err = -EBUSY;
140 switch (mode) { 146 switch (mode) {
@@ -156,21 +162,19 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
156 vol->exclusive = 1; 162 vol->exclusive = 1;
157 break; 163 break;
158 } 164 }
165 get_device(&vol->dev);
166 vol->ref_count += 1;
159 spin_unlock(&ubi->volumes_lock); 167 spin_unlock(&ubi->volumes_lock);
160 168
161 desc->vol = vol; 169 desc->vol = vol;
162 desc->mode = mode; 170 desc->mode = mode;
163 171
164 /* 172 mutex_lock(&ubi->ckvol_mutex);
165 * To prevent simultaneous checks of the same volume we use @vtbl_mutex,
166 * although it is not the purpose it was introduced for.
167 */
168 mutex_lock(&ubi->vtbl_mutex);
169 if (!vol->checked) { 173 if (!vol->checked) {
170 /* This is the first open - check the volume */ 174 /* This is the first open - check the volume */
171 err = ubi_check_volume(ubi, vol_id); 175 err = ubi_check_volume(ubi, vol_id);
172 if (err < 0) { 176 if (err < 0) {
173 mutex_unlock(&ubi->vtbl_mutex); 177 mutex_unlock(&ubi->ckvol_mutex);
174 ubi_close_volume(desc); 178 ubi_close_volume(desc);
175 return ERR_PTR(err); 179 return ERR_PTR(err);
176 } 180 }
@@ -181,14 +185,17 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
181 } 185 }
182 vol->checked = 1; 186 vol->checked = 1;
183 } 187 }
184 mutex_unlock(&ubi->vtbl_mutex); 188 mutex_unlock(&ubi->ckvol_mutex);
189
185 return desc; 190 return desc;
186 191
187out_unlock: 192out_unlock:
188 spin_unlock(&ubi->volumes_lock); 193 spin_unlock(&ubi->volumes_lock);
189 kfree(desc);
190out_put:
191 module_put(THIS_MODULE); 194 module_put(THIS_MODULE);
195out_free:
196 kfree(desc);
197out_put_ubi:
198 ubi_put_device(ubi);
192 return ERR_PTR(err); 199 return ERR_PTR(err);
193} 200}
194EXPORT_SYMBOL_GPL(ubi_open_volume); 201EXPORT_SYMBOL_GPL(ubi_open_volume);
@@ -205,8 +212,8 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
205 int mode) 212 int mode)
206{ 213{
207 int i, vol_id = -1, len; 214 int i, vol_id = -1, len;
208 struct ubi_volume_desc *ret;
209 struct ubi_device *ubi; 215 struct ubi_device *ubi;
216 struct ubi_volume_desc *ret;
210 217
211 dbg_msg("open volume %s, mode %d", name, mode); 218 dbg_msg("open volume %s, mode %d", name, mode);
212 219
@@ -217,14 +224,12 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
217 if (len > UBI_VOL_NAME_MAX) 224 if (len > UBI_VOL_NAME_MAX)
218 return ERR_PTR(-EINVAL); 225 return ERR_PTR(-EINVAL);
219 226
220 ret = ERR_PTR(-ENODEV); 227 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
221 if (!try_module_get(THIS_MODULE)) 228 return ERR_PTR(-EINVAL);
222 return ret;
223
224 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || !ubi_devices[ubi_num])
225 goto out_put;
226 229
227 ubi = ubi_devices[ubi_num]; 230 ubi = ubi_get_device(ubi_num);
231 if (!ubi)
232 return ERR_PTR(-ENODEV);
228 233
229 spin_lock(&ubi->volumes_lock); 234 spin_lock(&ubi->volumes_lock);
230 /* Walk all volumes of this UBI device */ 235 /* Walk all volumes of this UBI device */
@@ -238,13 +243,16 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
238 } 243 }
239 spin_unlock(&ubi->volumes_lock); 244 spin_unlock(&ubi->volumes_lock);
240 245
241 if (vol_id < 0) 246 if (vol_id >= 0)
242 goto out_put; 247 ret = ubi_open_volume(ubi_num, vol_id, mode);
248 else
249 ret = ERR_PTR(-ENODEV);
243 250
244 ret = ubi_open_volume(ubi_num, vol_id, mode); 251 /*
245 252 * We should put the UBI device even in case of success, because
246out_put: 253 * 'ubi_open_volume()' took a reference as well.
247 module_put(THIS_MODULE); 254 */
255 ubi_put_device(ubi);
248 return ret; 256 return ret;
249} 257}
250EXPORT_SYMBOL_GPL(ubi_open_volume_nm); 258EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
@@ -256,10 +264,11 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
256void ubi_close_volume(struct ubi_volume_desc *desc) 264void ubi_close_volume(struct ubi_volume_desc *desc)
257{ 265{
258 struct ubi_volume *vol = desc->vol; 266 struct ubi_volume *vol = desc->vol;
267 struct ubi_device *ubi = vol->ubi;
259 268
260 dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode); 269 dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode);
261 270
262 spin_lock(&vol->ubi->volumes_lock); 271 spin_lock(&ubi->volumes_lock);
263 switch (desc->mode) { 272 switch (desc->mode) {
264 case UBI_READONLY: 273 case UBI_READONLY:
265 vol->readers -= 1; 274 vol->readers -= 1;
@@ -270,9 +279,12 @@ void ubi_close_volume(struct ubi_volume_desc *desc)
270 case UBI_EXCLUSIVE: 279 case UBI_EXCLUSIVE:
271 vol->exclusive = 0; 280 vol->exclusive = 0;
272 } 281 }
273 spin_unlock(&vol->ubi->volumes_lock); 282 vol->ref_count -= 1;
283 spin_unlock(&ubi->volumes_lock);
274 284
275 kfree(desc); 285 kfree(desc);
286 put_device(&vol->dev);
287 ubi_put_device(ubi);
276 module_put(THIS_MODULE); 288 module_put(THIS_MODULE);
277} 289}
278EXPORT_SYMBOL_GPL(ubi_close_volume); 290EXPORT_SYMBOL_GPL(ubi_close_volume);
@@ -332,7 +344,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
332 if (len == 0) 344 if (len == 0)
333 return 0; 345 return 0;
334 346
335 err = ubi_eba_read_leb(ubi, vol_id, lnum, buf, offset, len, check); 347 err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
336 if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) { 348 if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) {
337 ubi_warn("mark volume %d as corrupted", vol_id); 349 ubi_warn("mark volume %d as corrupted", vol_id);
338 vol->corrupted = 1; 350 vol->corrupted = 1;
@@ -399,7 +411,7 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
399 if (len == 0) 411 if (len == 0)
400 return 0; 412 return 0;
401 413
402 return ubi_eba_write_leb(ubi, vol_id, lnum, buf, offset, len, dtype); 414 return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype);
403} 415}
404EXPORT_SYMBOL_GPL(ubi_leb_write); 416EXPORT_SYMBOL_GPL(ubi_leb_write);
405 417
@@ -448,7 +460,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
448 if (len == 0) 460 if (len == 0)
449 return 0; 461 return 0;
450 462
451 return ubi_eba_atomic_leb_change(ubi, vol_id, lnum, buf, len, dtype); 463 return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype);
452} 464}
453EXPORT_SYMBOL_GPL(ubi_leb_change); 465EXPORT_SYMBOL_GPL(ubi_leb_change);
454 466
@@ -468,9 +480,9 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
468{ 480{
469 struct ubi_volume *vol = desc->vol; 481 struct ubi_volume *vol = desc->vol;
470 struct ubi_device *ubi = vol->ubi; 482 struct ubi_device *ubi = vol->ubi;
471 int err, vol_id = vol->vol_id; 483 int err;
472 484
473 dbg_msg("erase LEB %d:%d", vol_id, lnum); 485 dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
474 486
475 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 487 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
476 return -EROFS; 488 return -EROFS;
@@ -481,7 +493,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
481 if (vol->upd_marker) 493 if (vol->upd_marker)
482 return -EBADF; 494 return -EBADF;
483 495
484 err = ubi_eba_unmap_leb(ubi, vol_id, lnum); 496 err = ubi_eba_unmap_leb(ubi, vol, lnum);
485 if (err) 497 if (err)
486 return err; 498 return err;
487 499
@@ -529,9 +541,8 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
529{ 541{
530 struct ubi_volume *vol = desc->vol; 542 struct ubi_volume *vol = desc->vol;
531 struct ubi_device *ubi = vol->ubi; 543 struct ubi_device *ubi = vol->ubi;
532 int vol_id = vol->vol_id;
533 544
534 dbg_msg("unmap LEB %d:%d", vol_id, lnum); 545 dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum);
535 546
536 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 547 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
537 return -EROFS; 548 return -EROFS;
@@ -542,11 +553,55 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
542 if (vol->upd_marker) 553 if (vol->upd_marker)
543 return -EBADF; 554 return -EBADF;
544 555
545 return ubi_eba_unmap_leb(ubi, vol_id, lnum); 556 return ubi_eba_unmap_leb(ubi, vol, lnum);
546} 557}
547EXPORT_SYMBOL_GPL(ubi_leb_unmap); 558EXPORT_SYMBOL_GPL(ubi_leb_unmap);
548 559
549/** 560/**
561 * ubi_leb_map - map logical erasblock to a physical eraseblock.
562 * @desc: volume descriptor
563 * @lnum: logical eraseblock number
564 * @dtype: expected data type
565 *
566 * This function maps an un-mapped logical eraseblock @lnum to a physical
567 * eraseblock. This means, that after a successfull invocation of this
568 * function the logical eraseblock @lnum will be empty (contain only %0xFF
569 * bytes) and be mapped to a physical eraseblock, even if an unclean reboot
570 * happens.
571 *
572 * This function returns zero in case of success, %-EBADF if the volume is
573 * damaged because of an interrupted update, %-EBADMSG if the logical
574 * eraseblock is already mapped, and other negative error codes in case of
575 * other failures.
576 */
577int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
578{
579 struct ubi_volume *vol = desc->vol;
580 struct ubi_device *ubi = vol->ubi;
581
582 dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum);
583
584 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
585 return -EROFS;
586
587 if (lnum < 0 || lnum >= vol->reserved_pebs)
588 return -EINVAL;
589
590 if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
591 dtype != UBI_UNKNOWN)
592 return -EINVAL;
593
594 if (vol->upd_marker)
595 return -EBADF;
596
597 if (vol->eba_tbl[lnum] >= 0)
598 return -EBADMSG;
599
600 return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
601}
602EXPORT_SYMBOL_GPL(ubi_leb_map);
603
604/**
550 * ubi_is_mapped - check if logical eraseblock is mapped. 605 * ubi_is_mapped - check if logical eraseblock is mapped.
551 * @desc: volume descriptor 606 * @desc: volume descriptor
552 * @lnum: logical eraseblock number 607 * @lnum: logical eraseblock number