Whamcloud - gitweb
Branch HEAD
authorscjody <scjody>
Tue, 20 Nov 2007 20:39:26 +0000 (20:39 +0000)
committerscjody <scjody>
Tue, 20 Nov 2007 20:39:26 +0000 (20:39 +0000)
Improved support for dependencies between external modules: add a patch to
SLES 9 and RHEL 4 to modernize their module symbol handling, and copy the
symbol version file around to use this information properly.

b=12842
i=johann
i=zhenyu.xu

build/autoMakefile.am.toplevel
lustre/autoconf/lustre-core.m4
lustre/kernel_patches/patches/modpost_external_module_updates_rhel4.patch [new file with mode: 0644]
lustre/kernel_patches/patches/modpost_external_module_updates_sles9.patch [new file with mode: 0644]
lustre/kernel_patches/series/2.6-rhel4.series
lustre/kernel_patches/series/2.6-suse-newer.series

index f9b2904..1084b12 100644 (file)
@@ -27,7 +27,7 @@ tags:
 if MODULES
 sources: all-sources
 
-all-sources:
+all-sources: $(EXTRA_SOURCES)
        for dir in $(SOURCES_SUBDIRS) ; do \
                $(MAKE) sources -C $$dir || exit $$? ; \
        done
index 8342e99..23fa733 100644 (file)
@@ -830,6 +830,18 @@ LB_LINUX_TRY_COMPILE([
 ])
 ])
 
+# LC_SYMVERFILE
+# SLES 9 uses a different name for this file - unsure about vanilla kernels
+# around this version, but it matters for servers only.
+AC_DEFUN([LC_SYMVERFILE],
+         [AC_MSG_CHECKING([name of symverfile])
+          if grep -q Modules.symvers $LINUX/scripts/Makefile.modpost ; then
+              SYMVERFILE=Modules.symvers
+          else
+              SYMVERFILE=Module.symvers
+          fi
+         AC_MSG_RESULT($SYMVERFILE)
+          AC_SUBST(SYMVERFILE)])
 
 # LC_DQUOTOFF_MUTEX
 # after 2.6.17 dquote use mutex instead if semaphore
