From 1d38a73cb31e44fdbd71f8d90635514936ec1b28 Mon Sep 17 00:00:00 2001 From: Marc Dionne Date: Fri, 22 Apr 2011 15:23:27 -0400 Subject: [PATCH] Linux: cleanup aio support 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 Tested-by: BuildBot (cherry picked from commit a8c46e5010c0b4e41ad66458b8723e32f99b427d) Change-Id: I3c20064cc911aabfce576178c22fcdc1a99b8125 Reviewed-on: http://gerrit.openafs.org/9492 Reviewed-by: Andrew Deason Reviewed-by: Derrick Brashear Reviewed-by: Stephan Wiesand Tested-by: BuildBot --- src/afs/LINUX/osi_vnodeops.c | 86 +++++++++++++++++++++++++++++++++--- src/afs/afs_trace.et | 2 + 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 8e7dfe2c4..2d982880c 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -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, diff --git a/src/afs/afs_trace.et b/src/afs/afs_trace.et index 5e9dbd37c..c86ae155b 100644 --- a/src/afs/afs_trace.et +++ b/src/afs/afs_trace.et @@ -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 -- 2.39.5