Commit 021f6019 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'ufs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull more ufs fixes from Al Viro:
 "More UFS fixes, unfortunately including build regression fix for the
  64-bit s_dsize commit. Fixed in this pile:

   - trivial bug in signedness of 32bit timestamps on ufs1

   - ESTALE instead of ufs_error() when doing open-by-fhandle on
     something deleted

   - build regression on 32bit in ufs_new_fragments() - calculating that
     many percents of u64 pulls libgcc stuff on some of those. Mea
     culpa.

   - fix hysteresis loop broken by typo in 2.4.14.7 (right next to the
     location of previous bug).

   - fix the insane limits of said hysteresis loop on filesystems with
     very low percentage of reserved blocks. If it's 5% or less, just
     use the OPTSPACE policy.

   - calculate those limits once and mount time.

  This tree does pass xfstests clean (both ufs1 and ufs2) and it _does_
  survive cross-builds.

  Again, my apologies for missing that, especially since I have noticed
  a related percentage-of-64bit issue in earlier patches (when dealing
  with amount of reserved blocks). Self-LART applied..."

* 'ufs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  ufs: fix the logics for tail relocation
  ufs_iget(): fail with -ESTALE on deleted inode
  fix signedness of timestamps on ufs1
parents bd726c90 77e9ce32
...@@ -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)) usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
break; } else {
usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
break;
default:
usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
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) {
......
...@@ -566,10 +566,8 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) ...@@ -566,10 +566,8 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
*/ */
inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
set_nlink(inode, fs16_to_cpu(sb, ufs_inode->ui_nlink)); set_nlink(inode, fs16_to_cpu(sb, ufs_inode->ui_nlink));
if (inode->i_nlink == 0) { if (inode->i_nlink == 0)
ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); return -ESTALE;
return -1;
}
/* /*
* Linux now has 32-bit uid and gid, so we can support EFT. * Linux now has 32-bit uid and gid, so we can support EFT.
...@@ -578,9 +576,9 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) ...@@ -578,9 +576,9 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
i_gid_write(inode, ufs_get_inode_gid(sb, ufs_inode)); i_gid_write(inode, ufs_get_inode_gid(sb, ufs_inode));
inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size); inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size);
inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec); inode->i_atime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec); inode->i_ctime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec); inode->i_mtime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
inode->i_mtime.tv_nsec = 0; inode->i_mtime.tv_nsec = 0;
inode->i_atime.tv_nsec = 0; inode->i_atime.tv_nsec = 0;
inode->i_ctime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0;
...@@ -614,10 +612,8 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) ...@@ -614,10 +612,8 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
*/ */
inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode); inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
set_nlink(inode, fs16_to_cpu(sb, ufs2_inode->ui_nlink)); set_nlink(inode, fs16_to_cpu(sb, ufs2_inode->ui_nlink));
if (inode->i_nlink == 0) { if (inode->i_nlink == 0)
ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); return -ESTALE;
return -1;
}
/* /*
* Linux now has 32-bit uid and gid, so we can support EFT. * Linux now has 32-bit uid and gid, so we can support EFT.
...@@ -657,7 +653,7 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino) ...@@ -657,7 +653,7 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct buffer_head * bh; struct buffer_head * bh;
struct inode *inode; struct inode *inode;
int err; int err = -EIO;
UFSD("ENTER, ino %lu\n", ino); UFSD("ENTER, ino %lu\n", ino);
...@@ -692,9 +688,10 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino) ...@@ -692,9 +688,10 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
err = ufs1_read_inode(inode, err = ufs1_read_inode(inode,
ufs_inode + ufs_inotofsbo(inode->i_ino)); ufs_inode + ufs_inotofsbo(inode->i_ino));
} }
brelse(bh);
if (err) if (err)
goto bad_inode; goto bad_inode;
inode->i_version++; inode->i_version++;
ufsi->i_lastfrag = ufsi->i_lastfrag =
(inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
...@@ -703,15 +700,13 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino) ...@@ -703,15 +700,13 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
ufs_set_inode_ops(inode); ufs_set_inode_ops(inode);
brelse(bh);
UFSD("EXIT\n"); UFSD("EXIT\n");
unlock_new_inode(inode); unlock_new_inode(inode);
return inode; return inode;
bad_inode: bad_inode:
iget_failed(inode); iget_failed(inode);
return ERR_PTR(-EIO); return ERR_PTR(err);
} }
static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode) static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode)
......
...@@ -1210,6 +1210,15 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1210,6 +1210,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