Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Jun 2010 15:57:17 GMT
From:      "Richard S. Conto" <Richard.Conto@gmail.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/147881: ZFS "sharenfs" doesn't allow different "exports" options for different hosts
Message-ID:  <201006151557.o5FFvH4j011637@www.freebsd.org>
Resent-Message-ID: <201006151600.o5FG01Uo004872@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         147881
>Category:       kern
>Synopsis:       ZFS "sharenfs" doesn't allow different "exports" options for different hosts
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jun 15 16:00:01 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Richard S. Conto
>Release:        FreeBSD 8 CURRENT
>Organization:
Home Use / University of Michigan
>Environment:
FreeBSD foundry.family 8.1-PRERELEASE FreeBSD 8.1-PRERELEASE #0: Sun Jun 13 03:31:00 EDT 2010     rsc@foundry.family:/usr/obj/usr/src/sys/FOUNDRY  i386


>Description:
I found that I was unable to selectively NFS export my ZFS filesystems such that some hosts had "-maproot=0" and others had "-maproot=nobody:nobody".

The syntax and operation of 'zfs set sharenfs="xxx" <poolname>' followed by "zfs share -a" doesn't allow for a multi-valued 'xxx'. 
>How-To-Repeat:
(1) Set up ZFS based NFS host
(2) Set up two NFS clients, one which should have "root" access to the NFS exports from the ZFS host, one which shouldn't
(3) Try to make it so.
>Fix:
Here's a patch to the compatibility shim "fsshare.c" that allows the following syntax for "sharenfs='xxxx' where 'xxxx' can be:

(1) <export_options>... <export_hosts>...
(2) <export_options_1>... <export_hosts_1> ; <export_options_2>... <export_hosts_2>... ; ... <export_options_n>... <export_hosts_n>...

Empty sets of '<exports_options_n>... <exports_hosts_n>...' are allowed (i.e.: multiple ';'s with only whitespace between them.

Comments (with a leading '#') for '<exports_options_n>... <exports_hosts_n>...' are supported to allow a ZFS administrator to disable a particular configuration.

Patch attached with submission follows:

Index: ./src/cddl/compat/opensolaris/misc/fsshare.c
===================================================================
RCS file: /shares/Home/cvsupin/FreeBSD/FreeBSD-all/src/cddl/compat/opensolaris/misc/fsshare.c,v
retrieving revision 1.3.4.1
diff -c -b -w -r1.3.4.1 fsshare.c
*** ./src/cddl/compat/opensolaris/misc/fsshare.c	3 Aug 2009 08:13:06 -0000	1.3.4.1
--- ./src/cddl/compat/opensolaris/misc/fsshare.c	13 Jun 2010 18:11:53 -0000
***************
*** 32,37 ****
--- 32,38 ----
  #include <unistd.h>
  #include <fcntl.h>
  #include <string.h>
+ #include <strings.h>
  #include <errno.h>
  #include <libutil.h>
  #include <assert.h>
***************
*** 149,157 ****
      int share)
  {
  	char tmpfile[PATH_MAX];
  	char *line;
  	FILE *newfd, *oldfd;
! 	int fd, error;
  
  	newfd = oldfd = NULL;
  	error = 0;
--- 150,160 ----
      int share)
  {
  	char tmpfile[PATH_MAX];
+ 	char each[OPTSSIZE];     /* Multiple export options per filesystem. */
  	char *line;
+ 	char *cur, *next;		/* Next set of mountopts/hosts */
  	FILE *newfd, *oldfd;
! 	int fd, error, count;
  
  	newfd = oldfd = NULL;
  	error = 0;
***************
*** 209,217 ****
--- 212,287 ----
  		goto out;
  	}
  	if (share) {
+ 	        /*
+ 		 * if 'shareopts' has ';' separators, then put out multiple
+ 		 * exports points with (with presumeably different mountoptions and
+ 		 * hosts.)
+ 		 *
+ 		 * If the mount options begin with a '#', treat as a comment and IGNORE
+ 		 * (to allow ZFS administrators to leave configurations in place but disabled.)
+ 		 */
+ 
+ 	  	if ((next = index(shareopts, ';')) == (char *) NULL) {
+ 			/* Original FreeBSD implementation - compatibility? 
+ 			 * Note: This DOESN'T check for '#' comment configurations!
+ 			 */
  		  	fprintf(newfd, "%s\t%s\n", mountpoint,
  				translate_opts(shareopts));
+ 		} else {
+ 		     /* This code doesn't need to be guarded - except for the 
+ 		      * extra noise comments it puts into the exports file. */
+ 		      count = 0; 
+ 		      strncpy (each, shareopts, sizeof(each)-1);  /* Local copy to edit. */
+ 
+ 		      fprintf(newfd, "#\n#%s\t%s\n", mountpoint, shareopts);	/* verbose: show originale */
+ 
+ 		      for (cur=each, next = index (each, ';');  next != (char *) NULL; 
+ 					   next = index(next+1, ';')) {
+ 			    /* If we blow up writing the new exports file, don't use it! */
+ 			    if (ferror(newfd)) {
+ 			     	error = ferror(newfd);
+ 				goto out;
+ 			    }
+ 
+ 			    *next = '\0';  /* Clobber the ';' */
+ 
+ 			    /* Skip leading whitespace. */
+ 			    while (*cur && isspace(*cur)) {
+ 			      	cur ++;
+ 			    }
+ 			    /* If there is anything left, use it - if it isn't a comment. */
+ 			    if (*cur && (*cur != '#'))  {
+ 			    	fprintf(newfd, "%s\t%s\n", mountpoint, 
+ 					 translate_opts(cur));
+ 				count ++;	/* Count only mountpoints */
+ 			    }
+ 
+ 			    cur = next + 1;  /* Point past the ';' we found. */
+ 		      }
+ 		      
+ 		      /* If anything is left, run it out too. */
+ 		      if (*cur) {
+ 			    /* Skip leading whitespace. */
+ 			    while (*cur && isspace(*cur)) {
+ 			    	cur ++;
+ 			    }
+ 			    if (*cur && (*cur != '#')) {
+ 			    	fprintf(newfd, "%s\t%s\n", mountpoint, 
+ 					translate_opts(cur));
+ 				count ++;
+ 			    }
+ 		      }
+ 
+ 		      fprintf(newfd, "# %d exports of \"%s\"\n", mountpoint);
+ 
+ 		} /* multi-valued ';' stuff (with '#'s too.) */
+ 
+ 		/* If we blew up writing the new exports file, don't use it! */
+ 		if (ferror(newfd)) {
+ 		      error = ferror(newfd);
+ 		      goto out;
  		}
+ 	} /* if (share) */
  
  out:
  	if (error != 0)


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006151557.o5FFvH4j011637>