Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2680d722 authored by Artem Bityutskiy's avatar Artem Bityutskiy
Browse files

UBIFS: introduce new flag for RO due to errors



The R/O state may have various reasons:

1. The UBI volume is R/O
2. The FS is mounted R/O
3. The FS switched to R/O mode because of an error

However, in UBIFS we have only one variable which represents cases
1 and 3 - 'c->ro_media'. Indeed, we set this to 1 if we switch to
R/O mode due to an error, and then we test it in many places to
make sure that we stop writing as soon as the error happens.

But this is very unclean. One consequence of this, for example, is
that in 'ubifs_remount_fs()' we use 'c->ro_media' to check whether
we are in R/O mode because on an error, and we print a message
in this case. However, if we are in R/O mode because the media
is R/O, our message is bogus.

This patch introduces new flag - 'c->ro_error' which is set when
we switch to R/O mode because of an error. It also changes all
"if (c->ro_media)" checks to "if (c->ro_error)" checks, because
this is what the checks actually mean. We do not need to check
for 'c->ro_media' because if the UBI volume is in R/O mode, we
do not allow R/W mounting, and now writes can happen. This is
guaranteed by VFS. But it is good to double-check this, so this
patch also adds many "ubifs_assert(!c->ro_media)" checks.

In the 'ubifs_remount_fs()' function this patch makes a bit more
changes - it fixes the error messages as well.

Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 8c893a55
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -63,7 +63,9 @@ static int do_commit(struct ubifs_info *c)
	struct ubifs_lp_stats lst;
	struct ubifs_lp_stats lst;


	dbg_cmt("start");
	dbg_cmt("start");
	if (c->ro_media) {
	ubifs_assert(!c->ro_media);

	if (c->ro_error) {
		err = -EROFS;
		err = -EROFS;
		goto out_up;
		goto out_up;
	}
	}
+4 −2
Original line number Original line Diff line number Diff line
@@ -433,8 +433,9 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
	struct page *page;
	struct page *page;


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


	if (unlikely(c->ro_media))
	if (unlikely(c->ro_error))
		return -EROFS;
		return -EROFS;


	/* Try out the fast-path part first */
	/* Try out the fast-path part first */
@@ -1440,8 +1441,9 @@ 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,
	dbg_gen("ino %lu, pg %lu, i_size %lld",	inode->i_ino, page->index,
		i_size_read(inode));
		i_size_read(inode));
	ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
	ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
	ubifs_assert(!c->ro_media);


	if (unlikely(c->ro_media))
	if (unlikely(c->ro_error))
		return VM_FAULT_SIGBUS; /* -EROFS */
		return VM_FAULT_SIGBUS; /* -EROFS */


	/*
	/*
+2 −1
Original line number Original line Diff line number Diff line
@@ -616,13 +616,14 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;


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


	if (ubifs_gc_should_commit(c))
	if (ubifs_gc_should_commit(c))
		return -EAGAIN;
		return -EAGAIN;


	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);


	if (c->ro_media) {
	if (c->ro_error) {
		ret = -EROFS;
		ret = -EROFS;
		goto out_unlock;
		goto out_unlock;
	}
	}
+10 −6
Original line number Original line Diff line number Diff line
@@ -61,8 +61,8 @@
 */
 */
void ubifs_ro_mode(struct ubifs_info *c, int err)
void ubifs_ro_mode(struct ubifs_info *c, int err)
{
{
	if (!c->ro_media) {
	if (!c->ro_error) {
		c->ro_media = 1;
		c->ro_error = 1;
		c->no_chk_data_crc = 0;
		c->no_chk_data_crc = 0;
		c->vfs_sb->s_flags |= MS_RDONLY;
		c->vfs_sb->s_flags |= MS_RDONLY;
		ubifs_warn("switched to read-only mode, error %d", err);
		ubifs_warn("switched to read-only mode, error %d", err);
@@ -359,8 +359,9 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
	ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
	ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
	ubifs_assert(!(wbuf->avail & 7));
	ubifs_assert(!(wbuf->avail & 7));
	ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
	ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
	ubifs_assert(!c->ro_media);


	if (c->ro_media)
	if (c->ro_error)
		return -EROFS;
		return -EROFS;


	ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
	ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
@@ -440,11 +441,12 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c)
{
{
	int err, i;
	int err, i;


	ubifs_assert(!c->ro_media);
	if (!c->need_wbuf_sync)
	if (!c->need_wbuf_sync)
		return 0;
		return 0;
	c->need_wbuf_sync = 0;
	c->need_wbuf_sync = 0;


	if (c->ro_media) {
	if (c->ro_error) {
		err = -EROFS;
		err = -EROFS;
		goto out_timers;
		goto out_timers;
	}
	}
@@ -519,6 +521,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->offs & 7) && wbuf->offs <= c->leb_size);
	ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
	ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
	ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
	ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
	ubifs_assert(!c->ro_media);


	if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
	if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
		err = -ENOSPC;
		err = -ENOSPC;
@@ -527,7 +530,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)


	cancel_wbuf_timer_nolock(wbuf);
	cancel_wbuf_timer_nolock(wbuf);


	if (c->ro_media)
	if (c->ro_error)
		return -EROFS;
		return -EROFS;


	if (aligned_len <= wbuf->avail) {
	if (aligned_len <= wbuf->avail) {
@@ -663,8 +666,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
	       buf_len);
	       buf_len);
	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
	ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
	ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
	ubifs_assert(!c->ro_media);


	if (c->ro_media)
	if (c->ro_error)
		return -EROFS;
		return -EROFS;


	ubifs_prepare_node(c, buf, len, 1);
	ubifs_prepare_node(c, buf, len, 1);
+2 −1
Original line number Original line Diff line number Diff line
@@ -122,11 +122,12 @@ 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
	 * better to try to allocate space at the ends of eraseblocks. This is
	 * what the squeeze parameter does.
	 * what the squeeze parameter does.
	 */
	 */
	ubifs_assert(!c->ro_media);
	squeeze = (jhead == BASEHD);
	squeeze = (jhead == BASEHD);
again:
again:
	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);


	if (c->ro_media) {
	if (c->ro_error) {
		err = -EROFS;
		err = -EROFS;
		goto out_unlock;
		goto out_unlock;
	}
	}
Loading