]> granicus.if.org Git - spl/commitdiff
Linux 3.1 compat, kern_path_parent()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 9 Nov 2011 20:29:51 +0000 (12:29 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 10 Nov 2011 00:51:25 +0000 (16:51 -0800)
Prior to Linux 3.1 the kern_path_parent symbol was exported for
use by kernel modules.  As of Linux 3.1 it is now longer easily
available.  To handle this case the spl will now dynamically
look up address of the missing symbol at module load time.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #52

config/spl-build.m4
configure
include/linux/file_compat.h
include/sys/vnode.h
module/spl/spl-generic.c
module/spl/spl-vnode.c
spl_config.h.in

index c046db830c54af3faa138470eaf03e2a48a9b733..f5696b943e2a52f1672860a8b40ce6eb03602465 100644 (file)
@@ -80,7 +80,8 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        SPL_AC_KERNEL_2ARGS_INVALIDATE_INODES
        SPL_AC_SHRINK_DCACHE_MEMORY
        SPL_AC_SHRINK_ICACHE_MEMORY
-       SPL_AC_KERN_PATH_PARENT
+       SPL_AC_KERN_PATH_PARENT_HEADER
+       SPL_AC_KERN_PATH_PARENT_SYMBOL
        SPL_AC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
        SPL_AC_SHRINK_CONTROL_STRUCT
 ])
@@ -587,6 +588,30 @@ AC_DEFUN([SPL_CHECK_SYMBOL_EXPORT],
        fi
 ])
 
+dnl #
+dnl # SPL_CHECK_SYMBOL_HEADER
+dnl # check if a symbol prototype is defined in listed headers.
+dnl #
+AC_DEFUN([SPL_CHECK_SYMBOL_HEADER], [
+       AC_MSG_CHECKING([whether symbol $1 exists in header])
+       header=0
+       for file in $3; do
+               grep -q "$2" "$LINUX/$file" 2>/dev/null
+               rc=$?
+               if test $rc -eq 0; then
+                       header=1
+                       break;
+               fi
+       done
+       if test $header -eq 0; then
+               AC_MSG_RESULT([no])
+               $5
+       else
+               AC_MSG_RESULT([yes])
+               $4
+       fi
+])
+
 dnl #
 dnl # SPL_CHECK_HEADER
 dnl # check whether header exists and define HAVE_$2_HEADER
@@ -1809,11 +1834,27 @@ dnl # and the flags argument has been removed.  The only behavior now
 dnl # offered is that of LOOKUP_PARENT.  The spl already always passed
 dnl # this flag so dropping the flag does not impact us.
 dnl #
