瀏覽代碼

UBI: tweak volumes locking

Transform vtbl_mutex to volumes_mutex - this just makes code
easier to understand.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Artem Bityutskiy 17 年之前
父節點
當前提交
cae0a77125
共有 6 個文件被更改,包括 34 次插入23 次删除
  1. 1 1
      drivers/mtd/ubi/build.c
  2. 6 5
      drivers/mtd/ubi/kapi.c
  3. 3 2
      drivers/mtd/ubi/ubi.h
  4. 4 0
      drivers/mtd/ubi/upd.c
  5. 16 6
      drivers/mtd/ubi/vmt.c
  6. 4 9
      drivers/mtd/ubi/vtbl.c

+ 1 - 1
drivers/mtd/ubi/build.c

@@ -264,7 +264,7 @@ static int uif_init(struct ubi_device *ubi)
 	int i, err;
 	int i, err;
 	dev_t dev;
 	dev_t dev;
 
 
-	mutex_init(&ubi->vtbl_mutex);
+	mutex_init(&ubi->volumes_mutex);
 	spin_lock_init(&ubi->volumes_lock);
 	spin_lock_init(&ubi->volumes_lock);
 
 
 	sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
 	sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);

+ 6 - 5
drivers/mtd/ubi/kapi.c

@@ -162,15 +162,16 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
 	desc->mode = mode;
 	desc->mode = mode;
 
 
 	/*
 	/*
-	 * To prevent simultaneous checks of the same volume we use @vtbl_mutex,
-	 * although it is not the purpose it was introduced for.
+	 * To prevent simultaneous checks of the same volume we use
+	 * @volumes_mutex, although it is not the purpose it was introduced
+	 * for.
 	 */
 	 */
-	mutex_lock(&ubi->vtbl_mutex);
+	mutex_lock(&ubi->volumes_mutex);
 	if (!vol->checked) {
 	if (!vol->checked) {
 		/* This is the first open - check the volume */
 		/* This is the first open - check the volume */
 		err = ubi_check_volume(ubi, vol_id);
 		err = ubi_check_volume(ubi, vol_id);
 		if (err < 0) {
 		if (err < 0) {
-			mutex_unlock(&ubi->vtbl_mutex);
+			mutex_unlock(&ubi->volumes_mutex);
 			ubi_close_volume(desc);
 			ubi_close_volume(desc);
 			return ERR_PTR(err);
 			return ERR_PTR(err);
 		}
 		}
@@ -181,7 +182,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
 		}
 		}
 		vol->checked = 1;
 		vol->checked = 1;
 	}
 	}
-	mutex_unlock(&ubi->vtbl_mutex);
+	mutex_unlock(&ubi->volumes_mutex);
 	return desc;
 	return desc;
 
 
 out_unlock:
 out_unlock:

+ 3 - 2
drivers/mtd/ubi/ubi.h

@@ -255,7 +255,8 @@ struct ubi_wl_entry;
  * @vtbl_slots: how many slots are available in the volume table
  * @vtbl_slots: how many slots are available in the volume table
  * @vtbl_size: size of the volume table in bytes
  * @vtbl_size: size of the volume table in bytes
  * @vtbl: in-RAM volume table copy
  * @vtbl: in-RAM volume table copy
- * @vtbl_mutex: protects on-flash volume table
+ * @volumes_mutex: protects on-flash volume table and serializes volume
+ *                 changes, like creation, deletion, update, resize
  *
  *
  * @max_ec: current highest erase counter value
  * @max_ec: current highest erase counter value
  * @mean_ec: current mean erase counter value
  * @mean_ec: current mean erase counter value
@@ -333,7 +334,7 @@ struct ubi_device {
 	int vtbl_slots;
 	int vtbl_slots;
 	int vtbl_size;
 	int vtbl_size;
 	struct ubi_vtbl_record *vtbl;
 	struct ubi_vtbl_record *vtbl;
-	struct mutex vtbl_mutex;
+	struct mutex volumes_mutex;
 
 
 	int max_ec;
 	int max_ec;
 	int mean_ec;
 	int mean_ec;

+ 4 - 0
drivers/mtd/ubi/upd.c

@@ -67,7 +67,9 @@ static int set_update_marker(struct ubi_device *ubi, int vol_id)
 	memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record));
 	memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record));
 	vtbl_rec.upd_marker = 1;
 	vtbl_rec.upd_marker = 1;
 
 
