From 9b0f9079d22f5a13903d3da4d94e8e306cfa40dd Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Mon, 18 Apr 2011 13:47:43 -0700 Subject: [PATCH] Linux 2.6.39 compat, invalidate_inodes() To resolve a potiential filesystem corruption issue a second argument was added to invalidate_inodes(). This argument controls whether dirty inodes are dropped or treated as busy when invalidating a super block. When only the legacy API is available the second argument will be dropped for compatibility. --- config/spl-build.m4 | 31 +++++++++ configure | 128 ++++++++++++++++++++++++++++++++++++++ include/linux/mm_compat.h | 20 +++++- module/spl/spl-kmem.c | 2 +- spl_config.h.in | 3 + 5 files changed, 181 insertions(+), 3 deletions(-) diff --git a/config/spl-build.m4 b/config/spl-build.m4 index 94c7f3e..84fbb8b 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -76,6 +76,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ SPL_AC_3ARGS_FILE_FSYNC SPL_AC_EXPORTED_RWSEM_IS_LOCKED SPL_AC_KERNEL_INVALIDATE_INODES + SPL_AC_KERNEL_2ARGS_INVALIDATE_INODES SPL_AC_SHRINK_DCACHE_MEMORY SPL_AC_SHRINK_ICACHE_MEMORY ]) @@ -1720,6 +1721,36 @@ AC_DEFUN([SPL_AC_KERNEL_INVALIDATE_INODES], [ []) ]) +dnl # +dnl # 2.6.39 API compat, +dnl # The function invalidate_inodes() now take 2 arguments. The second +dnl # 'kill_dirty' argument describes how invalidate_inodes() should +dnl # handle dirty inodes. Only when set will dirty inodes be discarded, +dnl # otherwise they will be handled as busy. +dnl # +dnl # Unfortunately, we don't have access to the invalidate_inodes() +dnl # prototype so it's not easy to check how many arguments it takes. +dnl # However, this change was done for the benefit of invalidate_device() +dnl # which also added an argument. The invalidate_device() symbol does +dnl # exist in the development headers so if it takes two arguments we +dnl # can fairly safely infer that invalidate_inodes() takes two arguments +dnl # as well. See commit 93b270f76e7ef3b81001576860c2701931cdc78b. +dnl # +AC_DEFUN([SPL_AC_KERNEL_2ARGS_INVALIDATE_INODES], + [AC_MSG_CHECKING([whether invalidate_inodes() wants 2 args]) + SPL_LINUX_TRY_COMPILE([ + #include + ],[ + return __invalidate_device(NULL, 0); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_2ARGS_INVALIDATE_INODES, 1, + [invalidate_inodes() wants 2 args]) + ],[ + AC_MSG_RESULT(no) + ]) +]) + dnl # dnl # 2.6.xx API compat, dnl # There currently exists no exposed API to partially shrink the dcache. diff --git a/configure b/configure index 317ab8e..f8dbd64 100755 --- a/configure +++ b/configure @@ -15462,6 +15462,70 @@ _ACEOF fi + { $as_echo "$as_me:$LINENO: checking whether invalidate_inodes() wants 2 args" >&5 +$as_echo_n "checking whether invalidate_inodes() wants 2 args... " >&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 + +int +main (void) +{ + + return __invalidate_device(NULL, 0); + + ; + 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_2ARGS_INVALIDATE_INODES 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 symbol shrink_dcache_memory is exported" >&5 $as_echo_n "checking whether symbol shrink_dcache_memory is exported... " >&6; } @@ -19366,6 +19430,70 @@ _ACEOF fi + { $as_echo "$as_me:$LINENO: checking whether invalidate_inodes() wants 2 args" >&5 +$as_echo_n "checking whether invalidate_inodes() wants 2 args... " >&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 + +int +main (void) +{ + + return __invalidate_device(NULL, 0); + + ; + 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_2ARGS_INVALIDATE_INODES 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 symbol shrink_dcache_memory is exported" >&5 $as_echo_n "checking whether symbol shrink_dcache_memory is exported... " >&6; } diff --git a/include/linux/mm_compat.h b/include/linux/mm_compat.h index 522db82..07231c9 100644 --- a/include/linux/mm_compat.h +++ b/include/linux/mm_compat.h @@ -49,11 +49,27 @@ * The function invalidate_inodes() is no longer exported by the kernel. * The prototype however is still available which means it is safe * to acquire the symbol's address using spl_kallsyms_lookup_name(). + * + * 2.6.39 API compat, + * As for 2.6.39 invalidate_inodes() was updated to take a second + * argument which controls how dirty inodes should be handled. */ -#ifndef HAVE_INVALIDATE_INODES +#ifdef HAVE_INVALIDATE_INODES +# ifdef HAVE_2ARGS_INVALIDATE_INODES +# define spl_invalidate_inodes(sb, kd) invalidate_inodes(sb, kd) +# else +# define spl_invalidate_inodes(sb, kd) invalidate_inodes(sb) +# endif /* HAVE_2ARGS_INVALIDATE_INODES */ +#else +# ifdef HAVE_2ARGS_INVALIDATE_INODES +typedef int (*invalidate_inodes_t)(struct super_block *sb, bool kd); +extern invalidate_inodes_t invalidate_inodes_fn; +# define spl_invalidate_inodes(sb, kd) invalidate_inodes_fn(sb, kd) +# else typedef int (*invalidate_inodes_t)(struct super_block *sb); extern invalidate_inodes_t invalidate_inodes_fn; -#define invalidate_inodes(sb) invalidate_inodes_fn(sb) +# define spl_invalidate_inodes(sb, kd) invalidate_inodes_fn(sb) +# endif /* HAVE_2ARGS_INVALIDATE_INODES */ #endif /* HAVE_INVALIDATE_INODES */ /* diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c index d96456c..e7fc5f2 100644 --- a/module/spl/spl-kmem.c +++ b/module/spl/spl-kmem.c @@ -2105,7 +2105,7 @@ spl_kmem_init_kallsyms_lookup(void) #ifndef HAVE_INVALIDATE_INODES invalidate_inodes_fn = (invalidate_inodes_t) - spl_kallsyms_lookup_name("invalidate_inodes"); + spl_kallsyms_lookup_name("invalidate_inodes"); if (!invalidate_inodes_fn) { printk(KERN_ERR "Error: Unknown symbol invalidate_inodes\n"); return -EFAULT; diff --git a/spl_config.h.in b/spl_config.h.in index 284b9b1..afa1535 100644 --- a/spl_config.h.in +++ b/spl_config.h.in @@ -9,6 +9,9 @@ /* Define to 1 to enable detailed kmem tracking */ #undef DEBUG_KMEM_TRACKING +/* invalidate_inodes() wants 2 args */ +#undef HAVE_2ARGS_INVALIDATE_INODES + /* register_sysctl_table() wants 2 args */ #undef HAVE_2ARGS_REGISTER_SYSCTL -- 2.39.2