From cf6c38b984e0aa1f901224a2e14704b3df090f22 Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Mon, 21 Feb 2005 01:13:24 +0000 Subject: [PATCH] STABLE14-linux-flush-release-rewrite-20050209 FIXES 17509 rewrite afs_linux_release and afs_linux_flush (cherry picked from commit a0732a579ac1aea9cfdee2de530b3afcffe30bac) --- src/afs/LINUX/osi_vnodeops.c | 60 ++++++++++++++---------------------- src/afs/afs.h | 1 - 2 files changed, 23 insertions(+), 38 deletions(-) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index ab196b5fa..417068751 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -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); diff --git a/src/afs/afs.h b/src/afs/afs.h index 16d29cbb0..af76a9869 100644 --- a/src/afs/afs.h +++ b/src/afs/afs.h @@ -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) -- 2.39.5