Skip to content

Commit

Permalink
UBIFS: introduce new flags for RO mounts
Browse files Browse the repository at this point in the history
Commit 2fde99c "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 <[email protected]>
  • Loading branch information
Artem Bityutskiy authored and Artem Bityutskiy committed Sep 19, 2010
1 parent 2680d72 commit 2ef1329
Show file tree
Hide file tree
Showing 14 changed files with 62 additions and 60 deletions.
2 changes: 1 addition & 1 deletion fs/ubifs/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static int do_commit(struct ubifs_info *c)
struct ubifs_lp_stats lst;

dbg_cmt("start");
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);

if (c->ro_error) {
err = -EROFS;
Expand Down
5 changes: 2 additions & 3 deletions fs/ubifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
struct page *page;

ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);

if (unlikely(c->ro_error))
return -EROFS;
Expand Down Expand Up @@ -1440,8 +1440,7 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vm

dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index,
i_size_read(inode));
ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);

if (unlikely(c->ro_error))
return VM_FAULT_SIGBUS; /* -EROFS */
Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;

ubifs_assert_cmt_locked(c);
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);

if (ubifs_gc_should_commit(c))
return -EAGAIN;
Expand Down
9 changes: 4 additions & 5 deletions fs/ubifs/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,9 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)

dbg_io("LEB %d:%d, %d bytes, jhead %s",
wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
ubifs_assert(!(wbuf->avail & 7));
ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);

if (c->ro_error)
return -EROFS;
Expand Down Expand Up @@ -441,7 +440,7 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c)
{
int err, i;

ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);
if (!c->need_wbuf_sync)
return 0;
c->need_wbuf_sync = 0;
Expand Down Expand Up @@ -521,7 +520,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);

if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
err = -ENOSPC;
Expand Down Expand Up @@ -666,7 +665,7 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
buf_len);
ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);

if (c->ro_error)
return -EROFS;
Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ static int reserve_space(struct ubifs_info *c, int jhead, int len)
* better to try to allocate space at the ends of eraseblocks. This is
* what the squeeze parameter does.
*/
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);
squeeze = (jhead == BASEHD);
again:
mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
Expand Down
4 changes: 2 additions & 2 deletions fs/ubifs/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
jhead = &c->jheads[bud->jhead];
list_add_tail(&bud->list, &jhead->buds_list);
} else
ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY));
ubifs_assert(c->replaying && c->ro_mount);

/*
* Note, although this is a new bud, we anyway account this space now,
Expand Down Expand Up @@ -223,7 +223,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
}

mutex_lock(&c->log_mutex);
ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error) {
err = -EROFS;
goto out_unlock;
Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/master.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ int ubifs_write_master(struct ubifs_info *c)
{
int err, lnum, offs, len;

ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;

Expand Down
6 changes: 3 additions & 3 deletions fs/ubifs/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
{
int err;

ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
err = ubi_leb_unmap(c->ubi, lnum);
Expand Down Expand Up @@ -160,7 +160,7 @@ static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
{
int err;

ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
Expand Down Expand Up @@ -188,7 +188,7 @@ static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
{
int err;

ubifs_assert(!c->ro_media);
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
Expand Down
8 changes: 4 additions & 4 deletions fs/ubifs/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ int ubifs_recover_master_node(struct ubifs_info *c)

memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);

if ((c->vfs_sb->s_flags & MS_RDONLY)) {
if (c->ro_mount) {
/* Read-only mode. Keep a copy for switching to rw mode */
c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
if (!c->rcvrd_mst_node) {
Expand Down Expand Up @@ -469,7 +469,7 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
endpt = snod->offs + snod->len;
}

if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) {
if (c->ro_mount && !c->remounting_rw) {
/* Add to recovery list */
struct ubifs_unclean_leb *ucleb;

Expand Down Expand Up @@ -883,7 +883,7 @@ int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
{
int err;

ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw);
ubifs_assert(!c->ro_mount || c->remounting_rw);

dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
Expand Down Expand Up @@ -1461,7 +1461,7 @@ int ubifs_recover_size(struct ubifs_info *c)
}
}
if (e->exists && e->i_size < e->d_size) {
if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) {
if (!e->inode && c->ro_mount) {
/* Fix the inode size and pin it in memory */
struct inode *inode;

Expand Down
3 changes: 1 addition & 2 deletions fs/ubifs/replay.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,8 +627,7 @@ static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
ubifs_assert(sleb->endpt - offs >= used);
ubifs_assert(sleb->endpt % c->min_io_size == 0);

if (sleb->endpt + c->min_io_size <= c->leb_size &&
!(c->vfs_sb->s_flags & MS_RDONLY))
if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
sleb->endpt, UBI_SHORTTERM);

Expand Down
9 changes: 3 additions & 6 deletions fs/ubifs/sb.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,11 +542,8 @@ int ubifs_read_superblock(struct ubifs_info *c)
* due to the unavailability of time-travelling equipment.
*/
if (c->fmt_version > UBIFS_FORMAT_VERSION) {
struct super_block *sb = c->vfs_sb;
int mounting_ro = sb->s_flags & MS_RDONLY;

ubifs_assert(!c->ro_media || mounting_ro);
if (!mounting_ro ||
ubifs_assert(!c->ro_media || c->ro_mount);
if (!c->ro_mount ||
c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
ubifs_err("on-flash format version is w%d/r%d, but "
"software only supports up to version "
Expand Down Expand Up @@ -624,7 +621,7 @@ int ubifs_read_superblock(struct ubifs_info *c)
c->old_leb_cnt = c->leb_cnt;
if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) {
c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size);
if (c->vfs_sb->s_flags & MS_RDONLY)
if (c->ro_mount)
dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs",
c->old_leb_cnt, c->leb_cnt);
else {
Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/shrinker.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ static int kick_a_thread(void)
dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt);

if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN ||
c->ro_media || c->ro_error) {
c->ro_mount || c->ro_error) {
mutex_unlock(&c->umount_mutex);
continue;
}
Expand Down
Loading

0 comments on commit 2ef1329

Please sign in to comment.