Commit 77e9ce32 authored by Al Viro's avatar Al Viro

ufs: fix the logics for tail relocation

* original hysteresis loop got broken by typo back in 2002; now
it never switches out of OPTTIME state.  Fixed.
* critical levels for switching from OPTTIME to OPTSPACE and back
ought to be calculated once, at mount time.
* we should use mul_u64_u32_div() for those calculations, now that
->s_dsize is 64bit.
* to quote Kirk McKusick (in 1995 FreeBSD commit message):
    The threshold for switching from time-space and space-time is too small
    when minfree is 5%...so make it stay at space in this case.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c0ef65d2
...@@ -455,24 +455,14 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, ...@@ -455,24 +455,14 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
/* /*
* allocate new block and move data * allocate new block and move data
*/ */
switch (fs32_to_cpu(sb, usb1->fs_optim)) { if (fs32_to_cpu(sb, usb1->fs_optim) == UFS_OPTSPACE) {
case UFS_OPTSPACE:
request = newcount; request = newcount;
if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree if (uspi->cs_total.cs_nffree < uspi->s_space_to_time)
> uspi->s_dsize * uspi->s_minfree / (2 * 100))
break;
usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
break;
default:
usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME); usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
} else {
case UFS_OPTTIME:
request = uspi->s_fpb; request = uspi->s_fpb;
if (uspi->cs_total.cs_nffree < uspi->s_dsize * if (uspi->cs_total.cs_nffree > uspi->s_time_to_space)
(uspi->s_minfree - 2) / 100) usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTSPACE);
break;
usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
break;
} }
result = ufs_alloc_fragments (inode, cgno, goal, request, err); result = ufs_alloc_fragments (inode, cgno, goal, request, err);
if (result) { if (result) {
......
...@@ -1211,6 +1211,15 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1211,6 +1211,15 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
uspi->s_root_blocks = mul_u64_u32_div(uspi->s_dsize, uspi->s_root_blocks = mul_u64_u32_div(uspi->s_dsize,
uspi->s_minfree, 100); uspi->s_minfree, 100);
if (uspi->s_minfree <= 5) {
uspi->s_time_to_space = ~0ULL;
uspi->s_space_to_time = 0;
usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTSPACE);
} else {
uspi->s_time_to_space = (uspi->s_root_blocks / 2) + 1;
uspi->s_space_to_time = mul_u64_u32_div(uspi->s_dsize,
uspi->s_minfree - 2, 100) - 1;
}
/* /*
* Compute another frequently used values * Compute another frequently used values
......
...@@ -792,6 +792,8 @@ struct ufs_sb_private_info { ...@@ -792,6 +792,8 @@ struct ufs_sb_private_info {
__s32 fs_magic; /* filesystem magic */ __s32 fs_magic; /* filesystem magic */
unsigned int s_dirblksize; unsigned int s_dirblksize;
__u64 s_root_blocks; __u64 s_root_blocks;
__u64 s_time_to_space;
__u64 s_space_to_time;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment