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

Commit d5db0f97 authored by Eric Sandeen's avatar Eric Sandeen Committed by Alex Elder
Browse files

xfs: more reserved blocks fixups



This mangles the reserved blocks counts a little more.

1) add a helper function for the default reserved count
2) add helper functions to save/restore counts on ro/rw
3) save/restore reserved blocks on freeze/thaw
4) disallow changing reserved count while readonly

V2: changed field name to match Dave's changes

Signed-off-by: default avatarEric Sandeen <sandeen@sandeen.net>
Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
parent 388f1f0c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1431,6 +1431,9 @@ xfs_file_ioctl(
		if (!capable(CAP_SYS_ADMIN))
			return -EPERM;

		if (mp->m_flags & XFS_MOUNT_RDONLY)
			return -XFS_ERROR(EROFS);

		if (copy_from_user(&inout, arg, sizeof(inout)))
			return -XFS_ERROR(EFAULT);

+37 −14
Original line number Diff line number Diff line
@@ -1256,6 +1256,29 @@ xfs_fs_statfs(
	return 0;
}

STATIC void
xfs_save_resvblks(struct xfs_mount *mp)
{
	__uint64_t resblks = 0;

	mp->m_resblks_save = mp->m_resblks;
	xfs_reserve_blocks(mp, &resblks, NULL);
}

STATIC void
xfs_restore_resvblks(struct xfs_mount *mp)
{
	__uint64_t resblks;

	if (mp->m_resblks_save) {
		resblks = mp->m_resblks_save;
		mp->m_resblks_save = 0;
	} else
		resblks = xfs_default_resblks(mp);

	xfs_reserve_blocks(mp, &resblks, NULL);
}

STATIC int
xfs_fs_remount(
	struct super_block	*sb,
@@ -1318,8 +1341,6 @@ xfs_fs_remount(

	/* ro -> rw */
	if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
		__uint64_t resblks;

		mp->m_flags &= ~XFS_MOUNT_RDONLY;
		if (mp->m_flags & XFS_MOUNT_BARRIER)
			xfs_mountfs_check_barriers(mp);
@@ -1342,15 +1363,7 @@ xfs_fs_remount(
		 * Fill out the reserve pool if it is empty. Use the stashed
		 * value if it is non-zero, otherwise go with the default.
		 */
		if (mp->m_resblks_save) {
			resblks = mp->m_resblks_save;
			mp->m_resblks_save = 0;
		} else {
			resblks = mp->m_sb.sb_dblocks;
			do_div(resblks, 20);
			resblks = min_t(__uint64_t, resblks, 1024);
		}
		xfs_reserve_blocks(mp, &resblks, NULL);
		xfs_restore_resvblks(mp);
	}

	/* rw -> ro */
@@ -1363,11 +1376,9 @@ xfs_fs_remount(
		 * so that if we get remounted rw, we can return it to the same
		 * size.
		 */
		__uint64_t resblks = 0;

		xfs_quiesce_data(mp);
		mp->m_resblks_save = mp->m_resblks;
		xfs_reserve_blocks(mp, &resblks, NULL);
		xfs_save_resvblks(mp);
		xfs_quiesce_attr(mp);
		mp->m_flags |= XFS_MOUNT_RDONLY;
	}
@@ -1386,10 +1397,21 @@ xfs_fs_freeze(
{
	struct xfs_mount	*mp = XFS_M(sb);

	xfs_save_resvblks(mp);
	xfs_quiesce_attr(mp);
	return -xfs_fs_log_dummy(mp);
}

STATIC int
xfs_fs_unfreeze(
	struct super_block	*sb)
{
	struct xfs_mount	*mp = XFS_M(sb);

	xfs_restore_resvblks(mp);
	return 0;
}

STATIC int
xfs_fs_show_options(
	struct seq_file		*m,
@@ -1612,6 +1634,7 @@ static const struct super_operations xfs_super_operations = {
	.put_super		= xfs_fs_put_super,
	.sync_fs		= xfs_fs_sync_fs,
	.freeze_fs		= xfs_fs_freeze,
	.unfreeze_fs		= xfs_fs_unfreeze,
	.statfs			= xfs_fs_statfs,
	.remount_fs		= xfs_fs_remount,
	.show_options		= xfs_fs_show_options,
+23 −11
Original line number Diff line number Diff line
@@ -1091,6 +1091,22 @@ xfs_mount_reset_sbqflags(
	return xfs_trans_commit(tp, 0);
}

__uint64_t
xfs_default_resblks(xfs_mount_t *mp)
{
	__uint64_t resblks;

	/*
	 * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
	 * This may drive us straight to ENOSPC on mount, but that implies
	 * we were already there on the last unmount. Warn if this occurs.
	 */
	resblks = mp->m_sb.sb_dblocks;
	do_div(resblks, 20);
	resblks = min_t(__uint64_t, resblks, 1024);
	return resblks;
}

/*
 * This function does the following on an initial mount of a file system:
 *	- reads the superblock from disk and init the mount struct
@@ -1401,18 +1417,14 @@ xfs_mountfs(
	 * when at ENOSPC. This is needed for operations like create with
	 * attr, unwritten extent conversion at ENOSPC, etc. Data allocations
	 * are not allowed to use this reserved space.
	 *
	 * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
	 * This may drive us straight to ENOSPC on mount, but that implies
	 * we were already there on the last unmount. Warn if this occurs.
	 */
	resblks = mp->m_sb.sb_dblocks;
	do_div(resblks, 20);
	resblks = min_t(__uint64_t, resblks, 1024);
	if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
		resblks = xfs_default_resblks(mp);
		error = xfs_reserve_blocks(mp, &resblks, NULL);
		if (error)
		cmn_err(CE_WARN, "XFS: Unable to allocate reserve blocks. "
				"Continuing without a reserve pool.");
			cmn_err(CE_WARN, "XFS: Unable to allocate reserve "
				"blocks. Continuing without a reserve pool.");
	}

	return 0;

+1 −0
Original line number Diff line number Diff line
@@ -421,6 +421,7 @@ typedef struct xfs_mod_sb {
} xfs_mod_sb_t;

extern int	xfs_log_sbcount(xfs_mount_t *, uint);
extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
extern int	xfs_mountfs(xfs_mount_t *mp);

extern void	xfs_unmountfs(xfs_mount_t *);