aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-01-23 11:23:03 -0500
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-01-26 05:54:11 -0500
commitb4978e949104844224ecf786170c9263efa601f3 (patch)
treea8002df0e1f8feace090a6dcd5ea294ab55f2060
parent84abf972ccff5c13d10b672972949eba431a6e0e (diff)
UBIFS: always clean up GC LEB space
When we mount UBIFS, GC LEB may contain out-of-date information, and UBIFS should update lprops and set free space for thei LEB. Currently UBIFS does this only if mounted R/W. But for R/O mount we have to do the same, because otherwise we will have incorrect FS free space reported to user-space. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
-rw-r--r--fs/ubifs/super.c47
1 files changed, 33 insertions, 14 deletions
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 5c814a71f33a..336073e4c391 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -397,6 +397,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
397 buf->f_namelen = UBIFS_MAX_NLEN; 397 buf->f_namelen = UBIFS_MAX_NLEN;
398 buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]); 398 buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]);
399 buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]); 399 buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]);
400 ubifs_assert(buf->f_bfree <= c->block_cnt);
400 return 0; 401 return 0;
401} 402}
402 403
@@ -735,12 +736,12 @@ static void init_constants_master(struct ubifs_info *c)
735 * take_gc_lnum - reserve GC LEB. 736 * take_gc_lnum - reserve GC LEB.
736 * @c: UBIFS file-system description object 737 * @c: UBIFS file-system description object
737 * 738 *
738 * This function ensures that the LEB reserved for garbage collection is 739 * This function ensures that the LEB reserved for garbage collection is marked
739 * unmapped and is marked as "taken" in lprops. We also have to set free space 740 * as "taken" in lprops. We also have to set free space to LEB size and dirty
740 * to LEB size and dirty space to zero, because lprops may contain out-of-date 741 * space to zero, because lprops may contain out-of-date information if the
741 * information if the file-system was un-mounted before it has been committed. 742 * file-system was un-mounted before it has been committed. This function
742 * This function returns zero in case of success and a negative error code in 743 * returns zero in case of success and a negative error code in case of
743 * case of failure. 744 * failure.
744 */ 745 */
745static int take_gc_lnum(struct ubifs_info *c) 746static int take_gc_lnum(struct ubifs_info *c)
746{ 747{
@@ -751,10 +752,6 @@ static int take_gc_lnum(struct ubifs_info *c)
751 return -EINVAL; 752 return -EINVAL;
752 } 753 }
753 754
754 err = ubifs_leb_unmap(c, c->gc_lnum);
755 if (err)
756 return err;
757
758 /* And we have to tell lprops that this LEB is taken */ 755 /* And we have to tell lprops that this LEB is taken */
759 err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0, 756 err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0,
760 LPROPS_TAKEN, 0, 0); 757 LPROPS_TAKEN, 0, 0);
@@ -1280,10 +1277,19 @@ static int mount_ubifs(struct ubifs_info *c)
1280 if (err) 1277 if (err)
1281 goto out_orphans; 1278 goto out_orphans;
1282 err = ubifs_rcvry_gc_commit(c); 1279 err = ubifs_rcvry_gc_commit(c);
1283 } else 1280 } else {
1284 err = take_gc_lnum(c); 1281 err = take_gc_lnum(c);
1285 if (err) 1282 if (err)
1286 goto out_orphans; 1283 goto out_orphans;
1284
1285 /*
1286 * GC LEB may contain garbage if there was an unclean
1287 * reboot, and it should be un-mapped.
1288 */
1289 err = ubifs_leb_unmap(c, c->gc_lnum);
1290 if (err)
1291 return err;
1292 }
1287 1293
1288 err = dbg_check_lprops(c); 1294 err = dbg_check_lprops(c);
1289 if (err) 1295 if (err)
@@ -1292,6 +1298,16 @@ static int mount_ubifs(struct ubifs_info *c)
1292 err = ubifs_recover_size(c); 1298 err = ubifs_recover_size(c);
1293 if (err) 1299 if (err)
1294 goto out_orphans; 1300 goto out_orphans;
1301 } else {
1302 /*
1303 * Even if we mount read-only, we have to set space in GC LEB
1304 * to proper value because this affects UBIFS free space
1305 * reporting. We do not want to have a situation when
1306 * re-mounting from R/O to R/W changes amount of free space.
1307 */
1308 err = take_gc_lnum(c);
1309 if (err)
1310 goto out_orphans;
1295 } 1311 }
1296 1312
1297 spin_lock(&ubifs_infos_lock); 1313 spin_lock(&ubifs_infos_lock);
@@ -1316,6 +1332,8 @@ static int mount_ubifs(struct ubifs_info *c)
1316 goto out_infos; 1332 goto out_infos;
1317 1333
1318 c->always_chk_crc = 0; 1334 c->always_chk_crc = 0;
1335 /* GC LEB has to be empty and taken at this point */
1336 ubifs_assert(c->lst.taken_empty_lebs == 1);
1319 1337
1320 ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", 1338 ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
1321 c->vi.ubi_num, c->vi.vol_id, c->vi.name); 1339 c->vi.ubi_num, c->vi.vol_id, c->vi.name);
@@ -1561,7 +1579,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
1561 if (c->need_recovery) 1579 if (c->need_recovery)
1562 err = ubifs_rcvry_gc_commit(c); 1580 err = ubifs_rcvry_gc_commit(c);
1563 else 1581 else
1564 err = take_gc_lnum(c); 1582 err = ubifs_leb_unmap(c, c->gc_lnum);
1565 if (err) 1583 if (err)
1566 goto out; 1584 goto out;
1567 1585
@@ -1786,6 +1804,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
1786 c->bu.buf = NULL; 1804 c->bu.buf = NULL;
1787 } 1805 }
1788 1806
1807 ubifs_assert(c->lst.taken_empty_lebs == 1);
1789 return 0; 1808 return 0;
1790} 1809}
1791 1810