diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-09-19 11:34:26 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-09-19 14:07:58 -0400 |
commit | 2ef13294d29bcfb306e0d360f1b97f37b647b0c0 (patch) | |
tree | 877e1ece00c14de0f0d79e86b6480d284d309216 /fs/ubifs | |
parent | 2680d722bf2c5f75225dd9acb3ec9e5a9e2652f4 (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>
Diffstat (limited to 'fs/ubifs')
-rw-r--r-- | fs/ubifs/commit.c | 2 | ||||
-rw-r--r-- | fs/ubifs/file.c | 5 | ||||
-rw-r--r-- | fs/ubifs/gc.c | 2 | ||||
-rw-r--r-- | fs/ubifs/io.c | 9 | ||||
-rw-r--r-- | fs/ubifs/journal.c | 2 | ||||
-rw-r--r-- | fs/ubifs/log.c | 4 | ||||
-rw-r--r-- | fs/ubifs/master.c | 2 | ||||
-rw-r--r-- | fs/ubifs/misc.h | 6 | ||||
-rw-r--r-- | fs/ubifs/recovery.c | 8 | ||||
-rw-r--r-- | fs/ubifs/replay.c | 3 | ||||
-rw-r--r-- | fs/ubifs/sb.c | 9 | ||||
-rw-r--r-- | fs/ubifs/shrinker.c | 2 | ||||
-rw-r--r-- | fs/ubifs/super.c | 55 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 13 |
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); |
127 | again: | 127 | again: |
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 | */ |
1138 | static int mount_ubifs(struct ubifs_info *c) | 1138 | static 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; |