From owner-svn-src-projects@freebsd.org Fri Apr 28 13:15:43 2017 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4E970D53E5D for ; Fri, 28 Apr 2017 13:15:43 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 11BB8174B; Fri, 28 Apr 2017 13:15:43 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v3SDFgwb063000; Fri, 28 Apr 2017 13:15:42 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v3SDFgPV062998; Fri, 28 Apr 2017 13:15:42 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201704281315.v3SDFgPV062998@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Fri, 28 Apr 2017 13:15:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r317553 - projects/pnfs-planb-server/usr.sbin/nfsd X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Apr 2017 13:15:43 -0000 Author: rmacklem Date: Fri Apr 28 13:15:41 2017 New Revision: 317553 URL: https://svnweb.freebsd.org/changeset/base/317553 Log: Update nfsd with the pNFS code. Modified: projects/pnfs-planb-server/usr.sbin/nfsd/nfsd.8 projects/pnfs-planb-server/usr.sbin/nfsd/nfsd.c Modified: projects/pnfs-planb-server/usr.sbin/nfsd/nfsd.8 ============================================================================== --- projects/pnfs-planb-server/usr.sbin/nfsd/nfsd.8 Fri Apr 28 13:13:23 2017 (r317552) +++ projects/pnfs-planb-server/usr.sbin/nfsd/nfsd.8 Fri Apr 28 13:15:41 2017 (r317553) @@ -41,6 +41,7 @@ server .Op Fl ardute .Op Fl n Ar num_servers .Op Fl h Ar bindip +.Op Fl p Ar pnfs_setup .Op Fl Fl maxthreads Ar max_threads .Op Fl Fl minthreads Ar min_threads .Sh DESCRIPTION @@ -103,6 +104,35 @@ It may also be specified in addition to options given. Note that NFS/UDP does not operate properly when bound to the wildcard IP address whether you use -a or do not use -h. +.It Fl p Ar pnfs_setup +Enables pNFS support in the server and specifies the information that the +daemon needs to start it. +This option can only be used on one server and specifies that this server +will be the MetaData Server (MDS) for the pNFS service. +This can only be done if there is at least one FreeBSD system configured +as a Data Server (DS) for it to use. +.Pp +The +.Ar pnfs_setup +string is a set of ',' separated fields: +.Bl -tag -width Ds +.It +Each of these fields specifies one Data Server. +It consists of a server hostname, followed by a ':' +and the directory path where the DS's data storage file system is mounted on +this MDS server. +The DS storage file systems must be mounted on this system before the +.Nm +is started with this option specified. +For example: +.sp +nfsv4-ds0:/DS0,nfsv4-ds1:/DS1 +.sp +Would specify two DS servers called nfsv4-ds0 and nfsv4-ds1 that comprise the +data storage component of the pNFS service. +The directories "/DS0" and "/DS1" are where the DS storage servers exported +storage directories are mounted on this system (which will act as the MDS). +.El .It Fl t Serve .Tn TCP NFS Modified: projects/pnfs-planb-server/usr.sbin/nfsd/nfsd.c ============================================================================== --- projects/pnfs-planb-server/usr.sbin/nfsd/nfsd.c Fri Apr 28 13:13:23 2017 (r317552) +++ projects/pnfs-planb-server/usr.sbin/nfsd/nfsd.c Fri Apr 28 13:15:41 2017 (r317553) @@ -59,12 +59,16 @@ static const char rcsid[] = #include #include #include +#include #include #include -#include #include +#include +#include +#include + #include #include #include @@ -95,6 +99,8 @@ static int stablefd = -1; /* Fd for the static int backupfd; /* Fd for the backup stable restart file */ static const char *getopt_shortopts; static const char *getopt_usage; +static char *dshost = NULL; +static int dshostc = 0; static int minthreads_set; static int maxthreads_set; @@ -103,9 +109,18 @@ static struct option longopts[] = { { "debug", no_argument, &debug, 1 }, { "minthreads", required_argument, &minthreads_set, 1 }, { "maxthreads", required_argument, &maxthreads_set, 1 }, + { "pnfs", required_argument, NULL, 'p' }, { NULL, 0, NULL, 0} }; +struct nfhret { + u_long stat; + long vers; + long auth; + long fhsize; + u_char nfh[NFS3_FHSIZE]; +}; + static void cleanup(int); static void child_cleanup(int); static void killchildren(void); @@ -114,13 +129,14 @@ static void nonfs(int); static void reapchild(int); static int setbindhost(struct addrinfo **ia, const char *bindhost, struct addrinfo hints); -static void start_server(int); +static void start_server(int, struct nfsd_nfsd_args *); static void unregistration(void); static void usage(void); static void open_stable(int *, int *); static void copy_stable(int, int); static void backup_stable(int); static void set_nfsdcnt(int); +static void parse_dsserver(const char *, struct nfsd_nfsd_args *); /* * Nfs server daemon mostly just a user context for nfssvc() @@ -166,15 +182,18 @@ main(int argc, char **argv) const char *lopt; char **bindhost = NULL; pid_t pid; + struct nfsd_nfsd_args nfsdargs; nfsdcnt = DEFNFSDCNT; unregister = reregister = tcpflag = maxsock = 0; bindanyflag = udpflag = connect_type_cnt = bindhostc = 0; - getopt_shortopts = "ah:n:rdtue"; + getopt_shortopts = "ah:n:rdtuep:"; getopt_usage = "usage:\n" " nfsd [-ardtue] [-h bindip]\n" - " [-n numservers] [--minthreads #] [--maxthreads #]\n"; + " [-n numservers] [--minthreads #] [--maxthreads #]\n" + " [-p/--pnfs dsserver0:/dsserver0-mounted-on-dir,...," + "dsserverN:/dsserverN-mounted-on-dir\n"; while ((ch = getopt_long(argc, argv, getopt_shortopts, longopts, &longindex)) != -1) switch (ch) { @@ -208,6 +227,10 @@ main(int argc, char **argv) case 'e': /* now a no-op, since this is the default */ break; + case 'p': + /* Parse out the DS server host names and the port#s. */ + parse_dsserver(optarg, &nfsdargs); + break; case 0: lopt = longopts[longindex].name; if (!strcmp(lopt, "minthreads")) { @@ -427,7 +450,7 @@ main(int argc, char **argv) exit(1); } nfssvc_addsock = NFSSVC_NFSDADDSOCK; - nfssvc_nfsd = NFSSVC_NFSDNFSD; + nfssvc_nfsd = NFSSVC_NFSDNFSD | NFSSVC_NEWSTRUCT; if (tcpflag) { /* @@ -445,7 +468,7 @@ main(int argc, char **argv) } else { (void)signal(SIGUSR1, child_cleanup); setproctitle("server"); - start_server(0); + start_server(0, &nfsdargs); } } @@ -766,7 +789,7 @@ main(int argc, char **argv) * a "server" too. start_server will not return. */ if (!tcpflag) - start_server(1); + start_server(1, &nfsdargs); /* * Loop forever accepting connections and passing the sockets @@ -990,10 +1013,9 @@ get_tuned_nfsdcount(void) } static void -start_server(int master) +start_server(int master, struct nfsd_nfsd_args *nfsdargp) { char principal[MAXHOSTNAMELEN + 5]; - struct nfsd_nfsd_args nfsdargs; int status, error; char hostname[MAXHOSTNAMELEN + 1], *cp; struct addrinfo *aip, hints; @@ -1016,17 +1038,17 @@ start_server(int master) freeaddrinfo(aip); } } - nfsdargs.principal = principal; + nfsdargp->principal = principal; if (nfsdcnt_set) - nfsdargs.minthreads = nfsdargs.maxthreads = nfsdcnt; + nfsdargp->minthreads = nfsdargp->maxthreads = nfsdcnt; else { - nfsdargs.minthreads = minthreads_set ? minthreads : get_tuned_nfsdcount(); - nfsdargs.maxthreads = maxthreads_set ? maxthreads : nfsdargs.minthreads; - if (nfsdargs.maxthreads < nfsdargs.minthreads) - nfsdargs.maxthreads = nfsdargs.minthreads; + nfsdargp->minthreads = minthreads_set ? minthreads : get_tuned_nfsdcount(); + nfsdargp->maxthreads = maxthreads_set ? maxthreads : nfsdargp->minthreads; + if (nfsdargp->maxthreads < nfsdargp->minthreads) + nfsdargp->maxthreads = nfsdargp->minthreads; } - error = nfssvc(nfssvc_nfsd, &nfsdargs); + error = nfssvc(nfssvc_nfsd, nfsdargp); if (error < 0 && errno == EAUTH) { /* * This indicates that it could not register the @@ -1036,7 +1058,7 @@ start_server(int master) */ syslog(LOG_ERR, "No gssd, using AUTH_SYS only"); principal[0] = '\0'; - error = nfssvc(nfssvc_nfsd, &nfsdargs); + error = nfssvc(nfssvc_nfsd, nfsdargp); } if (error < 0) { syslog(LOG_ERR, "nfssvc: %m"); @@ -1139,3 +1161,126 @@ backup_stable(__unused int signo) copy_stable(stablefd, backupfd); } +/* + * Parse the pNFS string and extract the DS servers and ports numbers. + */ +static void +parse_dsserver(const char *optarg, struct nfsd_nfsd_args *nfsdargp) +{ + char *ad, *cp, *cp2, *dsaddr, *dshost, *dspath, *dsvol, nfsprt[9]; + int adsiz, dsaddrcnt, dshostcnt, dspathcnt, ecode, hostsiz, pathsiz; + size_t dsaddrsiz, dshostsiz, dspathsiz, nfsprtsiz; + struct addrinfo hints, *ai_tcp; + struct sockaddr_in *sin; + + cp = strdup(optarg); + if (cp == NULL) + errx(1, "Out of memory"); + + /* Now, do the host names. */ + dspathsiz = 1024; + dspathcnt = 0; + dspath = malloc(dspathsiz); + if (dspath == NULL) + errx(1, "Out of memory"); + dshostsiz = 1024; + dshostcnt = 0; + dshost = malloc(dshostsiz); + if (dshost == NULL) + errx(1, "Out of memory"); + dsaddrsiz = 1024; + dsaddrcnt = 0; + dsaddr = malloc(dsaddrsiz); + if (dsaddr == NULL) + errx(1, "Out of memory"); + + /* Put the NFS port# in "." form. */ + snprintf(nfsprt, 9, ".%d.%d", 2049 >> 8, 2049 & 0xff); + nfsprtsiz = strlen(nfsprt); + + ai_tcp = NULL; + /* Loop around for each DS server name. */ + do { + cp2 = strchr(cp, ','); + if (cp2 != NULL) { + *cp2++ = '\0'; + if (*cp2 == '\0') + usage(); + } + dsvol = strchr(cp, ':'); + if (dsvol == NULL || *(dsvol + 1) == '\0') + usage(); + *dsvol++ = '\0'; + +printf("pnfs path=%s\n", dsvol); + /* Append this pathname to dspath. */ + pathsiz = strlen(dsvol); + if (dspathcnt + pathsiz + 1 > dspathsiz) { + dspathsiz *= 2; + dspath = realloc(dspath, dspathsiz); + if (dspath == NULL) + errx(1, "Out of memory"); + } + strcpy(&dspath[dspathcnt], dsvol); + dspathcnt += pathsiz + 1; + + if (ai_tcp != NULL) + freeaddrinfo(ai_tcp); + + /* Get the fully qualified domain name and IP address. */ + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + ecode = getaddrinfo(cp, NULL, &hints, &ai_tcp); + if (ecode != 0) + err(1, "getaddrinfo pnfs: %s %s", cp, + gai_strerror(ecode)); + sin = (struct sockaddr_in *)ai_tcp->ai_addr; + if (sin->sin_family != AF_INET) + err(1, "getaddrinfo() returned non-INET address"); + + /* Append this address to dsaddr. */ + ad = inet_ntoa(sin->sin_addr); + adsiz = strlen(ad); + if (dsaddrcnt + adsiz + nfsprtsiz + 1 > dsaddrsiz) { + dsaddrsiz *= 2; + dsaddr = realloc(dsaddr, dsaddrsiz); + if (dsaddr == NULL) + errx(1, "Out of memory"); + } + strcpy(&dsaddr[dsaddrcnt], ad); + strcat(&dsaddr[dsaddrcnt], nfsprt); + dsaddrcnt += adsiz + nfsprtsiz + 1; + + /* Append this hostname to dshost. */ + hostsiz = strlen(ai_tcp->ai_canonname); + if (dshostcnt + hostsiz + 1 > dshostsiz) { + dshostsiz *= 2; + dshost = realloc(dshost, dshostsiz); + if (dshost == NULL) + errx(1, "Out of memory"); + } + strcpy(&dshost[dshostcnt], ai_tcp->ai_canonname); + dshostcnt += hostsiz + 1; + + cp = cp2; + } while (cp != NULL); + + /* + * At the point, ai_tcp refers to the last DS server host and + * sin is set to point to the sockaddr structure in it. + * Set the port# for the DS Mount protocol and get the DS root FH. + */ + sin->sin_port = htons(2049); + nfsdargp->addr = dsaddr; + nfsdargp->addrlen = dsaddrcnt; + nfsdargp->dnshost = dshost; + nfsdargp->dnshostlen = dshostcnt; + nfsdargp->dspath = dspath; + nfsdargp->dspathlen = dspathcnt; + freeaddrinfo(ai_tcp); +} + +