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
This commit is contained in:
parent
95a8bcd854
commit
61e323a2fa
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user