summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/spl-build.m438
-rwxr-xr-xconfigure57
-rw-r--r--configure.ac2
-rw-r--r--include/sys/vmsystm.h30
-rw-r--r--module/spl/spl-kmem.c47
-rw-r--r--spl_config.h.in6
6 files changed, 157 insertions, 23 deletions
diff --git a/config/spl-build.m4 b/config/spl-build.m4
index ce798cc74..750218941 100644
--- a/config/spl-build.m4
+++ b/config/spl-build.m4
@@ -803,6 +803,31 @@ AC_DEFUN([SPL_AC_GET_VMALLOC_INFO], [
])
dnl #
+dnl # 2.6.17 API change
+dnl # The helper functions first_online_pgdat(), next_online_pgdat(), and
+dnl # next_zone() are introduced to simplify for_each_zone(). These symbols
+dnl # were exported in 2.6.17 for use by modules which was consistent with
+dnl # the previous implementation of for_each_zone(). From 2.6.18 - 2.6.19
+dnl # the symbols were exported as 'unused', and by 2.6.20 they exports
+dnl # were dropped entirely leaving modules no way to directly iterate over
+dnl # the zone list. Because we need access to the zone helpers we check
+dnl # if the kernel contains the old or new implementation. Then we check
+dnl # to see if the symbols we need for each version are available. If they
+dnl # are not, dynamically aquire the addresses with kallsyms_lookup_name().
+dnl #
+AC_DEFUN([SPL_AC_PGDAT_HELPERS], [
+ AC_MSG_CHECKING([whether symbol *_pgdat exist])
+ grep -q -E 'first_online_pgdat' $LINUX/include/linux/mmzone.h 2>/dev/null
+ rc=$?
+ if test $rc -eq 0; then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_PGDAT_HELPERS, 1, [pgdat helpers are available])
+ else
+ AC_MSG_RESULT([no])
+ fi
+])
+
+dnl #
dnl # Proposed API change,
dnl # This symbol is not available in stock kernels. You may build a
dnl # custom kernel with the *-spl-export-symbols.patch which will export
@@ -851,6 +876,19 @@ AC_DEFUN([SPL_AC_NEXT_ZONE], [
])
dnl #
+dnl # 2.6.17 API change,
+dnl # See SPL_AC_PGDAT_HELPERS for details.
+dnl #
+AC_DEFUN([SPL_AC_PGDAT_LIST], [
+ SPL_CHECK_SYMBOL_EXPORT(
+ [pgdat_list],
+ [],
+ [AC_DEFINE(HAVE_PGDAT_LIST, 1,
+ [pgdat_list is available])],
+ [])
+])
+
+dnl #
dnl # Proposed API change,
dnl # This symbol is not available in stock kernels. You may build a
dnl # custom kernel with the *-spl-export-symbols.patch which will export
diff --git a/configure b/configure
index 8ad6e7f53..e42d7bfb9 100755
--- a/configure
+++ b/configure
@@ -20798,6 +20798,24 @@ _ACEOF
+ echo "$as_me:$LINENO: checking whether symbol *_pgdat exist" >&5
+echo $ECHO_N "checking whether symbol *_pgdat exist... $ECHO_C" >&6
+ grep -q -E 'first_online_pgdat' $LINUX/include/linux/mmzone.h 2>/dev/null
+ rc=$?
+ if test $rc -eq 0; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PGDAT_HELPERS 1
+_ACEOF
+
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ fi
+
+
echo "$as_me:$LINENO: checking whether symbol first_online_pgdat is exported" >&5
echo $ECHO_N "checking whether symbol first_online_pgdat is exported... $ECHO_C" >&6
grep -q -E '[[:space:]]first_online_pgdat[[:space:]]' $LINUX_OBJ/Module.symvers 2>/dev/null
@@ -20915,6 +20933,45 @@ _ACEOF
+ echo "$as_me:$LINENO: checking whether symbol pgdat_list is exported" >&5
+echo $ECHO_N "checking whether symbol pgdat_list is exported... $ECHO_C" >&6
+ grep -q -E '[[:space:]]pgdat_list[[: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.*(pgdat_list)" "$LINUX_OBJ/$file" 2>/dev/null
+ rc=$?
+ if test $rc -eq 0; then
+ export=1
+ break;
+ fi
+ done
+ if test $export -eq 0; then
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+ else
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PGDAT_LIST 1
+_ACEOF
+
+ fi
+ else
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PGDAT_LIST 1
+_ACEOF
+
+ fi
+
+
+
echo "$as_me:$LINENO: checking whether symbol get_zone_counts is exported" >&5
echo $ECHO_N "checking whether symbol get_zone_counts is exported... $ECHO_C" >&6
grep -q -E '[[:space:]]get_zone_counts[[:space:]]' $LINUX_OBJ/Module.symvers 2>/dev/null
diff --git a/configure.ac b/configure.ac
index a073f4297..ecad8cbd0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,9 +73,11 @@ SPL_AC_DIV64_U64
SPL_AC_3ARGS_ON_EACH_CPU
SPL_AC_KALLSYMS_LOOKUP_NAME
SPL_AC_GET_VMALLOC_INFO
+SPL_AC_PGDAT_HELPERS
SPL_AC_FIRST_ONLINE_PGDAT
SPL_AC_NEXT_ONLINE_PGDAT
SPL_AC_NEXT_ZONE
+SPL_AC_PGDAT_LIST
SPL_AC_GET_ZONE_COUNTS
SPL_AC_GLOBAL_PAGE_STATE
SPL_AC_ZONE_STAT_ITEM_FIA
diff --git a/include/sys/vmsystm.h b/include/sys/vmsystm.h
index 71058eef8..75365fde0 100644
--- a/include/sys/vmsystm.h
+++ b/include/sys/vmsystm.h
@@ -93,26 +93,34 @@ extern get_vmalloc_info_t get_vmalloc_info_fn;
#endif /* CONFIG_MMU */
#endif /* HAVE_GET_VMALLOC_INFO */
+#ifdef HAVE_PGDAT_HELPERS
/* Source linux/mm/mmzone.c */
-#ifndef HAVE_FIRST_ONLINE_PGDAT
+# ifndef HAVE_FIRST_ONLINE_PGDAT
typedef struct pglist_data *(*first_online_pgdat_t)(void);
extern first_online_pgdat_t first_online_pgdat_fn;
-#define first_online_pgdat() first_online_pgdat_fn()
-#endif /* HAVE_FIRST_ONLINE_PGDAT */
+# define first_online_pgdat() first_online_pgdat_fn()
+# endif /* HAVE_FIRST_ONLINE_PGDAT */
-/* Source linux/mm/mmzone.c */
-#ifndef HAVE_NEXT_ONLINE_PGDAT
+# ifndef HAVE_NEXT_ONLINE_PGDAT
typedef struct pglist_data *(*next_online_pgdat_t)(struct pglist_data *);
extern next_online_pgdat_t next_online_pgdat_fn;
-#define next_online_pgdat(pgd) next_online_pgdat_fn(pgd)
-#endif /* HAVE_NEXT_ONLINE_PGDAT */
+# define next_online_pgdat(pgd) next_online_pgdat_fn(pgd)
+# endif /* HAVE_NEXT_ONLINE_PGDAT */
-/* Source linux/mm/mmzone.c */
-#ifndef HAVE_NEXT_ZONE
+# ifndef HAVE_NEXT_ZONE
typedef struct zone *(*next_zone_t)(struct zone *);
extern next_zone_t next_zone_fn;
-#define next_zone(zone) next_zone_fn(zone)
-#endif /* HAVE_NEXT_ZONE */
+# define next_zone(zone) next_zone_fn(zone)
+# endif /* HAVE_NEXT_ZONE */
+
+#else /* HAVE_PGDAT_HELPERS */
+
+# ifndef HAVE_PGDAT_LIST
+extern struct pglist_data *pgdat_list_addr;
+# define pgdat_list pgdat_list_addr
+# endif /* HAVE_PGDAT_LIST */
+
+#endif /* HAVE_PGDAT_HELPERS */
/* Source linux/mm/vmstat.c */
#ifndef HAVE_ZONE_STAT_ITEM_FIA
diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c
index 706691929..4009aa3b2 100644
--- a/module/spl/spl-kmem.c
+++ b/module/spl/spl-kmem.c
@@ -84,20 +84,30 @@ get_vmalloc_info_t get_vmalloc_info_fn = SYMBOL_POISON;
EXPORT_SYMBOL(get_vmalloc_info_fn);
#endif /* HAVE_GET_VMALLOC_INFO */
-#ifndef HAVE_FIRST_ONLINE_PGDAT
+#ifdef HAVE_PGDAT_HELPERS
+# ifndef HAVE_FIRST_ONLINE_PGDAT
first_online_pgdat_t first_online_pgdat_fn = SYMBOL_POISON;
EXPORT_SYMBOL(first_online_pgdat_fn);
-#endif /* HAVE_FIRST_ONLINE_PGDAT */
+# endif /* HAVE_FIRST_ONLINE_PGDAT */
-#ifndef HAVE_NEXT_ONLINE_PGDAT
+# ifndef HAVE_NEXT_ONLINE_PGDAT
next_online_pgdat_t next_online_pgdat_fn = SYMBOL_POISON;
EXPORT_SYMBOL(next_online_pgdat_fn);
-#endif /* HAVE_NEXT_ONLINE_PGDAT */
+# endif /* HAVE_NEXT_ONLINE_PGDAT */
-#ifndef HAVE_NEXT_ZONE
+# ifndef HAVE_NEXT_ZONE
next_zone_t next_zone_fn = SYMBOL_POISON;
EXPORT_SYMBOL(next_zone_fn);
-#endif /* HAVE_NEXT_ZONE */
+# endif /* HAVE_NEXT_ZONE */
+
+#else /* HAVE_PGDAT_HELPERS */
+
+# ifndef HAVE_PGDAT_LIST
+struct pglist_data *pgdat_list_addr = SYMBOL_POISON;
+EXPORT_SYMBOL(pgdat_list_addr);
+# endif /* HAVE_PGDAT_LIST */
+
+#endif /* HAVE_PGDAT_HELPERS */
#ifndef HAVE_ZONE_STAT_ITEM_FIA
# ifndef HAVE_GET_ZONE_COUNTS
@@ -1806,32 +1816,45 @@ spl_kmem_init_kallsyms_lookup(void)
}
#endif /* HAVE_GET_VMALLOC_INFO */
-#ifndef HAVE_FIRST_ONLINE_PGDAT
+#ifdef HAVE_PGDAT_HELPERS
+# ifndef HAVE_FIRST_ONLINE_PGDAT
first_online_pgdat_fn = (first_online_pgdat_t)
spl_kallsyms_lookup_name("first_online_pgdat");
if (!first_online_pgdat_fn) {
printk(KERN_ERR "Error: Unknown symbol first_online_pgdat\n");
return -EFAULT;
}
-#endif /* HAVE_FIRST_ONLINE_PGDAT */
+# endif /* HAVE_FIRST_ONLINE_PGDAT */
-#ifndef HAVE_NEXT_ONLINE_PGDAT
+# ifndef HAVE_NEXT_ONLINE_PGDAT
next_online_pgdat_fn = (next_online_pgdat_t)
spl_kallsyms_lookup_name("next_online_pgdat");
if (!next_online_pgdat_fn) {
printk(KERN_ERR "Error: Unknown symbol next_online_pgdat\n");
return -EFAULT;
}
-#endif /* HAVE_NEXT_ONLINE_PGDAT */
+# endif /* HAVE_NEXT_ONLINE_PGDAT */
-#ifndef HAVE_NEXT_ZONE
+# ifndef HAVE_NEXT_ZONE
next_zone_fn = (next_zone_t)
spl_kallsyms_lookup_name("next_zone");
if (!next_zone_fn) {
printk(KERN_ERR "Error: Unknown symbol next_zone\n");
return -EFAULT;
}
-#endif /* HAVE_NEXT_ZONE */
+# endif /* HAVE_NEXT_ZONE */
+
+#else /* HAVE_PGDAT_HELPERS */
+
+# ifndef HAVE_PGDAT_LIST
+ pgdat_list_addr = (struct pglist_data *)
+ spl_kallsyms_lookup_name("pgdat_list");
+ if (!pgdat_list_addr) {
+ printk(KERN_ERR "Error: Unknown symbol pgdat_list\n");
+ return -EFAULT;
+ }
+# endif /* HAVE_PGDAT_LIST */
+#endif /* HAVE_PGDAT_HELPERS */
#ifndef HAVE_ZONE_STAT_ITEM_FIA
# ifndef HAVE_GET_ZONE_COUNTS
diff --git a/spl_config.h.in b/spl_config.h.in
index 3e9e6b9af..3b07d993c 100644
--- a/spl_config.h.in
+++ b/spl_config.h.in
@@ -105,6 +105,12 @@
/* struct path used in struct nameidata */
#undef HAVE_PATH_IN_NAMEIDATA
+/* pgdat helpers are available */
+#undef HAVE_PGDAT_HELPERS
+
+/* pgdat_list is available */
+#undef HAVE_PGDAT_LIST
+
/* set_normalized_timespec() is available as export */
#undef HAVE_SET_NORMALIZED_TIMESPEC_EXPORT