linux-flush-release-rewrite-20050209
authorChas Williams <chas@cmf.nrl.navy.mil>
Thu, 10 Feb 2005 04:49:10 +0000 (04:49 +0000)
committerDerrick Brashear <shadow@dementia.org>
Thu, 10 Feb 2005 04:49:10 +0000 (04:49 +0000)
FIXES 17509

rewrite afs_linux_release and afs_linux_flush

src/afs/LINUX/osi_vnodeops.c
src/afs/afs.h

index ab196b5..4170687 100644 (file)
@@ -590,29 +590,18 @@ afs_linux_open(struct inode *ip, struct file *fp)
     return -code;
 }
 
-/* afs_Close is called from release, since release is used to handle all
- * file closings. In addition afs_linux_flush is called from sys_close to
- * handle flushing the data back to the server. The kicker is that we could
- * ignore flush completely if only sys_close took it's return value from
- * fput. See afs_linux_flush for notes on interactions between release and
- * flush.
- */
 static int
 afs_linux_release(struct inode *ip, struct file *fp)
 {
-    int code = 0;
-    cred_t *credp = crref();
     struct vcache *vcp = ITOAFS(ip);
+    cred_t *credp = crref();
+    int code = 0;
 
 #ifdef AFS_LINUX24_ENV
     lock_kernel();
 #endif
     AFS_GLOCK();
-    if (vcp->flushcnt) {
-       vcp->flushcnt--;        /* protected by AFS global lock. */
-    } else {
-       code = afs_close(vcp, fp->f_flags, credp);
-    }
+    code = afs_close(vcp, fp->f_flags, credp);
     AFS_GUNLOCK();
 #ifdef AFS_LINUX24_ENV
     unlock_kernel();
@@ -690,37 +679,34 @@ afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
 }
 
 /* afs_linux_flush
- * flush is called from sys_close. We could ignore it, but sys_close return
- * code comes from flush, not release. We need to use release to keep
- * the vcache open count correct. Note that flush is called before release
- * (via fput) in sys_close. vcp->flushcnt is a bit of ugliness to avoid
- * races and also avoid calling afs_close twice when closing the file.
- * If we merely checked for opens > 0 in afs_linux_release, then if an
- * new open occurred when storing back the file, afs_linux_release would
- * incorrectly close the file and decrement the opens count. Calling afs_close
- * on the just flushed file is wasteful, since the background daemon will
- * execute the code that finally decides there is nothing to do.
+ * essentially the same as afs_fsync() but we need to get the return
+ * code for the sys_close() here, not afs_linux_release(), so call
+ * afs_StoreAllSegments() with AFS_LASTSTORE
  */
 int
 afs_linux_flush(struct file *fp)
 {
+    struct vrequest treq;
     struct vcache *vcp = ITOAFS(FILE_INODE(fp));
-    int code = 0;
-    cred_t *credp;
+    cred_t *credp = crref();
+    int code;
 
-    /* Only do this on the last close of the file pointer. */
-#if defined(AFS_LINUX24_ENV)
-    if (atomic_read(&fp->f_count) > 1)
-#else
-    if (fp->f_count > 1)
-#endif
-       return 0;
+    AFS_GLOCK();
 
-    credp = crref();
+    code = afs_InitReq(&treq, credp);
+    if (code)
+       goto out;
 
-    AFS_GLOCK();
-    code = afs_close(vcp, fp->f_flags, credp);
-    vcp->flushcnt++;           /* protected by AFS global lock. */
+    ObtainSharedLock(&vcp->lock, 535);
+    if (vcp->execsOrWriters > 0) {
+       UpgradeSToWLock(&vcp->lock, 536);
+       code = afs_StoreAllSegments(vcp, &treq, AFS_SYNC | AFS_LASTSTORE);
+       ConvertWToSLock(&vcp->lock);
+    }
+    code = afs_CheckCode(code, &treq, 54);
+    ReleaseSharedLock(&vcp->lock);
+
+out:
     AFS_GUNLOCK();
 
     crfree(credp);
index 16d29cb..af76a98 100644 (file)
@@ -696,7 +696,6 @@ struct vcache {
        struct dcache *dchint;
     } h1;
 #ifdef AFS_LINUX22_ENV
-    u_short flushcnt;          /* Number of flushes which haven't released yet. */
     u_short mapcnt;            /* Number of mappings of this file. */
 #endif
 #if defined(AFS_SGI_ENV)