mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
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))
|
||||
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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
error = xfs_reserve_blocks(mp, &resblks, NULL);
|
||||
if (error)
|
||||
cmn_err(CE_WARN, "XFS: Unable to allocate reserve blocks. "
|
||||
"Continuing without a reserve pool.");
|
||||
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.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user