Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/mountd Change get_exportlist() to collect all expor...



details:   https://anonhg.NetBSD.org/src/rev/76805ea57808
branches:  trunk
changeset: 379517:76805ea57808
user:      hannken <hannken%NetBSD.org@localhost>
date:      Fri Jun 04 10:46:57 2021 +0000

description:
Change get_exportlist() to collect all exports and emit all
exports for a single mount in one call to nfssvc(2).

Should finally fix PR kern/5844 (NFS server sends "permission denied"
while mound re-read exports).

diffstat:

 usr.sbin/mountd/mountd.c |  110 ++++++++++++++++++++++++++++++++--------------
 1 files changed, 75 insertions(+), 35 deletions(-)

diffs (172 lines):

diff -r 75c8c031c64e -r 76805ea57808 usr.sbin/mountd/mountd.c
--- a/usr.sbin/mountd/mountd.c  Fri Jun 04 10:46:11 2021 +0000
+++ b/usr.sbin/mountd/mountd.c  Fri Jun 04 10:46:57 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mountd.c,v 1.135 2021/06/04 10:46:01 hannken Exp $      */
+/*     $NetBSD: mountd.c,v 1.136 2021/06/04 10:46:57 hannken Exp $      */
 
 /*
  * Copyright (c) 1989, 1993
@@ -42,7 +42,7 @@
 #if 0
 static char     sccsid[] = "@(#)mountd.c  8.15 (Berkeley) 5/1/95";
 #else
-__RCSID("$NetBSD: mountd.c,v 1.135 2021/06/04 10:46:01 hannken Exp $");
+__RCSID("$NetBSD: mountd.c,v 1.136 2021/06/04 10:46:57 hannken Exp $");
 #endif
 #endif                         /* not lint */
 
@@ -235,6 +235,8 @@ static struct uucred def_anon = {
        0,
        { 0 }
 };
+static struct mountd_exports_list *mel_tab;
+static int mel_tab_len;
 
 int      opt_flags;
 static int     have_v6 = 1;
@@ -1207,6 +1209,18 @@ nextline:
 }
 
 /*
+ * Compare two export lists by path.
+ */
+static int
+mel_compare(const void *a, const void *b)
+{
+       const struct mountd_exports_list *mela = a;
+       const struct mountd_exports_list *melb = b;
+
+       return strcmp(mela->mel_path, melb->mel_path);
+}
+
+/*
  * Get the export list
  */
 /* ARGSUSED */
@@ -1216,7 +1230,7 @@ get_exportlist(int n)
        struct exportlist *ep, *ep2;
        struct grouplist *grp, *tgrp;
        struct statvfs *fsp;
-       int num, i;
+       int i, j;
        FILE *exp_file;
 
 
@@ -1243,20 +1257,14 @@ get_exportlist(int n)
         * And delete exports that are in the kernel for all local
         * file systems.
         */
-       num = getmntinfo(&fsp, MNT_NOWAIT);
-       for (i = 0; i < num; i++) {
-               struct mountd_exports_list mel;
-
-               /* Delete all entries from the export list. */
-               mel.mel_path = fsp->f_mntonname;
-               mel.mel_nexports = 0;
-               if (nfssvc(NFSSVC_SETEXPORTSLIST, &mel) == -1 &&
-                   errno != EOPNOTSUPP)
-                       syslog(LOG_ERR, "Can't delete exports for %s (%m)",
-                           fsp->f_mntonname);
-
-               fsp++;
+       mel_tab_len = getmntinfo(&fsp, MNT_NOWAIT);
+       mel_tab = ecalloc(mel_tab_len, sizeof(*mel_tab));
+       for (i = 0; i < mel_tab_len; i++) {
+               mel_tab[i].mel_path = estrdup(fsp[i].f_mntonname);
+               mel_tab[i].mel_nexports = 0;
+               mel_tab[i].mel_exports = NULL;
        }
+       qsort(mel_tab, mel_tab_len, sizeof(mel_tab[0]), mel_compare);
 
        /*
         * Read in the exports file and build the list, calling
@@ -1278,6 +1286,30 @@ get_exportlist(int n)
 
                (void)fclose(exp_file);
        }
+
+       for (i = 0; i < mel_tab_len; i++) {
+               struct mountd_exports_list *mel = &mel_tab[i];
+
+               if (nfssvc(NFSSVC_REPLACEEXPORTSLIST, mel) == -1 &&
+                   (mel->mel_nexports > 0 || errno != EOPNOTSUPP))
+                       syslog(LOG_ERR, "Can't update exports for %s (%m)",
+                           mel_tab[i].mel_path);
+               for (j = 0; j < (int)mel_tab->mel_nexports; j++) {
+                       struct export_args *export = &mel->mel_exports[j];
+
+                       if (export->ex_indexfile)
+                               free(export->ex_indexfile);
+                       if (export->ex_addr)
+                               free(export->ex_addr);
+                       if (export->ex_mask)
+                               free(export->ex_mask);
+               }
+               if (mel->mel_nexports > 0)
+                       free(mel->mel_exports);
+               free(__UNCONST(mel->mel_path));
+       }
+       free(mel_tab);
+       mel_tab_len = 0;
 }
 
 /*
@@ -1923,30 +1955,38 @@ add_export_arg(const char *path, int exf
     struct sockaddr *addrp, int addrlen, struct sockaddr *maskp, int masklen,
     char *indexfile)
 {
-       struct mountd_exports_list mel;
-       struct export_args export;
-       int error;
+       const struct mountd_exports_list mel_key = { .mel_path = path };
+       struct mountd_exports_list *mel;
+       struct export_args *export;
 
        if (addrp != NULL && addrp->sa_family == AF_INET6 && have_v6 == 0)
                return 0;
 
-       mel.mel_path = path;
-       mel.mel_nexports = 1;
-       mel.mel_exports = &export;
+       mel = bsearch(&mel_key, mel_tab, mel_tab_len, sizeof(mel_tab[0]),
+           mel_compare);
+       if (mel == NULL) {
+               syslog(LOG_ERR, "Can't change attributes for %s: not found",
+                   path);
+               return 1;
+       }
+       ereallocarr(&mel->mel_exports, mel->mel_nexports + 1,
+           sizeof(*mel->mel_exports));
+       export = &mel->mel_exports[mel->mel_nexports++];
+       memset(export, 0, sizeof(*export));
 
-       export.ex_flags = exflags;
-       export.ex_anon = *anoncrp;
-       export.ex_indexfile = indexfile;
-       export.ex_addr = addrp;
-       export.ex_addrlen = addrlen;
-       export.ex_mask = maskp;
-       export.ex_masklen = masklen;
-
-       error = nfssvc(NFSSVC_SETEXPORTSLIST, &mel);
-
-       if (error) {
-               syslog(LOG_ERR, "Can't change attributes for %s: %m", path);
-               return 1;
+       export->ex_flags = exflags;
+       export->ex_anon = *anoncrp;
+       if (indexfile)
+               export->ex_indexfile = estrdup(indexfile);
+       if (addrlen > 0) {
+               export->ex_addr = emalloc(addrlen);
+               export->ex_addrlen = addrlen;
+               memcpy(export->ex_addr, addrp, addrlen);
+       }
+       if (masklen > 0) {
+               export->ex_mask = emalloc(masklen);
+               export->ex_masklen = masklen;
+               memcpy(export->ex_mask, maskp, masklen);
        }
 
        return 0;



Home | Main Index | Thread Index | Old Index