]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Linux: cleanup aio support
authorMarc Dionne <marc.c.dionne@gmail.com>
Fri, 22 Apr 2011 19:23:27 +0000 (15:23 -0400)
committerStephan Wiesand <stephan.wiesand@desy.de>
Wed, 3 Apr 2013 12:43:54 +0000 (05:43 -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

Reviewed-on: http://gerrit.openafs.org/4563
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit a8c46e5010c0b4e41ad66458b8723e32f99b427d)

Change-Id: I3c20064cc911aabfce576178c22fcdc1a99b8125
Reviewed-on: http://gerrit.openafs.org/9492
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
src/afs/LINUX/osi_vnodeops.c
src/afs/afs_trace.et

index 8e7dfe2c40e535286e31c6ea6d5ec5a68b0dbf8a..2d982880c08505352d4be5d12fe3b404678415f2 100644 (file)
@@ -96,6 +96,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)
 {
@@ -123,12 +153,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)
 {
@@ -170,6 +244,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);
 
@@ -663,11 +738,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 5e9dbd37cf6b2390eb8f6bd27e59059d23064fed..c86ae155be86618a9e1b9391a93420259a07ef16 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