From 7119bf704490bcb9abca9fa80214313024d381a2 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 1 Jul 2010 13:37:43 -0700 Subject: [PATCH] Add configure check for user_path_dir() I didn't notice at the time but user_path_dir() was not introduced at the same time as set_fs_pwd() change. I had lumped the two together but in fact user_path_dir() was introduced in 2.6.27 and set_fs_pwd() taking 2 args was introduced in 2.6.25. This means builds against 2.6.25-2.6.26 kernels were broken. To fix this I've added a check for user_path_dir() and no longer assume that if set_fs_pwd() takes 2 args then user_path_dir() is also available. --- config/spl-build.m4 | 14 ++++++++ configure | 82 ++++++++++++++++++++++++++++++++++++++++++ module/spl/spl-vnode.c | 18 +++++++++- spl_config.h.in | 3 ++ 4 files changed, 116 insertions(+), 1 deletion(-) diff --git a/config/spl-build.m4 b/config/spl-build.m4 index 3bbfd0195f..40f072bf71 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -68,6 +68,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ SPL_AC_ZONE_STAT_ITEM_INACTIVE SPL_AC_ZONE_STAT_ITEM_ACTIVE SPL_AC_GET_ZONE_COUNTS + SPL_AC_USER_PATH_DIR SPL_AC_SET_FS_PWD SPL_AC_2ARGS_SET_FS_PWD SPL_AC_2ARGS_VFS_UNLINK @@ -1298,6 +1299,19 @@ AC_DEFUN([SPL_AC_GET_ZONE_COUNTS], [ ]) ]) +dnl # +dnl # 2.6.27 API change, +dnl # The user_path_dir() replaces __user_walk() +dnl # +AC_DEFUN([SPL_AC_USER_PATH_DIR], [ + SPL_CHECK_SYMBOL_EXPORT( + [user_path_at], + [], + [AC_DEFINE(HAVE_USER_PATH_DIR, 1, + [user_path_dir() is available])], + []) +]) + dnl # dnl # Symbol available in RHEL kernels not in stock kernels. dnl # diff --git a/configure b/configure index a7ff89e264..4c5df996f4 100755 --- a/configure +++ b/configure @@ -14459,6 +14459,47 @@ fi + { $as_echo "$as_me:$LINENO: checking whether symbol user_path_at is exported" >&5 +$as_echo_n "checking whether symbol user_path_at is exported... " >&6; } + grep -q -E '[[:space:]]user_path_at[[:space:]]' \ + $LINUX_OBJ/Module*.symvers 2>/dev/null + rc=$? + if test $rc -ne 0; then + export=0 + for file in ; do + grep -q -E "EXPORT_SYMBOL.*(user_path_at)" \ + "$LINUX_OBJ/$file" 2>/dev/null + rc=$? + if test $rc -eq 0; then + export=1 + break; + fi + done + if test $export -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_USER_PATH_DIR 1 +_ACEOF + + fi + else + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_USER_PATH_DIR 1 +_ACEOF + + fi + + + { $as_echo "$as_me:$LINENO: checking whether symbol set_fs_pwd is exported" >&5 $as_echo_n "checking whether symbol set_fs_pwd is exported... " >&6; } grep -q -E '[[:space:]]set_fs_pwd[[:space:]]' \ @@ -17931,6 +17972,47 @@ fi + { $as_echo "$as_me:$LINENO: checking whether symbol user_path_at is exported" >&5 +$as_echo_n "checking whether symbol user_path_at is exported... " >&6; } + grep -q -E '[[:space:]]user_path_at[[:space:]]' \ + $LINUX_OBJ/Module*.symvers 2>/dev/null + rc=$? + if test $rc -ne 0; then + export=0 + for file in ; do + grep -q -E "EXPORT_SYMBOL.*(user_path_at)" \ + "$LINUX_OBJ/$file" 2>/dev/null + rc=$? + if test $rc -eq 0; then + export=1 + break; + fi + done + if test $export -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_USER_PATH_DIR 1 +_ACEOF + + fi + else + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_USER_PATH_DIR 1 +_ACEOF + + fi + + + { $as_echo "$as_me:$LINENO: checking whether symbol set_fs_pwd is exported" >&5 $as_echo_n "checking whether symbol set_fs_pwd is exported... " >&6; } grep -q -E '[[:space:]]set_fs_pwd[[:space:]]' \ diff --git a/module/spl/spl-vnode.c b/module/spl/spl-vnode.c index ec312aad10..b5c34fbcd0 100644 --- a/module/spl/spl-vnode.c +++ b/module/spl/spl-vnode.c @@ -648,7 +648,7 @@ set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, struct dentry *dentry) int vn_set_pwd(const char *filename) { -#ifdef HAVE_2ARGS_SET_FS_PWD +#if defined(HAVE_2ARGS_SET_FS_PWD) && defined(HAVE_USER_PATH_DIR) struct path path; #else struct nameidata nd; @@ -666,6 +666,7 @@ vn_set_pwd(const char *filename) set_fs(get_ds()); #ifdef HAVE_2ARGS_SET_FS_PWD +# ifdef HAVE_USER_PATH_DIR rc = user_path_dir(filename, &path); if (rc) GOTO(out, rc); @@ -678,6 +679,21 @@ vn_set_pwd(const char *filename) dput_and_out: path_put(&path); +# else + rc = __user_walk(filename, + LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd); + if (rc) + GOTO(out, rc); + + rc = vfs_permission(&nd, MAY_EXEC); + if (rc) + GOTO(dput_and_out, rc); + + set_fs_pwd(current->fs, &nd.path); + +dput_and_out: + path_put(&nd.path); +# endif /* HAVE_USER_PATH_DIR */ #else rc = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd); diff --git a/spl_config.h.in b/spl_config.h.in index a22ca7b8b9..48b610b320 100644 --- a/spl_config.h.in +++ b/spl_config.h.in @@ -183,6 +183,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* user_path_dir() is available */ +#undef HAVE_USER_PATH_DIR + /* Page state NR_ACTIVE is available */ #undef HAVE_ZONE_STAT_ITEM_NR_ACTIVE