UBI: do not panic if volume check fails
[pandora-kernel.git] / drivers / mtd / ubi / vmt.c
index d400668..1628e1f 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 #include <linux/err.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
 #include "ubi.h"
 
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
@@ -198,14 +198,13 @@ static void volume_sysfs_close(struct ubi_volume *vol)
  * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume
  * and saves it in @req->vol_id. Returns zero in case of success and a negative
  * error code in case of failure. Note, the caller has to have the
- * @ubi->volumes_mutex locked.
+ * @ubi->device_mutex locked.
  */
 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 {
        int i, err, vol_id = req->vol_id, do_free = 1;
        struct ubi_volume *vol;
        struct ubi_vtbl_record vtbl_rec;
-       uint64_t bytes;
        dev_t dev;
 
        if (ubi->ro_mode)
@@ -233,8 +232,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
                req->vol_id = vol_id;
        }
 
-       dbg_gen("volume ID %d, %llu bytes, type %d, name %s",
-               vol_id, (unsigned long long)req->bytes,
+       dbg_gen("create device %d, volume %d, %llu bytes, type %d, name %s",
+               ubi->ubi_num, vol_id, (unsigned long long)req->bytes,
                (int)req->vol_type, req->name);
 
        /* Ensure that this volume does not exist */
@@ -255,10 +254,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 
        /* Calculate how many eraseblocks are requested */
        vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment;
-       bytes = req->bytes;
-       if (do_div(bytes, vol->usable_leb_size))
-               vol->reserved_pebs = 1;
-       vol->reserved_pebs += bytes;
+       vol->reserved_pebs += div_u64(req->bytes + vol->usable_leb_size - 1,
+                                     vol->usable_leb_size);
 
        /* Reserve physical eraseblocks */
        if (vol->reserved_pebs > ubi->avail_pebs) {
@@ -301,10 +298,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
                vol->used_bytes =
                        (long long)vol->used_ebs * vol->usable_leb_size;
        } else {
-               bytes = vol->used_bytes;
-               vol->last_eb_bytes = do_div(bytes, vol->usable_leb_size);
-               vol->used_ebs = bytes;
-               if (vol->last_eb_bytes)
+               vol->used_ebs = div_u64_rem(vol->used_bytes,
+                                           vol->usable_leb_size,
+                                           &vol->last_eb_bytes);
+               if (vol->last_eb_bytes != 0)
                        vol->used_ebs += 1;
                else
                        vol->last_eb_bytes = vol->usable_leb_size;
@@ -361,7 +358,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        ubi->vol_count += 1;
        spin_unlock(&ubi->volumes_lock);
 
-       err = paranoid_check_volumes(ubi);
+       if (paranoid_check_volumes(ubi))
+               dbg_err("check failed while creating volume %d", vol_id);
        return err;
 
 out_sysfs:
@@ -406,7 +404,7 @@ out_unlock:
  *
  * This function removes volume described by @desc. The volume has to be opened
  * in "exclusive" mode. Returns zero in case of success and a negative error
- * code in case of failure. The caller has to have the @ubi->volumes_mutex
+ * code in case of failure. The caller has to have the @ubi->device_mutex
  * locked.
  */
 int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
@@ -415,7 +413,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
        struct ubi_device *ubi = vol->ubi;
        int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs;
 
-       dbg_gen("remove UBI volume %d", vol_id);
+       dbg_gen("remove device %d, volume %d", ubi->ubi_num, vol_id);
        ubi_assert(desc->mode == UBI_EXCLUSIVE);
        ubi_assert(vol == ubi->volumes[vol_id]);
 
@@ -468,8 +466,9 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
        ubi->vol_count -= 1;
        spin_unlock(&ubi->volumes_lock);
 
-       if (!no_vtbl)
-               err = paranoid_check_volumes(ubi);
+       if (!no_vtbl && paranoid_check_volumes(ubi))
+               dbg_err("check failed while removing volume %d", vol_id);
+
        return err;
 
 out_err:
@@ -488,7 +487,7 @@ out_unlock:
  *
  * This function re-sizes the volume and returns zero in case of success, and a
  * negative error code in case of failure. The caller has to have the
- * @ubi->volumes_mutex locked.
+ * @ubi->device_mutex locked.
  */
 int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
 {
@@ -501,8 +500,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
        if (ubi->ro_mode)
                return -EROFS;
 
-       dbg_gen("re-size volume %d to from %d to %d PEBs",
-               vol_id, vol->reserved_pebs, reserved_pebs);
+       dbg_gen("re-size device %d, volume %d to from %d to %d PEBs",
+               ubi->ubi_num, vol_id, vol->reserved_pebs, reserved_pebs);
 
        if (vol->vol_type == UBI_STATIC_VOLUME &&
            reserved_pebs < vol->used_ebs) {
@@ -590,7 +589,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
                        (long long)vol->used_ebs * vol->usable_leb_size;
        }
 
-       err = paranoid_check_volumes(ubi);
+       if (paranoid_check_volumes(ubi))
+               dbg_err("check failed while re-sizing volume %d", vol_id);
        return err;
 
 out_acc:
@@ -638,8 +638,8 @@ int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list)
                }
        }
 
-       if (!err)
-               paranoid_check_volumes(ubi);
+       if (!err && paranoid_check_volumes(ubi))
+               ;
        return err;
 }
 
@@ -691,7 +691,8 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
                return err;
        }
 
-       err = paranoid_check_volumes(ubi);
+       if (paranoid_check_volumes(ubi))
+               dbg_err("check failed while adding volume %d", vol_id);
        return err;
 
 out_gluebi:
@@ -871,6 +872,7 @@ fail:
        if (vol)
                ubi_dbg_dump_vol_info(vol);
        ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
+       dump_stack();
        spin_unlock(&ubi->volumes_lock);
        return -EINVAL;
 }