Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6
[cascardo/linux.git] / fs / ubifs / super.c
index cd5900b..9a47c9f 100644 (file)
@@ -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;
                }