diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-01-23 11:23:03 -0500 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-01-26 05:54:11 -0500 |
commit | b4978e949104844224ecf786170c9263efa601f3 (patch) | |
tree | a8002df0e1f8feace090a6dcd5ea294ab55f2060 /fs/ubifs | |
parent | 84abf972ccff5c13d10b672972949eba431a6e0e (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>
Diffstat (limited to 'fs/ubifs')
-rw-r--r-- | fs/ubifs/super.c | 47 |
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 | */ |
745 | static int take_gc_lnum(struct ubifs_info *c) | 746 | static 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 | ||