aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-09-19 11:34:26 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-09-19 14:07:58 -0400
commit2ef13294d29bcfb306e0d360f1b97f37b647b0c0 (patch)
tree877e1ece00c14de0f0d79e86b6480d284d309216
parent2680d722bf2c5f75225dd9acb3ec9e5a9e2652f4 (diff)
UBIFS: introduce new flags for RO mounts
Commit 2fde99cb55fb9d9b88180512a5e8a5d939d27fec "UBIFS: mark VFS SB RO too" introduced regression. This commit made UBIFS set the 'MS_RDONLY' flag in the VFS superblock when it switches to R/O mode due to an error. This was done to make VFS show the R/O UBIFS flag in /proc/mounts. However, several places in UBIFS relied on the 'MS_RDONLY' flag and assume this flag can only change when we re-mount. For example, 'ubifs_put_super()'. This patch introduces new UBIFS flag - 'c->ro_mount' which changes only when we re-mount, and preserves the way UBIFS was originally mounted (R/W or R/O). This allows us to de-initialize UBIFS cleanly in 'ubifs_put_super()'. This patch also changes all 'ubifs_assert(!c->ro_media)' assertions to 'ubifs_assert(!c->ro_media && !c->ro_mount)', because we never should write anything if the FS was mounter R/O. All the places where we test for 'MS_RDONLY' flag in the VFS SB were changed and now we test the 'c->ro_mount' flag instead, because it preserves the original UBIFS mount type, unlike the 'MS_RDONLY' flag. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
-rw-r--r--fs/ubifs/commit.c2
-rw-r--r--fs/ubifs/file.c5
-rw-r--r--fs/ubifs/gc.c2
-rw-r--r--fs/ubifs/io.c9
-rw-r--r--fs/ubifs/journal.c2
-rw-r--r--fs/ubifs/log.c4
-rw-r--r--fs/ubifs/master.c2
-rw-r--r--fs/ubifs/misc.h6
-rw-r--r--fs/ubifs/recovery.c8
-rw-r--r--fs/ubifs/replay.c3
-rw-r--r--fs/ubifs/sb.c9
-rw-r--r--fs/ubifs/shrinker.c2
-rw-r--r--fs/ubifs/super.c55
-rw-r--r--fs/ubifs/ubifs.h13
14 files changed, 62 insertions, 60 deletions
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 712432789fb8..02429d81ca33 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -63,7 +63,7 @@ static int do_commit(struct ubifs_info *c)
63 struct ubifs_lp_stats lst; 63 struct ubifs_lp_stats lst;
64 64
65 dbg_cmt("start"); 65 dbg_cmt("start");
66 ubifs_assert(!c->ro_media); 66 ubifs_assert(!c->ro_media && !c->ro_mount);
67 67
68 if (c->ro_error) { 68 if (c->ro_error) {
69 err = -EROFS; 69 err = -EROFS;
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index c6bc51c9f07c..d77db7e36484 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -433,7 +433,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
433 struct page *page; 433 struct page *page;
434 434
435 ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size); 435 ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
436 ubifs_assert(!c->ro_media); 436 ubifs_assert(!c->ro_media && !c->ro_mount);
437 437
438 if (unlikely(c->ro_error)) 438 if (unlikely(c->ro_error))
439 return -EROFS; 439 return -EROFS;
@@ -1440,8 +1440,7 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vm
1440 1440
1441 dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index, 1441 dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index,
1442 i_size_read(inode)); 1442 i_size_read(inode));
1443 ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY)); 1443 ubifs_assert(!c->ro_media && !c->ro_mount);
1444 ubifs_assert(!c->ro_media);
1445 1444
1446 if (unlikely(c->ro_error)) 1445 if (unlikely(c->ro_error))
1447 return VM_FAULT_SIGBUS; /* -EROFS */ 1446 return VM_FAULT_SIGBUS; /* -EROFS */
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index d927196d730b..151f10882820 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -616,7 +616,7 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
616 struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; 616 struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
617 617
618 ubifs_assert_cmt_locked(c); 618 ubifs_assert_cmt_locked(c);
619 ubifs_assert(!c->ro_media); 619 ubifs_assert(!c->ro_media && !c->ro_mount);
620 620
621 if (ubifs_gc_should_commit(c)) 621 if (ubifs_gc_should_commit(c))
622 return -EAGAIN; 622 return -EAGAIN;
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 18a4b8d7c844..d82173182eeb 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -356,10 +356,9 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
356 356
357 dbg_io("LEB %d:%d, %d bytes, jhead %s", 357 dbg_io("LEB %d:%d, %d bytes, jhead %s",
358 wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead)); 358 wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
359 ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
360 ubifs_assert(!(wbuf->avail & 7)); 359 ubifs_assert(!(wbuf->avail & 7));
361 ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); 360 ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
362 ubifs_assert(!c->ro_media); 361 ubifs_assert(!c->ro_media && !c->ro_mount);
363 362
364 if (c->ro_error) 363 if (c->ro_error)
365 return -EROFS; 364 return -EROFS;
@@ -441,7 +440,7 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c)
441{ 440{
442 int err, i; 441 int err, i;
443 442
444 ubifs_assert(!c->ro_media); 443 ubifs_assert(!c->ro_media && !c->ro_mount);
445 if (!c->need_wbuf_sync) 444 if (!c->need_wbuf_sync)
446 return 0; 445 return 0;
447 c->need_wbuf_sync = 0; 446 c->need_wbuf_sync = 0;
@@ -521,7 +520,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
521 ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size); 520 ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
522 ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size); 521 ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
523 ubifs_assert(mutex_is_locked(&wbuf->io_mutex)); 522 ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
524 ubifs_assert(!c->ro_media); 523 ubifs_assert(!c->ro_media && !c->ro_mount);
525 524
526 if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) { 525 if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
527 err = -ENOSPC; 526 err = -ENOSPC;
@@ -666,7 +665,7 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
666 buf_len); 665 buf_len);
667 ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); 666 ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
668 ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size); 667 ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
669 ubifs_assert(!c->ro_media); 668 ubifs_assert(!c->ro_media && !c->ro_mount);
670 669
671 if (c->ro_error) 670 if (c->ro_error)
672 return -EROFS; 671 return -EROFS;
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index a6da8aa68f37..914f1bd89e57 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -122,7 +122,7 @@ static int reserve_space(struct ubifs_info *c, int jhead, int len)
122 * better to try to allocate space at the ends of eraseblocks. This is 122 * better to try to allocate space at the ends of eraseblocks. This is
123 * what the squeeze parameter does. 123 * what the squeeze parameter does.
124 */ 124 */
125 ubifs_assert(!c->ro_media); 125 ubifs_assert(!c->ro_media && !c->ro_mount);
126 squeeze = (jhead == BASEHD); 126 squeeze = (jhead == BASEHD);
127again: 127again:
128 mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); 128 mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index a41713e2fbb3..4d0cb1241460 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -159,7 +159,7 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
159 jhead = &c->jheads[bud->jhead]; 159 jhead = &c->jheads[bud->jhead];
160 list_add_tail(&bud->list, &jhead->buds_list); 160 list_add_tail(&bud->list, &jhead->buds_list);
161 } else 161 } else
162 ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY)); 162 ubifs_assert(c->replaying && c->ro_mount);
163 163
164 /* 164 /*
165 * Note, although this is a new bud, we anyway account this space now, 165 * Note, although this is a new bud, we anyway account this space now,
@@ -223,7 +223,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
223 } 223 }
224 224
225 mutex_lock(&c->log_mutex); 225 mutex_lock(&c->log_mutex);
226 ubifs_assert(!c->ro_media); 226 ubifs_assert(!c->ro_media && !c->ro_mount);
227 if (c->ro_error) { 227 if (c->ro_error) {
228 err = -EROFS; 228 err = -EROFS;
229 goto out_unlock; 229 goto out_unlock;
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c
index 0c818e855f59..21f47afdacff 100644
--- a/fs/ubifs/master.c
+++ b/fs/ubifs/master.c
@@ -361,7 +361,7 @@ int ubifs_write_master(struct ubifs_info *c)
361{ 361{
362 int err, lnum, offs, len; 362 int err, lnum, offs, len;
363 363
364 ubifs_assert(!c->ro_media); 364 ubifs_assert(!c->ro_media && !c->ro_mount);
365 if (c->ro_error) 365 if (c->ro_error)
366 return -EROFS; 366 return -EROFS;
367 367
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h
index 5d476ba184e6..c3de04dc952a 100644
--- a/fs/ubifs/misc.h
+++ b/fs/ubifs/misc.h
@@ -132,7 +132,7 @@ static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
132{ 132{
133 int err; 133 int err;
134 134
135 ubifs_assert(!c->ro_media); 135 ubifs_assert(!c->ro_media && !c->ro_mount);
136 if (c->ro_error) 136 if (c->ro_error)
137 return -EROFS; 137 return -EROFS;
138 err = ubi_leb_unmap(c->ubi, lnum); 138 err = ubi_leb_unmap(c->ubi, lnum);
@@ -160,7 +160,7 @@ static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
160{ 160{
161 int err; 161 int err;
162 162
163 ubifs_assert(!c->ro_media); 163 ubifs_assert(!c->ro_media && !c->ro_mount);
164 if (c->ro_error) 164 if (c->ro_error)
165 return -EROFS; 165 return -EROFS;
166 err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); 166 err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
@@ -188,7 +188,7 @@ static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
188{ 188{
189 int err; 189 int err;
190 190
191 ubifs_assert(!c->ro_media); 191 ubifs_assert(!c->ro_media && !c->ro_mount);
192 if (c->ro_error) 192 if (c->ro_error)
193 return -EROFS; 193 return -EROFS;
194 err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); 194 err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index daae9e1f5382..c902a5de90ae 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -292,7 +292,7 @@ int ubifs_recover_master_node(struct ubifs_info *c)
292 292
293 memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ); 293 memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
294 294
295 if ((c->vfs_sb->s_flags & MS_RDONLY)) { 295 if (c->ro_mount) {
296 /* Read-only mode. Keep a copy for switching to rw mode */ 296 /* Read-only mode. Keep a copy for switching to rw mode */
297 c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL); 297 c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
298 if (!c->rcvrd_mst_node) { 298 if (!c->rcvrd_mst_node) {
@@ -469,7 +469,7 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
469 endpt = snod->offs + snod->len; 469 endpt = snod->offs + snod->len;
470 } 470 }
471 471
472 if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) { 472 if (c->ro_mount && !c->remounting_rw) {
473 /* Add to recovery list */ 473 /* Add to recovery list */
474 struct ubifs_unclean_leb *ucleb; 474 struct ubifs_unclean_leb *ucleb;
475 475
@@ -883,7 +883,7 @@ int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
883{ 883{
884 int err; 884 int err;
885 885
886 ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw); 886 ubifs_assert(!c->ro_mount || c->remounting_rw);
887 887
888 dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs); 888 dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
889 err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf); 889 err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
@@ -1461,7 +1461,7 @@ int ubifs_recover_size(struct ubifs_info *c)
1461 } 1461 }
1462 } 1462 }
1463 if (e->exists && e->i_size < e->d_size) { 1463 if (e->exists && e->i_size < e->d_size) {
1464 if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) { 1464 if (!e->inode && c->ro_mount) {
1465 /* Fix the inode size and pin it in memory */ 1465 /* Fix the inode size and pin it in memory */
1466 struct inode *inode; 1466 struct inode *inode;
1467 1467
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 5c2d6d759a3e..730598cf6342 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -627,8 +627,7 @@ static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
627 ubifs_assert(sleb->endpt - offs >= used); 627 ubifs_assert(sleb->endpt - offs >= used);
628 ubifs_assert(sleb->endpt % c->min_io_size == 0); 628 ubifs_assert(sleb->endpt % c->min_io_size == 0);
629 629
630 if (sleb->endpt + c->min_io_size <= c->leb_size && 630 if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
631 !(c->vfs_sb->s_flags & MS_RDONLY))
632 err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum, 631 err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
633 sleb->endpt, UBI_SHORTTERM); 632 sleb->endpt, UBI_SHORTTERM);
634 633
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 96cb62c8a9dd..bf31b4729e51 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -542,11 +542,8 @@ int ubifs_read_superblock(struct ubifs_info *c)
542 * due to the unavailability of time-travelling equipment. 542 * due to the unavailability of time-travelling equipment.
543 */ 543 */
544 if (c->fmt_version > UBIFS_FORMAT_VERSION) { 544 if (c->fmt_version > UBIFS_FORMAT_VERSION) {
545 struct super_block *sb = c->vfs_sb; 545 ubifs_assert(!c->ro_media || c->ro_mount);
546 int mounting_ro = sb->s_flags & MS_RDONLY; 546 if (!c->ro_mount ||
547
548 ubifs_assert(!c->ro_media || mounting_ro);
549 if (!mounting_ro ||
550 c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) { 547 c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
551 ubifs_err("on-flash format version is w%d/r%d, but " 548 ubifs_err("on-flash format version is w%d/r%d, but "
552 "software only supports up to version " 549 "software only supports up to version "
@@ -624,7 +621,7 @@ int ubifs_read_superblock(struct ubifs_info *c)
624 c->old_leb_cnt = c->leb_cnt; 621 c->old_leb_cnt = c->leb_cnt;
625 if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) { 622 if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) {
626 c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size); 623 c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size);
627 if (c->vfs_sb->s_flags & MS_RDONLY) 624 if (c->ro_mount)
628 dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs", 625 dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs",
629 c->old_leb_cnt, c->leb_cnt); 626 c->old_leb_cnt, c->leb_cnt);
630 else { 627 else {
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
index 10eec8778438..46961c003236 100644
--- a/fs/ubifs/shrinker.c
+++ b/fs/ubifs/shrinker.c
@@ -250,7 +250,7 @@ static int kick_a_thread(void)
250 dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt); 250 dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt);
251 251
252 if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN || 252 if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN ||
253 c->ro_media || c->ro_error) { 253 c->ro_mount || c->ro_error) {
254 mutex_unlock(&c->umount_mutex); 254 mutex_unlock(&c->umount_mutex);
255 continue; 255 continue;
256 } 256 }
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 1cfeec56df91..4e5bf3fbf782 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1137,11 +1137,11 @@ static int check_free_space(struct ubifs_info *c)
1137 */ 1137 */
1138static int mount_ubifs(struct ubifs_info *c) 1138static int mount_ubifs(struct ubifs_info *c)
1139{ 1139{
1140 struct super_block *sb = c->vfs_sb; 1140 int err;
1141 int err, mounted_read_only = (sb->s_flags & MS_RDONLY);
1142 long long x; 1141 long long x;
1143 size_t sz; 1142 size_t sz;
1144 1143
1144 c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
1145 err = init_constants_early(c); 1145 err = init_constants_early(c);
1146 if (err) 1146 if (err)
1147 return err; 1147 return err;
@@ -1154,7 +1154,7 @@ static int mount_ubifs(struct ubifs_info *c)
1154 if (err) 1154 if (err)
1155 goto out_free; 1155 goto out_free;
1156 1156
1157 if (c->empty && (mounted_read_only || c->ro_media)) { 1157 if (c->empty && (c->ro_mount || c->ro_media)) {
1158 /* 1158 /*
1159 * This UBI volume is empty, and read-only, or the file system 1159 * This UBI volume is empty, and read-only, or the file system
1160 * is mounted read-only - we cannot format it. 1160 * is mounted read-only - we cannot format it.
@@ -1165,7 +1165,7 @@ static int mount_ubifs(struct ubifs_info *c)
1165 goto out_free; 1165 goto out_free;
1166 } 1166 }
1167 1167
1168 if (c->ro_media && !mounted_read_only) { 1168 if (c->ro_media && !c->ro_mount) {
1169 ubifs_err("cannot mount read-write - read-only media"); 1169 ubifs_err("cannot mount read-write - read-only media");
1170 err = -EROFS; 1170 err = -EROFS;
1171 goto out_free; 1171 goto out_free;
@@ -1185,7 +1185,7 @@ static int mount_ubifs(struct ubifs_info *c)
1185 if (!c->sbuf) 1185 if (!c->sbuf)
1186 goto out_free; 1186 goto out_free;
1187 1187
1188 if (!mounted_read_only) { 1188 if (!c->ro_mount) {
1189 c->ileb_buf = vmalloc(c->leb_size); 1189 c->ileb_buf = vmalloc(c->leb_size);
1190 if (!c->ileb_buf) 1190 if (!c->ileb_buf)
1191 goto out_free; 1191 goto out_free;
@@ -1228,7 +1228,7 @@ static int mount_ubifs(struct ubifs_info *c)
1228 } 1228 }
1229 1229
1230 sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); 1230 sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
1231 if (!mounted_read_only) { 1231 if (!c->ro_mount) {
1232 err = alloc_wbufs(c); 1232 err = alloc_wbufs(c);
1233 if (err) 1233 if (err)
1234 goto out_cbuf; 1234 goto out_cbuf;
@@ -1254,12 +1254,12 @@ static int mount_ubifs(struct ubifs_info *c)
1254 if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) { 1254 if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
1255 ubifs_msg("recovery needed"); 1255 ubifs_msg("recovery needed");
1256 c->need_recovery = 1; 1256 c->need_recovery = 1;
1257 if (!mounted_read_only) { 1257 if (!c->ro_mount) {
1258 err = ubifs_recover_inl_heads(c, c->sbuf); 1258 err = ubifs_recover_inl_heads(c, c->sbuf);
1259 if (err) 1259 if (err)
1260 goto out_master; 1260 goto out_master;
1261 } 1261 }
1262 } else if (!mounted_read_only) { 1262 } else if (!c->ro_mount) {
1263 /* 1263 /*
1264 * Set the "dirty" flag so that if we reboot uncleanly we 1264 * Set the "dirty" flag so that if we reboot uncleanly we
1265 * will notice this immediately on the next mount. 1265 * will notice this immediately on the next mount.
@@ -1270,7 +1270,7 @@ static int mount_ubifs(struct ubifs_info *c)
1270 goto out_master; 1270 goto out_master;
1271 } 1271 }
1272 1272
1273 err = ubifs_lpt_init(c, 1, !mounted_read_only); 1273 err = ubifs_lpt_init(c, 1, !c->ro_mount);
1274 if (err) 1274 if (err)
1275 goto out_lpt; 1275 goto out_lpt;
1276 1276
@@ -1285,11 +1285,11 @@ static int mount_ubifs(struct ubifs_info *c)
1285 /* Calculate 'min_idx_lebs' after journal replay */ 1285 /* Calculate 'min_idx_lebs' after journal replay */
1286 c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); 1286 c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
1287 1287
1288 err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only); 1288 err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount);
1289 if (err) 1289 if (err)
1290 goto out_orphans; 1290 goto out_orphans;
1291 1291
1292 if (!mounted_read_only) { 1292 if (!c->ro_mount) {
1293 int lnum; 1293 int lnum;
1294 1294
1295 err = check_free_space(c); 1295 err = check_free_space(c);
@@ -1351,7 +1351,7 @@ static int mount_ubifs(struct ubifs_info *c)
1351 spin_unlock(&ubifs_infos_lock); 1351 spin_unlock(&ubifs_infos_lock);
1352 1352
1353 if (c->need_recovery) { 1353 if (c->need_recovery) {
1354 if (mounted_read_only) 1354 if (c->ro_mount)
1355 ubifs_msg("recovery deferred"); 1355 ubifs_msg("recovery deferred");
1356 else { 1356 else {
1357 c->need_recovery = 0; 1357 c->need_recovery = 0;
@@ -1378,7 +1378,7 @@ static int mount_ubifs(struct ubifs_info *c)
1378 1378
1379 ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", 1379 ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
1380 c->vi.ubi_num, c->vi.vol_id, c->vi.name); 1380 c->vi.ubi_num, c->vi.vol_id, c->vi.name);
1381 if (mounted_read_only) 1381 if (c->ro_mount)
1382 ubifs_msg("mounted read-only"); 1382 ubifs_msg("mounted read-only");
1383 x = (long long)c->main_lebs * c->leb_size; 1383 x = (long long)c->main_lebs * c->leb_size;
1384 ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, %d " 1384 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)
1640 } 1640 }
1641 1641
1642 dbg_gen("re-mounted read-write"); 1642 dbg_gen("re-mounted read-write");
1643 c->vfs_sb->s_flags &= ~MS_RDONLY; 1643 c->ro_mount = 0;
1644 c->remounting_rw = 0; 1644 c->remounting_rw = 0;
1645 c->always_chk_crc = 0; 1645 c->always_chk_crc = 0;
1646 err = dbg_check_space_info(c); 1646 err = dbg_check_space_info(c);
@@ -1676,7 +1676,7 @@ static void ubifs_remount_ro(struct ubifs_info *c)
1676 int i, err; 1676 int i, err;
1677 1677
1678 ubifs_assert(!c->need_recovery); 1678 ubifs_assert(!c->need_recovery);
1679 ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); 1679 ubifs_assert(!c->ro_mount);
1680 1680
1681 mutex_lock(&c->umount_mutex); 1681 mutex_lock(&c->umount_mutex);
1682 if (c->bgt) { 1682 if (c->bgt) {
@@ -1704,6 +1704,7 @@ static void ubifs_remount_ro(struct ubifs_info *c)
1704 vfree(c->ileb_buf); 1704 vfree(c->ileb_buf);
1705 c->ileb_buf = NULL; 1705 c->ileb_buf = NULL;
1706 ubifs_lpt_free(c, 1); 1706 ubifs_lpt_free(c, 1);
1707 c->ro_mount = 1;
1707 err = dbg_check_space_info(c); 1708 err = dbg_check_space_info(c);
1708 if (err) 1709 if (err)
1709 ubifs_ro_mode(c, err); 1710 ubifs_ro_mode(c, err);
@@ -1735,7 +1736,7 @@ static void ubifs_put_super(struct super_block *sb)
1735 * the mutex is locked. 1736 * the mutex is locked.
1736 */ 1737 */
1737 mutex_lock(&c->umount_mutex); 1738 mutex_lock(&c->umount_mutex);
1738 if (!(c->vfs_sb->s_flags & MS_RDONLY)) { 1739 if (!c->ro_mount) {
1739 /* 1740 /*
1740 * First of all kill the background thread to make sure it does 1741 * First of all kill the background thread to make sure it does
1741 * not interfere with un-mounting and freeing resources. 1742 * not interfere with un-mounting and freeing resources.
@@ -1745,23 +1746,23 @@ static void ubifs_put_super(struct super_block *sb)
1745 c->bgt = NULL; 1746 c->bgt = NULL;
1746 } 1747 }
1747 1748
1748 /* Synchronize write-buffers */
1749 if (c->jheads)
1750 for (i = 0; i < c->jhead_cnt; i++)
1751 ubifs_wbuf_sync(&c->jheads[i].wbuf);
1752
1753 /* 1749 /*
1754 * On fatal errors c->ro_error is set to 1, in which case we do 1750 * On fatal errors c->ro_error is set to 1, in which case we do
1755 * not write the master node. 1751 * not write the master node.
1756 */ 1752 */
1757 if (!c->ro_error) { 1753 if (!c->ro_error) {
1754 int err;
1755
1756 /* Synchronize write-buffers */
1757 if (c->jheads)
1758 for (i = 0; i < c->jhead_cnt; i++)
1759 ubifs_wbuf_sync(&c->jheads[i].wbuf);
1760
1758 /* 1761 /*
1759 * We are being cleanly unmounted which means the 1762 * We are being cleanly unmounted which means the
1760 * orphans were killed - indicate this in the master 1763 * orphans were killed - indicate this in the master
1761 * node. Also save the reserved GC LEB number. 1764 * node. Also save the reserved GC LEB number.
1762 */ 1765 */
1763 int err;
1764
1765 c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); 1766 c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
1766 c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); 1767 c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
1767 c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); 1768 c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
@@ -1797,7 +1798,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
1797 return err; 1798 return err;
1798 } 1799 }
1799 1800
1800 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { 1801 if (c->ro_mount && !(*flags & MS_RDONLY)) {
1801 if (c->ro_error) { 1802 if (c->ro_error) {
1802 ubifs_msg("cannot re-mount R/W due to prior errors"); 1803 ubifs_msg("cannot re-mount R/W due to prior errors");
1803 return -EROFS; 1804 return -EROFS;
@@ -1809,7 +1810,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
1809 err = ubifs_remount_rw(c); 1810 err = ubifs_remount_rw(c);
1810 if (err) 1811 if (err)
1811 return err; 1812 return err;
1812 } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { 1813 } else if (!c->ro_mount && (*flags & MS_RDONLY)) {
1813 if (c->ro_error) { 1814 if (c->ro_error) {
1814 ubifs_msg("cannot re-mount R/O due to prior errors"); 1815 ubifs_msg("cannot re-mount R/O due to prior errors");
1815 return -EROFS; 1816 return -EROFS;
@@ -2068,9 +2069,11 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
2068 } 2069 }
2069 2070
2070 if (sb->s_root) { 2071 if (sb->s_root) {
2072 struct ubifs_info *c1 = sb->s_fs_info;
2073
2071 /* A new mount point for already mounted UBIFS */ 2074 /* A new mount point for already mounted UBIFS */
2072 dbg_gen("this ubi volume is already mounted"); 2075 dbg_gen("this ubi volume is already mounted");
2073 if ((flags ^ sb->s_flags) & MS_RDONLY) { 2076 if (!!(flags & MS_RDONLY) != c1->ro_mount) {
2074 err = -EBUSY; 2077 err = -EBUSY;
2075 goto out_deact; 2078 goto out_deact;
2076 } 2079 }
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index f47ebb442d1c..381d6b207a52 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1032,6 +1032,7 @@ struct ubifs_debug_info;
1032 * @max_leb_cnt: maximum count of logical eraseblocks 1032 * @max_leb_cnt: maximum count of logical eraseblocks
1033 * @old_leb_cnt: count of logical eraseblocks before re-size 1033 * @old_leb_cnt: count of logical eraseblocks before re-size
1034 * @ro_media: the underlying UBI volume is read-only 1034 * @ro_media: the underlying UBI volume is read-only
1035 * @ro_mount: the file-system was mounted as read-only
1035 * @ro_error: UBIFS switched to R/O mode because an error happened 1036 * @ro_error: UBIFS switched to R/O mode because an error happened
1036 * 1037 *
1037 * @dirty_pg_cnt: number of dirty pages (not used) 1038 * @dirty_pg_cnt: number of dirty pages (not used)
@@ -1173,11 +1174,14 @@ struct ubifs_debug_info;
1173 * @replay_sqnum: sequence number of node currently being replayed 1174 * @replay_sqnum: sequence number of node currently being replayed
1174 * @need_recovery: file-system needs recovery 1175 * @need_recovery: file-system needs recovery
1175 * @replaying: set to %1 during journal replay 1176 * @replaying: set to %1 during journal replay
1176 * @unclean_leb_list: LEBs to recover when mounting ro to rw 1177 * @unclean_leb_list: LEBs to recover when re-mounting R/O mounted FS to R/W
1177 * @rcvrd_mst_node: recovered master node to write when mounting ro to rw 1178 * mode
1179 * @rcvrd_mst_node: recovered master node to write when re-mounting R/O mounted
1180 * FS to R/W mode
1178 * @size_tree: inode size information for recovery 1181 * @size_tree: inode size information for recovery
1179 * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY) 1182 * @remounting_rw: set while re-mounting from R/O mode to R/W mode
1180 * @always_chk_crc: always check CRCs (while mounting and remounting rw) 1183 * @always_chk_crc: always check CRCs (while mounting and remounting to R/W
1184 * mode)
1181 * @mount_opts: UBIFS-specific mount options 1185 * @mount_opts: UBIFS-specific mount options
1182 * 1186 *
1183 * @dbg: debugging-related information 1187 * @dbg: debugging-related information
@@ -1274,6 +1278,7 @@ struct ubifs_info {
1274 int max_leb_cnt; 1278 int max_leb_cnt;
1275 int old_leb_cnt; 1279 int old_leb_cnt;
1276 unsigned int ro_media:1; 1280 unsigned int ro_media:1;
1281 unsigned int ro_mount:1;
1277 unsigned int ro_error:1; 1282 unsigned int ro_error:1;
1278 1283
1279 atomic_long_t dirty_pg_cnt; 1284 atomic_long_t dirty_pg_cnt;