diff options
Diffstat (limited to 'drivers/mtd/ubi/vmt.c')
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 208 |
1 files changed, 116 insertions, 92 deletions
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 88629a320c2b..a3ca2257e601 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
@@ -63,21 +63,30 @@ static struct device_attribute attr_vol_upd_marker = | |||
63 | * B. process 2 removes volume Y; | 63 | * B. process 2 removes volume Y; |
64 | * C. process 1 starts reading the /<sysfs>/class/ubi/ubiX_Y/reserved_ebs file; | 64 | * C. process 1 starts reading the /<sysfs>/class/ubi/ubiX_Y/reserved_ebs file; |
65 | * | 65 | * |
66 | * What we want to do in a situation like that is to return error when the file | 66 | * In this situation, this function will return %-ENODEV because it will find |
67 | * is read. This is done by means of the 'removed' flag and the 'vol_lock' of | 67 | * out that the volume was removed from the @ubi->volumes array. |
68 | * the UBI volume description object. | ||
69 | */ | 68 | */ |
70 | static ssize_t vol_attribute_show(struct device *dev, | 69 | static ssize_t vol_attribute_show(struct device *dev, |
71 | struct device_attribute *attr, char *buf) | 70 | struct device_attribute *attr, char *buf) |
72 | { | 71 | { |
73 | int ret; | 72 | int ret; |
74 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 73 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
74 | struct ubi_device *ubi; | ||
75 | 75 | ||
76 | spin_lock(&vol->ubi->volumes_lock); | 76 | ubi = ubi_get_device(vol->ubi->ubi_num); |
77 | if (vol->removed) { | 77 | if (!ubi) |
78 | spin_unlock(&vol->ubi->volumes_lock); | 78 | return -ENODEV; |
79 | |||
80 | spin_lock(&ubi->volumes_lock); | ||
81 | if (!ubi->volumes[vol->vol_id]) { | ||
82 | spin_unlock(&ubi->volumes_lock); | ||
83 | ubi_put_device(ubi); | ||
79 | return -ENODEV; | 84 | return -ENODEV; |
80 | } | 85 | } |
86 | /* Take a reference to prevent volume removal */ | ||
87 | vol->ref_count += 1; | ||
88 | spin_unlock(&ubi->volumes_lock); | ||
89 | |||
81 | if (attr == &attr_vol_reserved_ebs) | 90 | if (attr == &attr_vol_reserved_ebs) |
82 | ret = sprintf(buf, "%d\n", vol->reserved_pebs); | 91 | ret = sprintf(buf, "%d\n", vol->reserved_pebs); |
83 | else if (attr == &attr_vol_type) { | 92 | else if (attr == &attr_vol_type) { |
@@ -94,15 +103,22 @@ static ssize_t vol_attribute_show(struct device *dev, | |||
94 | ret = sprintf(buf, "%d\n", vol->corrupted); | 103 | ret = sprintf(buf, "%d\n", vol->corrupted); |
95 | else if (attr == &attr_vol_alignment) | 104 | else if (attr == &attr_vol_alignment) |
96 | ret = sprintf(buf, "%d\n", vol->alignment); | 105 | ret = sprintf(buf, "%d\n", vol->alignment); |
97 | else if (attr == &attr_vol_usable_eb_size) { | 106 | else if (attr == &attr_vol_usable_eb_size) |
98 | ret = sprintf(buf, "%d\n", vol->usable_leb_size); | 107 | ret = sprintf(buf, "%d\n", vol->usable_leb_size); |
99 | } else if (attr == &attr_vol_data_bytes) | 108 | else if (attr == &attr_vol_data_bytes) |
100 | ret = sprintf(buf, "%lld\n", vol->used_bytes); | 109 | ret = sprintf(buf, "%lld\n", vol->used_bytes); |
101 | else if (attr == &attr_vol_upd_marker) | 110 | else if (attr == &attr_vol_upd_marker) |
102 | ret = sprintf(buf, "%d\n", vol->upd_marker); | 111 | ret = sprintf(buf, "%d\n", vol->upd_marker); |
103 | else | 112 | else |
104 | BUG(); | 113 | /* This must be a bug */ |
105 | spin_unlock(&vol->ubi->volumes_lock); | 114 | ret = -EINVAL; |
115 | |||
116 | /* We've done the operation, drop volume and UBI device references */ | ||
117 | spin_lock(&ubi->volumes_lock); | ||
118 | vol->ref_count -= 1; | ||
119 | ubi_assert(vol->ref_count >= 0); | ||
120 | spin_unlock(&ubi->volumes_lock); | ||
121 | ubi_put_device(ubi); | ||
106 | return ret; | 122 | return ret; |
107 | } | 123 | } |
108 | 124 | ||
@@ -110,7 +126,7 @@ static ssize_t vol_attribute_show(struct device *dev, | |||
110 | static void vol_release(struct device *dev) | 126 | static void vol_release(struct device *dev) |
111 | { | 127 | { |
112 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 128 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
113 | ubi_assert(vol->removed); | 129 | |
114 | kfree(vol); | 130 | kfree(vol); |
115 | } | 131 | } |
116 | 132 | ||
@@ -152,9 +168,7 @@ static int volume_sysfs_init(struct ubi_device *ubi, struct ubi_volume *vol) | |||
152 | if (err) | 168 | if (err) |
153 | return err; | 169 | return err; |
154 | err = device_create_file(&vol->dev, &attr_vol_upd_marker); | 170 | err = device_create_file(&vol->dev, &attr_vol_upd_marker); |
155 | if (err) | 171 | return err; |
156 | return err; | ||
157 | return 0; | ||
158 | } | 172 | } |
159 | 173 | ||
160 | /** | 174 | /** |
@@ -180,16 +194,18 @@ static void volume_sysfs_close(struct ubi_volume *vol) | |||
180 | * @req: volume creation request | 194 | * @req: volume creation request |
181 | * | 195 | * |
182 | * This function creates volume described by @req. If @req->vol_id id | 196 | * This function creates volume described by @req. If @req->vol_id id |
183 | * %UBI_VOL_NUM_AUTO, this function automatically assigne ID to the new volume | 197 | * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume |
184 | * and saves it in @req->vol_id. Returns zero in case of success and a negative | 198 | * and saves it in @req->vol_id. Returns zero in case of success and a negative |
185 | * error code in case of failure. | 199 | * error code in case of failure. Note, the caller has to have the |
200 | * @ubi->volumes_mutex locked. | ||
186 | */ | 201 | */ |
187 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | 202 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) |
188 | { | 203 | { |
189 | int i, err, vol_id = req->vol_id; | 204 | int i, err, vol_id = req->vol_id, dont_free = 0; |
190 | struct ubi_volume *vol; | 205 | struct ubi_volume *vol; |
191 | struct ubi_vtbl_record vtbl_rec; | 206 | struct ubi_vtbl_record vtbl_rec; |
192 | uint64_t bytes; | 207 | uint64_t bytes; |
208 | dev_t dev; | ||
193 | 209 | ||
194 | if (ubi->ro_mode) | 210 | if (ubi->ro_mode) |
195 | return -EROFS; | 211 | return -EROFS; |
@@ -199,7 +215,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
199 | return -ENOMEM; | 215 | return -ENOMEM; |
200 | 216 | ||
201 | spin_lock(&ubi->volumes_lock); | 217 | spin_lock(&ubi->volumes_lock); |
202 | |||
203 | if (vol_id == UBI_VOL_NUM_AUTO) { | 218 | if (vol_id == UBI_VOL_NUM_AUTO) { |
204 | /* Find unused volume ID */ | 219 | /* Find unused volume ID */ |
205 | dbg_msg("search for vacant volume ID"); | 220 | dbg_msg("search for vacant volume ID"); |
@@ -252,6 +267,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
252 | } | 267 | } |
253 | ubi->avail_pebs -= vol->reserved_pebs; | 268 | ubi->avail_pebs -= vol->reserved_pebs; |
254 | ubi->rsvd_pebs += vol->reserved_pebs; | 269 | ubi->rsvd_pebs += vol->reserved_pebs; |
270 | spin_unlock(&ubi->volumes_lock); | ||
255 | 271 | ||
256 | vol->vol_id = vol_id; | 272 | vol->vol_id = vol_id; |
257 | vol->alignment = req->alignment; | 273 | vol->alignment = req->alignment; |
@@ -259,10 +275,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
259 | vol->vol_type = req->vol_type; | 275 | vol->vol_type = req->vol_type; |
260 | vol->name_len = req->name_len; | 276 | vol->name_len = req->name_len; |
261 | memcpy(vol->name, req->name, vol->name_len + 1); | 277 | memcpy(vol->name, req->name, vol->name_len + 1); |
262 | vol->exclusive = 1; | ||
263 | vol->ubi = ubi; | 278 | vol->ubi = ubi; |
264 | ubi->volumes[vol_id] = vol; | ||
265 | spin_unlock(&ubi->volumes_lock); | ||
266 | 279 | ||
267 | /* | 280 | /* |
268 | * Finish all pending erases because there may be some LEBs belonging | 281 | * Finish all pending erases because there may be some LEBs belonging |
@@ -299,9 +312,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
299 | /* Register character device for the volume */ | 312 | /* Register character device for the volume */ |
300 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); | 313 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); |
301 | vol->cdev.owner = THIS_MODULE; | 314 | vol->cdev.owner = THIS_MODULE; |
302 | err = cdev_add(&vol->cdev, MKDEV(ubi->major, vol_id + 1), 1); | 315 | dev = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1); |
316 | err = cdev_add(&vol->cdev, dev, 1); | ||
303 | if (err) { | 317 | if (err) { |
304 | ubi_err("cannot add character device for volume %d", vol_id); | 318 | ubi_err("cannot add character device"); |
305 | goto out_mapping; | 319 | goto out_mapping; |
306 | } | 320 | } |
307 | 321 | ||
@@ -311,12 +325,15 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
311 | 325 | ||
312 | vol->dev.release = vol_release; | 326 | vol->dev.release = vol_release; |
313 | vol->dev.parent = &ubi->dev; | 327 | vol->dev.parent = &ubi->dev; |
314 | vol->dev.devt = MKDEV(ubi->major, vol->vol_id + 1); | 328 | vol->dev.devt = dev; |
315 | vol->dev.class = ubi_class; | 329 | vol->dev.class = ubi_class; |
330 | |||
316 | sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); | 331 | sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); |
317 | err = device_register(&vol->dev); | 332 | err = device_register(&vol->dev); |
318 | if (err) | 333 | if (err) { |
334 | ubi_err("cannot register device"); | ||
319 | goto out_gluebi; | 335 | goto out_gluebi; |
336 | } | ||
320 | 337 | ||
321 | err = volume_sysfs_init(ubi, vol); | 338 | err = volume_sysfs_init(ubi, vol); |
322 | if (err) | 339 | if (err) |
@@ -339,15 +356,27 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
339 | goto out_sysfs; | 356 | goto out_sysfs; |
340 | 357 | ||
341 | spin_lock(&ubi->volumes_lock); | 358 | spin_lock(&ubi->volumes_lock); |
359 | ubi->volumes[vol_id] = vol; | ||
342 | ubi->vol_count += 1; | 360 | ubi->vol_count += 1; |
343 | vol->exclusive = 0; | ||
344 | spin_unlock(&ubi->volumes_lock); | 361 | spin_unlock(&ubi->volumes_lock); |
345 | 362 | ||
346 | paranoid_check_volumes(ubi); | 363 | paranoid_check_volumes(ubi); |
347 | return 0; | 364 | return 0; |
348 | 365 | ||
366 | out_sysfs: | ||
367 | /* | ||
368 | * We have registered our device, we should not free the volume* | ||
369 | * description object in this function in case of an error - it is | ||
370 | * freed by the release function. | ||
371 | * | ||
372 | * Get device reference to prevent the release function from being | ||
373 | * called just after sysfs has been closed. | ||
374 | */ | ||
375 | dont_free = 1; | ||
376 | get_device(&vol->dev); | ||
377 | volume_sysfs_close(vol); | ||
349 | out_gluebi: | 378 | out_gluebi: |
350 | err = ubi_destroy_gluebi(vol); | 379 | ubi_destroy_gluebi(vol); |
351 | out_cdev: | 380 | out_cdev: |
352 | cdev_del(&vol->cdev); | 381 | cdev_del(&vol->cdev); |
353 | out_mapping: | 382 | out_mapping: |
@@ -356,26 +385,13 @@ out_acc: | |||
356 | spin_lock(&ubi->volumes_lock); | 385 | spin_lock(&ubi->volumes_lock); |
357 | ubi->rsvd_pebs -= vol->reserved_pebs; | 386 | ubi->rsvd_pebs -= vol->reserved_pebs; |
358 | ubi->avail_pebs += vol->reserved_pebs; | 387 | ubi->avail_pebs += vol->reserved_pebs; |
359 | ubi->volumes[vol_id] = NULL; | ||
360 | out_unlock: | 388 | out_unlock: |
361 | spin_unlock(&ubi->volumes_lock); | 389 | spin_unlock(&ubi->volumes_lock); |
362 | kfree(vol); | 390 | if (dont_free) |
363 | return err; | 391 | put_device(&vol->dev); |
364 | 392 | else | |
365 | /* | 393 | kfree(vol); |
366 | * We are registered, so @vol is destroyed in the release function and | 394 | ubi_err("cannot create volume %d, error %d", vol_id, err); |
367 | * we have to de-initialize differently. | ||
368 | */ | ||
369 | out_sysfs: | ||
370 | err = ubi_destroy_gluebi(vol); | ||
371 | cdev_del(&vol->cdev); | ||
372 | kfree(vol->eba_tbl); | ||
373 | spin_lock(&ubi->volumes_lock); | ||
374 | ubi->rsvd_pebs -= vol->reserved_pebs; | ||
375 | ubi->avail_pebs += vol->reserved_pebs; | ||
376 | ubi->volumes[vol_id] = NULL; | ||
377 | spin_unlock(&ubi->volumes_lock); | ||
378 | volume_sysfs_close(vol); | ||
379 | return err; | 395 | return err; |
380 | } | 396 | } |
381 | 397 | ||
@@ -385,7 +401,8 @@ out_sysfs: | |||
385 | * | 401 | * |
386 | * This function removes volume described by @desc. The volume has to be opened | 402 | * This function removes volume described by @desc. The volume has to be opened |
387 | * in "exclusive" mode. Returns zero in case of success and a negative error | 403 | * in "exclusive" mode. Returns zero in case of success and a negative error |
388 | * code in case of failure. | 404 | * code in case of failure. The caller has to have the @ubi->volumes_mutex |
405 | * locked. | ||
389 | */ | 406 | */ |
390 | int ubi_remove_volume(struct ubi_volume_desc *desc) | 407 | int ubi_remove_volume(struct ubi_volume_desc *desc) |
391 | { | 408 | { |
@@ -400,30 +417,36 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
400 | if (ubi->ro_mode) | 417 | if (ubi->ro_mode) |
401 | return -EROFS; | 418 | return -EROFS; |
402 | 419 | ||
420 | spin_lock(&ubi->volumes_lock); | ||
421 | if (vol->ref_count > 1) { | ||
422 | /* | ||
423 | * The volume is busy, probably someone is reading one of its | ||
424 | * sysfs files. | ||
425 | */ | ||
426 | err = -EBUSY; | ||
427 | goto out_unlock; | ||
428 | } | ||
429 | ubi->volumes[vol_id] = NULL; | ||
430 | spin_unlock(&ubi->volumes_lock); | ||
431 | |||
403 | err = ubi_destroy_gluebi(vol); | 432 | err = ubi_destroy_gluebi(vol); |
404 | if (err) | 433 | if (err) |
405 | return err; | 434 | goto out_err; |
406 | 435 | ||
407 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); | 436 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); |
408 | if (err) | 437 | if (err) |
409 | return err; | 438 | goto out_err; |
410 | 439 | ||
411 | for (i = 0; i < vol->reserved_pebs; i++) { | 440 | for (i = 0; i < vol->reserved_pebs; i++) { |
412 | err = ubi_eba_unmap_leb(ubi, vol_id, i); | 441 | err = ubi_eba_unmap_leb(ubi, vol, i); |
413 | if (err) | 442 | if (err) |
414 | return err; | 443 | goto out_err; |
415 | } | 444 | } |
416 | 445 | ||
417 | spin_lock(&ubi->volumes_lock); | ||
418 | vol->removed = 1; | ||
419 | ubi->volumes[vol_id] = NULL; | ||
420 | spin_unlock(&ubi->volumes_lock); | ||
421 | |||
422 | kfree(vol->eba_tbl); | 446 | kfree(vol->eba_tbl); |
423 | vol->eba_tbl = NULL; | 447 | vol->eba_tbl = NULL; |
424 | cdev_del(&vol->cdev); | 448 | cdev_del(&vol->cdev); |
425 | volume_sysfs_close(vol); | 449 | volume_sysfs_close(vol); |
426 | kfree(desc); | ||
427 | 450 | ||
428 | spin_lock(&ubi->volumes_lock); | 451 | spin_lock(&ubi->volumes_lock); |
429 | ubi->rsvd_pebs -= reserved_pebs; | 452 | ubi->rsvd_pebs -= reserved_pebs; |
@@ -441,8 +464,15 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
441 | spin_unlock(&ubi->volumes_lock); | 464 | spin_unlock(&ubi->volumes_lock); |
442 | 465 | ||
443 | paranoid_check_volumes(ubi); | 466 | paranoid_check_volumes(ubi); |
444 | module_put(THIS_MODULE); | ||
445 | return 0; | 467 | return 0; |
468 | |||
469 | out_err: | ||
470 | ubi_err("cannot remove volume %d, error %d", vol_id, err); | ||
471 | spin_lock(&ubi->volumes_lock); | ||
472 | ubi->volumes[vol_id] = vol; | ||
473 | out_unlock: | ||
474 | spin_unlock(&ubi->volumes_lock); | ||
475 | return err; | ||
446 | } | 476 | } |
447 | 477 | ||
448 | /** | 478 | /** |
@@ -450,8 +480,9 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
450 | * @desc: volume descriptor | 480 | * @desc: volume descriptor |
451 | * @reserved_pebs: new size in physical eraseblocks | 481 | * @reserved_pebs: new size in physical eraseblocks |
452 | * | 482 | * |
453 | * This function returns zero in case of success, and a negative error code in | 483 | * This function re-sizes the volume and returns zero in case of success, and a |
454 | * case of failure. | 484 | * negative error code in case of failure. The caller has to have the |
485 | * @ubi->volumes_mutex locked. | ||
455 | */ | 486 | */ |
456 | int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | 487 | int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) |
457 | { | 488 | { |
@@ -466,8 +497,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
466 | 497 | ||
467 | dbg_msg("re-size volume %d to from %d to %d PEBs", | 498 | dbg_msg("re-size volume %d to from %d to %d PEBs", |
468 | vol_id, vol->reserved_pebs, reserved_pebs); | 499 | vol_id, vol->reserved_pebs, reserved_pebs); |
469 | ubi_assert(desc->mode == UBI_EXCLUSIVE); | ||
470 | ubi_assert(vol == ubi->volumes[vol_id]); | ||
471 | 500 | ||
472 | if (vol->vol_type == UBI_STATIC_VOLUME && | 501 | if (vol->vol_type == UBI_STATIC_VOLUME && |
473 | reserved_pebs < vol->used_ebs) { | 502 | reserved_pebs < vol->used_ebs) { |
@@ -487,6 +516,14 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
487 | for (i = 0; i < reserved_pebs; i++) | 516 | for (i = 0; i < reserved_pebs; i++) |
488 | new_mapping[i] = UBI_LEB_UNMAPPED; | 517 | new_mapping[i] = UBI_LEB_UNMAPPED; |
489 | 518 | ||
519 | spin_lock(&ubi->volumes_lock); | ||
520 | if (vol->ref_count > 1) { | ||
521 | spin_unlock(&ubi->volumes_lock); | ||
522 | err = -EBUSY; | ||
523 | goto out_free; | ||
524 | } | ||
525 | spin_unlock(&ubi->volumes_lock); | ||
526 | |||
490 | /* Reserve physical eraseblocks */ | 527 | /* Reserve physical eraseblocks */ |
491 | pebs = reserved_pebs - vol->reserved_pebs; | 528 | pebs = reserved_pebs - vol->reserved_pebs; |
492 | if (pebs > 0) { | 529 | if (pebs > 0) { |
@@ -516,7 +553,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
516 | 553 | ||
517 | if (pebs < 0) { | 554 | if (pebs < 0) { |
518 | for (i = 0; i < -pebs; i++) { | 555 | for (i = 0; i < -pebs; i++) { |
519 | err = ubi_eba_unmap_leb(ubi, vol_id, reserved_pebs + i); | 556 | err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i); |
520 | if (err) | 557 | if (err) |
521 | goto out_acc; | 558 | goto out_acc; |
522 | } | 559 | } |
@@ -565,27 +602,28 @@ out_free: | |||
565 | /** | 602 | /** |
566 | * ubi_add_volume - add volume. | 603 | * ubi_add_volume - add volume. |
567 | * @ubi: UBI device description object | 604 | * @ubi: UBI device description object |
568 | * @vol_id: volume ID | 605 | * @vol: volume description object |
569 | * | 606 | * |
570 | * This function adds an existin volume and initializes all its data | 607 | * This function adds an existing volume and initializes all its data |
571 | * structures. Returnes zero in case of success and a negative error code in | 608 | * structures. Returns zero in case of success and a negative error code in |
572 | * case of failure. | 609 | * case of failure. |
573 | */ | 610 | */ |
574 | int ubi_add_volume(struct ubi_device *ubi, int vol_id) | 611 | int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) |
575 | { | 612 | { |
576 | int err; | 613 | int err, vol_id = vol->vol_id; |
577 | struct ubi_volume *vol = ubi->volumes[vol_id]; | 614 | dev_t dev; |
578 | 615 | ||
579 | dbg_msg("add volume %d", vol_id); | 616 | dbg_msg("add volume %d", vol_id); |
580 | ubi_dbg_dump_vol_info(vol); | 617 | ubi_dbg_dump_vol_info(vol); |
581 | ubi_assert(vol); | ||
582 | 618 | ||
583 | /* Register character device for the volume */ | 619 | /* Register character device for the volume */ |
584 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); | 620 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); |
585 | vol->cdev.owner = THIS_MODULE; | 621 | vol->cdev.owner = THIS_MODULE; |
586 | err = cdev_add(&vol->cdev, MKDEV(ubi->major, vol->vol_id + 1), 1); | 622 | dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1); |
623 | err = cdev_add(&vol->cdev, dev, 1); | ||
587 | if (err) { | 624 | if (err) { |
588 | ubi_err("cannot add character device for volume %d", vol_id); | 625 | ubi_err("cannot add character device for volume %d, error %d", |
626 | vol_id, err); | ||
589 | return err; | 627 | return err; |
590 | } | 628 | } |
591 | 629 | ||
@@ -595,7 +633,7 @@ int ubi_add_volume(struct ubi_device *ubi, int vol_id) | |||
595 | 633 | ||
596 | vol->dev.release = vol_release; | 634 | vol->dev.release = vol_release; |
597 | vol->dev.parent = &ubi->dev; | 635 | vol->dev.parent = &ubi->dev; |
598 | vol->dev.devt = MKDEV(ubi->major, vol->vol_id + 1); | 636 | vol->dev.devt = dev; |
599 | vol->dev.class = ubi_class; | 637 | vol->dev.class = ubi_class; |
600 | sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); | 638 | sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); |
601 | err = device_register(&vol->dev); | 639 | err = device_register(&vol->dev); |
@@ -623,22 +661,19 @@ out_cdev: | |||
623 | /** | 661 | /** |
624 | * ubi_free_volume - free volume. | 662 | * ubi_free_volume - free volume. |
625 | * @ubi: UBI device description object | 663 | * @ubi: UBI device description object |
626 | * @vol_id: volume ID | 664 | * @vol: volume description object |
627 | * | 665 | * |
628 | * This function frees all resources for volume @vol_id but does not remove it. | 666 | * This function frees all resources for volume @vol but does not remove it. |
629 | * Used only when the UBI device is detached. | 667 | * Used only when the UBI device is detached. |
630 | */ | 668 | */ |
631 | void ubi_free_volume(struct ubi_device *ubi, int vol_id) | 669 | void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) |
632 | { | 670 | { |
633 | int err; | 671 | int err; |
634 | struct ubi_volume *vol = ubi->volumes[vol_id]; | ||
635 | 672 | ||
636 | dbg_msg("free volume %d", vol_id); | 673 | dbg_msg("free volume %d", vol->vol_id); |
637 | ubi_assert(vol); | ||
638 | 674 | ||
639 | vol->removed = 1; | 675 | ubi->volumes[vol->vol_id] = NULL; |
640 | err = ubi_destroy_gluebi(vol); | 676 | err = ubi_destroy_gluebi(vol); |
641 | ubi->volumes[vol_id] = NULL; | ||
642 | cdev_del(&vol->cdev); | 677 | cdev_del(&vol->cdev); |
643 | volume_sysfs_close(vol); | 678 | volume_sysfs_close(vol); |
644 | } | 679 | } |
@@ -708,11 +743,6 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
708 | goto fail; | 743 | goto fail; |
709 | } | 744 | } |
710 | 745 | ||
711 | if (vol->upd_marker != 0 && vol->upd_marker != 1) { | ||
712 | ubi_err("bad upd_marker"); | ||
713 | goto fail; | ||
714 | } | ||
715 | |||
716 | if (vol->upd_marker && vol->corrupted) { | 746 | if (vol->upd_marker && vol->corrupted) { |
717 | dbg_err("update marker and corrupted simultaneously"); | 747 | dbg_err("update marker and corrupted simultaneously"); |
718 | goto fail; | 748 | goto fail; |
@@ -747,7 +777,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
747 | 777 | ||
748 | n = (long long)vol->used_ebs * vol->usable_leb_size; | 778 | n = (long long)vol->used_ebs * vol->usable_leb_size; |
749 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { | 779 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
750 | if (vol->corrupted != 0) { | 780 | if (vol->corrupted) { |
751 | ubi_err("corrupted dynamic volume"); | 781 | ubi_err("corrupted dynamic volume"); |
752 | goto fail; | 782 | goto fail; |
753 | } | 783 | } |
@@ -764,10 +794,6 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
764 | goto fail; | 794 | goto fail; |
765 | } | 795 | } |
766 | } else { | 796 | } else { |
767 | if (vol->corrupted != 0 && vol->corrupted != 1) { | ||
768 | ubi_err("bad corrupted"); | ||
769 | goto fail; | ||
770 | } | ||
771 | if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) { | 797 | if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) { |
772 | ubi_err("bad used_ebs"); | 798 | ubi_err("bad used_ebs"); |
773 | goto fail; | 799 | goto fail; |
@@ -820,9 +846,7 @@ static void paranoid_check_volumes(struct ubi_device *ubi) | |||
820 | { | 846 | { |
821 | int i; | 847 | int i; |
822 | 848 | ||
823 | mutex_lock(&ubi->vtbl_mutex); | ||
824 | for (i = 0; i < ubi->vtbl_slots; i++) | 849 | for (i = 0; i < ubi->vtbl_slots; i++) |
825 | paranoid_check_volume(ubi, i); | 850 | paranoid_check_volume(ubi, i); |
826 | mutex_unlock(&ubi->vtbl_mutex); | ||
827 | } | 851 | } |
828 | #endif | 852 | #endif |