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>
This commit is contained in:
Artem Bityutskiy 2007-12-17 12:46:48 +02:00
parent 89b96b6929
commit cae0a77125
6 changed files with 34 additions and 23 deletions

View File

@ -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);

View File

@ -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, * To prevent simultaneous checks of the same volume we use
* although it is not the purpose it was introduced for. * @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:

View File

@ -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;

View File

@ -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;
} }

View File

@ -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

View File

@ -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) { if (err)
mutex_unlock(&ubi->vtbl_mutex);
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) { if (err)
mutex_unlock(&ubi->vtbl_mutex);
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);
} }