Commit 2ef13294d29bcfb306e0d360f1b97f37b647b0c0

Authored by Artem Bityutskiy
1 parent 2680d722bf

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>

Showing 14 changed files with 62 additions and 60 deletions Side-by-side Diff

... ... @@ -63,7 +63,7 @@
63 63 struct ubifs_lp_stats lst;
64 64  
65 65 dbg_cmt("start");
66   - ubifs_assert(!c->ro_media);
  66 + ubifs_assert(!c->ro_media && !c->ro_mount);
67 67  
68 68 if (c->ro_error) {
69 69 err = -EROFS;
... ... @@ -433,7 +433,7 @@
433 433 struct page *page;
434 434  
435 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 438 if (unlikely(c->ro_error))
439 439 return -EROFS;
... ... @@ -1440,8 +1440,7 @@
1440 1440  
1441 1441 dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index,
1442 1442 i_size_read(inode));
1443   - ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
1444   - ubifs_assert(!c->ro_media);
  1443 + ubifs_assert(!c->ro_media && !c->ro_mount);
1445 1444  
1446 1445 if (unlikely(c->ro_error))
1447 1446 return VM_FAULT_SIGBUS; /* -EROFS */
... ... @@ -616,7 +616,7 @@
616 616 struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
617 617  
618 618 ubifs_assert_cmt_locked(c);
619   - ubifs_assert(!c->ro_media);
  619 + ubifs_assert(!c->ro_media && !c->ro_mount);
620 620  
621 621 if (ubifs_gc_should_commit(c))
622 622 return -EAGAIN;
... ... @@ -356,10 +356,9 @@
356 356  
357 357 dbg_io("LEB %d:%d, %d bytes, jhead %s",
358 358 wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
359   - ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
360 359 ubifs_assert(!(wbuf->avail & 7));
361 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 363 if (c->ro_error)
365 364 return -EROFS;
... ... @@ -441,7 +440,7 @@
441 440 {
442 441 int err, i;
443 442  
444   - ubifs_assert(!c->ro_media);
  443 + ubifs_assert(!c->ro_media && !c->ro_mount);
445 444 if (!c->need_wbuf_sync)
446 445 return 0;
447 446 c->need_wbuf_sync = 0;
... ... @@ -521,7 +520,7 @@
521 520 ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
522 521 ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
523 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 525 if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
527 526 err = -ENOSPC;
... ... @@ -666,7 +665,7 @@
666 665 buf_len);
667 666 ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
668 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 670 if (c->ro_error)
672 671 return -EROFS;
... ... @@ -122,7 +122,7 @@
122 122 * better to try to allocate space at the ends of eraseblocks. This is
123 123 * what the squeeze parameter does.
124 124 */
125   - ubifs_assert(!c->ro_media);
  125 + ubifs_assert(!c->ro_media && !c->ro_mount);
126 126 squeeze = (jhead == BASEHD);
127 127 again:
128 128 mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
... ... @@ -159,7 +159,7 @@
159 159 jhead = &c->jheads[bud->jhead];
160 160 list_add_tail(&bud->list, &jhead->buds_list);
161 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 165 * Note, although this is a new bud, we anyway account this space now,
... ... @@ -223,7 +223,7 @@
223 223 }
224 224  
225 225 mutex_lock(&c->log_mutex);
226   - ubifs_assert(!c->ro_media);
  226 + ubifs_assert(!c->ro_media && !c->ro_mount);