@@ -1277,97 +1289,98 @@ CFLAGS="$tmp_flags"
 # Lustre linux kernel checks
 #
 AC_DEFUN([LC_PROG_LINUX],
-[ LC_LUSTRE_VERSION_H
-if test x$enable_server = xyes ; then
-        LC_CONFIG_BACKINGFS
-fi
-LC_CONFIG_PINGER
-LC_CONFIG_CHECKSUM
-LC_CONFIG_LIBLUSTRE_RECOVERY
-LC_CONFIG_QUOTA
-LC_CONFIG_HEALTH_CHECK_WRITE
-LC_CONFIG_LRU_RESIZE
-
-
-LC_TASK_PPTR
-# RHEL4 patches
-LC_EXPORT_TRUNCATE_COMPLETE
-LC_EXPORT_D_REHASH_COND
-LC_EXPORT___D_REHASH
-LC_EXPORT_NODE_TO_CPUMASK
-
-LC_STRUCT_KIOBUF
-LC_FUNC_COND_RESCHED
-LC_FUNC_ZAP_PAGE_RANGE
-LC_FUNC_PDE
-LC_FUNC_DIRECT_IO
-LC_HEADER_MM_INLINE
-LC_STRUCT_INODE
-LC_FUNC_REGISTER_CACHE
-LC_FUNC_GRAB_CACHE_PAGE_NOWAIT_GFP
-LC_FUNC_DEV_SET_RDONLY
-LC_FUNC_FILEMAP_FDATAWRITE
-LC_STRUCT_STATFS
-LC_FUNC_PAGE_MAPPED
-LC_STRUCT_FILE_OPS_UNLOCKED_IOCTL
-LC_FILEMAP_POPULATE
-LC_D_ADD_UNIQUE
-LC_BIT_SPINLOCK_H
-
-LC_XATTR_ACL
-LC_POSIX_ACL_XATTR_H
-LC_CONST_ACL_SIZE
-
-LC_STRUCT_INTENT_FILE
-
-LC_FUNC_SET_FS_PWD
-LC_CAPA_CRYPTO
-LC_CONFIG_GSS
-LC_FUNC_MS_FLOCK_LOCK
-LC_FUNC_HAVE_CAN_SLEEP_ARG
-LC_FUNC_F_OP_FLOCK
-LC_QUOTA_READ
-LC_COOKIE_FOLLOW_LINK
-LC_FUNC_RCU
-
-# does the kernel have VFS intent patches?
-LC_VFS_INTENT_PATCHES
-
-# ~2.6.11
-LC_S_TIME_GRAN
-LC_SB_TIME_GRAN
-
-# 2.6.12
-LC_RW_TREE_LOCK
-
-# 2.6.15
-LC_INODE_I_MUTEX
-
-# 2.6.17
-LC_DQUOTOFF_MUTEX
-
-# 2.6.18
-LC_NR_PAGECACHE
-LC_STATFS_DENTRY_PARAM
-LC_VFS_KERN_MOUNT
-LC_INVALIDATEPAGE_RETURN_INT
-LC_UMOUNTBEGIN_HAS_VFSMOUNT
-
-#2.6.18 + RHEL5 (fc6)
-LC_PG_FS_MISC
-
-# 2.6.19
-LC_INODE_BLKSIZE
-LC_VFS_READDIR_U64_INO
-LC_GENERIC_FILE_READ
-LC_GENERIC_FILE_WRITE
-
-# 2.6.20
-LC_CANCEL_DIRTY_PAGE
-
-# raid5-zerocopy patch
-LC_PAGE_CONSTANT
-])
+         [LC_LUSTRE_VERSION_H
+         if test x$enable_server = xyes ; then
+             LC_CONFIG_BACKINGFS
+         fi
+         LC_CONFIG_PINGER
+         LC_CONFIG_CHECKSUM
+         LC_CONFIG_LIBLUSTRE_RECOVERY
+         LC_CONFIG_QUOTA
+         LC_CONFIG_HEALTH_CHECK_WRITE
+         LC_CONFIG_LRU_RESIZE
+
+         LC_TASK_PPTR
+         # RHEL4 patches
+         LC_EXPORT_TRUNCATE_COMPLETE
+         LC_EXPORT_D_REHASH_COND
+         LC_EXPORT___D_REHASH
+         LC_EXPORT_NODE_TO_CPUMASK
+
+         LC_STRUCT_KIOBUF
+         LC_FUNC_COND_RESCHED
+         LC_FUNC_ZAP_PAGE_RANGE
+         LC_FUNC_PDE
+         LC_FUNC_DIRECT_IO
+         LC_HEADER_MM_INLINE
+         LC_STRUCT_INODE
+         LC_FUNC_REGISTER_CACHE
+         LC_FUNC_GRAB_CACHE_PAGE_NOWAIT_GFP
+         LC_FUNC_DEV_SET_RDONLY
+         LC_FUNC_FILEMAP_FDATAWRITE
+         LC_STRUCT_STATFS
+         LC_FUNC_PAGE_MAPPED
+         LC_STRUCT_FILE_OPS_UNLOCKED_IOCTL
+         LC_FILEMAP_POPULATE
+         LC_D_ADD_UNIQUE
+         LC_BIT_SPINLOCK_H
+
+         LC_XATTR_ACL
+         LC_POSIX_ACL_XATTR_H
+         LC_CONST_ACL_SIZE
+
+         LC_STRUCT_INTENT_FILE
+
+         LC_FUNC_SET_FS_PWD
+         LC_CAPA_CRYPTO
+         LC_CONFIG_GSS
+         LC_FUNC_MS_FLOCK_LOCK
+         LC_FUNC_HAVE_CAN_SLEEP_ARG
+         LC_FUNC_F_OP_FLOCK
+         LC_QUOTA_READ
+         LC_COOKIE_FOLLOW_LINK
+         LC_FUNC_RCU
+
+         # does the kernel have VFS intent patches?
+         LC_VFS_INTENT_PATCHES
+
+         # ~2.6.11
+         LC_S_TIME_GRAN
+         LC_SB_TIME_GRAN
+
+         # 2.6.12
+         LC_RW_TREE_LOCK
+
+         # 2.6.15
+         LC_INODE_I_MUTEX
+
+         # SLES 10 (at least)
+         LC_SYMVERFILE
+
+         # 2.6.17
+         LC_DQUOTOFF_MUTEX
+
+         # 2.6.18
+         LC_NR_PAGECACHE
+         LC_STATFS_DENTRY_PARAM
+         LC_VFS_KERN_MOUNT
+         LC_INVALIDATEPAGE_RETURN_INT
+         LC_UMOUNTBEGIN_HAS_VFSMOUNT
+
+         #2.6.18 + RHEL5 (fc6)
+         LC_PG_FS_MISC
+
+         # 2.6.19
+         LC_INODE_BLKSIZE
+         LC_VFS_READDIR_U64_INO
+         LC_GENERIC_FILE_READ
+         LC_GENERIC_FILE_WRITE
+
+         # 2.6.20
+         LC_CANCEL_DIRTY_PAGE
+
+         # raid5-zerocopy patch
+         LC_PAGE_CONSTANT])
 
 #
 # LC_CONFIG_CLIENT_SERVER
