]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE14-linux-truncate-race-20090109
authorSimon Wilkinson <sxw@inf.ed.ac.uk>
Fri, 9 Jan 2009 15:09:33 +0000 (15:09 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 9 Jan 2009 15:09:33 +0000 (15:09 +0000)
LICENSE IPL10
FIXES 124094

avoid a race during truncation which trips an issue when fsx is run

(cherry picked from commit f49bf1d919b48901533da78c9fe38ca0339b7bca)

acinclude.m4
src/afs/LINUX/osi_file.c
src/afs/LINUX/osi_vfs.hin
src/afs/LINUX/osi_vfsops.c
src/afs/LINUX/osi_vnodeops.c
src/afs/VNOPS/afs_vnop_attrs.c
src/cf/linux-test4.m4

index b402a084137c9a512dd75d129709408a096b324c..326360e8b43f7ea7cc03b9a55a319a73612e4b08 100644 (file)
@@ -776,6 +776,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
index 7099665e2fb15d7263134098118fbfd07a36fe47..8c129f02e2946264e1fdc41f627c91517bd40670 100644 (file)
@@ -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);
     }
index b94a2ca02b4471a79b621505d1805a641cd953aa..bd6de53646e17b64377f9262474ba7f28e58405e 100644 (file)
@@ -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_ */
index 29dca45d01d102669286fe88193d8043f6103e5c..c3e8d5455542237df81fa91d3c70f9f541f5b50d 100644 (file)
@@ -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;
index 926fa5dc6aa1656ac02b04d2268dddd9c5ebf956..f86f616236fc2fa3336b2629af8f05b954b99968 100644 (file)
@@ -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) {
index c5dc1bc59dbf382fc70375c92b998afe35bd3fb9..3d12537f68a408e43c31c3921f2d2645b51da43b 100644 (file)
@@ -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)) {
index 801f6d59ae9bb2eccac0fa022e6a95ed3b4db060..fad9c728ef9c19323d9124340838d2c67cea1de9 100644 (file)
@@ -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 <linux/fs.h>],
+[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], [