227 227 if (c->ro_error) {
228 228 err = -EROFS;
229 229 goto out_unlock;
... ... @@ -361,7 +361,7 @@
361 361 {
362 362 int err, lnum, offs, len;
363 363  
364   - ubifs_assert(!c->ro_media);
  364 + ubifs_assert(!c->ro_media && !c->ro_mount);
365 365 if (c->ro_error)
366 366 return -EROFS;
367 367  
... ... @@ -132,7 +132,7 @@
132 132 {
133 133 int err;
134 134  
135   - ubifs_assert(!c->ro_media);
  135 + ubifs_assert(!c->ro_media && !c->ro_mount);
136 136 if (c->ro_error)
137 137 return -EROFS;
138 138 err = ubi_leb_unmap(c->ubi, lnum);
... ... @@ -160,7 +160,7 @@
160 160 {
161 161 int err;
162 162  
163   - ubifs_assert(!c->ro_media);
  163 + ubifs_assert(!c->ro_media && !c->ro_mount);
164 164 if (c->ro_error)
165 165 return -EROFS;
166 166 err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
... ... @@ -188,7 +188,7 @@
188 188 {
189 189 int err;
190 190  
191   - ubifs_assert(!c->ro_media);
  191 + ubifs_assert(!c->ro_media && !c->ro_mount);
192 192 if (c->ro_error)
193 193 return -EROFS;
194 194 err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
... ... @@ -292,7 +292,7 @@
292 292  
293 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 296 /* Read-only mode. Keep a copy for switching to rw mode */
297 297 c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
298 298 if (!c->rcvrd_mst_node) {
... ... @@ -469,7 +469,7 @@
469 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 473 /* Add to recovery list */
474 474 struct ubifs_unclean_leb *ucleb;
475 475  
... ... @@ -883,7 +883,7 @@
883 883 {
884 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 888 dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
889 889 err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
... ... @@ -1461,7 +1461,7 @@
1461 1461 }
1462 1462 }
1463 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 1465 /* Fix the inode size and pin it in memory */
1466 1466 struct inode *inode;
1467 1467  
... ... @@ -627,8 +627,7 @@
627 627 ubifs_assert(sleb->endpt - offs >= used);
628 628 ubifs_assert(sleb->endpt % c->min_io_size == 0);
629 629  
630   - if (sleb->endpt + c->min_io_size <= c->leb_size &&
631   - !(c->vfs_sb->s_flags & MS_RDONLY))
  630 + if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
632 631 err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
633 632 sleb->endpt, UBI_SHORTTERM);
634 633  
... ... @@ -542,11 +542,8 @@
542 542 * due to the unavailability of time-travelling equipment.
543 543 */
544 544 if (c->fmt_version > UBIFS_FORMAT_VERSION) {
545   - struct super_block *sb = c->vfs_sb;
546   - int mounting_ro = sb->s_flags & MS_RDONLY;
547   -
548   - ubifs_assert(!c->ro_media || mounting_ro);
549   - if (!mounting_ro ||
  545 + ubifs_assert(!c->ro_media || c->ro_mount);
  546 + if (!c->ro_mount ||
550 547 c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
551 548 ubifs_err("on-flash format version is w%d/r%d, but "
552 549 "software only supports up to version "
... ... @@ -624,7 +621,7 @@
624 621 c->old_leb_cnt = c->leb_cnt;
625 622 if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) {
626 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 625 dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs",
629 626 c->old_leb_cnt, c->leb_cnt);
630 627 else {
... ... @@ -250,7 +250,7 @@
250 250 dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt);
251 251  
252 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 254 mutex_unlock(&c->umount_mutex);
255 255 continue;
256 256 }
... ... @@ -1137,11 +1137,11 @@
1137 1137 */
1138 1138 static int mount_ubifs(struct ubifs_info *c)
1139 1139 {
1140   - struct super_block *sb = c->vfs_sb;
1141   - int err, mounted_read_only = (sb->s_flags & MS_RDONLY);
  1140 + int err;
1142 1141 long long x;
1143 1142 size_t sz;
1144 1143  
  1144 + c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
1145 1145 err = init_constants_early(c);
1146 1146 if (err)
1147 1147 return err;
... ... @@ -1154,7 +1154,7 @@
1154 1154 if (err)
1155 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 1159 * This UBI volume is empty, and read-only, or the file system
1160 1160 * is mounted read-only - we cannot format it.
... ... @@ -1165,7 +1165,7 @@
1165 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 1169 ubifs_err("cannot mount read-write - read-only media");
1170 1170 err = -EROFS;
1171 1171 goto out_free;
... ... @@ -1185,7 +1185,7 @@
1185 1185 if (!c->sbuf)
1186 1186 goto out_free;
1187 1187  
1188   - if (!mounted_read_only) {
  1188 + if (!c->ro_mount) {
1189 1189 c->ileb_buf = vmalloc(c->leb_size);
1190 1190 if (!c->ileb_buf)
1191 1191 goto out_free;
... ... @@ -1228,7 +1228,7 @@
1228 1228 }
1229 1229  
1230 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 1232 err = alloc_wbufs(c);
1233 1233 if (err)
1234 1234 goto out_cbuf;
1235 1235  
... ... @@ -1254,12 +1254,12 @@
1254 1254 if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
1255 1255 ubifs_msg("recovery needed");
1256 1256 c->need_recovery = 1;
1257   - if (!mounted_read_only) {
  1257 + if (!c->ro_mount) {
1258 1258 err = ubifs_recover_inl_heads(c, c->sbuf);
1259 1259 if (err)
1260 1260 goto out_master;
1261 1261 }
1262   - } else if (!mounted_read_only) {
  1262 + } else if (!c->ro_mount) {
1263 1263 /*
1264 1264 * Set the "dirty" flag so that if we reboot uncleanly we
1265 1265 * will notice this immediately on the next mount.
... ... @@ -1270,7 +1270,7 @@
1270 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 1274 if (err)
1275 1275 goto out_lpt;
1276 1276  
1277 1277  
... ... @@ -1285,11 +1285,11 @@
1285 1285 /* Calculate 'min_idx_lebs' after journal replay */
1286 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 1289 if (err)
1290 1290 goto out_orphans;
1291 1291  
1292   - if (!mounted_read_only) {
  1292 + if (!c->ro_mount) {
1293 1293 int lnum;
1294 1294  
1295 1295 err = check_free_space(c);
... ... @@ -1351,7 +1351,7 @@
1351 1351 spin_unlock(&ubifs_infos_lock);
1352 1352  
1353 1353 if (c->need_recovery) {
1354   - if (mounted_read_only)
  1354 + if (c->ro_mount)
1355 1355 ubifs_msg("recovery deferred");
1356 1356 else {
1357 1357 c->need_recovery = 0;
... ... @@ -1378,7 +1378,7 @@
1378 1378  
1379 1379 ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
1380 1380 c->vi.ubi_num, c->vi.vol_id, c->vi.name);
1381   - if (mounted_read_only)
  1381 + if (c->ro_mount)
1382 1382 ubifs_msg("mounted read-only");
1383 1383 x = (long long)c->main_lebs * c->leb_size;
1384 1384 ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, %d "
... ... @@ -1640,7 +1640,7 @@
1640 1640 }
1641 1641  
1642 1642 dbg_gen("re-mounted read-write");
1643   - c->vfs_sb->s_flags &= ~MS_RDONLY;
  1643 + c->ro_mount = 0;
1644 1644 c->remounting_rw = 0;
1645 1645 c->always_chk_crc = 0;
1646 1646 err = dbg_check_space_info(c);
... ... @@ -1676,7 +1676,7 @@
1676 1676 int i, err;
1677 1677  
1678 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 1681 mutex_lock(&c->umount_mutex);
1682 1682 if (c->bgt) {
... ... @@ -1704,6 +1704,7 @@
1704 1704 vfree(c->ileb_buf);
1705 1705 c->ileb_buf = NULL;
1706 1706 ubifs_lpt_free(c, 1);
  1707 + c->ro_mount = 1;
1707 1708 err = dbg_check_space_info(c);
1708 1709 if (err)
1709 1710 ubifs_ro_mode(c, err);
... ... @@ -1735,7 +1736,7 @@
1735 1736 * the mutex is locked.
1736 1737 */
1737 1738 mutex_lock(&c->umount_mutex);
1738   - if (!(c->vfs_sb->s_flags & MS_RDONLY)) {
  1739 + if (!c->ro_mount) {
1739 1740 /*
1740 1741 * First of all kill the background thread to make sure it does
1741 1742 * not interfere with un-mounting and freeing resources.
1742 1743  
1743 1744  
... ... @@ -1745,23 +1746,23 @@
1745 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 1750 * On fatal errors c->ro_error is set to 1, in which case we do
1755 1751 * not write the master node.
1756 1752 */
1757 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 1762 * We are being cleanly unmounted which means the
1760 1763 * orphans were killed - indicate this in the master
1761 1764 * node. Also save the reserved GC LEB number.
1762 1765 */
1763   - int err;
1764   -
1765 1766 c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
1766 1767 c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
1767 1768 c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
... ... @@ -1797,7 +1798,7 @@
1797 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 1802 if (c->ro_error) {
1802 1803 ubifs_msg("cannot re-mount R/W due to prior errors");
1803 1804 return -EROFS;
... ... @@ -1809,7 +1810,7 @@
1809 1810 err = ubifs_remount_rw(c);
1810 1811 if (err)
1811 1812 return err;
1812   - } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
  1813 + } else if (!c->ro_mount && (*flags & MS_RDONLY)) {
1813 1814 if (c->ro_error) {
1814 1815 ubifs_msg("cannot re-mount R/O due to prior errors");
1815 1816 return -EROFS;
1816 1817  
... ... @@ -2068,9 +2069,11 @@
2068 2069 }
2069 2070  
2070 2071 if (sb->s_root) {
  2072 + struct ubifs_info *c1 = sb->s_fs_info;
  2073 +
2071 2074 /* A new mount point for already mounted UBIFS */
2072 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 2077 err = -EBUSY;
2075 2078 goto out_deact;
2076 2079 }
... ... @@ -1032,6 +1032,7 @@
1032 1032 * @max_leb_cnt: maximum count of logical eraseblocks
1033 1033 * @old_leb_cnt: count of logical eraseblocks before re-size
1034 1034 * @ro_media: the underlying UBI volume is read-only
  1035 + * @ro_mount: the file-system was mounted as read-only
1035 1036 * @ro_error: UBIFS switched to R/O mode because an error happened
1036 1037 *
1037 1038 * @dirty_pg_cnt: number of dirty pages (not used)
1038 1039  
... ... @@ -1173,11 +1174,14 @@
1173 1174 * @replay_sqnum: sequence number of node currently being replayed
1174 1175 * @need_recovery: file-system needs recovery
1175 1176 * @replaying: set to %1 during journal replay
1176   - * @unclean_leb_list: LEBs to recover when mounting ro to rw
1177   - * @rcvrd_mst_node: recovered master node to write when mounting ro to rw
  1177 + * @unclean_leb_list: LEBs to recover when re-mounting R/O mounted FS to R/W
  1178 + * mode
  1179 + * @rcvrd_mst_node: recovered master node to write when re-mounting R/O mounted
  1180 + * FS to R/W mode
1178 1181 * @size_tree: inode size information for recovery
1179   - * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY)
1180   - * @always_chk_crc: always check CRCs (while mounting and remounting rw)
  1182 + * @remounting_rw: set while re-mounting from R/O mode to R/W mode
  1183 + * @always_chk_crc: always check CRCs (while mounting and remounting to R/W
  1184 + * mode)
1181 1185 * @mount_opts: UBIFS-specific mount options
1182 1186 *
1183 1187 * @dbg: debugging-related information
... ... @@ -1274,6 +1278,7 @@
1274 1278 int max_leb_cnt;
1275 1279 int old_leb_cnt;
1276 1280 unsigned int ro_media:1;
  1281 + unsigned int ro_mount:1;
1277 1282 unsigned int ro_error:1;
1278 1283  
1279 1284 atomic_long_t dirty_pg_cnt;