+	mutex_lock(&ubi->volumes_mutex);
 	err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
 	err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
+	mutex_unlock(&ubi->volumes_mutex);
 	vol->upd_marker = 1;
 	vol->upd_marker = 1;
 	return err;
 	return err;
 }
 }
@@ -106,7 +108,9 @@ static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long byt
 			vol->last_eb_bytes = vol->usable_leb_size;
 			vol->last_eb_bytes = vol->usable_leb_size;
 	}
 	}
 
 
+	mutex_lock(&ubi->volumes_mutex);
 	err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
 	err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
+	mutex_unlock(&ubi->volumes_mutex);
 	vol->upd_marker = 0;
 	vol->upd_marker = 0;
 	return err;
 	return err;
 }
 }

+ 16 - 6
drivers/mtd/ubi/vmt.c

@@ -201,8 +201,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 	if (!vol)
 	if (!vol)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	mutex_lock(&ubi->volumes_mutex);
 	spin_lock(&ubi->volumes_lock);
 	spin_lock(&ubi->volumes_lock);
-
 	if (vol_id == UBI_VOL_NUM_AUTO) {
 	if (vol_id == UBI_VOL_NUM_AUTO) {
 		/* Find unused volume ID */
 		/* Find unused volume ID */
 		dbg_msg("search for vacant volume ID");
 		dbg_msg("search for vacant volume ID");
@@ -350,6 +350,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 	spin_unlock(&ubi->volumes_lock);
 	spin_unlock(&ubi->volumes_lock);
 
 
 	paranoid_check_volumes(ubi);
 	paranoid_check_volumes(ubi);
+	mutex_unlock(&ubi->volumes_mutex);
 	return 0;
 	return 0;
 
 
 out_gluebi:
 out_gluebi:
@@ -365,6 +366,7 @@ out_acc:
 	ubi->volumes[vol_id] = NULL;
 	ubi->volumes[vol_id] = NULL;
 out_unlock:
 out_unlock:
 	spin_unlock(&ubi->volumes_lock);
 	spin_unlock(&ubi->volumes_lock);
+	mutex_unlock(&ubi->volumes_mutex);
 	kfree(vol);
 	kfree(vol);
 	ubi_err("cannot create volume %d, error %d", vol_id, err);
 	ubi_err("cannot create volume %d, error %d", vol_id, err);
 	return err;
 	return err;
@@ -382,6 +384,7 @@ out_sysfs:
 	ubi->avail_pebs += vol->reserved_pebs;
 	ubi->avail_pebs += vol->reserved_pebs;
 	ubi->volumes[vol_id] = NULL;
 	ubi->volumes[vol_id] = NULL;
 	spin_unlock(&ubi->volumes_lock);
 	spin_unlock(&ubi->volumes_lock);
+	mutex_unlock(&ubi->volumes_mutex);
 	volume_sysfs_close(vol);
 	volume_sysfs_close(vol);
 	ubi_err("cannot create volume %d, error %d", vol_id, err);
 	ubi_err("cannot create volume %d, error %d", vol_id, err);
 	return err;
 	return err;
@@ -408,18 +411,19 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
 	if (ubi->ro_mode)
 	if (ubi->ro_mode)
 		return -EROFS;
 		return -EROFS;
 
 
+	mutex_lock(&ubi->volumes_mutex);
 	err = ubi_destroy_gluebi(vol);
 	err = ubi_destroy_gluebi(vol);
 	if (err)
 	if (err)
-		return err;
+		goto out;
 
 
 	err = ubi_change_vtbl_record(ubi, vol_id, NULL);
 	err = ubi_change_vtbl_record(ubi, vol_id, NULL);
 	if (err)
 	if (err)
-		return err;
+		goto out;
 
 
 	for (i = 0; i < vol->reserved_pebs; i++) {
 	for (i = 0; i < vol->reserved_pebs; i++) {
 		err = ubi_eba_unmap_leb(ubi, vol, i);
 		err = ubi_eba_unmap_leb(ubi, vol, i);
 		if (err)
 		if (err)
-			return err;
+			goto out;
 	}
 	}
 
 
 	spin_lock(&ubi->volumes_lock);
 	spin_lock(&ubi->volumes_lock);
@@ -449,8 +453,13 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
 	spin_unlock(&ubi->volumes_lock);
 	spin_unlock(&ubi->volumes_lock);
 
 
 	paranoid_check_volumes(ubi);
 	paranoid_check_volumes(ubi);
+	mutex_unlock(&ubi->volumes_mutex);
 	module_put(THIS_MODULE);
 	module_put(THIS_MODULE);
 	return 0;
 	return 0;
+
+out:
+	mutex_unlock(&ubi->volumes_mutex);
+	return err;
 }
 }
 
 
 /**
 /**
@@ -496,6 +505,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
 		new_mapping[i] = UBI_LEB_UNMAPPED;
 		new_mapping[i] = UBI_LEB_UNMAPPED;
 
 
 	/* Reserve physical eraseblocks */
 	/* Reserve physical eraseblocks */
