Date: Sat, 15 Dec 2001 00:34:35 +0000 From: Ian Dowse <iedowse@maths.tcd.ie> To: current@freebsd.org Subject: mountd(8) leaving filesystems exported Message-ID: <200112150034.aa63895@salmon.maths.tcd.ie>
next in thread | raw e-mail | index | archive | help
There are quite a few assumptions in mountd(8) about the layout of the per-filesystem mount(2) `data' struct, which make the code quite ugly. It uses a union to ensure that it supplies a large enough structure to mount(2), but regardless of the filesystem type, it always initialises the UFS version. One nasty bug is that the code for un-exporting filesystems checks to see if the filesystem is among a list of supported types, but the code for exporting doesn't. This list of supported filesystems does not include ext2fs or hpfs, so you can successfully export these filesystems, but they remain exported even when the /etc/exports entry is removed and mountd is restarted or sent a SIGHUP, and no errors are logged... The patch below should address this issue by checking the same list of filesystems in both cases, and adding ext2fs and hpfs to the filesystem list. It also avoids the need to assume that all xxx_args have the export_args in the same place by storing the offsets in a table. I am aware that there is work ongoing in the area of mount(2), so maybe the patch is overkill at this time. Any comments? Ian Index: mountd.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sbin/mountd/mountd.c,v retrieving revision 1.59 diff -u -r1.59 mountd.c --- mountd.c 20 Sep 2001 02:15:17 -0000 1.59 +++ mountd.c 15 Dec 2001 00:10:47 -0000 @@ -76,6 +76,7 @@ #include <netdb.h> #include <pwd.h> #include <signal.h> +#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -157,6 +158,29 @@ nfsfh_t fhr_fh; }; +/* Union of mount(2) `data' structs for supported filesystems. */ +union mountdata { + struct ufs_args ua; + struct iso_args ia; + struct msdosfs_args da; + struct ntfs_args na; +}; + +/* Find the offset into the mountdata union of a filesystem's export_args. */ +struct ea_off { + char *fsname; + int exportargs_off; +} ea_offtable[] = { + {"ufs", offsetof(union mountdata, ua.export)}, + {"ifs", offsetof(union mountdata, ua.export)}, + {"ext2fs", offsetof(union mountdata, ua.export)}, + {"cd9660", offsetof(union mountdata, ia.export)}, + {"msdosfs", offsetof(union mountdata, da.export)}, + {"ntfs", offsetof(union mountdata, na.export)}, + {"hpfs", offsetof(union mountdata, ua.export)}, /* XXX */ + {NULL, 0} +}; + /* Global defs */ char *add_expdir __P((struct dirlist **, char *, int)); void add_dlist __P((struct dirlist **, struct dirlist *, @@ -191,6 +215,7 @@ void huphandler(int sig); int makemask(struct sockaddr_storage *ssp, int bitlen); void mntsrv __P((struct svc_req *, SVCXPRT *)); +struct export_args *mountdata_to_eap __P((union mountdata *, struct statfs *)); void nextfield __P((char **, char **)); void out_of_mem __P((void)); void parsecred __P((char *, struct xucred *)); @@ -884,6 +909,8 @@ void get_exportlist() { + union mountdata args; + struct export_args *eap; struct exportlist *ep, *ep2; struct grouplist *grp, *tgrp; struct exportlist **epp; @@ -918,26 +945,16 @@ /* * And delete exports that are in the kernel for all local * file systems. - * XXX: Should know how to handle all local exportable file systems - * instead of just "ufs". */ num = getmntinfo(&fsp, MNT_NOWAIT); for (i = 0; i < num; i++) { - union { - struct ufs_args ua; - struct iso_args ia; - struct msdosfs_args da; - struct ntfs_args na; - } targs; - - if (!strcmp(fsp->f_fstypename, "ufs") || - !strcmp(fsp->f_fstypename, "msdosfs") || - !strcmp(fsp->f_fstypename, "ntfs") || - !strcmp(fsp->f_fstypename, "cd9660")) { - targs.ua.fspec = NULL; - targs.ua.export.ex_flags = MNT_DELEXPORT; + eap = mountdata_to_eap(&args, fsp); + if (eap != NULL) { + /* This is a filesystem that supports NFS exports. */ + bzero(&args, sizeof(args)); + eap->ex_flags = MNT_DELEXPORT; if (mount(fsp->f_fstypename, fsp->f_mntonname, - fsp->f_flags | MNT_UPDATE, (caddr_t)&targs) < 0 && + fsp->f_flags | MNT_UPDATE, &args) < 0 && errno != ENOENT) syslog(LOG_ERR, "can't delete exports for %s: %m", @@ -1711,23 +1728,23 @@ int dirplen; struct statfs *fsb; { + union mountdata args; struct statfs fsb1; struct addrinfo *ai; struct export_args *eap; char *cp = NULL; int done; char savedc = '\0'; - union { - struct ufs_args ua; - struct iso_args ia; - struct msdosfs_args da; - struct ntfs_args na; - } args; bzero(&args, sizeof args); - /* XXX, we assume that all xx_args look like ufs_args. */ - args.ua.fspec = 0; - eap = &args.ua.export; + if ((eap = mountdata_to_eap(&args, fsb)) == NULL) { + if (debug) + warnx("%s: cannot export %s filesystems", dirp, + fsb->f_fstypename); + syslog(LOG_ERR, "%s: cannot export %s filesystems", dirp, + fsb->f_fstypename); + return (1); + } eap->ex_flags = exflags; eap->ex_anon = *anoncrp; @@ -1777,8 +1794,6 @@ * XXX: * Maybe I should just use the fsb->f_mntonname path instead * of looping back up the dirp to the mount point?? - * Also, needs to know how to export all types of local - * exportable file systems and not just "ufs". */ while (mount(fsb->f_fstypename, dirp, fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { @@ -1829,6 +1844,25 @@ if (cp) *cp = savedc; return (0); +} + +/* + * For the filesystem specified by fsp, return a pointer to the + * export_args structure within the mountdata union. If the filesystem + * does not support NFS exports, NULL is returned instead. + */ +struct export_args * +mountdata_to_eap(mntdata, fsp) + union mountdata *mntdata; + struct statfs *fsp; +{ + struct ea_off *p; + + for (p = ea_offtable; p->fsname != NULL; p++) + if (strcmp(fsp->f_fstypename, p->fsname) == 0) + return (struct export_args *)((char *)mntdata + + p->exportargs_off); + return (NULL); } /* To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <200112150034.aa63895>