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

Commit b4978e94 authored by Artem Bityutskiy's avatar Artem Bityutskiy
Browse files

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: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 84abf972
Loading
Loading
Loading
Loading
+33 −14
Original line number Diff line number Diff line
@@ -397,6 +397,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
	buf->f_namelen = UBIFS_MAX_NLEN;
	buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]);
	buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]);
	ubifs_assert(buf->f_bfree <= c->block_cnt);
	return 0;
}

@@ -735,12 +736,12 @@ static void init_constants_master(struct ubifs_info *c)
 * take_gc_lnum - reserve GC LEB.
 * @c: UBIFS file-system description object
 *
 * This function ensures that the LEB reserved for garbage collection is
 * unmapped and is marked as "taken" in lprops. We also have to set free space
 * to LEB size and dirty space to zero, because lprops may contain out-of-date
 * information if the file-system was un-mounted before it has been committed.
 * This function returns zero in case of success and a negative error code in
 * case of failure.
 * This function ensures that the LEB reserved for garbage collection is marked
 * as "taken" in lprops. We also have to set free space to LEB size and dirty
 * space to zero, because lprops may contain out-of-date information if the
 * file-system was un-mounted before it has been committed. This function
 * returns zero in case of success and a negative error code in case of
 * failure.
 */
static int take_gc_lnum(struct ubifs_info *c)
{
@@ -751,10 +752,6 @@ static int take_gc_lnum(struct ubifs_info *c)
		return -EINVAL;
	}

	err = ubifs_leb_unmap(c, c->gc_lnum);
	if (err)
		return err;

	/* And we have to tell lprops that this LEB is taken */
	err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0,
				  LPROPS_TAKEN, 0, 0);
@@ -1280,11 +1277,20 @@ static int mount_ubifs(struct ubifs_info *c)
			if (err)
				goto out_orphans;
			err = ubifs_rcvry_gc_commit(c);
		} else
		} else {
			err = take_gc_lnum(c);
			if (err)
				goto out_orphans;

			/*
			 * GC LEB may contain garbage if there was an unclean
			 * reboot, and it should be un-mapped.
			 */
			err = ubifs_leb_unmap(c, c->gc_lnum);
			if (err)
				return err;
		}

		err = dbg_check_lprops(c);
		if (err)
			goto out_orphans;
@@ -1292,6 +1298,16 @@ static int mount_ubifs(struct ubifs_info *c)
		err = ubifs_recover_size(c);
		if (err)
			goto out_orphans;
	} else {
		/*
		 * Even if we mount read-only, we have to set space in GC LEB
		 * to proper value because this affects UBIFS free space
		 * reporting. We do not want to have a situation when
		 * re-mounting from R/O to R/W changes amount of free space.
		 */
		err = take_gc_lnum(c);
		if (err)
			goto out_orphans;
	}

	spin_lock(&ubifs_infos_lock);
@@ -1316,6 +1332,8 @@ static int mount_ubifs(struct ubifs_info *c)
		goto out_infos;

	c->always_chk_crc = 0;
	/* GC LEB has to be empty and taken at this point */
	ubifs_assert(c->lst.taken_empty_lebs == 1);

	ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
		  c->vi.ubi_num, c->vi.vol_id, c->vi.name);
@@ -1561,7 +1579,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
	if (c->need_recovery)
		err = ubifs_rcvry_gc_commit(c);
	else
		err = take_gc_lnum(c);
		err = ubifs_leb_unmap(c, c->gc_lnum);
	if (err)
		goto out;

@@ -1786,6 +1804,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
		c->bu.buf = NULL;
	}

	ubifs_assert(c->lst.taken_empty_lebs == 1);
	return 0;
}