+	mutex_lock(&ubi->volumes_mutex);
 	pebs = reserved_pebs - vol->reserved_pebs;
 	pebs = reserved_pebs - vol->reserved_pebs;
 	if (pebs > 0) {
 	if (pebs > 0) {
 		spin_lock(&ubi->volumes_lock);
 		spin_lock(&ubi->volumes_lock);
@@ -556,6 +566,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
 	}
 	}
 
 
 	paranoid_check_volumes(ubi);
 	paranoid_check_volumes(ubi);
+	mutex_unlock(&ubi->volumes_mutex);
 	return 0;
 	return 0;
 
 
 out_acc:
 out_acc:
@@ -567,6 +578,7 @@ out_acc:
 	}
 	}
 out_free:
 out_free:
 	kfree(new_mapping);
 	kfree(new_mapping);
+	mutex_unlock(&ubi->volumes_mutex);
 	return err;
 	return err;
 }
 }
 
 
@@ -829,9 +841,7 @@ static void paranoid_check_volumes(struct ubi_device *ubi)
 {
 {
 	int i;
 	int i;
 
 
-	mutex_lock(&ubi->vtbl_mutex);
 	for (i = 0; i < ubi->vtbl_slots; i++)
 	for (i = 0; i < ubi->vtbl_slots; i++)
 		paranoid_check_volume(ubi, i);
 		paranoid_check_volume(ubi, i);
-	mutex_unlock(&ubi->vtbl_mutex);
 }
 }
 #endif
 #endif

+ 4 - 9
drivers/mtd/ubi/vtbl.c

@@ -89,7 +89,7 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
 	struct ubi_volume *layout_vol;
 	struct ubi_volume *layout_vol;
 
 
 	ubi_assert(idx >= 0 && idx < ubi->vtbl_slots);
 	ubi_assert(idx >= 0 && idx < ubi->vtbl_slots);
-	layout_vol = ubi->volumes[vol_id2idx(UBI_LAYOUT_VOL_ID)];
+	layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOL_ID)];
 
 
 	if (!vtbl_rec)
 	if (!vtbl_rec)
 		vtbl_rec = &empty_vtbl_record;
 		vtbl_rec = &empty_vtbl_record;
@@ -98,24 +98,19 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
 		vtbl_rec->crc = cpu_to_be32(crc);
 		vtbl_rec->crc = cpu_to_be32(crc);
 	}
 	}
 
 
-	mutex_lock(&ubi->vtbl_mutex);
 	memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record));
 	memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record));
 	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
 	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
 		err = ubi_eba_unmap_leb(ubi, layout_vol, i);
 		err = ubi_eba_unmap_leb(ubi, layout_vol, i);
-		if (err) {
-			mutex_unlock(&ubi->vtbl_mutex);
+		if (err)
 			return err;
 			return err;
-		}
+
 		err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
 		err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
 					ubi->vtbl_size, UBI_LONGTERM);
 					ubi->vtbl_size, UBI_LONGTERM);
-		if (err) {
-			mutex_unlock(&ubi->vtbl_mutex);
+		if (err)
 			return err;
 			return err;
-		}
 	}
 	}
 
 
 	paranoid_vtbl_check(ubi);
 	paranoid_vtbl_check(ubi);
-	mutex_unlock(&ubi->vtbl_mutex);
 	return ubi_wl_flush(ubi);
 	return ubi_wl_flush(ubi);
 }
 }