diff --git a/lustre/kernel_patches/patches/modpost_external_module_updates_rhel4.patch b/lustre/kernel_patches/patches/modpost_external_module_updates_rhel4.patch
new file mode 100644 (file)
index 0000000..35bf139
--- /dev/null
@@ -0,0 +1,351 @@
+This patch updates the RHEL 4 module build system to properly support
+dependencies between external modules, similarly to the way they are
+supported in newer kernels.
+
+Index: linux-2.6.9-55.EL/scripts/Makefile.modpost
+===================================================================
+--- linux-2.6.9-55.EL.orig/scripts/Makefile.modpost
++++ linux-2.6.9-55.EL/scripts/Makefile.modpost
+@@ -38,7 +38,8 @@ _modpost: __modpost
+ include .config
+ include scripts/Makefile.lib
+-symverfile := $(objtree)/Module.symvers
++kernelsymfile := $(objtree)/Module.symvers
++modulesymfile := $(KBUILD_EXTMOD)/Module.symvers
+ # Step 1), find all modules listed in $(MODVERDIR)/
+ __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+@@ -52,7 +53,9 @@ _modpost: $(modules)
+ quiet_cmd_modpost = MODPOST
+       cmd_modpost = scripts/mod/modpost            \
+         $(if $(CONFIG_MODVERSIONS),-m)             \
+-      $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
++      $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
++      $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
++      $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+       $(filter-out FORCE,$^)
+ .PHONY: __modpost
+Index: linux-2.6.9-55.EL/scripts/mod/modpost.c
+===================================================================
+--- linux-2.6.9-55.EL.orig/scripts/mod/modpost.c
++++ linux-2.6.9-55.EL/scripts/mod/modpost.c
+@@ -1,7 +1,8 @@
+ /* Postprocess module symbol versions
+  *
+  * Copyright 2003       Kai Germaschewski
+- *           2002-2003  Rusty Russell, IBM Corporation
++ *           2002-2004  Rusty Russell, IBM Corporation
++ * Copyright 2006       Sam Ravnborg
+  *
+  * Based in part on module-init-tools/depmod.c,file2alias
+  *
+@@ -18,6 +19,8 @@
+ int modversions = 0;
+ /* Warn about undefined symbols? (do so if we have vmlinux) */
+ int have_vmlinux = 0;
++/* If we are modposting external module set to 1 */
++static int external_module = 0;
+ void
+ fatal(const char *fmt, ...)
+@@ -45,6 +48,19 @@ warn(const char *fmt, ...)
+       va_end(arglist);
+ }
++int
++is_vmlinux(const char *modname)
++{
++      const char *myname;
++
++      if ((myname = strrchr(modname, '/')))
++              myname++;
++      else
++              myname = modname;
++
++      return strcmp(myname, "vmlinux") == 0;
++}
++
+ void *do_nofail(void *ptr, const char *file, int line, const char *expr)
+ {
+       if (!ptr) {
+@@ -102,6 +118,10 @@ struct symbol {
+       struct module *module;
+       unsigned int crc;
+       int crc_valid;
++      unsigned int vmlinux:1;    /* 1 if symbol is defined in vmlinux */
++      unsigned int kernel:1;     /* 1 if symbol is from kernel
++                                  *  (only for external modules) **/
++      unsigned int preloaded:1;  /* 1 if symbol from Module.symvers */
+       char name[0];
+ };
+@@ -136,8 +156,8 @@ alloc_symbol(const char *name, struct sy
+ /* For the hash of exported symbols */
+-void
+-new_symbol(const char *name, struct module *module, unsigned int *crc)
++static struct symbol *
++new_symbol(const char *name, struct module *module)
+ {
+       unsigned int hash;
+       struct symbol *new;
+@@ -145,10 +165,7 @@ new_symbol(const char *name, struct modu
+       hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
+       new = symbolhash[hash] = alloc_symbol(name, symbolhash[hash]);
+       new->module = module;
+-      if (crc) {
+-              new->crc = *crc;
+-              new->crc_valid = 1;
+-      }
++      return new;
+ }
+ struct symbol *
+@@ -169,19 +186,29 @@ find_symbol(const char *name)
+ /* Add an exported symbol - it may have already been added without a
+  * CRC, in this case just update the CRC */
+-void
+-add_exported_symbol(const char *name, struct module *module, unsigned int *crc)
++static struct symbol *
++sym_add_exported(const char *name, struct module *mod)
+ {
+       struct symbol *s = find_symbol(name);
+       if (!s) {
+-              new_symbol(name, module, crc);
+-              return;
+-      }
+-      if (crc) {
+-              s->crc = *crc;
+-              s->crc_valid = 1;
++              s = new_symbol(name, mod);
+       }
++      s->preloaded = 0;
++      s->vmlinux   = is_vmlinux(mod->name);
++      s->kernel    = 0;
++      return s;
++}
++
++static void
++sym_update_crc(const char *name, struct module *mod, unsigned int crc)
++{
++      struct symbol *s = find_symbol(name);
++
++      if (!s)
++              s = new_symbol(name, mod);
++      s->crc = crc;
++      s->crc_valid = 1;
+ }
+ void *
+@@ -341,13 +368,13 @@ handle_modversions(struct module *mod, s
+               /* CRC'd symbol */
+               if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
+                       crc = (unsigned int) sym->st_value;
+-                      add_exported_symbol(symname + strlen(CRC_PFX),
+-                                          mod, &crc);
++                      sym_update_crc(symname + strlen(CRC_PFX), mod, crc);
+               }
+               break;
+       case SHN_UNDEF:
+               /* undefined symbol */
+-              if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
++              if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
++                  ELF_ST_BIND(sym->st_info) != STB_WEAK)
+                       break;
+               /* ignore global offset table */
+               if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
+@@ -373,8 +400,7 @@ handle_modversions(struct module *mod, s
+       default:
+               /* All exported symbols */
+               if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
+-                      add_exported_symbol(symname + strlen(KSYMTAB_PFX),
+-                                          mod, NULL);
++                      sym_add_exported(symname + strlen(KSYMTAB_PFX), mod);
+               }
+               if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
+                       mod->has_init = 1;
+@@ -384,19 +410,6 @@ handle_modversions(struct module *mod, s
+       }
+ }
+-int
+-is_vmlinux(const char *modname)
+-{
+-      const char *myname;
+-
+-      if ((myname = strrchr(modname, '/')))
+-              myname++;
+-      else
+-              myname = modname;
+-
+-      return strcmp(myname, "vmlinux") == 0;
+-}
+-
+ void
+ read_symbols(char *modname)
+ {
+@@ -412,9 +425,7 @@ read_symbols(char *modname)
+       /* When there's no vmlinux, don't print warnings about
+        * unresolved symbols (since there'll be too many ;) */
+       if (is_vmlinux(modname)) {
+-              unsigned int fake_crc = 0;
+               have_vmlinux = 1;
+-              add_exported_symbol("struct_module", mod, &fake_crc);
+               mod->skip = 1;
+       }
+@@ -426,6 +437,7 @@ read_symbols(char *modname)
+       }
+       maybe_frob_version(modname, info.modinfo, info.modinfo_len,
+                          (void *)info.modinfo - (void *)info.hdr);
++
+       parse_elf_finish(&info);
+       /* Our trick to get versioning for struct_module - it's
+@@ -451,12 +463,7 @@ buf_printf(struct buffer *buf, const cha
+       
+       va_start(ap, fmt);
+       len = vsnprintf(tmp, SZ, fmt, ap);
+-      if (buf->size - buf->pos < len + 1) {
+-              buf->size += 128;
+-              buf->p = realloc(buf->p, buf->size);
+-      }
+-      strncpy(buf->p + buf->pos, tmp, len + 1);
+-      buf->pos += len;
++      buf_write(buf, tmp, len);
+       va_end(ap);
+ }
+@@ -464,7 +471,7 @@ void
+ buf_write(struct buffer *buf, const char *s, int len)
+ {
+       if (buf->size - buf->pos < len) {
+-              buf->size += len;
++              buf->size += len + SZ;
+               buf->p = realloc(buf->p, buf->size);
+       }
+       strncpy(buf->p + buf->pos, s, len);
+@@ -506,8 +513,8 @@ add_versions(struct buffer *b, struct mo
+               exp = find_symbol(s->name);
+               if (!exp || exp->module == mod) {
+                       if (have_vmlinux)
+-                              fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
+-                              "undefined!\n", s->name, mod->name);
++                              warn("\"%s\" [%s.ko] undefined!\n",
++                                   s->name, mod->name);
+                       continue;
+               }
+               s->module = exp->module;
+@@ -615,8 +622,11 @@ write_if_changed(struct buffer *b, const
+       fclose(file);
+ }
++/* parse Module.symvers file. line format:
++ * 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something]
++ **/
+ void
+-read_dump(const char *fname)
++read_dump(const char *fname, unsigned int kernel)
+ {
+       unsigned long size, pos = 0;
+       void *file = grab_file(fname, &size);
+@@ -630,6 +640,7 @@ read_dump(const char *fname)
+               char *symname, *modname, *d;
+               unsigned int crc;
+               struct module *mod;
++                struct symbol *s;
+               if (!(symname = strchr(line, '\t')))
+                       goto fail;
+@@ -650,13 +661,30 @@ read_dump(const char *fname)
+                       mod = new_module(NOFAIL(strdup(modname)));
+                       mod->skip = 1;
+               }
+-              add_exported_symbol(symname, mod, &crc);
++                s = sym_add_exported(symname, mod);
++              s->kernel    = kernel;
++              s->preloaded = 1;
++              sym_update_crc(symname, mod, crc);
+       }
+       return;
+ fail:
+       fatal("parse error in symbol dump file\n");
+ }
++/* For normal builds always dump all symbols.
++ * For external modules only dump symbols
++ * that are not read from kernel Module.symvers.
++ **/
++static int
++dump_sym(struct symbol *sym)
++{
++      if (!external_module)
++              return 1;
++      if (sym->vmlinux || sym->kernel)
++              return 0;
++      return 1;
++}
++
+ void
+ write_dump(const char *fname)
+ {
+@@ -667,15 +695,10 @@ write_dump(const char *fname)
+       for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
+               symbol = symbolhash[n];
+               while (symbol) {
+-                      symbol = symbol->next;
+-              }
+-      }
+-
+-      for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
+-              symbol = symbolhash[n];
+-              while (symbol) {
+-                      buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc,
+-                              symbol->name, symbol->module->name);
++                      if (dump_sym(symbol))
++                              buf_printf(&buf, "0x%08x\t%s\t%s\n",
++                                      symbol->crc, symbol->name,
++                                      symbol->module->name);
+                       symbol = symbol->next;
+               }
+       }
+@@ -688,13 +711,18 @@ main(int argc, char **argv)
+       struct module *mod;
+       struct buffer buf = { };
+       char fname[SZ];
+-      char *dump_read = NULL, *dump_write = NULL;
++      char *kernel_read = NULL, *module_read = NULL;
++      char *dump_write = NULL;
+       int opt;
+-      while ((opt = getopt(argc, argv, "i:mo:")) != -1) {
++      while ((opt = getopt(argc, argv, "i:I:mo:")) != -1) {
+               switch(opt) {
+                       case 'i':
+-                              dump_read = optarg;
++                              kernel_read = optarg;
++                              break;
++                      case 'I':
++                              module_read = optarg;
++                              external_module = 1;
+                               break;
+                       case 'm':
+                               modversions = 1;
+@@ -707,8 +735,10 @@ main(int argc, char **argv)
+               }
+       }
+-      if (dump_read)
+-              read_dump(dump_read);
++      if (kernel_read)
++              read_dump(kernel_read, 1);
++      if (module_read)
++              read_dump(module_read, 0);
+       while (optind < argc) {
+               read_symbols(argv[optind++]);
diff --git a/lustre/kernel_patches/patches/modpost_external_module_updates_sles9.patch b/lustre/kernel_patches/patches/modpost_external_module_updates_sles9.patch
new file mode 100644 (file)
index 0000000..39b85d4
--- /dev/null
@@ -0,0 +1,342 @@
+This patch updates the SLES 9 module build system to properly support
+dependencies between external modules, similarly to the way they are
+supported in newer kernels.
+
+Index: linux-2.6.5-7.286/scripts/Makefile.modpost
+===================================================================
+--- linux-2.6.5-7.286.orig/scripts/Makefile.modpost
++++ linux-2.6.5-7.286/scripts/Makefile.modpost
+@@ -38,7 +38,8 @@ _modpost: __modpost
+ include .config
+ include scripts/Makefile.lib
+-symverfile := $(objtree)/Module.symvers
++kernelsymfile := $(objtree)/Module.symvers
++modulesymfile := $(KBUILD_EXTMOD)/Module.symvers
+ # Step 1), find all modules listed in $(MODVERDIR)/
+ __modules := $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod))
+@@ -51,7 +52,9 @@ _modpost: $(modules)
+ #  Includes step 3,4
+ quiet_cmd_modpost = MODPOST
+       cmd_modpost = scripts/modpost \
+-      $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
++      $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
++      $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
++      $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+       -s $(firstword $(wildcard $(dir $(MODVERDIR))/Module.supported \
+                                 $(objtree)/Module.supported /dev/null)) \
+       $(filter-out FORCE,$^)
+Index: linux-2.6.5-7.286/scripts/modpost.c
+===================================================================
+--- linux-2.6.5-7.286.orig/scripts/modpost.c
++++ linux-2.6.5-7.286/scripts/modpost.c
+@@ -1,7 +1,8 @@
+ /* Postprocess module symbol versions
+  *
+  * Copyright 2003       Kai Germaschewski
+- *           2002-2003  Rusty Russell, IBM Corporation
++ *           2002-2004  Rusty Russell, IBM Corporation
++ * Copyright 2006       Sam Ravnborg
+  *
+  * Based in part on module-init-tools/depmod.c,file2alias
+  *
+@@ -18,6 +19,8 @@
+ int modversions = 0;
+ /* Warn about undefined symbols? (do so if we have vmlinux) */
+ int have_vmlinux = 0;
++/* If we are modposting external module set to 1 */
++static int external_module = 0;
+ void
+ fatal(const char *fmt, ...)
+@@ -45,6 +48,19 @@ warn(const char *fmt, ...)
+       va_end(arglist);
+ }
++int
++is_vmlinux(const char *modname)
++{
++      const char *myname;
++
++      if ((myname = strrchr(modname, '/')))
++              myname++;
++      else
++              myname = modname;
++
++      return strcmp(myname, "vmlinux") == 0;
++}
++
+ void *do_nofail(void *ptr, const char *expr)
+ {
+       if (!ptr) {
+@@ -101,6 +117,9 @@ struct symbol {
+       struct module *module;
+       unsigned int crc;
+       int crc_valid;
++      unsigned int vmlinux:1;    /* 1 if symbol is defined in vmlinux */
++      unsigned int kernel:1;     /* 1 if symbol is from kernel
++                                  *  (only for external modules) **/
+       char name[0];
+ };
+@@ -135,8 +154,8 @@ alloc_symbol(const char *name, struct sy
+ /* For the hash of exported symbols */
+-void
+-new_symbol(const char *name, struct module *module, unsigned int *crc)
++static struct symbol *
++new_symbol(const char *name, struct module *module)
+ {
+       unsigned int hash;
+       struct symbol *new;
+@@ -144,10 +163,7 @@ new_symbol(const char *name, struct modu
+       hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
+       new = symbolhash[hash] = alloc_symbol(name, symbolhash[hash]);
+       new->module = module;
+-      if (crc) {
+-              new->crc = *crc;
+-              new->crc_valid = 1;
+-      }
++      return new;
+ }
+ struct symbol *
+@@ -168,19 +184,28 @@ find_symbol(const char *name)
+ /* Add an exported symbol - it may have already been added without a
+  * CRC, in this case just update the CRC */
+-void
+-add_exported_symbol(const char *name, struct module *module, unsigned int *crc)
++static struct symbol *
++sym_add_exported(const char *name, struct module *mod)
+ {
+       struct symbol *s = find_symbol(name);
+       if (!s) {
+-              new_symbol(name, module, crc);
+-              return;
+-      }
+-      if (crc) {
+-              s->crc = *crc;
+-              s->crc_valid = 1;
++              s = new_symbol(name, mod);
+       }
++      s->vmlinux   = is_vmlinux(mod->name);
++      s->kernel    = 0;
++      return s;
++}
++
++static void
++sym_update_crc(const char *name, struct module *mod, unsigned int crc)
++{
++      struct symbol *s = find_symbol(name);
++
++      if (!s)
++              s = new_symbol(name, mod);
++      s->crc = crc;
++      s->crc_valid = 1;
+ }
+ void *
+@@ -339,8 +364,7 @@ handle_modversions(struct module *mod, s
+               /* CRC'd symbol */
+               if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
+                       crc = (unsigned int) sym->st_value;
+-                      add_exported_symbol(symname + strlen(CRC_PFX),
+-                                          mod, &crc);
++                      sym_update_crc(symname + strlen(CRC_PFX), mod, crc);
+                       modversions = 1;
+               }
+               break;
+@@ -372,26 +396,12 @@ handle_modversions(struct module *mod, s
+       default:
+               /* All exported symbols */
+               if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
+-                      add_exported_symbol(symname + strlen(KSYMTAB_PFX),
+-                                          mod, NULL);
++                      sym_add_exported(symname + strlen(KSYMTAB_PFX), mod);
+               }
+               break;
+       }
+ }
+-int
+-is_vmlinux(const char *modname)
+-{
+-      const char *myname;
+-
+-      if ((myname = strrchr(modname, '/')))
+-              myname++;
+-      else
+-              myname = modname;
+-
+-      return strcmp(myname, "vmlinux") == 0;
+-}
+-
+ static struct {
+       void *file;
+       unsigned long size;
+@@ -451,12 +461,7 @@ read_symbols(char *modname)
+       /* When there's no vmlinux, don't print warnings about
+        * unresolved symbols (since there'll be too many ;) */
+       if (is_vmlinux(modname)) {
+-              unsigned int fake_crc = 0;
+               have_vmlinux = 1;
+-              /* May not have this if !CONFIG_MODULE_UNLOAD: fake it.
+-                 If it appears, we'll get the real CRC. */
+-              add_exported_symbol("cleanup_module", mod, &fake_crc);
+-              add_exported_symbol("struct_module", mod, &fake_crc);
+               mod->skip = 1;
+       }
+@@ -499,12 +504,7 @@ buf_printf(struct buffer *buf, const cha
+       
+       va_start(ap, fmt);
+       len = vsnprintf(tmp, SZ, fmt, ap);
+-      if (buf->size - buf->pos < len + 1) {
+-              buf->size += 128;
+-              buf->p = realloc(buf->p, buf->size);
+-      }
+-      strncpy(buf->p + buf->pos, tmp, len + 1);
+-      buf->pos += len;
++      buf_write(buf, tmp, len);
+       va_end(ap);
+ }
+@@ -512,7 +512,7 @@ void
+ buf_write(struct buffer *buf, const char *s, int len)
+ {
+       if (buf->size - buf->pos < len) {
+-              buf->size += len;
++              buf->size += len + SZ;
+               buf->p = realloc(buf->p, buf->size);
+       }
+       strncpy(buf->p + buf->pos, s, len);
+@@ -522,7 +522,7 @@ buf_write(struct buffer *buf, const char
+ /* Header for the generated file */
+ void
+-add_header(struct buffer *b)
++add_header(struct buffer *b, struct module *mod)
+ {
+       buf_printf(b, "#include <linux/module.h>\n");
+       buf_printf(b, "#include <linux/vermagic.h>\n");
+@@ -676,8 +676,11 @@ read_supported(const char *fname)
+               ; /* ignore error */
+ }
++/* parse Module.symvers file. line format:
++ * 0x12345678<tab>symbol<tab>module[<tab>something]
++ **/
+ void
+-read_dump(const char *fname)
++read_dump(const char *fname, unsigned int kernel)
+ {
+       unsigned long size, pos = 0;
+       void *file = grab_file(fname, &size);
+@@ -691,6 +694,7 @@ read_dump(const char *fname)
+               char *symname, *modname, *d;
+               unsigned int crc;
+               struct module *mod;
++                struct symbol *s;
+               if (!(symname = strchr(line, '\t')))
+                       goto fail;
+@@ -712,13 +716,29 @@ read_dump(const char *fname)
+                       mod = new_module(NOFAIL(strdup(modname)));
+                       mod->skip = 1;
+               }
+-              add_exported_symbol(symname, mod, &crc);
++                s = sym_add_exported(symname, mod);
++              s->kernel    = kernel;
++              sym_update_crc(symname, mod, crc);
+       }
+       return;
+ fail:
+       fatal("parse error in symbol dump file\n");
+ }
++/* For normal builds always dump all symbols.
++ * For external modules only dump symbols
++ * that are not read from kernel Module.symvers.
++ **/
++static int
++dump_sym(struct symbol *sym)
++{
++      if (!external_module)
++              return 1;
++      if (sym->vmlinux || sym->kernel)
++              return 0;
++      return 1;
++}
++
+ void
+ write_dump(const char *fname)
+ {
+@@ -729,15 +749,10 @@ write_dump(const char *fname)
+       for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
+               symbol = symbolhash[n];
+               while (symbol) {
+-                      symbol = symbol->next;
+-              }
+-      }
+-
+-      for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
+-              symbol = symbolhash[n];
+-              while (symbol) {
+-                      buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc,
+-                              symbol->name, symbol->module->name);
++                      if (dump_sym(symbol))
++                              buf_printf(&buf, "0x%08x\t%s\t%s\n",
++                                      symbol->crc, symbol->name,
++                                      symbol->module->name);
+                       symbol = symbol->next;
+               }
+       }
+@@ -750,14 +765,19 @@ main(int argc, char **argv)
+       struct module *mod;
+       struct buffer buf = { };
+       char fname[SZ];
+-      char *dump_read = NULL, *dump_write = NULL;
++      char *kernel_read = NULL, *module_read = NULL;
++      char *dump_write = NULL;
+       char *supp = NULL;
+       int opt;
+-      while ((opt = getopt(argc, argv, "i:o:s:")) != -1) {
++      while ((opt = getopt(argc, argv, "i:I:o:s:")) != -1) {
+               switch(opt) {
+                       case 'i':
+-                              dump_read = optarg;
++                              kernel_read = optarg;
++                              break;
++                      case 'I':
++                              module_read = optarg;
++                              external_module = 1;
+                               break;
+                       case 'o':
+                               dump_write = optarg;
+@@ -773,8 +793,10 @@ main(int argc, char **argv)
+       if (supp)
+               read_supported(supp);
+-      if (dump_read)
+-              read_dump(dump_read);
++      if (kernel_read)
++              read_dump(kernel_read, 1);
++      if (module_read)
++              read_dump(module_read, 0);
+       while (optind < argc) {
+               read_symbols(argv[optind++]);
+@@ -786,7 +808,7 @@ main(int argc, char **argv)
+               buf.pos = 0;
+-              add_header(&buf);
++              add_header(&buf, mod);
+               add_supported_flag(&buf, mod);
+               add_versions(&buf, mod);
+               add_depends(&buf, mod, modules);
index 1ae8a02..7c3c430 100644 (file)
@@ -31,3 +31,4 @@ dynamic-locks-common.patch
 dynamic-locks-2.6.9.patch
 export-nr_free_buffer_pages.patch
 vfs-keep-inode-hashed-for-clear-inode.patch
+modpost_external_module_updates_rhel4.patch
index 1e56ba5..39cdca6 100644 (file)
@@ -12,3 +12,4 @@ jbd-stats-2.6.5.patch
 bitops_ext2_find_next_le_bit-2.6.patch
 2.6.5-quotafix.patch
 vfs_intent-reduce-stack-usage-2.6-suse-newer.patch
+modpost_external_module_updates_sles9.patch