From 7a7946ce4a46e66b25b271692e4dbbc49c28e36c Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Thu, 12 Feb 2009 10:54:35 -0800 Subject: [PATCH] Apply upstream STABLE14-linux-truncate-race-20090109 Avoid a race condition during truncation, and a preerequisite for later upstream deltas. --- acinclude.m4 | 1 + debian/changelog | 2 ++ src/afs/LINUX/osi_file.c | 10 +++++----- src/afs/LINUX/osi_vfs.hin | 5 +++++ src/afs/LINUX/osi_vfsops.c | 4 ++-- src/afs/LINUX/osi_vnodeops.c | 10 +++++----- src/afs/VNOPS/afs_vnop_attrs.c | 9 ++++++++- src/cf/linux-test4.m4 | 16 ++++++++++++++++ 8 files changed, 44 insertions(+), 13 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 40205442b..4e315455b 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -766,6 +766,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/debian/changelog b/debian/changelog index f5ac050b3..786100e1b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,8 @@ openafs (1.4.8.dfsg1-1) UNRELEASED; urgency=low - Include vos clone man page. (LP: #324449) * Apply upstream CVS deltas: - STABLE14-libuafs-updates-20081229: prerequisite for other deltas. + - STABLE14-linux-truncate-race-20090109: avoid race condition during + truncation. * Make dynroot the default for new installations. It works much better with systems that don't bring up their network until late in the boot process, such as wireless laptops. (LP: #249240, #318605) diff --git a/src/afs/LINUX/osi_file.c b/src/afs/LINUX/osi_file.c index 268917130..17d581110 100644 --- a/src/afs/LINUX/osi_file.c +++ b/src/afs/LINUX/osi_file.c @@ -11,7 +11,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/LINUX/osi_file.c,v 1.19.2.16 2008/03/26 04:10:52 shadow Exp $"); + ("$Header: /cvs/openafs/src/afs/LINUX/osi_file.c,v 1.19.2.17 2009/01/09 14:58:03 shadow Exp $"); #ifdef AFS_LINUX24_ENV #include "h/module.h" /* early to avoid printf->printk mapping */ @@ -82,7 +82,7 @@ osi_UFSOpen(afs_int32 ainode) if (IS_ERR(filp)) osi_Panic("Can't open inode %d\n", ainode); 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; @@ -133,7 +133,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; @@ -148,7 +148,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; @@ -238,7 +238,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 b94a2ca02..bd6de5364 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 d7fc11911..0c72679b8 100644 --- a/src/afs/LINUX/osi_vfsops.c +++ b/src/afs/LINUX/osi_vfsops.c @@ -16,7 +16,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/LINUX/osi_vfsops.c,v 1.29.2.28 2007/11/23 13:45:04 shadow Exp $"); + ("$Header: /cvs/openafs/src/afs/LINUX/osi_vfsops.c,v 1.29.2.30 2009/01/09 15:09:33 shadow Exp $"); #define __NO_VERSION__ /* don't define kernel_version in module.h */ #include /* early to avoid printf->printk mapping */ @@ -532,7 +532,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 45fb5c866..0027851dc 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -22,7 +22,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v 1.81.2.73 2008/11/08 16:49:59 shadow Exp $"); + ("$Header: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v 1.81.2.74 2009/01/09 14:58:03 shadow Exp $"); #include "afs/sysincludes.h" #include "afsincludes.h" @@ -1581,7 +1581,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) { @@ -1635,13 +1635,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; @@ -1684,7 +1684,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 21fdbdff0..0825f88ba 100644 --- a/src/afs/VNOPS/afs_vnop_attrs.c +++ b/src/afs/VNOPS/afs_vnop_attrs.c @@ -24,7 +24,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.27.2.12 2008/12/29 21:26:25 shadow Exp $"); + ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.27.2.13 2009/01/09 14:58:03 shadow Exp $"); #include "afs/sysincludes.h" /* Standard vendor system headers */ #include "afsincludes.h" /* Afs-based standard headers */ @@ -530,6 +530,13 @@ afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs, ObtainWriteLock(&avc->lock, 128); 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 801f6d59a..fad9c728e 100644 --- a/src/cf/linux-test4.m4 +++ b/src/cf/linux-test4.m4 @@ -816,6 +816,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], [ -- 2.39.5