From 9b2048c26b2579f2de40a185dc56261dd98e7ea3 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 9 Nov 2010 11:15:32 -0800 Subject: [PATCH] Linux 2.6.36 compat, fs_struct->lock type change In the linux-2.6.36 kernel the fs_struct lock was changed from a rwlock_t to a spinlock_t. If the kernel would export the set_fs_pwd() symbol by default this would not have caused us any issues, but they don't. So we're forced to add a new autoconf check which sets the HAVE_FS_STRUCT_SPINLOCK define when a spinlock_t is used. We can then correctly use either spin_lock or write_lock in our custom set_fs_pwd() implementation. --- config/spl-build.m4 | 23 +++++++ configure | 134 +++++++++++++++++++++++++++++++++++++++++ module/spl/spl-vnode.c | 28 ++++++--- spl_config.h.in | 3 + 4 files changed, 178 insertions(+), 10 deletions(-) diff --git a/config/spl-build.m4 b/config/spl-build.m4 index ec7bda7..c18db70 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -66,6 +66,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ SPL_AC_2ARGS_SET_FS_PWD SPL_AC_2ARGS_VFS_UNLINK SPL_AC_4ARGS_VFS_RENAME + SPL_AC_FS_STRUCT_SPINLOCK SPL_AC_CRED_STRUCT SPL_AC_GROUPS_SEARCH SPL_AC_PUT_TASK_STRUCT @@ -1547,6 +1548,28 @@ AC_DEFUN([SPL_AC_4ARGS_VFS_RENAME], ]) ]) +dnl # +dnl # 2.6.36 API change, +dnl # The 'struct fs_struct->lock' was changed from a rwlock_t to +dnl # a spinlock_t to improve the fastpath performance. +dnl # +AC_DEFUN([SPL_AC_FS_STRUCT_SPINLOCK], [ + AC_MSG_CHECKING([whether struct fs_struct uses spinlock_t]) + SPL_LINUX_TRY_COMPILE([ + #include + #include + ],[ + struct fs_struct fs; + spin_lock_init(&fs.lock); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_FS_STRUCT_SPINLOCK, 1, + [struct fs_struct uses spinlock_t]) + ],[ + AC_MSG_RESULT(no) + ]) +]) + dnl # dnl # 2.6.29 API change, dnl # check whether 'struct cred' exists diff --git a/configure b/configure index 1a3b376..189f0f9 100755 --- a/configure +++ b/configure @@ -14903,6 +14903,73 @@ fi + { $as_echo "$as_me:$LINENO: checking whether struct fs_struct uses spinlock_t" >&5 +$as_echo_n "checking whether struct fs_struct uses spinlock_t... " >&6; } + + +cat confdefs.h - <<_ACEOF >conftest.c +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + + #include + #include + +int +main (void) +{ + + struct fs_struct fs; + spin_lock_init(&fs.lock); + + ; + return 0; +} + +_ACEOF + + + rm -Rf build && mkdir -p build + echo "obj-m := conftest.o" >build/Makefile + if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FS_STRUCT_SPINLOCK 1 +_ACEOF + + +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + + + +fi + + rm -Rf build + + + + { $as_echo "$as_me:$LINENO: checking whether struct cred exists" >&5 $as_echo_n "checking whether struct cred exists... " >&6; } @@ -18525,6 +18592,73 @@ fi + { $as_echo "$as_me:$LINENO: checking whether struct fs_struct uses spinlock_t" >&5 +$as_echo_n "checking whether struct fs_struct uses spinlock_t... " >&6; } + + +cat confdefs.h - <<_ACEOF >conftest.c +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + + #include + #include + +int +main (void) +{ + + struct fs_struct fs; + spin_lock_init(&fs.lock); + + ; + return 0; +} + +_ACEOF + + + rm -Rf build && mkdir -p build + echo "obj-m := conftest.o" >build/Makefile + if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FS_STRUCT_SPINLOCK 1 +_ACEOF + + +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + + + +fi + + rm -Rf build + + + + { $as_echo "$as_me:$LINENO: checking whether struct cred exists" >&5 $as_echo_n "checking whether struct cred exists... " >&6; } diff --git a/module/spl/spl-vnode.c b/module/spl/spl-vnode.c index 29028c3..5c64f05 100644 --- a/module/spl/spl-vnode.c +++ b/module/spl/spl-vnode.c @@ -617,16 +617,24 @@ EXPORT_SYMBOL(releasef); void set_fs_pwd(struct fs_struct *fs, struct path *path) { - struct path old_pwd; - - write_lock(&fs->lock); - old_pwd = fs->pwd; - fs->pwd = *path; - path_get(path); - write_unlock(&fs->lock); - - if (old_pwd.dentry) - path_put(&old_pwd); + struct path old_pwd; + +# ifdef HAVE_FS_STRUCT_SPINLOCK + spin_lock(&fs->lock); + old_pwd = fs->pwd; + fs->pwd = *path; + path_get(path); + spin_unlock(&fs->lock); +# else + write_lock(&fs->lock); + old_pwd = fs->pwd; + fs->pwd = *path; + path_get(path); + write_unlock(&fs->lock); +# endif /* HAVE_FS_STRUCT_SPINLOCK */ + + if (old_pwd.dentry) + path_put(&old_pwd); } # else /* Used from 2.6.11 - 2.6.24 */ diff --git a/spl_config.h.in b/spl_config.h.in index 2a08694..7863f7b 100644 --- a/spl_config.h.in +++ b/spl_config.h.in @@ -78,6 +78,9 @@ /* fls64() is available */ #undef HAVE_FLS64 +/* struct fs_struct uses spinlock_t */ +#undef HAVE_FS_STRUCT_SPINLOCK + /* get_vmalloc_info() is available */ #undef HAVE_GET_VMALLOC_INFO -- 2.40.0