Re: 2.6.2-rc2 nfsd+xfs spins in i_size_read()

Steve Lord
2004-02-04T15:08:46Z

Christoph Hellwig wrote:
> Okay, what about this little patch?:
>
>
> Index: fs/xfs/linux-2.6/xfs_iops.c
> ===================================================================
> RCS file: /cvs/linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c,v
> retrieving revision 1.212
> diff -u -p -r1.212 xfs_iops.c
> --- fs/xfs/linux-2.6/xfs_iops.c 12 Dec 2003 04:17:52 -0000 1.212
> +++ fs/xfs/linux-2.6/xfs_iops.c 3 Feb 2004 23:56:17 -0000
> @@ -80,11 +80,15 @@ validate_fields(
> vattr_t va;
> int error;
>
> - va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
> + va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS|XFS_AT_SIZE;
> VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error);
> ip->i_nlink = va.va_nlink;
> ip->i_size = va.va_size;
> ip->i_blocks = va.va_nblocks;
> +
> + /* we're under i_sem so i_size can't change under us */
> + if (i_size_read(ip) != va.va_size)
> + i_size_write(ip, va.va_size);
> }
>
> /*
> @@ -186,8 +190,7 @@ linvfs_mknod(
>
> if (S_ISCHR(mode) || S_ISBLK(mode))
> ip->i_rdev = rdev;
> - else if (S_ISDIR(mode))
> - validate_fields(ip);
> + validate_fields(ip);

There was some reason this was only necessary on directories, but I
cannot remember why just now.

> d_instantiate(dentry, ip);
> validate_fields(dir);
> }
> @@ -536,6 +539,7 @@ linvfs_setattr(
> if (error)
> return(-error); /* Positive error up from XFS */
> if (ia_valid & ATTR_SIZE) {
> + i_size_write(inode, vattr.va_size);
> error = vmtruncate(inode, attr->ia_size);
> }
>
> Index: fs/xfs/linux-2.6/xfs_vnode.c
> ===================================================================
> RCS file: /cvs/linux-2.6-xfs/fs/xfs/linux-2.6/xfs_vnode.c,v
> retrieving revision 1.120
> diff -u -p -r1.120 xfs_vnode.c
> --- fs/xfs/linux-2.6/xfs_vnode.c 20 Oct 2003 02:08:58 -0000 1.120
> +++ fs/xfs/linux-2.6/xfs_vnode.c 3 Feb 2004 23:56:17 -0000
> @@ -213,7 +213,6 @@ vn_revalidate(
> inode->i_mtime = va.va_mtime;
> inode->i_ctime = va.va_ctime;
> inode->i_atime = va.va_atime;
> - i_size_write(inode, va.va_size);
> if (va.va_xflags & XFS_XFLAG_IMMUTABLE)
> inode->i_flags |= S_IMMUTABLE;
> else
>

I think this should work, it just leaves the extending O_DIRECT write
case. Keeping the revalidate call out of the path for creating regular
files would be nice though, why did you deem that necessary?

Steve