diff -up nfs-utils-1.3.0/configure.ac.orig nfs-utils-1.3.0/configure.ac --- nfs-utils-1.3.0/configure.ac.orig 2017-03-31 15:55:05.544831618 -0400 +++ nfs-utils-1.3.0/configure.ac 2017-03-31 15:58:38.833955546 -0400 @@ -64,8 +64,14 @@ unitdir=/usr/lib/systemd/system AC_ARG_WITH(systemd, [AC_HELP_STRING([--with-systemd@<:@=unit-dir-path@:>@], [install systemd unit files @<:@Default: no, and path defaults to /usr/lib/systemd/system if not given@:>@])], - test "$withval" = "no" && use_systemd=0 || unitdir=$withval use_systemd=1 - use_systemd=0 + if test "$withval" != "no" ; then + use_systemd=1 + if test "$withval" != "yes" ; then + unitdir=$withval + fi + else + use_systemd=0 + fi ) AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1]) AC_SUBST(unitdir) diff -up nfs-utils-1.3.0/.gitignore.orig nfs-utils-1.3.0/.gitignore --- nfs-utils-1.3.0/.gitignore.orig 2014-03-25 11:12:07.000000000 -0400 +++ nfs-utils-1.3.0/.gitignore 2017-03-31 15:55:47.123245655 -0400 @@ -69,6 +69,7 @@ tests/nsm_client/nlm_sm_inter_clnt.c tests/nsm_client/nlm_sm_inter_svc.c tests/nsm_client/nlm_sm_inter_xdr.c utils/nfsidmap/nfsidmap +systemd/nfs-server-generator # cscope database files cscope.* # generic editor backup et al diff -up nfs-utils-1.3.0/support/export/export.c.orig nfs-utils-1.3.0/support/export/export.c --- nfs-utils-1.3.0/support/export/export.c.orig 2017-03-31 15:55:05.528831459 -0400 +++ nfs-utils-1.3.0/support/export/export.c 2017-03-31 15:55:47.124245665 -0400 @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "xmalloc.h" #include "nfslib.h" #include "exportfs.h" @@ -68,11 +70,15 @@ static void warn_duplicated_exports(nfs_ /** * export_read - read entries from /etc/exports * @fname: name of file to read from + * @ignore_hosts: don't check validity of host names * * Returns number of read entries. + * @ignore_hosts can be set when the host names won't be used + * and when getting delays or errors due to problems with + * hostname looking is not acceptable. */ int -export_read(char *fname) +export_read(char *fname, int ignore_hosts) { struct exportent *eep; nfs_export *exp; @@ -81,7 +87,7 @@ export_read(char *fname) setexportent(fname, "r"); while ((eep = getexportent(0,1)) != NULL) { - exp = export_lookup(eep->e_hostname, eep->e_path, 0); + exp = export_lookup(eep->e_hostname, eep->e_path, ignore_hosts); if (!exp) { if (export_create(eep, 0)) /* possible complaints already logged */ @@ -94,6 +100,70 @@ export_read(char *fname) return volumes; } + +/** + * export_d_read - read entries from /etc/exports. + * @fname: name of directory to read from + * @ignore_hosts: don't check validity of host names + * + * Returns number of read entries. + * Based on mnt_table_parse_dir() in + * util-linux-ng/shlibs/mount/src/tab_parse.c + */ +int +export_d_read(const char *dname, int ignore_hosts) +{ + int n = 0, i; + struct dirent **namelist = NULL; + int volumes = 0; + + + n = scandir(dname, &namelist, NULL, versionsort); + if (n < 0) { + if (errno == ENOENT) + /* Silently return */ + return volumes; + xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno)); + } else if (n == 0) + return volumes; + + for (i = 0; i < n; i++) { + struct dirent *d = namelist[i]; + size_t namesz; + char fname[PATH_MAX + 1]; + int fname_len; + + + if (d->d_type != DT_UNKNOWN + && d->d_type != DT_REG + && d->d_type != DT_LNK) + continue; + if (*d->d_name == '.') + continue; + +#define _EXT_EXPORT_SIZ (sizeof(_EXT_EXPORT) - 1) + namesz = strlen(d->d_name); + if (!namesz + || namesz < _EXT_EXPORT_SIZ + 1 + || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ), + _EXT_EXPORT)) + continue; + + fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name); + if (fname_len > PATH_MAX) { + xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname); + continue; + } + + volumes += export_read(fname, ignore_hosts); + } + + for (i = 0; i < n; i++) + free(namelist[i]); + free(namelist); + + return volumes; +} /** * export_create - create an in-core nfs_export record from an export entry diff -up nfs-utils-1.3.0/support/include/exportfs.h.orig nfs-utils-1.3.0/support/include/exportfs.h --- nfs-utils-1.3.0/support/include/exportfs.h.orig 2017-03-31 15:55:05.528831459 -0400 +++ nfs-utils-1.3.0/support/include/exportfs.h 2017-03-31 15:55:47.124245665 -0400 @@ -133,7 +133,8 @@ struct addrinfo * client_resolve(const int client_member(const char *client, const char *name); -int export_read(char *fname); +int export_read(char *fname, int ignore_hosts); +int export_d_read(const char *dname, int ignore_hosts); void export_reset(nfs_export *); nfs_export * export_lookup(char *hname, char *path, int caconical); nfs_export * export_find(const struct addrinfo *ai, diff -up nfs-utils-1.3.0/systemd/Makefile.am.orig nfs-utils-1.3.0/systemd/Makefile.am --- nfs-utils-1.3.0/systemd/Makefile.am.orig 2017-03-31 15:55:05.545831628 -0400 +++ nfs-utils-1.3.0/systemd/Makefile.am 2017-03-31 15:55:47.124245665 -0400 @@ -4,7 +4,6 @@ MAINTAINERCLEANFILES = Makefile.in unit_files = \ nfs-client.target \ - \ auth-rpcgss-module.service \ nfs-blkmap.service \ nfs-config.service \ @@ -15,8 +14,6 @@ unit_files = \ rpc-gssd.service \ rpc-statd-notify.service \ rpc-statd.service \ - rpc-svcgssd.service \ - \ proc-fs-nfsd.mount \ var-lib-nfs-rpc_pipefs.mount @@ -25,8 +22,16 @@ man7_MANS = nfs.systemd.man EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS) unit_dir = /usr/lib/systemd/system +generator_dir = /usr/lib/systemd/system-generators + +EXTRA_PROGRAMS = nfs-server-generator +genexecdir = $(generator_dir) +nfs_server_generator_LDADD = ../support/export/libexport.a \ + ../support/nfs/libnfs.a \ + ../support/misc/libmisc.a if INSTALL_SYSTEMD +genexec_PROGRAMS = nfs-server-generator install-data-hook: $(unit_files) mkdir -p $(DESTDIR)/$(unitdir) cp $(unit_files) $(DESTDIR)/$(unitdir) diff -up nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig nfs-utils-1.3.0/systemd/nfs-server-generator.c --- nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig 2017-03-31 15:55:47.124245665 -0400 +++ nfs-utils-1.3.0/systemd/nfs-server-generator.c 2017-03-31 15:55:47.124245665 -0400 @@ -0,0 +1,179 @@ +/* + * nfs-server-generator: + * systemd generator to create ordering dependencies between + * nfs-server and various filesystem mounts + * + * 1/ nfs-server should start Before any 'nfs' mountpoints are + * mounted, in case they are loop-back mounts. This ordering is particularly + * important for the shutdown side, so the nfs-server is stopped + * after the filesystems are unmounted. + * 2/ nfs-server should start After all exported filesystems are mounted + * so there is no risk of exporting the underlying directory. + * This is particularly important for _net mounts which + * are not caught by "local-fs.target". + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" +#include "nfslib.h" +#include "exportfs.h" + +/* A simple "set of strings" to remove duplicates + * found in /etc/exports + */ +struct list { + struct list *next; + char *name; +}; +static int is_unique(struct list **lp, char *path) +{ + struct list *l = *lp; + + while (l) { + if (strcmp(l->name, path) == 0) + return 0; + l = l->next; + } + l = malloc(sizeof(*l)); + if (l == NULL) + return 0; + l->name = path; + l->next = *lp; + *lp = l; + return 1; +} + +/* We need to convert a path name to a systemd unit + * name. This requires some translation ('/' -> '-') + * and some escaping. + */ +static void systemd_escape(FILE *f, char *path) +{ + while (*path == '/') + path++; + if (!*path) { + /* "/" becomes "-", otherwise leading "/" is ignored */ + fputs("-", f); + return; + } + while (*path) { + char c = *path++; + + if (c == '/') { + /* multiple non-trailing slashes become '-' */ + while (*path == '/') + path++; + if (*path) + fputs("-", f); + } else if (isalnum(c) || c == ':' || c == '.') + fputc(c, f); + else + fprintf(f, "\\x%02x", c & 0xff); + } +} + +static int has_noauto_flag(char *path) +{ + FILE *fstab; + struct mntent *mnt; + + fstab = setmntent("/etc/fstab", "r"); + if (!fstab) + return 0; + + while ((mnt = getmntent(fstab)) != NULL) { + int l = strlen(mnt->mnt_dir); + if (strncmp(mnt->mnt_dir, path, l) != 0) + continue; + if (path[l] && path[l] != '/') + continue; + if (hasmntopt(mnt, "noauto")) + break; + } + fclose(fstab); + return mnt != NULL; +} + +int main(int argc, char *argv[]) +{ + char *path; + char dirbase[] = "/nfs-server.service.d"; + char filebase[] = "/order-with-mounts.conf"; + nfs_export *exp; + int i; + struct list *list = NULL; + FILE *f, *fstab; + struct mntent *mnt; + + /* Avoid using any external services */ + xlog_syslog(0); + + if (argc != 4 || argv[1][0] != '/') { + fprintf(stderr, "nfs-server-generator: create systemd dependencies for nfs-server\n"); + fprintf(stderr, "Usage: normal-dir early-dir late-dir\n"); + exit(1); + } + + path = malloc(strlen(argv[1]) + sizeof(dirbase) + sizeof(filebase)); + if (!path) + exit(2); + if (export_read(_PATH_EXPORTS, 1) + + export_d_read(_PATH_EXPORTS_D, 1) == 0) + /* Nothing is exported, so nothing to do */ + exit(0); + + strcat(strcpy(path, argv[1]), dirbase); + mkdir(path, 0755); + strcat(path, filebase); + f = fopen(path, "w"); + if (!f) + exit(1); + fprintf(f, "# Automatically generated by nfs-server-generator\n\n[Unit]\n"); + + for (i = 0; i < MCL_MAXTYPES; i++) { + for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + if (!is_unique(&list, exp->m_export.e_path)) + continue; + if (exp->m_export.e_mountpoint) + continue; + if (has_noauto_flag(exp->m_export.e_path)) + continue; + if (strchr(exp->m_export.e_path, ' ')) + fprintf(f, "RequiresMountsFor=\"%s\"\n", + exp->m_export.e_path); + else + fprintf(f, "RequiresMountsFor=%s\n", + exp->m_export.e_path); + } + } + + fstab = setmntent("/etc/fstab", "r"); + if (!fstab) + exit(1); + + while ((mnt = getmntent(fstab)) != NULL) { + if (strcmp(mnt->mnt_type, "nfs") != 0 && + strcmp(mnt->mnt_type, "nfs4") != 0) + continue; + fprintf(f, "Before= "); + systemd_escape(f, mnt->mnt_dir); + fprintf(f, ".mount\n"); + } + + fclose(fstab); + fclose(f); + + exit(0); +} diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c --- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig 2017-03-31 15:55:05.553831708 -0400 +++ nfs-utils-1.3.0/utils/exportfs/exportfs.c 2017-03-31 15:55:47.125245675 -0400 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -48,7 +47,6 @@ static void error(nfs_export *exp, int e static void usage(const char *progname, int n); static void validate_export(nfs_export *exp); static int matchhostname(const char *hostname1, const char *hostname2); -static int export_d_read(const char *dname); static void grab_lockfile(void); static void release_lockfile(void); @@ -190,8 +188,8 @@ main(int argc, char **argv) atexit(release_lockfile); if (f_export && ! f_ignore) { - if (! (export_read(_PATH_EXPORTS) + - export_d_read(_PATH_EXPORTS_D))) { + if (! (export_read(_PATH_EXPORTS, 0) + + export_d_read(_PATH_EXPORTS_D, 0))) { if (f_verbose) xlog(L_WARNING, "No file systems exported!"); } @@ -705,63 +703,6 @@ out: return result; } -/* Based on mnt_table_parse_dir() in - util-linux-ng/shlibs/mount/src/tab_parse.c */ -static int -export_d_read(const char *dname) -{ - int n = 0, i; - struct dirent **namelist = NULL; - int volumes = 0; - - - n = scandir(dname, &namelist, NULL, versionsort); - if (n < 0) { - if (errno == ENOENT) - /* Silently return */ - return volumes; - xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno)); - } else if (n == 0) - return volumes; - - for (i = 0; i < n; i++) { - struct dirent *d = namelist[i]; - size_t namesz; - char fname[PATH_MAX + 1]; - int fname_len; - - - if (d->d_type != DT_UNKNOWN - && d->d_type != DT_REG - && d->d_type != DT_LNK) - continue; - if (*d->d_name == '.') - continue; - -#define _EXT_EXPORT_SIZ (sizeof(_EXT_EXPORT) - 1) - namesz = strlen(d->d_name); - if (!namesz - || namesz < _EXT_EXPORT_SIZ + 1 - || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ), - _EXT_EXPORT)) - continue; - - fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name); - if (fname_len > PATH_MAX) { - xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname); - continue; - } - - volumes += export_read(fname); - } - - for (i = 0; i < n; i++) - free(namelist[i]); - free(namelist); - - return volumes; -} - static char dumpopt(char c, char *fmt, ...) {