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:
parent
89b96b6929
commit
cae0a77125
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue