|
@@ -1137,11 +1137,11 @@ static int check_free_space(struct ubifs_info *c)
|
|
|
*/
|
|
|
static int mount_ubifs(struct ubifs_info *c)
|
|
|
{
|
|
|
- struct super_block *sb = c->vfs_sb;
|
|
|
- int err, mounted_read_only = (sb->s_flags & MS_RDONLY);
|
|
|
+ int err;
|
|
|
long long x;
|
|
|
size_t sz;
|
|
|
|
|
|
+ c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
|
|
|
err = init_constants_early(c);
|
|
|
if (err)
|
|
|
return err;
|
|
@@ -1154,7 +1154,7 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
if (err)
|
|
|
goto out_free;
|
|
|
|
|
|
- if (c->empty && (mounted_read_only || c->ro_media)) {
|
|
|
+ if (c->empty && (c->ro_mount || c->ro_media)) {
|
|
|
/*
|
|
|
* This UBI volume is empty, and read-only, or the file system
|
|
|
* is mounted read-only - we cannot format it.
|
|
@@ -1165,7 +1165,7 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
goto out_free;
|
|
|
}
|
|
|
|
|
|
- if (c->ro_media && !mounted_read_only) {
|
|
|
+ if (c->ro_media && !c->ro_mount) {
|
|
|
ubifs_err("cannot mount read-write - read-only media");
|
|
|
err = -EROFS;
|
|
|
goto out_free;
|
|
@@ -1185,7 +1185,7 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
if (!c->sbuf)
|
|
|
goto out_free;
|
|
|
|
|
|
- if (!mounted_read_only) {
|
|
|
+ if (!c->ro_mount) {
|
|
|
c->ileb_buf = vmalloc(c->leb_size);
|
|
|
if (!c->ileb_buf)
|
|
|
goto out_free;
|
|
@@ -1228,7 +1228,7 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
}
|
|
|
|
|
|
sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
|
|
|
- if (!mounted_read_only) {
|
|
|
+ if (!c->ro_mount) {
|
|
|
err = alloc_wbufs(c);
|
|
|
if (err)
|
|
|
goto out_cbuf;
|
|
@@ -1254,12 +1254,12 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
|
|
|
ubifs_msg("recovery needed");
|
|
|
c->need_recovery = 1;
|
|
|
- if (!mounted_read_only) {
|
|
|
+ if (!c->ro_mount) {
|
|
|
err = ubifs_recover_inl_heads(c, c->sbuf);
|
|
|
if (err)
|
|
|
goto out_master;
|
|
|
}
|
|
|
- } else if (!mounted_read_only) {
|
|
|
+ } else if (!c->ro_mount) {
|
|
|
/*
|
|
|
* Set the "dirty" flag so that if we reboot uncleanly we
|
|
|
* will notice this immediately on the next mount.
|
|
@@ -1270,7 +1270,7 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
goto out_master;
|
|
|
}
|
|
|
|
|
|
- err = ubifs_lpt_init(c, 1, !mounted_read_only);
|
|
|
+ err = ubifs_lpt_init(c, 1, !c->ro_mount);
|
|
|
if (err)
|
|
|
goto out_lpt;
|
|
|
|
|
@@ -1285,11 +1285,11 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
/* Calculate 'min_idx_lebs' after journal replay */
|
|
|
c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
|
|
|
|
|
|
- err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only);
|
|
|
+ err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount);
|
|
|
if (err)
|
|
|
goto out_orphans;
|
|
|
|
|
|
- if (!mounted_read_only) {
|
|
|
+ if (!c->ro_mount) {
|
|
|
int lnum;
|
|
|
|
|
|
err = check_free_space(c);
|
|
@@ -1351,7 +1351,7 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
spin_unlock(&ubifs_infos_lock);
|
|
|
|
|
|
if (c->need_recovery) {
|
|
|
- if (mounted_read_only)
|
|
|
+ if (c->ro_mount)
|
|
|
ubifs_msg("recovery deferred");
|
|
|
else {
|
|
|
c->need_recovery = 0;
|
|
@@ -1378,7 +1378,7 @@ static int mount_ubifs(struct ubifs_info *c)
|
|
|
|
|
|
ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
|
|
|
c->vi.ubi_num, c->vi.vol_id, c->vi.name);
|
|
|
- if (mounted_read_only)
|
|
|
+ if (c->ro_mount)
|
|
|
ubifs_msg("mounted read-only");
|
|
|
x = (long long)c->main_lebs * c->leb_size;
|
|
|
ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, %d "
|
|
@@ -1640,7 +1640,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
|
|
|
}
|
|
|
|
|
|
dbg_gen("re-mounted read-write");
|
|
|
- c->vfs_sb->s_flags &= ~MS_RDONLY;
|
|
|
+ c->ro_mount = 0;
|
|
|
c->remounting_rw = 0;
|
|
|
c->always_chk_crc = 0;
|
|
|
err = dbg_check_space_info(c);
|
|
@@ -1676,7 +1676,7 @@ static void ubifs_remount_ro(struct ubifs_info *c)
|
|
|
int i, err;
|
|
|
|
|
|
ubifs_assert(!c->need_recovery);
|
|
|
- ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
|
|
|
+ ubifs_assert(!c->ro_mount);
|
|
|
|
|
|
mutex_lock(&c->umount_mutex);
|
|
|
if (c->bgt) {
|
|
@@ -1686,10 +1686,8 @@ static void ubifs_remount_ro(struct ubifs_info *c)
|
|
|
|
|
|
dbg_save_space_info(c);
|
|
|
|
|
|
- for (i = 0; i < c->jhead_cnt; i++) {
|
|
|
+ for (i = 0; i < c->jhead_cnt; i++)
|
|
|
ubifs_wbuf_sync(&c->jheads[i].wbuf);
|
|
|
- hrtimer_cancel(&c->jheads[i].wbuf.timer);
|
|
|
- }
|
|
|
|
|
|
c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
|
|
|
c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
|
|
@@ -1704,6 +1702,7 @@ static void ubifs_remount_ro(struct ubifs_info *c)
|
|
|
vfree(c->ileb_buf);
|
|
|
c->ileb_buf = NULL;
|
|
|
ubifs_lpt_free(c, 1);
|
|
|
+ c->ro_mount = 1;
|
|
|
err = dbg_check_space_info(c);
|
|
|
if (err)
|
|
|
ubifs_ro_mode(c, err);
|
|
@@ -1735,7 +1734,7 @@ static void ubifs_put_super(struct super_block *sb)
|
|
|
* the mutex is locked.
|
|
|
*/
|
|
|
mutex_lock(&c->umount_mutex);
|
|
|
- if (!(c->vfs_sb->s_flags & MS_RDONLY)) {
|
|
|
+ if (!c->ro_mount) {
|
|
|
/*
|
|
|
* First of all kill the background thread to make sure it does
|
|
|
* not interfere with un-mounting and freeing resources.
|
|
@@ -1745,23 +1744,22 @@ static void ubifs_put_super(struct super_block *sb)
|
|
|
c->bgt = NULL;
|
|
|
}
|
|
|
|
|
|
- /* Synchronize write-buffers */
|
|
|
- if (c->jheads)
|
|
|
- for (i = 0; i < c->jhead_cnt; i++)
|
|
|
- ubifs_wbuf_sync(&c->jheads[i].wbuf);
|
|
|
-
|
|
|
/*
|
|
|
- * On fatal errors c->ro_media is set to 1, in which case we do
|
|
|
+ * On fatal errors c->ro_error is set to 1, in which case we do
|
|
|
* not write the master node.
|
|
|
*/
|
|
|
- if (!c->ro_media) {
|
|
|
+ if (!c->ro_error) {
|
|
|
+ int err;
|
|
|
+
|
|
|
+ /* Synchronize write-buffers */
|
|
|
+ for (i = 0; i < c->jhead_cnt; i++)
|
|
|
+ ubifs_wbuf_sync(&c->jheads[i].wbuf);
|
|
|
+
|
|
|
/*
|
|
|
* We are being cleanly unmounted which means the
|
|
|
* orphans were killed - indicate this in the master
|
|
|
* node. Also save the reserved GC LEB number.
|
|
|
*/
|
|
|
- int err;
|
|
|
-
|
|
|
c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
|
|
|
c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
|
|
|
c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
|
|
@@ -1774,6 +1772,10 @@ static void ubifs_put_super(struct super_block *sb)
|
|
|
*/
|
|
|
ubifs_err("failed to write master node, "
|
|
|
"error %d", err);
|
|
|
+ } else {
|
|
|
+ for (i = 0; i < c->jhead_cnt; i++)
|
|
|
+ /* Make sure write-buffer timers are canceled */
|
|
|
+ hrtimer_cancel(&c->jheads[i].wbuf.timer);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1797,17 +1799,21 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
- if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
|
|
|
+ if (c->ro_mount && !(*flags & MS_RDONLY)) {
|
|
|
+ if (c->ro_error) {
|
|
|
+ ubifs_msg("cannot re-mount R/W due to prior errors");
|
|
|
+ return -EROFS;
|
|
|
+ }
|
|
|
if (c->ro_media) {
|
|
|
- ubifs_msg("cannot re-mount due to prior errors");
|
|
|
+ ubifs_msg("cannot re-mount R/W - UBI volume is R/O");
|
|
|
return -EROFS;
|
|
|
}
|
|
|
err = ubifs_remount_rw(c);
|
|
|
if (err)
|
|
|
return err;
|
|
|
- } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
|
|
|
- if (c->ro_media) {
|
|
|
- ubifs_msg("cannot re-mount due to prior errors");
|
|
|
+ } else if (!c->ro_mount && (*flags & MS_RDONLY)) {
|
|
|
+ if (c->ro_error) {
|
|
|
+ ubifs_msg("cannot re-mount R/O due to prior errors");
|
|
|
return -EROFS;
|
|
|
}
|
|
|
ubifs_remount_ro(c);
|
|
@@ -2049,8 +2055,8 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
|
|
|
*/
|
|
|
ubi = open_ubi(name, UBI_READONLY);
|
|
|
if (IS_ERR(ubi)) {
|
|
|
- ubifs_err("cannot open \"%s\", error %d",
|
|
|
- name, (int)PTR_ERR(ubi));
|
|
|
+ dbg_err("cannot open \"%s\", error %d",
|
|
|
+ name, (int)PTR_ERR(ubi));
|
|
|
return PTR_ERR(ubi);
|
|
|
}
|
|
|
ubi_get_volume_info(ubi, &vi);
|
|
@@ -2064,9 +2070,11 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
|
|
|
}
|
|
|
|
|
|
if (sb->s_root) {
|
|
|
+ struct ubifs_info *c1 = sb->s_fs_info;
|
|
|
+
|
|
|
/* A new mount point for already mounted UBIFS */
|
|
|
dbg_gen("this ubi volume is already mounted");
|
|
|
- if ((flags ^ sb->s_flags) & MS_RDONLY) {
|
|
|
+ if (!!(flags & MS_RDONLY) != c1->ro_mount) {
|
|
|
err = -EBUSY;
|
|
|
goto out_deact;
|
|
|
}
|