aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ubifs
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-09-17 09:44:28 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-09-17 10:08:09 -0400
commit2680d722bf2c5f75225dd9acb3ec9e5a9e2652f4 (patch)
treeaf016ede5f300a33ddd3ad66a8c3c0e6bf05774e /fs/ubifs
parent8c893a5545ca772744376295690723dcb0b47d96 (diff)
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: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'fs/ubifs')
-rw-r--r--fs/ubifs/commit.c4
-rw-r--r--fs/ubifs/file.c6
-rw-r--r--fs/ubifs/gc.c3
-rw-r--r--fs/ubifs/io.c16
-rw-r--r--fs/ubifs/journal.c3
-rw-r--r--fs/ubifs/log.c4
-rw-r--r--fs/ubifs/master.c3
-rw-r--r--fs/ubifs/misc.h9
-rw-r--r--fs/ubifs/shrinker.c2
-rw-r--r--fs/ubifs/super.c14
-rw-r--r--fs/ubifs/ubifs.h4
11 files changed, 44 insertions, 24 deletions
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 37fa7ed062d8..712432789fb8 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -63,7 +63,9 @@ 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 if (c->ro_media) { 66 ubifs_assert(!c->ro_media);
67
68 if (c->ro_error) {
67 err = -EROFS; 69 err = -EROFS;
68 goto out_up; 70 goto out_up;
69 } 71 }
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 03ae894c45de..c6bc51c9f07c 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -433,8 +433,9 @@ 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 437
437 if (unlikely(c->ro_media)) 438 if (unlikely(c->ro_error))
438 return -EROFS; 439 return -EROFS;
439 440
440 /* Try out the fast-path part first */ 441 /* 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
1440 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,
1441 i_size_read(inode)); 1442 i_size_read(inode));
1442 ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY)); 1443 ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
1444 ubifs_assert(!c->ro_media);
1443 1445
1444 if (unlikely(c->ro_media)) 1446 if (unlikely(c->ro_error))
1445 return VM_FAULT_SIGBUS; /* -EROFS */ 1447 return VM_FAULT_SIGBUS; /* -EROFS */
1446 1448
1447 /* 1449 /*
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 396f24a30af9..d927196d730b 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -616,13 +616,14 @@ 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 620
620 if (ubifs_gc_should_commit(c)) 621 if (ubifs_gc_should_commit(c))
621 return -EAGAIN; 622 return -EAGAIN;
622 623
623 mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); 624 mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
624 625
625 if (c->ro_media) { 626 if (c->ro_error) {
626 ret = -EROFS; 627 ret = -EROFS;
627 goto out_unlock; 628 goto out_unlock;
628 } 629 }
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 9432431bf595..18a4b8d7c844 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -61,8 +61,8 @@
61 */ 61 */
62void ubifs_ro_mode(struct ubifs_info *c, int err) 62void ubifs_ro_mode(struct ubifs_info *c, int err)
63{ 63{
64 if (!c->ro_media) { 64 if (!c->ro_error) {
65 c->ro_media = 1; 65 c->ro_error = 1;
66 c->no_chk_data_crc = 0; 66 c->no_chk_data_crc = 0;
67 c->vfs_sb->s_flags |= MS_RDONLY; 67 c->vfs_sb->s_flags |= MS_RDONLY;
68 ubifs_warn("switched to read-only mode, error %d", err); 68 ubifs_warn("switched to read-only mode, error %d", err);
@@ -359,8 +359,9 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
359 ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); 359 ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
360 ubifs_assert(!(wbuf->avail & 7)); 360 ubifs_assert(!(wbuf->avail & 7));
361 ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); 361 ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
362 ubifs_assert(!c->ro_media);
362 363
363 if (c->ro_media) 364 if (c->ro_error)
364 return -EROFS; 365 return -EROFS;
365 366
366 ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail); 367 ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
@@ -440,11 +441,12 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c)
440{ 441{
441 int err, i; 442 int err, i;
442 443
444 ubifs_assert(!c->ro_media);
443 if (!c->need_wbuf_sync) 445 if (!c->need_wbuf_sync)
444 return 0; 446 return 0;
445 c->need_wbuf_sync = 0; 447 c->need_wbuf_sync = 0;
446 448
447 if (c->ro_media) { 449 if (c->ro_error) {
448 err = -EROFS; 450 err = -EROFS;
449 goto out_timers; 451 goto out_timers;
450 } 452 }
@@ -519,6 +521,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
519 ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size); 521 ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
520 ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size); 522 ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
521 ubifs_assert(mutex_is_locked(&wbuf->io_mutex)); 523 ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
524 ubifs_assert(!c->ro_media);
522 525
523 if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) { 526 if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
524 err = -ENOSPC; 527 err = -ENOSPC;
@@ -527,7 +530,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
527 530
528 cancel_wbuf_timer_nolock(wbuf); 531 cancel_wbuf_timer_nolock(wbuf);
529 532
530 if (c->ro_media) 533 if (c->ro_error)
531 return -EROFS; 534 return -EROFS;
532 535
533 if (aligned_len <= wbuf->avail) { 536 if (aligned_len <= wbuf->avail) {
@@ -663,8 +666,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
663 buf_len); 666 buf_len);
664 ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); 667 ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
665 ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size); 668 ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
669 ubifs_assert(!c->ro_media);
666 670
667 if (c->ro_media) 671 if (c->ro_error)
668 return -EROFS; 672 return -EROFS;
669 673
670 ubifs_prepare_node(c, buf, len, 1); 674 ubifs_prepare_node(c, buf, len, 1);
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index d321baeca68d..a6da8aa68f37 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -122,11 +122,12 @@ 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 squeeze = (jhead == BASEHD); 126 squeeze = (jhead == BASEHD);
126again: 127again:
127 mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); 128 mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
128 129
129 if (c->ro_media) { 130 if (c->ro_error) {
130 err = -EROFS; 131 err = -EROFS;
131 goto out_unlock; 132 goto out_unlock;
132 } 133 }
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index c345e125f42c..a41713e2fbb3 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -223,8 +223,8 @@ 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 226 ubifs_assert(!c->ro_media);
227 if (c->ro_media) { 227 if (c->ro_error) {
228 err = -EROFS; 228 err = -EROFS;
229 goto out_unlock; 229 goto out_unlock;
230 } 230 }
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c
index 28beaeedadc0..0c818e855f59 100644
--- a/fs/ubifs/master.c
+++ b/fs/ubifs/master.c
@@ -361,7 +361,8 @@ 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 if (c->ro_media) 364 ubifs_assert(!c->ro_media);
365 if (c->ro_error)
365 return -EROFS; 366 return -EROFS;
366 367
367 lnum = UBIFS_MST_LNUM; 368 lnum = UBIFS_MST_LNUM;
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h
index 4fa81d867e41..5d476ba184e6 100644
--- a/fs/ubifs/misc.h
+++ b/fs/ubifs/misc.h
@@ -132,7 +132,8 @@ static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
132{ 132{
133 int err; 133 int err;
134 134
135 if (c->ro_media) 135 ubifs_assert(!c->ro_media);
136 if (c->ro_error)
136 return -EROFS; 137 return -EROFS;
137 err = ubi_leb_unmap(c->ubi, lnum); 138 err = ubi_leb_unmap(c->ubi, lnum);
138 if (err) { 139 if (err) {
@@ -159,7 +160,8 @@ static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
159{ 160{
160 int err; 161 int err;
161 162
162 if (c->ro_media) 163 ubifs_assert(!c->ro_media);
164 if (c->ro_error)
163 return -EROFS; 165 return -EROFS;
164 err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); 166 err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
165 if (err) { 167 if (err) {
@@ -186,7 +188,8 @@ static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
186{ 188{
187 int err; 189 int err;
188 190
189 if (c->ro_media) 191 ubifs_assert(!c->ro_media);
192 if (c->ro_error)
190 return -EROFS; 193 return -EROFS;
191 err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); 194 err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
192 if (err) { 195 if (err) {
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
index 0b201114a5ad..10eec8778438 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) { 253 c->ro_media || 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 cd5900b85d38..1cfeec56df91 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1751,10 +1751,10 @@ static void ubifs_put_super(struct super_block *sb)
1751 ubifs_wbuf_sync(&c->jheads[i].wbuf); 1751 ubifs_wbuf_sync(&c->jheads[i].wbuf);
1752 1752
1753 /* 1753 /*
1754 * On fatal errors c->ro_media is set to 1, in which case we do 1754 * On fatal errors c->ro_error is set to 1, in which case we do
1755 * not write the master node. 1755 * not write the master node.
1756 */ 1756 */
1757 if (!c->ro_media) { 1757 if (!c->ro_error) {
1758 /* 1758 /*
1759 * We are being cleanly unmounted which means the 1759 * We are being cleanly unmounted which means the
1760 * orphans were killed - indicate this in the master 1760 * orphans were killed - indicate this in the master
@@ -1798,16 +1798,20 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
1798 } 1798 }
1799 1799
1800 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { 1800 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
1801 if (c->ro_error) {
1802 ubifs_msg("cannot re-mount R/W due to prior errors");
1803 return -EROFS;
1804 }
1801 if (c->ro_media) { 1805 if (c->ro_media) {
1802 ubifs_msg("cannot re-mount due to prior errors"); 1806 ubifs_msg("cannot re-mount R/W - UBI volume is R/O");
1803 return -EROFS; 1807 return -EROFS;
1804 } 1808 }
1805 err = ubifs_remount_rw(c); 1809 err = ubifs_remount_rw(c);
1806 if (err) 1810 if (err)
1807 return err; 1811 return err;
1808 } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { 1812 } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
1809 if (c->ro_media) { 1813 if (c->ro_error) {
1810 ubifs_msg("cannot re-mount due to prior errors"); 1814 ubifs_msg("cannot re-mount R/O due to prior errors");
1811 return -EROFS; 1815 return -EROFS;
1812 } 1816 }
1813 ubifs_remount_ro(c); 1817 ubifs_remount_ro(c);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index c4dc9b18f73e..f47ebb442d1c 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_error: UBIFS switched to R/O mode because an error happened
1035 * 1036 *
1036 * @dirty_pg_cnt: number of dirty pages (not used) 1037 * @dirty_pg_cnt: number of dirty pages (not used)
1037 * @dirty_zn_cnt: number of dirty znodes 1038 * @dirty_zn_cnt: number of dirty znodes
@@ -1272,7 +1273,8 @@ struct ubifs_info {
1272 int leb_cnt; 1273 int leb_cnt;
1273 int max_leb_cnt; 1274 int max_leb_cnt;
1274 int old_leb_cnt; 1275 int old_leb_cnt;
1275 int ro_media; 1276 unsigned int ro_media:1;
1277 unsigned int ro_error:1;
1276 1278
1277 atomic_long_t dirty_pg_cnt; 1279 atomic_long_t dirty_pg_cnt;
1278 atomic_long_t dirty_zn_cnt; 1280 atomic_long_t dirty_zn_cnt;