From f49bf1d919b48901533da78c9fe38ca0339b7bca Mon Sep 17 00:00:00 2001 From: Simon Wilkinson Date: Fri, 9 Jan 2009 15:09:14 +0000 Subject: [PATCH] linux-truncate-race-20090109 LICENSE IPL10 FIXES 124094 avoid a race during truncation which trips an issue when fsx is run --- acinclude.m4 | 1 + src/afs/LINUX/osi_file.c | 8 ++++---- src/afs/LINUX/osi_vfs.hin | 5 +++++ src/afs/LINUX/osi_vfsops.c | 2 +- src/afs/LINUX/osi_vnodeops.c | 8 ++++---- src/afs/VNOPS/afs_vnop_attrs.c | 7 +++++++ src/cf/linux-test4.m4 | 16 ++++++++++++++++ 7 files changed, 38 insertions(+), 9 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 7b3e659..6ee19bf 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -905,6 +905,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*) LINUX_REGISTER_SYSCTL_TABLE_NOFLAG LINUX_SYSCTL_TABLE_CHECKING LINUX_HAVE_IGET + LINUX_HAVE_I_SIZE_READ LINUX_FS_STRUCT_NAMEIDATA_HAS_PATH LINUX_EXPORTS_INIT_MM LINUX_EXPORTS_SYS_CHDIR diff --git a/src/afs/LINUX/osi_file.c b/src/afs/LINUX/osi_file.c index 31194f6..f138981 100644 --- a/src/afs/LINUX/osi_file.c +++ b/src/afs/LINUX/osi_file.c @@ -95,7 +95,7 @@ osi_UFSOpen(afs_int32 ainode) osi_Panic("Can't open inode %d\n", ainode); #endif afile->filp = filp; - afile->size = FILE_INODE(filp)->i_size; + afile->size = i_size_read(FILE_INODE(filp)->i_size); AFS_GLOCK(); afile->offset = 0; afile->proc = (int (*)())0; @@ -150,7 +150,7 @@ osi_UFSOpen(afs_int32 ainode) code = filp->f_op->open(tip, filp); if (code) osi_Panic("Can't open inode %d\n", ainode); - afile->size = tip->i_size; + afile->size = i_size_read(tip); AFS_GLOCK(); afile->offset = 0; afile->proc = (int (*)())0; @@ -182,7 +182,7 @@ afs_osi_Stat(register struct osi_file *afile, register struct osi_stat *astat) register afs_int32 code; AFS_STATCNT(osi_Stat); MObtainWriteLock(&afs_xosi, 320); - astat->size = OSIFILE_INODE(afile)->i_size; + astat->size = i_size_read(OSIFILE_INODE(afile)); #if defined(AFS_LINUX26_ENV) astat->mtime = OSIFILE_INODE(afile)->i_mtime.tv_sec; astat->atime = OSIFILE_INODE(afile)->i_atime.tv_sec; @@ -272,7 +272,7 @@ osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize) if (!code) truncate_inode_pages(&inode->i_data, asize); #else - inode->i_size = asize; + i_size_write(inode, asize); if (inode->i_sb->s_op && inode->i_sb->s_op->notify_change) { code = inode->i_sb->s_op->notify_change(&afile->dentry, &newattrs); } diff --git a/src/afs/LINUX/osi_vfs.hin b/src/afs/LINUX/osi_vfs.hin index b94a2ca..bd6de53 100644 --- a/src/afs/LINUX/osi_vfs.hin +++ b/src/afs/LINUX/osi_vfs.hin @@ -78,4 +78,9 @@ typedef struct vattr { #define VATTR_NULL(A) memset(A, 0, sizeof(struct vattr)) +#ifndef HAVE_LINUX_I_SIZE_READ +#define i_size_read(X) ((X)->i_size) +#define i_size_write(X,Y) (X)->i_size = Y +#endif + #endif /* OSI_VFS_H_ */ diff --git a/src/afs/LINUX/osi_vfsops.c b/src/afs/LINUX/osi_vfsops.c index 5cf5d55..4b609e0 100644 --- a/src/afs/LINUX/osi_vfsops.c +++ b/src/afs/LINUX/osi_vfsops.c @@ -544,7 +544,7 @@ vattr2inode(struct inode *ip, struct vattr *vp) ip->i_mode = vp->va_mode; ip->i_uid = vp->va_uid; ip->i_gid = vp->va_gid; - ip->i_size = vp->va_size; + i_size_write(ip, vp->va_size); #if defined(AFS_LINUX26_ENV) ip->i_atime.tv_sec = vp->va_atime.tv_sec; ip->i_atime.tv_nsec = 0; diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 70f7098..c8f7a5e 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1918,7 +1918,7 @@ afs_linux_writepage_sync(struct inode *ip, struct page *pp, code = afs_write(vcp, &tuio, f_flags, credp, 0); - ip->i_size = vcp->m.Length; + i_size_write(ip, vcp->m.Length); ip->i_blocks = ((vcp->m.Length + 1023) >> 10) << 1; if (!code) { @@ -1972,13 +1972,13 @@ afs_linux_writepage(struct page *pp) #endif inode = (struct inode *)mapping->host; - end_index = inode->i_size >> PAGE_CACHE_SHIFT; + end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; /* easy case */ if (pp->index < end_index) goto do_it; /* things got complicated... */ - offset = inode->i_size & (PAGE_CACHE_SIZE - 1); + offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1); /* OK, are we completely out? */ if (pp->index >= end_index + 1 || !offset) return -EIO; @@ -2021,7 +2021,7 @@ afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset, code = afs_write(vcp, &tuio, fp->f_flags, credp, 0); - ip->i_size = vcp->m.Length; + i_size_write(ip, vcp->m.Length); ip->i_blocks = ((vcp->m.Length + 1023) >> 10) << 1; if (!code) { diff --git a/src/afs/VNOPS/afs_vnop_attrs.c b/src/afs/VNOPS/afs_vnop_attrs.c index 36606aa..58b9a00 100644 --- a/src/afs/VNOPS/afs_vnop_attrs.c +++ b/src/afs/VNOPS/afs_vnop_attrs.c @@ -546,6 +546,13 @@ afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs, avc->states |= CDirty; code = afs_TruncateAllSegments(avc, tsize, &treq, acred); +#ifdef AFS_LINUX_26_ENV + /* We must update the Linux kernel's idea of file size as soon as + * possible, to avoid racing with delayed writepages delivered by + * pdflush */ + if (code == 0) + i_size_write(AFSTOV(avc), tsize); +#endif /* if date not explicitly set by this call, set it ourselves, since we * changed the data */ if (!(astat.Mask & AFS_SETMODTIME)) { diff --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4 index 6b24ce5..180083a 100644 --- a/src/cf/linux-test4.m4 +++ b/src/cf/linux-test4.m4 @@ -825,6 +825,22 @@ AC_DEFUN([LINUX_GENERIC_FILE_AIO_READ], [ AC_DEFINE([GENERIC_FILE_AIO_READ], 1, [define if your kernel has generic_file_aio_read()]) fi]) +AC_DEFUN([LINUX_HAVE_I_SIZE_READ], [ + AC_MSG_CHECKING([for linux i_size_read()]) + AC_CACHE_VAL([ac_cv_linux_i_size_read], [ + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -Werror-implicit-function-declaration" + AC_TRY_KBUILD( +[#include ], +[i_size_read(NULL);], + ac_cv_linux_i_size_read=yes, + ac_cv_linux_i_size_read=no) + CPPFLAGS="$save_CPPFLAGS"]) + AC_MSG_RESULT($ac_cv_linux_i_size_read) + if test "x$ac_cv_linux_i_size_read" = "xyes"; then + AC_DEFINE([HAVE_LINUX_I_SIZE_READ], 1, [define if your kernel has i_size_read()]) + fi]) + AC_DEFUN([LINUX_FREEZER_H_EXISTS], [ AC_MSG_CHECKING([for linux/freezer.h existance]) AC_CACHE_VAL([ac_cv_linux_freezer_h_exists], [ -- 1.9.4