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: Eric Sandeen <sandeen@sandeen.net> Signed-off-by: Alex Elder <aelder@sgi.com>
This commit is contained in:
parent
388f1f0c34
commit
d5db0f97fb
|
@ -1431,6 +1431,9 @@ xfs_file_ioctl(
|
||||||
if (!capable(CAP_SYS_ADMIN))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
|
if (mp->m_flags & XFS_MOUNT_RDONLY)
|
||||||
|
return -XFS_ERROR(EROFS);
|
||||||
|
|
||||||
if (copy_from_user(&inout, arg, sizeof(inout)))
|
if (copy_from_user(&inout, arg, sizeof(inout)))
|
||||||
return -XFS_ERROR(EFAULT);
|
return -XFS_ERROR(EFAULT);
|
||||||
|
|
||||||
|
|
|
@ -1256,6 +1256,29 @@ xfs_fs_statfs(
|
||||||
return 0;
|
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
|
STATIC int
|
||||||
xfs_fs_remount(
|
xfs_fs_remount(
|
||||||
struct super_block *sb,
|
struct super_block *sb,
|
||||||
|
@ -1318,8 +1341,6 @@ xfs_fs_remount(
|
||||||
|
|
||||||
/* ro -> rw */
|
/* ro -> rw */
|
||||||
if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
|
if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
|
||||||
__uint64_t resblks;
|
|
||||||
|
|
||||||
mp->m_flags &= ~XFS_MOUNT_RDONLY;
|
mp->m_flags &= ~XFS_MOUNT_RDONLY;
|
||||||
if (mp->m_flags & XFS_MOUNT_BARRIER)
|
if (mp->m_flags & XFS_MOUNT_BARRIER)
|
||||||
xfs_mountfs_check_barriers(mp);
|
xfs_mountfs_check_barriers(mp);
|
||||||
|
@ -1342,15 +1363,7 @@ xfs_fs_remount(
|
||||||
* Fill out the reserve pool if it is empty. Use the stashed
|
* Fill out the reserve pool if it is empty. Use the stashed
|
||||||
* value if it is non-zero, otherwise go with the default.
|
* value if it is non-zero, otherwise go with the default.
|
||||||
*/
|
*/
|
||||||
if (mp->m_resblks_save) {
|
xfs_restore_resvblks(mp);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rw -> ro */
|
/* rw -> ro */
|
||||||
|
@ -1363,11 +1376,9 @@ xfs_fs_remount(
|
||||||
* so that if we get remounted rw, we can return it to the same
|
* so that if we get remounted rw, we can return it to the same
|
||||||
* size.
|
* size.
|
||||||
*/
|
*/
|
||||||
__uint64_t resblks = 0;
|
|
||||||
|
|
||||||
xfs_quiesce_data(mp);
|
xfs_quiesce_data(mp);
|
||||||
mp->m_resblks_save = mp->m_resblks;
|
xfs_save_resvblks(mp);
|
||||||
xfs_reserve_blocks(mp, &resblks, NULL);
|
|
||||||
xfs_quiesce_attr(mp);
|
xfs_quiesce_attr(mp);
|
||||||
mp->m_flags |= XFS_MOUNT_RDONLY;
|
mp->m_flags |= XFS_MOUNT_RDONLY;
|
||||||
}
|
}
|
||||||
|
@ -1386,10 +1397,21 @@ xfs_fs_freeze(
|
||||||
{
|
{
|
||||||
struct xfs_mount *mp = XFS_M(sb);
|
struct xfs_mount *mp = XFS_M(sb);
|
||||||
|
|
||||||
|
xfs_save_resvblks(mp);
|
||||||
xfs_quiesce_attr(mp);
|
xfs_quiesce_attr(mp);
|
||||||
return -xfs_fs_log_dummy(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
|
STATIC int
|
||||||
xfs_fs_show_options(
|
xfs_fs_show_options(
|
||||||
struct seq_file *m,
|
struct seq_file *m,
|
||||||
|
@ -1612,6 +1634,7 @@ static const struct super_operations xfs_super_operations = {
|
||||||
.put_super = xfs_fs_put_super,
|
.put_super = xfs_fs_put_super,
|
||||||
.sync_fs = xfs_fs_sync_fs,
|
.sync_fs = xfs_fs_sync_fs,
|
||||||
.freeze_fs = xfs_fs_freeze,
|
.freeze_fs = xfs_fs_freeze,
|
||||||
|
.unfreeze_fs = xfs_fs_unfreeze,
|
||||||
.statfs = xfs_fs_statfs,
|
.statfs = xfs_fs_statfs,
|
||||||
.remount_fs = xfs_fs_remount,
|
.remount_fs = xfs_fs_remount,
|
||||||
.show_options = xfs_fs_show_options,
|
.show_options = xfs_fs_show_options,
|
||||||
|
|
|
@ -1091,6 +1091,22 @@ xfs_mount_reset_sbqflags(
|
||||||
return xfs_trans_commit(tp, 0);
|
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:
|
* This function does the following on an initial mount of a file system:
|
||||||
* - reads the superblock from disk and init the mount struct
|
* - 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
|
* when at ENOSPC. This is needed for operations like create with
|
||||||
* attr, unwritten extent conversion at ENOSPC, etc. Data allocations
|
* attr, unwritten extent conversion at ENOSPC, etc. Data allocations
|
||||||
* are not allowed to use this reserved space.
|
* 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;
|
if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
|
||||||
do_div(resblks, 20);
|
resblks = xfs_default_resblks(mp);
|
||||||
resblks = min_t(__uint64_t, resblks, 1024);
|
error = xfs_reserve_blocks(mp, &resblks, NULL);
|
||||||
error = xfs_reserve_blocks(mp, &resblks, NULL);
|
if (error)
|
||||||
if (error)
|
cmn_err(CE_WARN, "XFS: Unable to allocate reserve "
|
||||||
cmn_err(CE_WARN, "XFS: Unable to allocate reserve blocks. "
|
"blocks. Continuing without a reserve pool.");
|
||||||
"Continuing without a reserve pool.");
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -421,6 +421,7 @@ typedef struct xfs_mod_sb {
|
||||||
} xfs_mod_sb_t;
|
} xfs_mod_sb_t;
|
||||||
|
|
||||||
extern int xfs_log_sbcount(xfs_mount_t *, uint);
|
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 int xfs_mountfs(xfs_mount_t *mp);
|
||||||
|
|
||||||
extern void xfs_unmountfs(xfs_mount_t *);
|
extern void xfs_unmountfs(xfs_mount_t *);
|
||||||
|
|
Loading…
Reference in New Issue