-AC_DEFUN([SPL_AC_KERN_PATH_PARENT], [
+AC_DEFUN([SPL_AC_KERN_PATH_PARENT_HEADER], [
+       SPL_CHECK_SYMBOL_HEADER(
+               [kern_path_parent],
+               [int kern_path_parent(const char \*, struct nameidata \*)],
+               [include/linux/namei.h],
+               [AC_DEFINE(HAVE_KERN_PATH_PARENT_HEADER, 1,
+               [kern_path_parent() is available])],
+               [])
+])
+
+dnl #
+dnl # 3.1 API compat,
+dnl # The kern_path_parent() symbol is no longer exported by the kernel.
+dnl # However, it remains the prefered interface and since we still have
+dnl # access to the prototype we dynamically lookup the required address.
+dnl #
+AC_DEFUN([SPL_AC_KERN_PATH_PARENT_SYMBOL], [
        SPL_CHECK_SYMBOL_EXPORT(
                [kern_path_parent],
                [fs/namei.c],
-               [AC_DEFINE(HAVE_KERN_PATH_PARENT, 1,
+               [AC_DEFINE(HAVE_KERN_PATH_PARENT_SYMBOL, 1,
                [kern_path_parent() is available])],
                [])
 ])
index 1369ca05d96fc64dc243f3efd2cea07a455dfce7..beeb6d59d6e552c4566bff22df772fcb482887d3 100755 (executable)
--- a/configure
+++ b/configure
@@ -15684,6 +15684,34 @@ _ACEOF
 
 
 
+
+       { $as_echo "$as_me:$LINENO: checking whether symbol kern_path_parent exists in header" >&5
+$as_echo_n "checking whether symbol kern_path_parent exists in header... " >&6; }
+       header=0
+       for file in include/linux/namei.h; do
+               grep -q "int kern_path_parent(const char \*, struct nameidata \*)" "$LINUX/$file" 2>/dev/null
+               rc=$?
+               if test $rc -eq 0; then
+                       header=1
+                       break;
+               fi
+       done
+       if test $header -eq 0; then
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+       else
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_KERN_PATH_PARENT_HEADER 1
+_ACEOF
+
+       fi
+
+
+
        { $as_echo "$as_me:$LINENO: checking whether symbol kern_path_parent is exported" >&5
 $as_echo_n "checking whether symbol kern_path_parent is exported... " >&6; }
        grep -q -E '[[:space:]]kern_path_parent[[:space:]]' \
@@ -15709,7 +15737,7 @@ $as_echo "no" >&6; }
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_KERN_PATH_PARENT 1
+#define HAVE_KERN_PATH_PARENT_SYMBOL 1
 _ACEOF
 
                fi
@@ -15718,7 +15746,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_KERN_PATH_PARENT 1
+#define HAVE_KERN_PATH_PARENT_SYMBOL 1
 _ACEOF
 
        fi
@@ -19885,6 +19913,34 @@ _ACEOF
 
 
 
+
+       { $as_echo "$as_me:$LINENO: checking whether symbol kern_path_parent exists in header" >&5
+$as_echo_n "checking whether symbol kern_path_parent exists in header... " >&6; }
+       header=0
+       for file in include/linux/namei.h; do
+               grep -q "int kern_path_parent(const char \*, struct nameidata \*)" "$LINUX/$file" 2>/dev/null
+               rc=$?
+               if test $rc -eq 0; then
+                       header=1
+                       break;
+               fi
+       done
+       if test $header -eq 0; then
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+       else
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_KERN_PATH_PARENT_HEADER 1
+_ACEOF
+
+       fi
+
+
+
        { $as_echo "$as_me:$LINENO: checking whether symbol kern_path_parent is exported" >&5
 $as_echo_n "checking whether symbol kern_path_parent is exported... " >&6; }
        grep -q -E '[[:space:]]kern_path_parent[[:space:]]' \
@@ -19910,7 +19966,7 @@ $as_echo "no" >&6; }
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_KERN_PATH_PARENT 1
+#define HAVE_KERN_PATH_PARENT_SYMBOL 1
 _ACEOF
 
                fi
@@ -19919,7 +19975,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_KERN_PATH_PARENT 1
+#define HAVE_KERN_PATH_PARENT_SYMBOL 1
 _ACEOF
 
        fi
index 97bd7639610b05ac299fa3bb9d8ecbdf518f34c5..d5fb2bc608cc57268b57d7b9aca815e4cfabae9d 100644 (file)
@@ -67,11 +67,17 @@ spl_filp_open(const char *name, int flags, int mode, int *err)
 #define spl_inode_unlock(ip)           (up(&(ip)->i_sem))
 #endif /* HAVE_INODE_I_MUTEX */
 
-#ifdef HAVE_KERN_PATH_PARENT
-#define spl_kern_path_parent(path, nd) kern_path_parent(path, nd)
+#ifdef HAVE_KERN_PATH_PARENT_HEADER
+# ifndef HAVE_KERN_PATH_PARENT_SYMBOL
+typedef int (*kern_path_parent_t)(const char *, struct nameidata *);
+extern kern_path_parent_t kern_path_parent_fn;
+#  define spl_kern_path_parent(path, nd)       kern_path_parent_fn(path, nd)
+# else
+#  define spl_kern_path_parent(path, nd)       kern_path_parent(path, nd)
+# endif /* HAVE_KERN_PATH_PARENT_SYMBOL */
 #else
-#define spl_kern_path_parent(path, nd) path_lookup(path, LOOKUP_PARENT, nd)
-#endif /* HAVE_KERN_PATH_PARENT */
+# define spl_kern_path_parent(path, nd)        path_lookup(path, LOOKUP_PARENT, nd)
+#endif /* HAVE_KERN_PATH_PARENT_HEADER */
 
 #endif /* SPL_FILE_COMPAT_H */
 
index 36605ca4a56287830838769ae3a2c3cf9dd939da..03462bd7091a7a4b196bb69e31abe24778783798 100644 (file)
@@ -189,8 +189,9 @@ extern file_t *vn_getf(int fd);
 extern void vn_releasef(int fd);
 extern int vn_set_pwd(const char *filename);
 
-int vn_init(void);
-void vn_fini(void);
+int spl_vn_init_kallsyms_lookup(void);
+int spl_vn_init(void);
+void spl_vn_fini(void);
 
 #define VOP_CLOSE                              vn_close
 #define VOP_SEEK                               vn_seek
index 1dedf76cf22cf78d6e84f540dd6f129e51b35984..3f042cc0dd8dc318998d7db3cbb5026281fbafa9 100644 (file)
@@ -561,7 +561,7 @@ __init spl_init(void)
        if ((rc = spl_taskq_init()))
                SGOTO(out4, rc);
 
-       if ((rc = vn_init()))
+       if ((rc = spl_vn_init()))
                SGOTO(out5, rc);
 
        if ((rc = proc_init()))
@@ -594,6 +594,9 @@ __init spl_init(void)
        if ((rc = spl_kmem_init_kallsyms_lookup()))
                SGOTO(out10, rc);
 
+       if ((rc = spl_vn_init_kallsyms_lookup()))
+               SGOTO(out10, rc);
+
        printk(KERN_NOTICE "SPL: Loaded module v%s%s, using hostid 0x%08x\n",
               SPL_META_VERSION, SPL_DEBUG_STR, (unsigned int) spl_hostid);
        SRETURN(rc);
@@ -606,7 +609,7 @@ out8:
 out7:
        proc_fini();
 out6:
-       vn_fini();
+       spl_vn_fini();
 out5:
        spl_taskq_fini();
 out4:
@@ -634,7 +637,7 @@ spl_fini(void)
        tsd_fini();
        kstat_fini();
        proc_fini();
-       vn_fini();
+       spl_vn_fini();
        spl_taskq_fini();
        spl_rw_fini();
        spl_mutex_fini();
index 354e8798b9709b5a1ac80d053e0afc7a1fdaff71..cd0fa2cd1eb83fbc35a5ff607645c232c2891f86 100644 (file)
@@ -42,6 +42,13 @@ static spl_kmem_cache_t *vn_file_cache;
 static DEFINE_SPINLOCK(vn_file_lock);
 static LIST_HEAD(vn_file_list);
 
+#ifdef HAVE_KERN_PATH_PARENT_HEADER
+#ifndef HAVE_KERN_PATH_PARENT_SYMBOL
+kern_path_parent_t kern_path_parent_fn = SYMBOL_POISON;
+EXPORT_SYMBOL(kern_path_parent_fn);
+#endif /* HAVE_KERN_PATH_PARENT_SYMBOL */
+#endif /* HAVE_KERN_PATH_PARENT_HEADER */
+
 vtype_t
 vn_mode_to_vtype(mode_t mode)
 {
@@ -789,8 +796,24 @@ vn_file_cache_destructor(void *buf, void *cdrarg)
        mutex_destroy(&fp->f_lock);
 } /* vn_file_cache_destructor() */
 
+int spl_vn_init_kallsyms_lookup(void)
+{
+#ifdef HAVE_KERN_PATH_PARENT_HEADER
+#ifndef HAVE_KERN_PATH_PARENT_SYMBOL
+       kern_path_parent_fn = (kern_path_parent_t)
+               spl_kallsyms_lookup_name("kern_path_parent");
+       if (!kern_path_parent_fn) {
+               printk(KERN_ERR "Error: Unknown symbol kern_path_parent\n");
+               return -EFAULT;
+       }
+#endif /* HAVE_KERN_PATH_PARENT_SYMBOL */
+#endif /* HAVE_KERN_PATH_PARENT_HEADER */
+
+       return (0);
+}
+
 int
-vn_init(void)
+spl_vn_init(void)
 {
        SENTRY;
        vn_cache = kmem_cache_create("spl_vn_cache",
@@ -808,7 +831,7 @@ vn_init(void)
 } /* vn_init() */
 
 void
-vn_fini(void)
+spl_vn_fini(void)
 {
         file_t *fp, *next_fp;
        int leaked = 0;
index 97f0e06f310d3c1f1a90dc9ac498fdfee89eaf61..612205969f1c6e77dfc0df91a2762108baedf099 100644 (file)
 #undef HAVE_KALLSYMS_LOOKUP_NAME
 
 /* kern_path_parent() is available */
-#undef HAVE_KERN_PATH_PARENT
+#undef HAVE_KERN_PATH_PARENT_HEADER
+
+/* kern_path_parent() is available */
+#undef HAVE_KERN_PATH_PARENT_SYMBOL
 
 /* kmalloc_node() is available */
 #undef HAVE_KMALLOC_NODE