Linux: Don't roll our own llseek
authorSimon Wilkinson <sxw@inf.ed.ac.uk>
Fri, 23 Apr 2010 14:07:58 +0000 (15:07 +0100)
committerDerrick Brashear <shadow@dementia.org>
Mon, 26 Apr 2010 04:04:13 +0000 (21:04 -0700)
llseek is a little more complex than just setting the pos field of
the file structure.

Where vfs_llseek is available to us (it has been since 2.6.8) use that
directly. If vfs_llseek isn't available, then use either the
filesystem's llseek method, or default_llseek (available since 2.6.0),
to ensure we get the proper locking.

Change-Id: I26bcbff984c7164be1724eee7a46cbe6e02bc510
Reviewed-on: http://gerrit.openafs.org/1816
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

acinclude.m4
src/afs/LINUX/osi_compat.h
src/afs/LINUX/osi_file.c
src/cf/linux-test4.m4

index 80cb33a..14f10e8 100644 (file)
@@ -815,6 +815,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 LINUX_HAVE_SPLICE_DIRECT_TO_ACTOR
                 LINUX_HAVE_PAGE_OFFSET
                 LINUX_HAVE_ZERO_USER_SEGMENTS
+                LINUX_HAVE_VFS_LLSEEK
                  LINUX_STRUCT_TASK_HAS_CRED
                 LINUX_STRUCT_PROC_DIR_ENTRY_HAS_OWNER
                 LINUX_HAVE_KMEM_CACHE_T
index 0b52019..e507e6b 100644 (file)
@@ -230,3 +230,12 @@ zero_user_segments(struct page *pp, unsigned int from1, unsigned int to1,
 }
 #endif
 
+#ifndef HAVE_VFS_LLSEEK
+static inline loff_t
+vfs_llseek(struct file *filp, loff_t offset, int origin) {
+    if (filp->f_op->llseek)
+       return filp->f_op->llseek(filp, offset, origin);
+    return default_llseek(filp, offset, origin);
+}
+#endif
+
index f5e21d5..8b2151a 100644 (file)
@@ -387,13 +387,10 @@ osi_rdwr(struct osi_file *osifile, uio_t * uiop, int rw)
        TO_USER_SPACE();
 
     /* seek to the desired position. Return -1 on error. */
-    if (filp->f_op->llseek) {
-       if (filp->f_op->llseek(filp, (loff_t) uiop->uio_offset, 0) != uiop->uio_offset) {
-           code = -1;
-           goto out;
-       }
-    } else
-       filp->f_pos = uiop->uio_offset;
+    if (vfs_llseek(filp, (loff_t) uiop->uio_offset, 0) != uiop->uio_offset) {
+       code = -1;
+       goto out;
+    }
 
     while (code == 0 && uiop->uio_resid > 0 && uiop->uio_iovcnt > 0) {
        iov = uiop->uio_iov;
index 14cf9a6..8d0a00f 100644 (file)
@@ -1257,3 +1257,16 @@ AC_DEFUN([LINUX_HAVE_PAGE_OFFSET], [
     AC_DEFINE([HAVE_PAGE_OFFSET], 1, [define if your kernel has the page_offset function])
   fi])
 
+AC_DEFUN([LINUX_HAVE_VFS_LLSEEK], [
+  AC_MSG_CHECKING([for vfs_llseek])
+  AC_CACHE_VAL([ac_cv_linux_have_vfs_llseek], [
+    AC_TRY_KBUILD(
+[#include <linux/fs.h>],
+[vfs_llseek(NULL, 0, 0);],
+      ac_cv_linux_have_vfs_llseek=yes,
+      ac_cv_linux_have_vfs_llseek=no)])
+  AC_MSG_RESULT($ac_cv_linux_have_vfs_llseek)
+  if test "x$ac_cv_linux_have_vfs_llseek" = "xyes"; then
+    AC_DEFINE([HAVE_VFS_LLSEEK], 1, [define if your kernel has the vfs_llseek function])
+  fi])
+