]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - support/export/xtab.c
Exportfs and rpc.mountd optimalization
[nfs-utils.git] / support / export / xtab.c
index 4289d7ce5fc1537c6ce5b8d05e4088a761916f27..510765a3f0d59b5517e06b0542f1eb8d0d702f03 100644 (file)
@@ -6,7 +6,9 @@
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #include <sys/fcntl.h>
 #include <unistd.h>
 #include "xio.h"
 #include "xlog.h"
 
+static void cond_rename(char *newfile, char *oldfile);
+
 static int
 xtab_read(char *xtab, int is_export)
 {
+    /* is_export == 0  => reading /proc/fs/nfs/exports - we know these things are exported to kernel
+     * is_export == 1  => reading /var/lib/nfs/etab - these things are allowed to be exported
+     * is_export == 2  => reading /var/lib/nfs/xtab - these things might be known to kernel
+     */
        struct exportent        *xp;
        nfs_export              *exp;
        int                     lockid;
@@ -28,16 +36,23 @@ xtab_read(char *xtab, int is_export)
        if ((lockid = xflock(xtab, "r")) < 0)
                return 0;
        setexportent(xtab, "r");
-       while ((xp = getexportent()) != NULL) {
-               if (!(exp = export_lookup(xp->e_hostname, xp->e_path)) &&
-                   !(exp = export_create(xp))) {
+       while ((xp = getexportent(is_export==0, 0)) != NULL) {
+               if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
+                   !(exp = export_create(xp, is_export!=1))) {
                        continue;
                }
-               if (is_export) {
+               switch (is_export) {
+               case 0:
+                       exp->m_exported = 1;
+                       break;
+               case 1:
                        exp->m_xtabent = 1;
                        exp->m_mayexport = 1;
-               } else
-                       exp->m_exported = 1;
+                       break;
+               case 2:
+                       exp->m_exported = -1;/* may be exported */
+                       break;
+               }
        }
        endexportent();
        xfunlock(lockid);
@@ -52,8 +67,11 @@ xtab_mount_read(void)
        if ((fd=open(_PATH_PROC_EXPORTS, O_RDONLY))>=0) {
                close(fd);
                return xtab_read(_PATH_PROC_EXPORTS, 0);
+       } else if ((fd=open(_PATH_PROC_EXPORTS_ALT, O_RDONLY) >= 0)) {
+               close(fd);
+               return xtab_read(_PATH_PROC_EXPORTS_ALT, 0);
        } else
-               return xtab_read(_PATH_XTAB, 0);
+               return xtab_read(_PATH_XTAB, 2);
 }
 
 int
@@ -62,6 +80,12 @@ xtab_export_read(void)
        return xtab_read(_PATH_ETAB, 1);
 }
 
+/*
+ * mountd now keeps an open fd for the etab at all times to make sure that the
+ * inode number changes when the xtab_export_write is done. If you change the
+ * routine below such that the files are edited in place, then you'll need to
+ * fix the auth_reload logic as well...
+ */
 static int
 xtab_write(char *xtab, char *xtabtmp, int is_export)
 {
@@ -76,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)
@@ -84,16 +108,13 @@ xtab_write(char *xtab, char *xtabtmp, int is_export)
 
                        /* write out the export entry using the FQDN */
                        xe = exp->m_export;
-                       strncpy(xe.e_hostname,
-                               exp->m_client->m_hostname,
-                               sizeof (xe.e_hostname) - 1);
-                       xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
+                       xe.e_hostname = exp->m_client->m_hostname;
                        putexportent(&xe);
                }
        }
        endexportent();
 
-       rename(xtabtmp, xtab);
+       cond_rename(xtabtmp, xtab);
 
        xfunlock(lockid);
 
@@ -122,12 +143,53 @@ xtab_append(nfs_export *exp)
                return;
        setexportent(_PATH_XTAB, "a");
        xe = exp->m_export;
-       strncpy(xe.e_hostname, exp->m_client->m_hostname,
-              sizeof (xe.e_hostname) - 1);
-       xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
+       xe.e_hostname = exp->m_client->m_hostname;
        putexportent(&xe);
        endexportent();
        xfunlock(lockid);
        exp->m_xtabent = 1;
 }
 
+/*
+ * rename newfile onto oldfile unless
+ * they are identical
+ */
+static void cond_rename(char *newfile, char *oldfile)
+{
+       int nfd, ofd;
+       char nbuf[4096], obuf[4096];
+       int ncnt, ocnt;
+
+       nfd = open(newfile, 0);
+       if (nfd < 0)
+               return;
+       ofd = open(oldfile, 0);
+       if (ofd < 0) {
+               close(nfd);
+               rename(newfile, oldfile);
+               return;
+       }
+
+       do {
+               ncnt = read(nfd, nbuf, sizeof(nbuf));
+               if (ncnt < 0)
+                       break;
+               ocnt = read(ofd, obuf, sizeof(obuf));
+               if (ocnt < 0)
+                       break;
+               if (ncnt != ocnt)
+                       break;
+               if (ncnt == 0) {
+                       close(nfd);
+                       close(ofd);
+                       unlink(newfile);
+                       return;
+               }
+       } while (memcmp(obuf, nbuf, ncnt) == 0);
+
+       /* some mis-match */
+       close(nfd);
+       close(ofd);
+       rename(newfile, oldfile);
+       return;
+}