Skip to content

Commit

Permalink
Linux 3.1 compat, kern_path_parent()
Browse files Browse the repository at this point in the history
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 <[email protected]>
Issue #52
  • Loading branch information
behlendorf committed Nov 10, 2011
1 parent b8b6e4c commit 12ff95f
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 19 deletions.
47 changes: 44 additions & 3 deletions config/spl-build.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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
])
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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])],
[])
])
Expand Down
64 changes: 60 additions & 4 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -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:]]' \
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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:]]' \
Expand All @@ -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
Expand All @@ -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
Expand Down
14 changes: 10 additions & 4 deletions include/linux/file_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

5 changes: 3 additions & 2 deletions include/sys/vnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions module/spl/spl-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
Expand Down Expand Up @@ -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);
Expand All @@ -606,7 +609,7 @@ __init spl_init(void)
out7:
proc_fini();
out6:
vn_fini();
spl_vn_fini();
out5:
spl_taskq_fini();
out4:
Expand Down Expand Up @@ -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();
Expand Down
27 changes: 25 additions & 2 deletions module/spl/spl-vnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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",
Expand All @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion spl_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@
#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
Expand Down

0 comments on commit 12ff95f

Please sign in to comment.