]> git.decadent.org.uk Git - nfs-utils.git/commitdiff
Exportfs and rpc.mountd optimalization
authorTomas Richter <krik3t@gmail.com>
Wed, 18 Feb 2009 18:33:27 +0000 (13:33 -0500)
committerSteve Dickson <steved@redhat.com>
Wed, 18 Feb 2009 18:33:27 +0000 (13:33 -0500)
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
<for_all_in_hash_table>.

Signed-off-by: Tomas Richter <krik3t@gmail.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
support/export/export.c
support/export/xtab.c
support/include/exportfs.h
support/misc/tcpwrapper.c
utils/exportfs/exportfs.c
utils/mountd/auth.c
utils/mountd/cache.c
utils/mountd/mountd.c

index 14af11219fcfc8fa358d6376fcf003ada044be85..e5e6cb0504158447d006c8855c58e54a4e5c581e 100644 (file)
@@ -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 hostent *hp)
 
        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 *path)
        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 *hp, char *path)
        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 *path)
        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;
+}
index 990113e14bf471da86269867a8b4b4ef4fb7528b..510765a3f0d59b5517e06b0542f1eb8d0d702f03 100644 (file)
@@ -100,7 +100,7 @@ xtab_write(char *xtab, char *xtabtmp, int is_export)
        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)
index c1ba54357fa677f9d9eb48cb5e2517ff8d63a0c3..a5cf482584af668e5f8a847909ec7e827a747705 100644 (file)
@@ -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 in_addr addr);
 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);
index 977dfcaf5a11d0fa3dc9babe7fb849a32e8b015f..e9eb1df91a3063c39f3e8b348125e0d92f09ee2d 100644 (file)
@@ -122,7 +122,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;
 }
index fec2571934b0a04e263f81dfa58985cd74fd7d54..593a8ebd467e1081b4f7ed4110df89712bc8c248 100644 (file)
@@ -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 */
index dfe61ea7fcc7c8d49faa697541f31ebf0e8d9eee..575f207bd028f0d74eed6097a82d485499c4d8b8 100644 (file)
@@ -142,7 +142,7 @@ auth_authenticate_internal(char *what, struct sockaddr_in *caller,
 
                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))
index fa154725b95b809dfe88c9a727fd98e4e1160e8b..9bbbfb3c3a6cc3a4c616eefd64a3a0d300004f9b 100644 (file)
@@ -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) {
index 6adb68fdc5e33b7af04bef23f8e829326536b26b..deeaa07b6699d8af68fd8f4a128bf414f454fe89 100644 (file)
@@ -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;