SLES10 Fixes (part 6)

- Prior to 2.6.17 there were no *_pgdat helper functions in mm/mmzone.c.
  Instead for_each_zone() operated directly on pgdat_list which may or
  may not have been exported depending on how your kernel was compiled.
  Now new configure checks determine if you have the helpers or not, and
  if the needed symbols are exported.  If they are not exported then they
  are dynamically aquired at runtime by kallsyms_lookup_name().
This commit is contained in:
Brian Behlendorf 2009-05-20 14:23:13 -07:00
parent 3731931529
commit 5232d256b4
6 changed files with 157 additions and 23 deletions

View File

@ -802,6 +802,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
@ -850,6 +875,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

57
configure vendored
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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