Linux: cleanup aio support
authorMarc Dionne <marc.c.dionne@gmail.com>
Fri, 22 Apr 2011 19:23:27 +0000 (15:23 -0400)
committerDerrick Brashear <shadow@dementia.org>
Tue, 26 Apr 2011 14:33:11 +0000 (07:33 -0700)
Code that called directly into the aio operations (ex: readv/writev)
would bypass the AFS specific operations found in afs_linux_read
and afs_linux_write.

Rework the handlers:
- For newer kernels with aio, let the kernel use its default read
and write operations, and define the aio_read and aio_write operations,
with the AFS specific bits, calling into generic_file_aio_read/write.
The kernels default read/write operations are just wrappers around the
aio versions.
- For older kernels, leave things as is, pointing read and write to
afs_linux_read/write

Change-Id: I2a12c6716dc1974683c2582eb9ada5f841067dd9
Reviewed-on: http://gerrit.openafs.org/4563
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/afs/LINUX/osi_vnodeops.c
src/afs/afs_trace.et

index 796c805..2b02f55 100644 (file)
@@ -97,6 +97,36 @@ afs_linux_VerifyVCache(struct vcache *avc, cred_t **retcred) {
     return afs_convert_code(code);
 }
 
+#ifdef HAVE_LINUX_GENERIC_FILE_AIO_READ
+static ssize_t
+afs_linux_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long segs, loff_t pos)
+{
+    struct file *fp = iocb->ki_filp;
+    ssize_t code = 0;
+    struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
+
+    AFS_GLOCK();
+    afs_Trace4(afs_iclSetp, CM_TRACE_AIOREADOP, ICL_TYPE_POINTER, vcp,
+              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(pos), ICL_TYPE_INT32, segs, ICL_TYPE_INT32,
+              99999);
+    code = afs_linux_VerifyVCache(vcp, NULL);
+
+    if (code == 0) {
+       /* Linux's FlushPages implementation doesn't ever use credp,
+        * so we optimise by not using it */
+       osi_FlushPages(vcp, NULL);      /* ensure stale pages are gone */
+       AFS_GUNLOCK();
+       code = generic_file_aio_read(iocb, iov, segs, pos);
+       AFS_GLOCK();
+    }
+
+    afs_Trace4(afs_iclSetp, CM_TRACE_AIOREADOP, ICL_TYPE_POINTER, vcp,
+              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(pos), ICL_TYPE_INT32, segs, ICL_TYPE_INT32,
+              code);
+    AFS_GUNLOCK();
+    return code;
+}
+#else
 static ssize_t
 afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
 {
@@ -124,12 +154,56 @@ afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
     AFS_GUNLOCK();
     return code;
 }
+#endif
 
 
-/* Now we have integrated VM for writes as well as reads. generic_file_write
- * also takes care of re-positioning the pointer if file is open in append
+/* Now we have integrated VM for writes as well as reads. the generic write operations
+ * also take care of re-positioning the pointer if file is open in append
  * mode. Call fake open/close to ensure we do writes of core dumps.
  */
+#ifdef HAVE_LINUX_GENERIC_FILE_AIO_READ
+static ssize_t
+afs_linux_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long segs, loff_t pos)
+{
+    ssize_t code = 0;
+    struct vcache *vcp = VTOAFS(iocb->ki_filp->f_dentry->d_inode);
+    cred_t *credp;
+
+    AFS_GLOCK();
+
+    afs_Trace4(afs_iclSetp, CM_TRACE_AIOWRITEOP, ICL_TYPE_POINTER, vcp,
+              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(pos), ICL_TYPE_INT32, segs, ICL_TYPE_INT32,
+              (iocb->ki_filp->f_flags & O_APPEND) ? 99998 : 99999);
+
+    code = afs_linux_VerifyVCache(vcp, &credp);
+
+    ObtainWriteLock(&vcp->lock, 529);
+    afs_FakeOpen(vcp);
+    ReleaseWriteLock(&vcp->lock);
+    if (code == 0) {
+           AFS_GUNLOCK();
+           code = generic_file_aio_write(iocb, iov, segs, pos);
+           AFS_GLOCK();
+    }
+
+    ObtainWriteLock(&vcp->lock, 530);
+
+    if (vcp->execsOrWriters == 1 && !credp)
+      credp = crref();
+
+    afs_FakeClose(vcp, credp);
+    ReleaseWriteLock(&vcp->lock);
+
+    afs_Trace4(afs_iclSetp, CM_TRACE_AIOWRITEOP, ICL_TYPE_POINTER, vcp,
+              ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(pos), ICL_TYPE_INT32, segs, ICL_TYPE_INT32,
+              code);
+
+    if (credp)
+      crfree(credp);
+    AFS_GUNLOCK();
+    return code;
+}
+#else
 static ssize_t
 afs_linux_write(struct file *fp, const char *buf, size_t count, loff_t * offp)
 {
@@ -171,6 +245,7 @@ afs_linux_write(struct file *fp, const char *buf, size_t count, loff_t * offp)
     AFS_GUNLOCK();
     return code;
 }
+#endif
 
 extern int BlobScan(struct dcache * afile, afs_int32 ablob);
 
@@ -656,11 +731,12 @@ struct file_operations afs_dir_fops = {
 };
 
 struct file_operations afs_file_fops = {
+#ifdef HAVE_LINUX_GENERIC_FILE_AIO_READ
+  .aio_read =  afs_linux_aio_read,
+  .aio_write = afs_linux_aio_write,
+#else
   .read =      afs_linux_read,
   .write =     afs_linux_write,
-#ifdef HAVE_LINUX_GENERIC_FILE_AIO_READ
-  .aio_read =  generic_file_aio_read,
-  .aio_write = generic_file_aio_write,
 #endif
 #ifdef HAVE_UNLOCKED_IOCTL
   .unlocked_ioctl = afs_unlocked_xioctl,
index 5e9dbd3..c86ae15 100644 (file)
@@ -173,5 +173,7 @@ error_table 2 ZCM
        ec      CM_TRACE_WRITEFAILED, "osi_Write failed len %ld resid %ld err %ld"
        ec      CM_TRACE_ADJUSTSIZE2, "AdjustSize dc = 0x%lx, chunkBytes = 0x%x used = %ld, diff = %ld"
        ec      CM_TRACE_AFSDB, "AFSDB lookup %s returned %d"
+       ec      CM_TRACE_AIOREADOP, "Iaioread ip x%lx pos (0x%x, 0x%x) segs 0x%x code %x"
+       ec      CM_TRACE_AIOWRITEOP, "Iaiowrite ip x%lx pos (0x%x, 0x%x) segs 0x%x code %x"
 end