UBI: tweak volumes locking some more
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Mon, 17 Dec 2007 15:08:55 +0000 (17:08 +0200)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Wed, 26 Dec 2007 17:15:16 +0000 (19:15 +0200)
Make the code more consistent by requiring the caller to lock the
ubi->volume_mutex, because this is what we do for updates.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/vmt.c

index 35d34b675c78edc69d5002c817998ca583dd2444..22c15a388f28947dab4a56a1f2991aa36a3b8270 100644 (file)
@@ -605,7 +605,9 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
 
                req.name[req.name_len] = '\0';
 
+               mutex_lock(&ubi->volumes_mutex);
                err = ubi_create_volume(ubi, &req);
+               mutex_unlock(&ubi->volumes_mutex);
                if (err)
                        break;
 
@@ -634,11 +636,14 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
                        break;
                }
 
+               mutex_lock(&ubi->volumes_mutex);
                err = ubi_remove_volume(desc);
+               mutex_unlock(&ubi->volumes_mutex);
+
                /*
-                * The volume is deleted, and the 'struct ubi_volume' object
-                * will be freed when 'ubi_close_volume()' will call
-                * 'put_device()'.
+                * The volume is deleted (unless an error occurred), and the
+                * 'struct ubi_volume' object will be freed when
+                * 'ubi_close_volume()' will call 'put_device()'.
                 */
                ubi_close_volume(desc);
                break;
@@ -673,7 +678,9 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
                pebs = !!do_div(tmp, desc->vol->usable_leb_size);
                pebs += tmp;
 
+               mutex_lock(&ubi->volumes_mutex);
                err = ubi_resize_volume(desc, pebs);
+               mutex_unlock(&ubi->volumes_mutex);
                ubi_close_volume(desc);
                break;
        }
index 18ef1e1da496144df2b00f3444e730bb6c9a3c51..3ed63dc37386daaff1decb868f7902f31dbeb8f7 100644 (file)
@@ -189,7 +189,8 @@ static void volume_sysfs_close(struct ubi_volume *vol)
  * This function creates volume described by @req. If @req->vol_id id
  * %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.
+ * error code in case of failure. Note, the caller has to have the
+ * @ubi->volumes_mutex locked.
  */
 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 {
@@ -206,7 +207,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        if (!vol)
                return -ENOMEM;
 
-       mutex_lock(&ubi->volumes_mutex);
        spin_lock(&ubi->volumes_lock);
        if (vol_id == UBI_VOL_NUM_AUTO) {
                /* Find unused volume ID */
@@ -356,7 +356,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        spin_unlock(&ubi->volumes_lock);
 
        paranoid_check_volumes(ubi);
-       mutex_unlock(&ubi->volumes_mutex);
        return 0;
 
 out_sysfs:
@@ -383,7 +382,6 @@ out_acc:
        ubi->avail_pebs += vol->reserved_pebs;
 out_unlock:
        spin_unlock(&ubi->volumes_lock);
-       mutex_unlock(&ubi->volumes_mutex);
        if (dont_free)
                put_device(&vol->dev);
        else
@@ -398,7 +396,8 @@ 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.
+ * code in case of failure. The caller has to have the @ubi->volumes_mutex
+ * locked.
  */
 int ubi_remove_volume(struct ubi_volume_desc *desc)
 {
@@ -413,7 +412,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
        if (ubi->ro_mode)
                return -EROFS;
 
-       mutex_lock(&ubi->volumes_mutex);
        spin_lock(&ubi->volumes_lock);
        if (vol->ref_count > 1) {
                /*
@@ -461,7 +459,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
        spin_unlock(&ubi->volumes_lock);
 
        paranoid_check_volumes(ubi);
-       mutex_unlock(&ubi->volumes_mutex);
        return 0;
 
 out_err:
@@ -470,7 +467,6 @@ out_err:
        ubi->volumes[vol_id] = vol;
 out_unlock:
        spin_unlock(&ubi->volumes_lock);
-       mutex_unlock(&ubi->volumes_mutex);
        return err;
 }
 
@@ -479,8 +475,9 @@ out_unlock:
  * @desc: volume descriptor
  * @reserved_pebs: new size in physical eraseblocks
  *
- * This function returns zero in case of success, and a negative error code in
- * case of failure.
+ * 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.
  */
 int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
 {
@@ -516,7 +513,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
        for (i = 0; i < reserved_pebs; i++)
                new_mapping[i] = UBI_LEB_UNMAPPED;
 
-       mutex_lock(&ubi->volumes_mutex);
        spin_lock(&ubi->volumes_lock);
        if (vol->ref_count > 1) {
                spin_unlock(&ubi->volumes_lock);
@@ -587,7 +583,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
        }
 
        paranoid_check_volumes(ubi);
-       mutex_unlock(&ubi->volumes_mutex);
        return 0;
 
 out_acc:
@@ -599,7 +594,6 @@ out_acc:
        }
 out_free:
        kfree(new_mapping);
-       mutex_unlock(&ubi->volumes_mutex);
        return err;
 }