From 29ef9bb31f31c371272ee9b2860729af2277ab95 Mon Sep 17 00:00:00 2001
From: Marc Dionne <marc.c.dionne@gmail.com>
Date: Fri, 28 Jan 2011 19:41:32 -0500
Subject: [PATCH 4/8] Linux: 2.6.38: Adjust for permission inode operation changes

The permission i_op has a new signature with a flags argument, and
must now deal with RCU path walking.
- Fix existing configure test for this i_op, it succeeds when it
shouldn't
- Add a new configure test for the new signature
- Make our permission i_op "RCU-walk aware" - return ECHILD if
called in that mode

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

Change-Id: I38db16f0f62500f46fad9c92d045ccfa6cfe1c38
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
Reviewed-on: http://gerrit.openafs.org/3997
Reviewed-by: Simon Wilkinson <sxw@inf.ed.ac.uk>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Russ Allbery <rra@stanford.edu>
Reviewed-on: http://gerrit.openafs.org/4040
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
---
 acinclude.m4                 |    1 +
 src/afs/LINUX/osi_vnodeops.c |   13 +++++++++++--
 src/cf/linux-test4.m4        |   16 ++++++++++++++--
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/acinclude.m4 b/acinclude.m4
index 60c47d1..de82283 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -768,6 +768,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
 	  	 LINUX_WRITE_INODE_RETURN_TYPE
 	  	 LINUX_IOP_I_CREATE_TAKES_NAMEIDATA
 	  	 LINUX_IOP_I_LOOKUP_TAKES_NAMEIDATA
+		 LINUX_IOP_I_PERMISSION_TAKES_FLAGS
 	  	 LINUX_IOP_I_PERMISSION_TAKES_NAMEIDATA
 	  	 LINUX_IOP_I_PUT_LINK_TAKES_COOKIE
 	  	 LINUX_DOP_D_REVALIDATE_TAKES_NAMEIDATA
diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
index 2389389..8352769 100644
--- a/src/afs/LINUX/osi_vnodeops.c
+++ b/src/afs/LINUX/osi_vnodeops.c
@@ -1786,16 +1786,25 @@ afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
  * Check access rights - returns error if can't check or permission denied.
  */
 static int
-#ifdef IOP_PERMISSION_TAKES_NAMEIDATA
+#if defined(IOP_PERMISSION_TAKES_FLAGS)
+afs_linux_permission(struct inode *ip, int mode, unsigned int flags)
+#elif defined(IOP_PERMISSION_TAKES_NAMEIDATA)
 afs_linux_permission(struct inode *ip, int mode, struct nameidata *nd)
 #else
 afs_linux_permission(struct inode *ip, int mode)
 #endif
 {
     int code;
-    cred_t *credp = crref();
+    cred_t *credp;
     int tmp = 0;
 
+#if defined(IOP_PERMISSION_TAKES_FLAGS)
+    /* We don't support RCU path walking */
+    if (flags & IPERM_FLAG_RCU)
+       return -ECHILD;
+#endif
+
+    credp = crref();
     AFS_GLOCK();
     if (mode & MAY_EXEC)
 	tmp |= VEXEC;
diff --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4
index 67ddf91..88e4863 100644
--- a/src/cf/linux-test4.m4
+++ b/src/cf/linux-test4.m4
@@ -680,12 +680,24 @@ AC_DEFUN([LINUX_IOP_I_PERMISSION_TAKES_NAMEIDATA], [
 [#include <linux/fs.h>
 #include <linux/namei.h>],
 [struct inode _inode;
-struct dentry _dentry;
 struct nameidata _nameidata;
 (void)_inode.i_op->permission(&_inode, 0, &_nameidata);],
 		       [IOP_PERMISSION_TAKES_NAMEIDATA],
 		       [define if your iops.permission takes a nameidata argument],
-		       [])
+		       [-Werror])
+])
+
+
+AC_DEFUN([LINUX_IOP_I_PERMISSION_TAKES_FLAGS], [
+  AC_CHECK_LINUX_BUILD([whether inode_operations.permission takes flags],
+			[ac_cv_linux_func_i_permission_takes_flags],
+			[#include <linux/fs.h>],
+			[struct inode _inode;
+			unsigned int flags = 0;
+			(void)_inode.i_op->permission(&_inode, 0, flags);],
+		       [IOP_PERMISSION_TAKES_FLAGS],
+		       [define if your iops.permission takes a flags argument],
+		       [-Werror])
 ])
 
 
-- 
1.7.3.4

