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();
}
/* 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);