diff --git a/nfs-utils-1.1.4-export-hash.patch b/nfs-utils-1.1.4-export-hash.patch new file mode 100644 index 0000000..7e5373e --- /dev/null +++ b/nfs-utils-1.1.4-export-hash.patch @@ -0,0 +1,357 @@ +commit 4cacc965afc4fb03a465ffcc6cb3078aeadc3818 +Author: Tomas Richter +Date: Wed Feb 18 13:33:27 2009 -0500 + + Exportfs and rpc.mountd optimalization + + There were some problems with exportfs and rpc.mountd for long export + lists - see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=76643 + I do optimalization as my bachelors thesis (Facuulty of informatics, + Masaryk's university Brno, Czech Republic), under lead of Yenya + Kasprzak. + + Both exportfs and rpc.mount build linked list of exports (shared + functions in export.c). Every time they are inserting new export into + list, they search for same export in list. + I replaced linked list by hash table and functions export_add and + export_lookup by functions hash_export_add and hash_export_lookup + (export.c). + + Because some other functions required exportlist as linked list, hash + table has some implementation modification im comparison with ordinary + hash table. It also keeps exports in linked list and has pointer to + head of the list. So there's no need of implementation function + . + + Signed-off-by: Tomas Richter + Signed-off-by: Steve Dickson + +diff -up nfs-utils-1.1.4/support/export/export.c.orig nfs-utils-1.1.4/support/export/export.c +--- nfs-utils-1.1.4/support/export/export.c.orig 2008-10-17 10:20:09.000000000 -0400 ++++ nfs-utils-1.1.4/support/export/export.c 2009-02-18 19:42:13.000000000 -0500 +@@ -19,7 +19,8 @@ + #include "nfslib.h" + #include "exportfs.h" + +-nfs_export *exportlist[MCL_MAXTYPES] = { NULL, }; ++exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL}, }}, }; ++static int export_hash(char *); + + static void export_init(nfs_export *exp, nfs_client *clp, + struct exportent *nep); +@@ -125,22 +126,35 @@ export_dup(nfs_export *exp, struct hoste + + return new; + } +- +-void ++/* ++ * Add export entry to hash table ++ */ ++void + export_add(nfs_export *exp) + { +- nfs_export **epp; +- int type = exp->m_client->m_type; +- int slen = strlen(exp->m_export.e_path); +- +- if (type < 0 || type >= MCL_MAXTYPES) +- xlog(L_FATAL, "unknown client type in export_add"); +- +- epp = exportlist + type; +- while (*epp && slen <= strlen((*epp)->m_export.e_path)) +- epp = &((*epp)->m_next); +- exp->m_next = *epp; +- *epp = exp; ++ exp_hash_table *p_tbl; ++ exp_hash_entry *p_hen; ++ nfs_export *p_next; ++ ++ int type = exp->m_client->m_type; ++ int pos; ++ ++ pos = export_hash(exp->m_export.e_path); ++ p_tbl = &(exportlist[type]); /* pointer to hash table */ ++ p_hen = &(p_tbl->entries[pos]); /* pointer to hash table entry */ ++ ++ if (!(p_hen->p_first)) { /* hash table entry is empty */ ++ p_hen->p_first = exp; ++ p_hen->p_last = exp; ++ ++ exp->m_next = p_tbl->p_head; ++ p_tbl->p_head = exp; ++ } else { /* hash table entry is NOT empty */ ++ p_next = p_hen->p_last->m_next; ++ p_hen->p_last->m_next = exp; ++ exp->m_next = p_next; ++ p_hen->p_last = exp; ++ } + } + + nfs_export * +@@ -150,7 +164,7 @@ export_find(struct hostent *hp, char *pa + int i; + + for (i = 0; i < MCL_MAXTYPES; i++) { +- for (exp = exportlist[i]; exp; exp = exp->m_next) { ++ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + if (!export_check(exp, hp, path)) + continue; + if (exp->m_client->m_type == MCL_FQDN) +@@ -169,7 +183,7 @@ export_allowed_internal (struct hostent + int i; + + for (i = 0; i < MCL_MAXTYPES; i++) { +- for (exp = exportlist[i]; exp; exp = exp->m_next) { ++ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + if (!exp->m_mayexport || + !export_check(exp, hp, path)) + continue; +@@ -207,17 +221,30 @@ export_allowed(struct hostent *hp, char + return NULL; + } + ++/* ++ * Search hash table for export entry. ++ */ + nfs_export * +-export_lookup(char *hname, char *path, int canonical) ++export_lookup(char *hname, char *path, int canonical) + { +- nfs_client *clp; +- nfs_export *exp; ++ nfs_client *clp; ++ nfs_export *exp; ++ exp_hash_entry *p_hen; ++ ++ int pos; + +- if (!(clp = client_lookup(hname, canonical))) ++ clp = client_lookup(hname, canonical); ++ if(clp == NULL) + return NULL; +- for (exp = exportlist[clp->m_type]; exp; exp = exp->m_next) +- if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path)) +- return exp; ++ ++ pos = export_hash(path); ++ p_hen = &(exportlist[clp->m_type].entries[pos]); ++ for(exp = p_hen->p_first; exp && (exp != p_hen->p_last->m_next); ++ exp = exp->m_next) { ++ if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path)) { ++ return exp; ++ } ++ } + return NULL; + } + +@@ -234,10 +261,10 @@ void + export_freeall(void) + { + nfs_export *exp, *nxt; +- int i; ++ int i, j; + + for (i = 0; i < MCL_MAXTYPES; i++) { +- for (exp = exportlist[i]; exp; exp = nxt) { ++ for (exp = exportlist[i].p_head; exp; exp = nxt) { + nxt = exp->m_next; + client_release(exp->m_client); + if (exp->m_export.e_squids) +@@ -251,7 +278,40 @@ export_freeall(void) + xfree(exp->m_export.e_hostname); + xfree(exp); + } +- exportlist[i] = NULL; ++ for(j = 0; j < HASH_TABLE_SIZE; j++) { ++ exportlist[i].entries[j].p_first = NULL; ++ exportlist[i].entries[j].p_last = NULL; ++ } ++ exportlist[i].p_head = NULL; + } + client_freeall(); + } ++ ++/* ++ * Compute and returns integer from string. ++ * Note: Its understood the smae integers can be same for ++ * different strings, but it should not matter. ++ */ ++static unsigned int ++strtoint(char *str) ++{ ++ int i = 0; ++ unsigned int n = 0; ++ ++ while ( str[i] != '\0') { ++ n+=((int)str[i])*i; ++ i++; ++ } ++ return n; ++} ++ ++/* ++ * Hash function ++ */ ++static int ++export_hash(char *str) ++{ ++ int num = strtoint(str); ++ ++ return num % HASH_TABLE_SIZE; ++} +diff -up nfs-utils-1.1.4/support/export/xtab.c.orig nfs-utils-1.1.4/support/export/xtab.c +--- nfs-utils-1.1.4/support/export/xtab.c.orig 2008-10-17 10:20:09.000000000 -0400 ++++ nfs-utils-1.1.4/support/export/xtab.c 2009-02-18 19:42:13.000000000 -0500 +@@ -100,7 +100,7 @@ xtab_write(char *xtab, char *xtabtmp, in + setexportent(xtabtmp, "w"); + + for (i = 0; i < MCL_MAXTYPES; i++) { +- for (exp = exportlist[i]; exp; exp = exp->m_next) { ++ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + if (is_export && !exp->m_xtabent) + continue; + if (!is_export && ! exp->m_exported) +diff -up nfs-utils-1.1.4/support/include/exportfs.h.orig nfs-utils-1.1.4/support/include/exportfs.h +--- nfs-utils-1.1.4/support/include/exportfs.h.orig 2008-10-17 10:20:09.000000000 -0400 ++++ nfs-utils-1.1.4/support/include/exportfs.h 2009-02-18 19:42:13.000000000 -0500 +@@ -52,8 +52,21 @@ typedef struct mexport { + * matching one client */ + } nfs_export; + ++#define HASH_TABLE_SIZE 1021 ++ ++typedef struct _exp_hash_entry { ++ nfs_export * p_first; ++ nfs_export * p_last; ++} exp_hash_entry; ++ ++typedef struct _exp_hash_table { ++ nfs_export * p_head; ++ exp_hash_entry entries[HASH_TABLE_SIZE]; ++} exp_hash_table; ++ ++extern exp_hash_table exportlist[MCL_MAXTYPES]; ++ + extern nfs_client * clientlist[MCL_MAXTYPES]; +-extern nfs_export * exportlist[MCL_MAXTYPES]; + + nfs_client * client_lookup(char *hname, int canonical); + nfs_client * client_find(struct hostent *); +@@ -69,7 +82,7 @@ struct hostent * client_resolve(struct + int client_member(char *client, char *name); + + int export_read(char *fname); +-void export_add(nfs_export *); ++void export_add(nfs_export *); + void export_reset(nfs_export *); + nfs_export * export_lookup(char *hname, char *path, int caconical); + nfs_export * export_find(struct hostent *, char *path); +diff -up nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig nfs-utils-1.1.4/support/misc/tcpwrapper.c +--- nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig 2009-02-17 16:45:04.000000000 -0500 ++++ nfs-utils-1.1.4/support/misc/tcpwrapper.c 2009-02-18 19:42:13.000000000 -0500 +@@ -91,7 +91,7 @@ inline unsigned int strtoint(char *str) + + return n; + } +-inline int hashint(unsigned int num) ++static inline int hashint(unsigned int num) + { + return num % HASH_TABLE_SIZE; + } +diff -up nfs-utils-1.1.4/utils/exportfs/exportfs.c.orig nfs-utils-1.1.4/utils/exportfs/exportfs.c +--- nfs-utils-1.1.4/utils/exportfs/exportfs.c.orig 2008-10-17 10:20:09.000000000 -0400 ++++ nfs-utils-1.1.4/utils/exportfs/exportfs.c 2009-02-18 19:42:13.000000000 -0500 +@@ -111,7 +111,6 @@ main(int argc, char **argv) + return 0; + } + } +- + if (f_export && ! f_ignore) + export_read(_PATH_EXPORTS); + if (f_export) { +@@ -193,10 +192,10 @@ exports_update(int verbose) + { + nfs_export *exp; + +- for (exp = exportlist[MCL_FQDN]; exp; exp=exp->m_next) { ++ for (exp = exportlist[MCL_FQDN].p_head; exp; exp=exp->m_next) { + exports_update_one(exp, verbose); + } +- for (exp = exportlist[MCL_GSS]; exp; exp=exp->m_next) { ++ for (exp = exportlist[MCL_GSS].p_head; exp; exp=exp->m_next) { + exports_update_one(exp, verbose); + } + } +@@ -212,7 +211,7 @@ export_all(int verbose) + int i; + + for (i = 0; i < MCL_MAXTYPES; i++) { +- for (exp = exportlist[i]; exp; exp = exp->m_next) { ++ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + if (verbose) + printf("exporting %s:%s\n", + exp->m_client->m_hostname, +@@ -308,7 +307,7 @@ unexportfs(char *arg, int verbose) + } + } + +- for (exp = exportlist[htype]; exp; exp = exp->m_next) { ++ for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) { + if (path && strcmp(path, exp->m_export.e_path)) + continue; + if (htype != exp->m_client->m_type) +@@ -453,7 +452,7 @@ dump(int verbose) + char *hname, c; + + for (htype = 0; htype < MCL_MAXTYPES; htype++) { +- for (exp = exportlist[htype]; exp; exp = exp->m_next) { ++ for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) { + ep = &exp->m_export; + if (!exp->m_xtabent) + continue; /* neilb */ +diff -up nfs-utils-1.1.4/utils/mountd/auth.c.orig nfs-utils-1.1.4/utils/mountd/auth.c +--- nfs-utils-1.1.4/utils/mountd/auth.c.orig 2008-10-17 10:20:09.000000000 -0400 ++++ nfs-utils-1.1.4/utils/mountd/auth.c 2009-02-18 19:42:13.000000000 -0500 +@@ -142,7 +142,7 @@ auth_authenticate_internal(char *what, s + + exp = NULL; + for (i = 0; !exp && i < MCL_MAXTYPES; i++) +- for (exp = exportlist[i]; exp; exp = exp->m_next) { ++ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + if (strcmp(path, exp->m_export.e_path)) + continue; + if (!use_ipaddr && !client_member(my_client.m_hostname, exp->m_client->m_hostname)) +diff -up nfs-utils-1.1.4/utils/mountd/cache.c.orig nfs-utils-1.1.4/utils/mountd/cache.c +--- nfs-utils-1.1.4/utils/mountd/cache.c.orig 2008-10-17 10:20:09.000000000 -0400 ++++ nfs-utils-1.1.4/utils/mountd/cache.c 2009-02-18 19:42:13.000000000 -0500 +@@ -394,7 +394,7 @@ void nfsd_fh(FILE *f) + /* Now determine export point for this fsid/domain */ + for (i=0 ; i < MCL_MAXTYPES; i++) { + nfs_export *next_exp; +- for (exp = exportlist[i]; exp; exp = next_exp) { ++ for (exp = exportlist[i].p_head; exp; exp = next_exp) { + struct stat stb; + char u[16]; + char *path; +@@ -654,7 +654,7 @@ void nfsd_export(FILE *f) + + /* now find flags for this export point in this domain */ + for (i=0 ; i < MCL_MAXTYPES; i++) { +- for (exp = exportlist[i]; exp; exp = exp->m_next) { ++ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + if (!use_ipaddr && !client_member(dom, exp->m_client->m_hostname)) + continue; + if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) { +diff -up nfs-utils-1.1.4/utils/mountd/mountd.c.orig nfs-utils-1.1.4/utils/mountd/mountd.c +--- nfs-utils-1.1.4/utils/mountd/mountd.c.orig 2008-10-17 10:20:09.000000000 -0400 ++++ nfs-utils-1.1.4/utils/mountd/mountd.c 2009-02-18 19:42:13.000000000 -0500 +@@ -521,7 +521,7 @@ get_exportlist(void) + elist = NULL; + + for (i = 0; i < MCL_MAXTYPES; i++) { +- for (exp = exportlist[i]; exp; exp = exp->m_next) { ++ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + for (e = elist; e != NULL; e = e->ex_next) { + if (!strcmp(exp->m_export.e_path, e->ex_dir)) + break; diff --git a/nfs-utils.spec b/nfs-utils.spec index 6a88252..d1f3953 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser Name: nfs-utils URL: http://sourceforge.net/projects/nfs Version: 1.1.4 -Release: 18%{?dist} +Release: 19%{?dist} Epoch: 1 # group all 32bit related archs @@ -51,6 +51,7 @@ Patch121: nfs-utils-1.1.4-mount-textbased.patch Patch122: nfs-utils-1.1.4-mount-nolock.patch Patch123: nfs-utils-1.1.4-mount-udponly.patch Patch124: nfs-utils-1.1.4-umount-ipv6.patch +Patch125: nfs-utils-1.1.4-export-hash.patch %if %{enablefscache} Patch90: nfs-utils-1.1.0-mount-fsc.patch @@ -130,6 +131,7 @@ This package also contains the mount.nfs and umount.nfs program. %patch122 -p1 %patch123 -p1 %patch124 -p1 +%patch125 -p1 %if %{enablefscache} %patch90 -p1 @@ -293,6 +295,9 @@ fi %attr(4755,root,root) /sbin/umount.nfs4 %changelog +* Wed Feb 18 2009 Steve Dickson 1.1.4-19 +- Exportfs and rpc.mountd optimalization (bz 76643) + * Tue Feb 17 2009 Steve Dickson 1.1.4-18 - umount.nfs command: Add an AF_INET6-capable version of nfs_call_unmount() - umount.nfs command: Support AF_INET6 server addresses