summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_export.c
diff options
context:
space:
mode:
authorrodrigc <rodrigc@FreeBSD.org>2007-01-23 06:19:16 +0000
committerrodrigc <rodrigc@FreeBSD.org>2007-01-23 06:19:16 +0000
commit4c351de443e9ab2b6fa6a4032334f316e51f66dc (patch)
treeb37424f0f000b513a4705e0682e802d7a9efc514 /sys/kern/vfs_export.c
parent2685a7063ba2fa89c4894fea7e9bd320a72ba10f (diff)
downloadFreeBSD-src-4c351de443e9ab2b6fa6a4032334f316e51f66dc.zip
FreeBSD-src-4c351de443e9ab2b6fa6a4032334f316e51f66dc.tar.gz
When exiting vfs_export(), delete the "export" option from
the mount options list with vfs_deleteopt(). At this point, the export information is saved in mp->mnt_export, so we can delete the "export" mount option from mp->mnt_optnew and mp->mnt_opt. This fixes read-write/read-only update mounts (mount -u -o rw, mount -u -o ro) of NFS exported directories. For some reason, I could only reproduce the problem with a configuration supplied by Andre: - "options QUOTA" enabled in kernel config - "/ -maproot=root 10.0.1.105" in /etc/exports Reported by: kris, Andre Guibert de Bruet <andy siliconlandmark com>, Andrzej Tobola <ato iem pw edu pl> Tested by: Andre Guibert de Bruet
Diffstat (limited to 'sys/kern/vfs_export.c')
-rw-r--r--sys/kern/vfs_export.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 4ddd758..8a2906b 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -101,12 +101,18 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
* with fields like cr_uidinfo and cr_prison? Currently, this
* routine does not touch them (leaves them as NULL).
*/
- if (argp->ex_anon.cr_version != XUCRED_VERSION)
+ if (argp->ex_anon.cr_version != XUCRED_VERSION) {
+ vfs_mount_error(mp, "ex_anon.cr_version: %d != %d",
+ argp->ex_anon.cr_version, XUCRED_VERSION);
return (EINVAL);
+ }
if (argp->ex_addrlen == 0) {
- if (mp->mnt_flag & MNT_DEFEXPORTED)
+ if (mp->mnt_flag & MNT_DEFEXPORTED) {
+ vfs_mount_error(mp,
+ "MNT_DEFEXPORTED already set for mount %p", mp);
return (EPERM);
+ }
np = &nep->ne_defexported;
np->netc_exflags = argp->ex_flags;
bzero(&np->netc_anon, sizeof(np->netc_anon));
@@ -134,8 +140,9 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
saddr = (struct sockaddr *) (np + 1);
if ((error = copyin(argp->ex_addr, saddr, argp->ex_addrlen)))
goto out;
- if (saddr->sa_family > AF_MAX) {
+ if (saddr->sa_family == AF_UNSPEC || saddr->sa_family > AF_MAX) {
error = EINVAL;
+ vfs_mount_error(mp, "Invalid saddr->sa_family: %d");
goto out;
}
if (saddr->sa_len > argp->ex_addrlen)
@@ -162,8 +169,9 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
}
if ((rnh = nep->ne_rtable[i]) == NULL) {
error = ENOBUFS;
- vfs_mount_error(mp,
- "Unable to initialize radix node head");
+ vfs_mount_error(mp, "%s %s %d",
+ "Unable to initialize radix node head ",
+ "for address family", i);
goto out;
}
}
@@ -233,10 +241,11 @@ vfs_export(struct mount *mp, struct export_args *argp)
int error;
nep = mp->mnt_export;
+ error = 0;
if (argp->ex_flags & MNT_DELEXPORT) {
if (nep == NULL) {
- vfs_deleteopt(mp->mnt_optnew, "export");
- return (ENOENT);
+ error = ENOENT;
+ goto out;
}
if (mp->mnt_flag & MNT_EXPUBLIC) {
vfs_setpublicfs(NULL, NULL, NULL);
@@ -251,7 +260,6 @@ vfs_export(struct mount *mp, struct export_args *argp)
MNT_ILOCK(mp);
mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
MNT_IUNLOCK(mp);
- vfs_deleteopt(mp->mnt_optnew, "export");
}
if (argp->ex_flags & MNT_EXPORTED) {
if (nep == NULL) {
@@ -260,18 +268,30 @@ vfs_export(struct mount *mp, struct export_args *argp)
}
if (argp->ex_flags & MNT_EXPUBLIC) {
if ((error = vfs_setpublicfs(mp, nep, argp)) != 0)
- return (error);
+ goto out;
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_EXPUBLIC;
MNT_IUNLOCK(mp);
}
if ((error = vfs_hang_addrlist(mp, nep, argp)))
- return (error);
+ goto out;
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_EXPORTED;
MNT_IUNLOCK(mp);
}
- return (0);
+
+out:
+ /*
+ * Once we have executed the vfs_export() command, we do
+ * not want to keep the "export" option around in the
+ * options list, since that will cause subsequent MNT_UPDATE
+ * calls to fail. The export information is saved in
+ * mp->mnt_export, so we can safely delete the "export" mount option
+ * here.
+ */
+ vfs_deleteopt(mp->mnt_optnew, "export");
+ vfs_deleteopt(mp->mnt_opt, "export");
+ return (error);
}
/*
OpenPOWER on IntegriCloud