int i, err;
dev_t dev;
- mutex_init(&ubi->vtbl_mutex);
+ mutex_init(&ubi->volumes_mutex);
spin_lock_init(&ubi->volumes_lock);
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
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) {
/* This is the first open - check the volume */
err = ubi_check_volume(ubi, vol_id);
if (err < 0) {
- mutex_unlock(&ubi->vtbl_mutex);
+ mutex_unlock(&ubi->volumes_mutex);
ubi_close_volume(desc);
return ERR_PTR(err);
}
}
vol->checked = 1;
}
- mutex_unlock(&ubi->vtbl_mutex);
+ mutex_unlock(&ubi->volumes_mutex);
return desc;
out_unlock:
* @vtbl_slots: how many slots are available in the volume table
* @vtbl_size: size of the volume table in bytes
* @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
* @mean_ec: current mean erase counter value
int vtbl_slots;
int vtbl_size;
struct ubi_vtbl_record *vtbl;
- struct mutex vtbl_mutex;
+ struct mutex volumes_mutex;
int max_ec;
int mean_ec;
memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record));
vtbl_rec.upd_marker = 1;
+ mutex_lock(&ubi->volumes_mutex);
err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
+ mutex_unlock(&ubi->volumes_mutex);
vol->upd_marker = 1;
return err;
}
vol->last_eb_bytes = vol->usable_leb_size;
}
+ mutex_lock(&ubi->volumes_mutex);
err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
+ mutex_unlock(&ubi->volumes_mutex);
vol->upd_marker = 0;
return err;
}
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 */
dbg_msg("search for vacant volume ID");
spin_unlock(&ubi->volumes_lock);
paranoid_check_volumes(ubi);
+ mutex_unlock(&ubi->volumes_mutex);
return 0;
out_gluebi:
ubi->volumes[vol_id] = NULL;
out_unlock:
spin_unlock(&ubi->volumes_lock);
+ mutex_unlock(&ubi->volumes_mutex);
kfree(vol);
ubi_err("cannot create volume %d, error %d", vol_id, err);
return err;
ubi->avail_pebs += vol->reserved_pebs;
ubi->volumes[vol_id] = NULL;
spin_unlock(&ubi->volumes_lock);
+ mutex_unlock(&ubi->volumes_mutex);
volume_sysfs_close(vol);
ubi_err("cannot create volume %d, error %d", vol_id, err);
return err;
if (ubi->ro_mode)
return -EROFS;
+ mutex_lock(&ubi->volumes_mutex);
err = ubi_destroy_gluebi(vol);
if (err)
- return err;
+ goto out;
err = ubi_change_vtbl_record(ubi, vol_id, NULL);
if (err)
- return err;
+ goto out;
for (i = 0; i < vol->reserved_pebs; i++) {
err = ubi_eba_unmap_leb(ubi, vol, i);
if (err)
- return err;
+ goto out;
}
spin_lock(&ubi->volumes_lock);
spin_unlock(&ubi->volumes_lock);
paranoid_check_volumes(ubi);
+ mutex_unlock(&ubi->volumes_mutex);
module_put(THIS_MODULE);
return 0;
+
+out:
+ mutex_unlock(&ubi->volumes_mutex);
+ return err;
}
/**
new_mapping[i] = UBI_LEB_UNMAPPED;
/* Reserve physical eraseblocks */
+ mutex_lock(&ubi->volumes_mutex);
pebs = reserved_pebs - vol->reserved_pebs;
if (pebs > 0) {
spin_lock(&ubi->volumes_lock);
}
paranoid_check_volumes(ubi);
+ mutex_unlock(&ubi->volumes_mutex);
return 0;
out_acc:
}
out_free:
kfree(new_mapping);
+ mutex_unlock(&ubi->volumes_mutex);
return err;
}
{
int i;
- mutex_lock(&ubi->vtbl_mutex);
for (i = 0; i < ubi->vtbl_slots; i++)
paranoid_check_volume(ubi, i);
- mutex_unlock(&ubi->vtbl_mutex);
}
#endif
struct ubi_volume *layout_vol;
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)
vtbl_rec = &empty_vtbl_record;
vtbl_rec->crc = cpu_to_be32(crc);
}
- mutex_lock(&ubi->vtbl_mutex);
memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record));
for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
err = ubi_eba_unmap_leb(ubi, layout_vol, i);
- if (err) {
- mutex_unlock(&ubi->vtbl_mutex);
+ if (err)
return err;
- }
+
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
ubi->vtbl_size, UBI_LONGTERM);
- if (err) {
- mutex_unlock(&ubi->vtbl_mutex);
+ if (err)
return err;
- }
}
paranoid_vtbl_check(ubi);
- mutex_unlock(&ubi->vtbl_mutex);
return ubi_wl_flush(ubi);
}