b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * CDDL HEADER START
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * The contents of this file are subject to the terms of the
b9238976491622ad75a67ab0c12edf99e36212b9th * Common Development and Distribution License (the "License").
b9238976491622ad75a67ab0c12edf99e36212b9th * You may not use this file except in compliance with the License.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b9238976491622ad75a67ab0c12edf99e36212b9th * or http://www.opensolaris.org/os/licensing.
b9238976491622ad75a67ab0c12edf99e36212b9th * See the License for the specific language governing permissions
b9238976491622ad75a67ab0c12edf99e36212b9th * and limitations under the License.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * When distributing Covered Code, include this CDDL HEADER in each
b9238976491622ad75a67ab0c12edf99e36212b9th * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b9238976491622ad75a67ab0c12edf99e36212b9th * If applicable, add the following below this CDDL HEADER, with the
b9238976491622ad75a67ab0c12edf99e36212b9th * fields enclosed by brackets "[]" replaced with your own identifying
b9238976491622ad75a67ab0c12edf99e36212b9th * information: Portions Copyright [yyyy] [name of copyright owner]
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * CDDL HEADER END
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
b9238976491622ad75a67ab0c12edf99e36212b9th * Use is subject to license terms.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Support for ephemeral mounts, e.g. mirror-mounts. These mounts are
b9238976491622ad75a67ab0c12edf99e36212b9th * triggered from a "stub" rnode via a special set of vnodeops.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/param.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/types.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/systm.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/cred.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/time.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/vnode.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/vfs.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/vfs_opreg.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/file.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/filio.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/uio.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/buf.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/mman.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/pathname.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/dirent.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/debug.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/vmsystm.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/fcntl.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/flock.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/swap.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/errno.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/strsubr.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/sysmacros.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/kmem.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/mount.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/cmn_err.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/pathconf.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/utsname.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/dnlc.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/acl.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/systeminfo.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/policy.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/sdt.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/list.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/stat.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/mntent.h>
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow#include <sys/priv.h>
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th#include <rpc/types.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <rpc/auth.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <rpc/clnt.h>
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th#include <nfs/nfs.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <nfs/nfs_clnt.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <nfs/nfs_acl.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <nfs/lm.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <nfs/nfs4.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <nfs/nfs4_kprot.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <nfs/rnode4.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <nfs/nfs4_clnt.h>
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow#include <nfs/nfsid_map.h>
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow#include <nfs/nfs4_idmap_impl.h>
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th#include <vm/hat.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <vm/as.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <vm/page.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <vm/pvn.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <vm/seg.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <vm/seg_map.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <vm/seg_kpm.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <vm/seg_vn.h>
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th#include <fs/fs_subr.h>
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/ddi.h>
b9238976491622ad75a67ab0c12edf99e36212b9th#include <sys/int_fmtio.h>
b9238976491622ad75a67ab0c12edf99e36212b9th
f39b87890f92b92a38d84654c635ca63e14ffb1dth#include <sys/sunddi.h>
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes#include <sys/priv_names.h>
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowextern zone_key_t nfs4clnt_zone_key;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowextern zone_key_t nfsidmap_zone_key;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * The automatic unmounter thread stuff!
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int nfs4_trigger_thread_timer = 20; /* in seconds */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Just a default....
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic uint_t nfs4_trigger_mount_to = 240;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thtypedef struct nfs4_trigger_globals {
b9238976491622ad75a67ab0c12edf99e36212b9th kmutex_t ntg_forest_lock;
b9238976491622ad75a67ab0c12edf99e36212b9th uint_t ntg_mount_to;
b9238976491622ad75a67ab0c12edf99e36212b9th int ntg_thread_started;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *ntg_forest;
b9238976491622ad75a67ab0c12edf99e36212b9th} nfs4_trigger_globals_t;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thkmutex_t nfs4_ephemeral_thread_lock;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thzone_key_t nfs4_ephemeral_key = ZONE_KEY_UNINITIALIZED;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void nfs4_ephemeral_start_harvester(nfs4_trigger_globals_t *);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Used for ephemeral mounts; contains data either duplicated from
b9238976491622ad75a67ab0c12edf99e36212b9th * servinfo4_t, or hand-crafted, depending on type of ephemeral mount.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * It's intended that this structure is used solely for ephemeral
b9238976491622ad75a67ab0c12edf99e36212b9th * mount-type specific data, for passing this data to
b9238976491622ad75a67ab0c12edf99e36212b9th * nfs4_trigger_nargs_create().
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thtypedef struct ephemeral_servinfo {
b9238976491622ad75a67ab0c12edf99e36212b9th char *esi_hostname;
b9238976491622ad75a67ab0c12edf99e36212b9th char *esi_netname;
b9238976491622ad75a67ab0c12edf99e36212b9th char *esi_path;
b9238976491622ad75a67ab0c12edf99e36212b9th int esi_path_len;
b9238976491622ad75a67ab0c12edf99e36212b9th int esi_mount_flags;
b9238976491622ad75a67ab0c12edf99e36212b9th struct netbuf *esi_addr;
b9238976491622ad75a67ab0c12edf99e36212b9th struct netbuf *esi_syncaddr;
b9238976491622ad75a67ab0c12edf99e36212b9th struct knetconfig *esi_knconf;
b9238976491622ad75a67ab0c12edf99e36212b9th} ephemeral_servinfo_t;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Collect together the mount-type specific and generic data args.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thtypedef struct domount_args {
b9238976491622ad75a67ab0c12edf99e36212b9th ephemeral_servinfo_t *dma_esi;
b9238976491622ad75a67ab0c12edf99e36212b9th char *dma_hostlist; /* comma-sep. for RO failover */
b9238976491622ad75a67ab0c12edf99e36212b9th struct nfs_args *dma_nargs;
b9238976491622ad75a67ab0c12edf99e36212b9th} domount_args_t;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * The vnode ops functions for a trigger stub vnode
b9238976491622ad75a67ab0c12edf99e36212b9th */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_open(vnode_t **, int, cred_t *, caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_getattr(vnode_t *, struct vattr *, int, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_setattr(vnode_t *, struct vattr *, int, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_access(vnode_t *, int, int, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_readlink(vnode_t *, struct uio *, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_lookup(vnode_t *, char *, vnode_t **,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct pathname *, int, vnode_t *, cred_t *, caller_context_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int *, pathname_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_create(vnode_t *, char *, struct vattr *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw enum vcexcl, int, vnode_t **, cred_t *, int, caller_context_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vsecattr_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_remove(vnode_t *, char *, cred_t *, caller_context_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_link(vnode_t *, vnode_t *, char *, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *, int);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_rename(vnode_t *, char *, vnode_t *, char *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *, caller_context_t *, int);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_mkdir(vnode_t *, char *, struct vattr *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw vnode_t **, cred_t *, caller_context_t *, int, vsecattr_t *vsecp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *, int);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_symlink(vnode_t *, char *, struct vattr *, char *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *, caller_context_t *, int);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nfs4_trigger_cmp(vnode_t *, vnode_t *, caller_context_t *);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Regular NFSv4 vnodeops that we need to reference directly
b9238976491622ad75a67ab0c12edf99e36212b9th */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwextern int nfs4_getattr(vnode_t *, struct vattr *, int, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwextern void nfs4_inactive(vnode_t *, cred_t *, caller_context_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thextern int nfs4_rwlock(vnode_t *, int, caller_context_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thextern void nfs4_rwunlock(vnode_t *, int, caller_context_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thextern int nfs4_lookup(vnode_t *, char *, vnode_t **,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct pathname *, int, vnode_t *, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *, int *, pathname_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwextern int nfs4_pathconf(vnode_t *, int, ulong_t *, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwextern int nfs4_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwextern int nfs4_fid(vnode_t *, fid_t *, caller_context_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwextern int nfs4_realvp(vnode_t *, vnode_t **, caller_context_t *);
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynesstatic int nfs4_trigger_mount(vnode_t *, cred_t *, vnode_t **);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int nfs4_trigger_domount(vnode_t *, domount_args_t *, vfs_t **,
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes cred_t *, vnode_t **);
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkertstatic int nfs4_trigger_domount_args_create(vnode_t *, cred_t *,
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert domount_args_t **dmap);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void nfs4_trigger_domount_args_destroy(domount_args_t *dma,
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *vp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowstatic ephemeral_servinfo_t *nfs4_trigger_esi_create(vnode_t *, servinfo4_t *,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow cred_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void nfs4_trigger_esi_destroy(ephemeral_servinfo_t *, vnode_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic ephemeral_servinfo_t *nfs4_trigger_esi_create_mirrormount(vnode_t *,
b9238976491622ad75a67ab0c12edf99e36212b9th servinfo4_t *);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowstatic ephemeral_servinfo_t *nfs4_trigger_esi_create_referral(vnode_t *,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow cred_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic struct nfs_args *nfs4_trigger_nargs_create(mntinfo4_t *, servinfo4_t *,
b9238976491622ad75a67ab0c12edf99e36212b9th ephemeral_servinfo_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void nfs4_trigger_nargs_destroy(struct nfs_args *);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic char *nfs4_trigger_create_mntopts(vfs_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void nfs4_trigger_destroy_mntopts(char *);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int nfs4_trigger_add_mntopt(char *, char *, vfs_t *);
b9238976491622ad75a67ab0c12edf99e36212b9thstatic enum clnt_stat nfs4_trigger_ping_server(servinfo4_t *, int);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowstatic enum clnt_stat nfs4_ping_server_common(struct knetconfig *,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct netbuf *, int);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thextern int umount2_engine(vfs_t *, int, cred_t *, int);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thvnodeops_t *nfs4_trigger_vnodeops;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * These are the vnodeops that we must define for stub vnodes.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Many of the VOPs defined for NFSv4 do not need to be defined here,
b9238976491622ad75a67ab0c12edf99e36212b9th * for various reasons. This will result in the VFS default function being
b9238976491622ad75a67ab0c12edf99e36212b9th * used:
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * - These VOPs require a previous VOP_OPEN to have occurred. That will have
b9238976491622ad75a67ab0c12edf99e36212b9th * lost the reference to the stub vnode, meaning these should not be called:
b9238976491622ad75a67ab0c12edf99e36212b9th * close, read, write, ioctl, readdir, seek.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * - These VOPs are meaningless for vnodes without data pages. Since the
b9238976491622ad75a67ab0c12edf99e36212b9th * stub vnode is of type VDIR, these should not be called:
b9238976491622ad75a67ab0c12edf99e36212b9th * space, getpage, putpage, map, addmap, delmap, pageio, fsync.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * - These VOPs are otherwise not applicable, and should not be called:
b9238976491622ad75a67ab0c12edf99e36212b9th * dump, setsecattr.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * These VOPs we do not want to define, but nor do we want the VFS default
b9238976491622ad75a67ab0c12edf99e36212b9th * action. Instead, we specify the VFS error function, with fs_error(), but
b9238976491622ad75a67ab0c12edf99e36212b9th * note that fs_error() is not actually called. Instead it results in the
b9238976491622ad75a67ab0c12edf99e36212b9th * use of the error function defined for the particular VOP, in vn_ops_table[]:
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * - frlock, dispose, shrlock.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * These VOPs we define to use the corresponding regular NFSv4 vnodeop.
b9238976491622ad75a67ab0c12edf99e36212b9th * NOTE: if any of these ops involve an OTW call with the stub FH, then
b9238976491622ad75a67ab0c12edf99e36212b9th * that call must be wrapped with save_mnt_secinfo()/check_mnt_secinfo()
b9238976491622ad75a67ab0c12edf99e36212b9th * to protect the security data in the servinfo4_t for the "parent"
b9238976491622ad75a67ab0c12edf99e36212b9th * filesystem that contains the stub.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * - These VOPs should not trigger a mount, so that "ls -l" does not:
b9238976491622ad75a67ab0c12edf99e36212b9th * pathconf, getsecattr.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * - These VOPs would not make sense to trigger:
b9238976491622ad75a67ab0c12edf99e36212b9th * inactive, rwlock, rwunlock, fid, realvp.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thconst fs_operation_def_t nfs4_trigger_vnodeops_template[] = {
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_OPEN, { .vop_open = nfs4_trigger_open },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_GETATTR, { .vop_getattr = nfs4_trigger_getattr },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_SETATTR, { .vop_setattr = nfs4_trigger_setattr },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_ACCESS, { .vop_access = nfs4_trigger_access },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_LOOKUP, { .vop_lookup = nfs4_trigger_lookup },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_CREATE, { .vop_create = nfs4_trigger_create },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_REMOVE, { .vop_remove = nfs4_trigger_remove },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_LINK, { .vop_link = nfs4_trigger_link },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_RENAME, { .vop_rename = nfs4_trigger_rename },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_MKDIR, { .vop_mkdir = nfs4_trigger_mkdir },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_RMDIR, { .vop_rmdir = nfs4_trigger_rmdir },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_SYMLINK, { .vop_symlink = nfs4_trigger_symlink },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_READLINK, { .vop_readlink = nfs4_trigger_readlink },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_INACTIVE, { .vop_inactive = nfs4_inactive },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_FID, { .vop_fid = nfs4_fid },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_RWLOCK, { .vop_rwlock = nfs4_rwlock },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_RWUNLOCK, { .vop_rwunlock = nfs4_rwunlock },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_REALVP, { .vop_realvp = nfs4_realvp },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_GETSECATTR, { .vop_getsecattr = nfs4_getsecattr },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_PATHCONF, { .vop_pathconf = nfs4_pathconf },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_FRLOCK, { .error = fs_error },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_DISPOSE, { .error = fs_error },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_SHRLOCK, { .error = fs_error },
b9238976491622ad75a67ab0c12edf99e36212b9th VOPNAME_VNEVENT, { .vop_vnevent = fs_vnevent_support },
b9238976491622ad75a67ab0c12edf99e36212b9th NULL, NULL
b9238976491622ad75a67ab0c12edf99e36212b9th};
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynesstatic void
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynesnfs4_ephemeral_tree_incr(nfs4_ephemeral_tree_t *net)
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes{
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes ASSERT(mutex_owned(&net->net_cnt_lock));
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes net->net_refcnt++;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes ASSERT(net->net_refcnt != 0);
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes}
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynesstatic void
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynesnfs4_ephemeral_tree_hold(nfs4_ephemeral_tree_t *net)
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes{
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes mutex_enter(&net->net_cnt_lock);
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes nfs4_ephemeral_tree_incr(net);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes}
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes/*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * We need a safe way to decrement the refcnt whilst the
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * lock is being held.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynesstatic void
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynesnfs4_ephemeral_tree_decr(nfs4_ephemeral_tree_t *net)
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes{
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes ASSERT(mutex_owned(&net->net_cnt_lock));
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes ASSERT(net->net_refcnt != 0);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes net->net_refcnt--;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes}
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynesstatic void
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynesnfs4_ephemeral_tree_rele(nfs4_ephemeral_tree_t *net)
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes{
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_enter(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes nfs4_ephemeral_tree_decr(net);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes}
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Trigger ops for stub vnodes; for mirror mounts, etc.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * The general idea is that a "triggering" op will first call
b9238976491622ad75a67ab0c12edf99e36212b9th * nfs4_trigger_mount(), which will find out whether a mount has already
b9238976491622ad75a67ab0c12edf99e36212b9th * been triggered.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * If it has, then nfs4_trigger_mount() sets newvp to the root vnode
b9238976491622ad75a67ab0c12edf99e36212b9th * of the covering vfs.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * If a mount has not yet been triggered, nfs4_trigger_mount() will do so,
b9238976491622ad75a67ab0c12edf99e36212b9th * and again set newvp, as above.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * The triggering op may then re-issue the VOP by calling it on newvp.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Note that some ops may perform custom action, and may or may not need
b9238976491622ad75a67ab0c12edf99e36212b9th * to trigger a mount.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Some ops need to call the regular NFSv4 vnodeop for a stub vnode. We
b9238976491622ad75a67ab0c12edf99e36212b9th * obviously can't do this with VOP_<whatever>, since it's a stub vnode
b9238976491622ad75a67ab0c12edf99e36212b9th * and that would just recurse. Instead, we call the v4 op directly,
b9238976491622ad75a67ab0c12edf99e36212b9th * by name. This is OK, since we know that the vnode is for NFSv4,
b9238976491622ad75a67ab0c12edf99e36212b9th * otherwise it couldn't be a stub.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnfs4_trigger_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(*vpp, cr, &newvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* Release the stub vnode, as we're losing the reference to it */
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(*vpp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* Give the caller the root vnode of the newly-mounted fs */
b9238976491622ad75a67ab0c12edf99e36212b9th *vpp = newvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* return with VN_HELD(newvp) */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (VOP_OPEN(vpp, flag, cr, ct));
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowvoid
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_fake_attrs(vnode_t *vp, struct vattr *vap)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow uint_t mask;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow timespec_t now;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Set some attributes here for referrals.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mask = vap->va_mask;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bzero(vap, sizeof (struct vattr));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_mask = mask;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_uid = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_gid = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_nlink = 1;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_size = 1;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow gethrestime(&now);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_atime = now;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_mtime = now;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_ctime = now;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_type = VDIR;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_mode = 0555;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_fsid = vp->v_vfsp->vfs_dev;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_rdev = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_blksize = MAXBSIZE;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_nblocks = 1;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vap->va_seq = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow}
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * For the majority of cases, nfs4_trigger_getattr() will not trigger
b9238976491622ad75a67ab0c12edf99e36212b9th * a mount. However, if ATTR_TRIGGER is set, we are being informed
b9238976491622ad75a67ab0c12edf99e36212b9th * that we need to force the mount before we attempt to determine
b9238976491622ad75a67ab0c12edf99e36212b9th * the attributes. The intent is an atomic operation for security
b9238976491622ad75a67ab0c12edf99e36212b9th * testing.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * If we're not triggering a mount, we can still inquire about the
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * actual attributes from the server in the mirror mount case,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * and will return manufactured attributes for a referral (see
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * the 'create' branch of find_referral_stubvp()).
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnfs4_trigger_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (flags & ATTR_TRIGGER) {
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(vp, cr, &newvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_GETATTR(newvp, vap, flags, cr, ct);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow } else if (RP_ISSTUB_MIRRORMOUNT(VTOR4(vp))) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = nfs4_getattr(vp, vap, flags, cr, ct);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow } else if (RP_ISSTUB_REFERRAL(VTOR4(vp))) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_fake_attrs(vp, vap);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow error = 0;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
b9238976491622ad75a67ab0c12edf99e36212b9th caller_context_t *ct)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(vp, cr, &newvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th error = VOP_SETATTR(newvp, vap, flags, cr, ct);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnfs4_trigger_access(vnode_t *vp, int mode, int flags, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(vp, cr, &newvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_ACCESS(newvp, mode, flags, cr, ct);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnfs4_trigger_lookup(vnode_t *dvp, char *nm, vnode_t **vpp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct pathname *pnp, int flags, vnode_t *rdir, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int *deflags, pathname_t *rpnp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newdvp;
b9238976491622ad75a67ab0c12edf99e36212b9th rnode4_t *drp = VTOR4(dvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(RP_ISSTUB(drp));
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * It's not legal to lookup ".." for an fs root, so we mustn't pass
b9238976491622ad75a67ab0c12edf99e36212b9th * that up. Instead, pass onto the regular op, regardless of whether
b9238976491622ad75a67ab0c12edf99e36212b9th * we've triggered a mount.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (strcmp(nm, "..") == 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (RP_ISSTUB_MIRRORMOUNT(drp)) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (nfs4_lookup(dvp, nm, vpp, pnp, flags, rdir, cr,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow ct, deflags, rpnp));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow } else if (RP_ISSTUB_REFERRAL(drp)) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* Return the parent vnode */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (vtodv(dvp, vpp, cr, TRUE));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(dvp, cr, &newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_LOOKUP(newdvp, nm, vpp, pnp, flags, rdir, cr, ct,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw deflags, rpnp);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_create(vnode_t *dvp, char *nm, struct vattr *va,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw enum vcexcl exclusive, int mode, vnode_t **vpp, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int flags, caller_context_t *ct, vsecattr_t *vsecp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newdvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(dvp, cr, &newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_CREATE(newdvp, nm, va, exclusive, mode, vpp, cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw flags, ct, vsecp);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnfs4_trigger_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int flags)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newdvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(dvp, cr, &newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_REMOVE(newdvp, nm, cr, ct, flags);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnfs4_trigger_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newtdvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(tdvp, cr, &newtdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We don't check whether svp is a stub. Let the NFSv4 code
b9238976491622ad75a67ab0c12edf99e36212b9th * detect that error, and return accordingly.
b9238976491622ad75a67ab0c12edf99e36212b9th */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_LINK(newtdvp, svp, tnm, cr, ct, flags);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newtdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *cr, caller_context_t *ct, int flags)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newsdvp;
b9238976491622ad75a67ab0c12edf99e36212b9th rnode4_t *tdrp = VTOR4(tdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We know that sdvp is a stub, otherwise we would not be here.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * If tdvp is also be a stub, there are two possibilities: it
b9238976491622ad75a67ab0c12edf99e36212b9th * is either the same stub as sdvp [i.e. VN_CMP(sdvp, tdvp)]
b9238976491622ad75a67ab0c12edf99e36212b9th * or it is a different stub [!VN_CMP(sdvp, tdvp)].
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * In the former case, just trigger sdvp, and treat tdvp as
b9238976491622ad75a67ab0c12edf99e36212b9th * though it were not a stub.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * In the latter case, it might be a different stub for the
b9238976491622ad75a67ab0c12edf99e36212b9th * same server fs as sdvp, or for a different server fs.
b9238976491622ad75a67ab0c12edf99e36212b9th * Regardless, from the client perspective this would still
b9238976491622ad75a67ab0c12edf99e36212b9th * be a cross-filesystem rename, and should not be allowed,
b9238976491622ad75a67ab0c12edf99e36212b9th * so return EXDEV, without triggering either mount.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (RP_ISSTUB(tdrp) && !VN_CMP(sdvp, tdvp))
b9238976491622ad75a67ab0c12edf99e36212b9th return (EXDEV);
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(sdvp, cr, &newsdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_RENAME(newsdvp, snm, tdvp, tnm, cr, ct, flags);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newsdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* ARGSUSED */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newdvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(dvp, cr, &newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_MKDIR(newdvp, nm, va, vpp, cr, ct, flags, vsecp);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnfs4_trigger_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct, int flags)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newdvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(dvp, cr, &newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_RMDIR(newdvp, nm, cdir, cr, ct, flags);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_symlink(vnode_t *dvp, char *lnm, struct vattr *tva, char *tnm,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cred_t *cr, caller_context_t *ct, int flags)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newdvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(dvp, cr, &newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_SYMLINK(newdvp, lnm, tva, tnm, cr, ct, flags);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newdvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwnfs4_trigger_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw caller_context_t *ct)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vnode_t *newvp;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = nfs4_trigger_mount(vp, cr, &newvp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_READLINK(newvp, uiop, cr, ct);
b9238976491622ad75a67ab0c12edf99e36212b9th VN_RELE(newvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/* end of trigger vnode ops */
b9238976491622ad75a67ab0c12edf99e36212b9th
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes/*
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes * See if the mount has already been done by another caller.
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes */
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynesstatic int
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynesnfs4_trigger_mounted_already(vnode_t *vp, vnode_t **newvpp,
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes bool_t *was_mounted, vfs_t **vfsp)
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes{
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes int error;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes mntinfo4_t *mi = VTOMI4(vp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes *was_mounted = FALSE;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes error = vn_vfsrlock_wait(vp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes if (error)
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes return (error);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes *vfsp = vn_mountedvfs(vp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes if (*vfsp != NULL) {
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes /* the mount has already occurred */
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes error = VFS_ROOT(*vfsp, newvpp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes if (!error) {
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes /* need to update the reference time */
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes mutex_enter(&mi->mi_lock);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes if (mi->mi_ephemeral)
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes mi->mi_ephemeral->ne_ref_time =
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes gethrestime_sec();
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes mutex_exit(&mi->mi_lock);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes *was_mounted = TRUE;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes }
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes }
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes vn_vfsunlock(vp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes return (0);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes}
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th/*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Mount upon a trigger vnode; for mirror-mounts, referrals, etc.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * The mount may have already occurred, via another thread. If not,
b9238976491622ad75a67ab0c12edf99e36212b9th * assemble the location information - which may require fetching - and
b9238976491622ad75a67ab0c12edf99e36212b9th * perform the mount.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Sets newvp to be the root of the fs that is now covering vp. Note
b9238976491622ad75a67ab0c12edf99e36212b9th * that we return with VN_HELD(*newvp).
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * The caller is responsible for passing the VOP onto the covering fs.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynesnfs4_trigger_mount(vnode_t *vp, cred_t *cr, vnode_t **newvpp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th vfs_t *vfsp;
b9238976491622ad75a67ab0c12edf99e36212b9th rnode4_t *rp = VTOR4(vp);
b9238976491622ad75a67ab0c12edf99e36212b9th mntinfo4_t *mi = VTOMI4(vp);
b9238976491622ad75a67ab0c12edf99e36212b9th domount_args_t *dma;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *net;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th bool_t must_unlock = FALSE;
b9238976491622ad75a67ab0c12edf99e36212b9th bool_t is_building = FALSE;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes bool_t was_mounted = FALSE;
b9238976491622ad75a67ab0c12edf99e36212b9th
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes cred_t *mcred = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_globals_t *ntg;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th zone_t *zone = curproc->p_zone;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(RP_ISSTUB(rp));
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th *newvpp = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Has the mount already occurred?
b9238976491622ad75a67ab0c12edf99e36212b9th */
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes error = nfs4_trigger_mounted_already(vp, newvpp,
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes &was_mounted, &vfsp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes if (error || was_mounted)
b9238976491622ad75a67ab0c12edf99e36212b9th goto done;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ntg = zone_getspecific(nfs4_ephemeral_key, zone);
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(ntg != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We need to lock down the ephemeral tree.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_ephemeral_tree == NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th net = kmem_zalloc(sizeof (*net), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_init(&net->net_tree_lock, NULL, MUTEX_DEFAULT, NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_init(&net->net_cnt_lock, NULL, MUTEX_DEFAULT, NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_refcnt = 1;
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status = NFS4_EPHEMERAL_TREE_BUILDING;
b9238976491622ad75a67ab0c12edf99e36212b9th is_building = TRUE;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We need to add it to the zone specific list for
b9238976491622ad75a67ab0c12edf99e36212b9th * automatic unmounting and harvesting of deadwood.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&ntg->ntg_forest_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th if (ntg->ntg_forest != NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_next = ntg->ntg_forest;
b9238976491622ad75a67ab0c12edf99e36212b9th ntg->ntg_forest = net;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&ntg->ntg_forest_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * No lock order confusion with mi_lock because no
b9238976491622ad75a67ab0c12edf99e36212b9th * other node could have grabbed net_tree_lock.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th mi->mi_ephemeral_tree = net;
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_mount = mi;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&mi->mi_lock);
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes MI4_HOLD(mi);
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes VFS_HOLD(mi->mi_vfsp);
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th net = mi->mi_ephemeral_tree;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes nfs4_ephemeral_tree_hold(net);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes mutex_exit(&mi->mi_lock);
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_enter(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * We can only procede if the tree is neither locked
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * nor being torn down.
b9238976491622ad75a67ab0c12edf99e36212b9th */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_enter(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (net->net_status & NFS4_EPHEMERAL_TREE_PROCESSING) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes nfs4_ephemeral_tree_decr(net);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_tree_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes return (EIO);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes }
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status |= NFS4_EPHEMERAL_TREE_MOUNTING;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th must_unlock = TRUE;
b9238976491622ad75a67ab0c12edf99e36212b9th
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert error = nfs4_trigger_domount_args_create(vp, cr, &dma);
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert if (error)
b9238976491622ad75a67ab0c12edf99e36212b9th goto done;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Note that since we define mirror mounts to work
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes * for any user, we simply extend the privileges of
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes * the user's credentials to allow the mount to
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes * proceed.
b9238976491622ad75a67ab0c12edf99e36212b9th */
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes mcred = crdup(cr);
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes if (mcred == NULL) {
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes error = EINVAL;
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert nfs4_trigger_domount_args_destroy(dma, vp);
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes goto done;
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes }
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes crset_zone_privall(mcred);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (is_system_labeled())
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) setpflags(NET_MAC_AWARE, 1, mcred);
b9238976491622ad75a67ab0c12edf99e36212b9th
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes error = nfs4_trigger_domount(vp, dma, &vfsp, mcred, newvpp);
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_domount_args_destroy(dma, vp);
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(nfs4clnt__func__referral__mount,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vnode_t *, vp, int, error);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes crfree(mcred);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thdone:
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th if (must_unlock) {
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status &= ~NFS4_EPHEMERAL_TREE_MOUNTING;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * REFCNT: If we are the root of the tree, then we need
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * to keep a reference because we malloced the tree and
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * this is where we tied it to our mntinfo.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * If we are not the root of the tree, then our tie to
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * the mntinfo occured elsewhere and we need to
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * decrement the reference to the tree.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
b9238976491622ad75a67ab0c12edf99e36212b9th if (is_building)
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status &= ~NFS4_EPHEMERAL_TREE_BUILDING;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow else
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_tree_decr(net);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (!error && (newvpp == NULL || *newvpp == NULL))
b9238976491622ad75a67ab0c12edf99e36212b9th error = ENOSYS;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Collect together both the generic & mount-type specific args.
b9238976491622ad75a67ab0c12edf99e36212b9th */
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkertstatic int
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkertnfs4_trigger_domount_args_create(vnode_t *vp, cred_t *cr, domount_args_t **dmap)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int nointr;
b9238976491622ad75a67ab0c12edf99e36212b9th char *hostlist;
b9238976491622ad75a67ab0c12edf99e36212b9th servinfo4_t *svp;
b9238976491622ad75a67ab0c12edf99e36212b9th struct nfs_args *nargs, *nargs_head;
b9238976491622ad75a67ab0c12edf99e36212b9th enum clnt_stat status;
b9238976491622ad75a67ab0c12edf99e36212b9th ephemeral_servinfo_t *esi, *esi_first;
b9238976491622ad75a67ab0c12edf99e36212b9th domount_args_t *dma;
b9238976491622ad75a67ab0c12edf99e36212b9th mntinfo4_t *mi = VTOMI4(vp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nointr = !(mi->mi_flags & MI4_INT);
b9238976491622ad75a67ab0c12edf99e36212b9th hostlist = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th svp = mi->mi_curr_serv;
b9238976491622ad75a67ab0c12edf99e36212b9th /* check if the current server is responding */
b9238976491622ad75a67ab0c12edf99e36212b9th status = nfs4_trigger_ping_server(svp, nointr);
b9238976491622ad75a67ab0c12edf99e36212b9th if (status == RPC_SUCCESS) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi_first = nfs4_trigger_esi_create(vp, svp, cr);
b9238976491622ad75a67ab0c12edf99e36212b9th if (esi_first == NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(hostlist, MAXPATHLEN);
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert return (EINVAL);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strlcpy(hostlist, esi_first->esi_hostname, MAXPATHLEN);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nargs_head = nfs4_trigger_nargs_create(mi, svp, esi_first);
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th /* current server did not respond */
b9238976491622ad75a67ab0c12edf99e36212b9th esi_first = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs_head = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th nargs = nargs_head;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * NFS RO failover.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * If we have multiple servinfo4 structures, linked via sv_next,
b9238976491622ad75a67ab0c12edf99e36212b9th * we must create one nfs_args for each, linking the nfs_args via
b9238976491622ad75a67ab0c12edf99e36212b9th * nfs_ext_u.nfs_extB.next.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * We need to build a corresponding esi for each, too, but that is
b9238976491622ad75a67ab0c12edf99e36212b9th * used solely for building nfs_args, and may be immediately
b9238976491622ad75a67ab0c12edf99e36212b9th * discarded, as domount() requires the info from just one esi,
b9238976491622ad75a67ab0c12edf99e36212b9th * but all the nfs_args.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Currently, the NFS mount code will hang if not all servers
b9238976491622ad75a67ab0c12edf99e36212b9th * requested are available. To avoid that, we need to ping each
b9238976491622ad75a67ab0c12edf99e36212b9th * server, here, and remove it from the list if it is not
b9238976491622ad75a67ab0c12edf99e36212b9th * responding. This has the side-effect of that server then
b9238976491622ad75a67ab0c12edf99e36212b9th * being permanently unavailable for this failover mount, even if
b9238976491622ad75a67ab0c12edf99e36212b9th * it recovers. That's unfortunate, but the best we can do until
b9238976491622ad75a67ab0c12edf99e36212b9th * the mount code path is fixed.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If the current server was down, loop indefinitely until we find
b9238976491622ad75a67ab0c12edf99e36212b9th * at least one responsive server.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th do {
b9238976491622ad75a67ab0c12edf99e36212b9th /* no locking needed for sv_next; it is only set at fs mount */
b9238976491622ad75a67ab0c12edf99e36212b9th for (svp = mi->mi_servers; svp != NULL; svp = svp->sv_next) {
b9238976491622ad75a67ab0c12edf99e36212b9th struct nfs_args *next;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * nargs_head: the head of the nfs_args list
b9238976491622ad75a67ab0c12edf99e36212b9th * nargs: the current tail of the list
b9238976491622ad75a67ab0c12edf99e36212b9th * next: the newly-created element to be added
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We've already tried the current server, above;
b9238976491622ad75a67ab0c12edf99e36212b9th * if it was responding, we have already included it
b9238976491622ad75a67ab0c12edf99e36212b9th * and it may now be ignored.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Otherwise, try it again, since it may now have
b9238976491622ad75a67ab0c12edf99e36212b9th * recovered.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (svp == mi->mi_curr_serv && esi_first != NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th (void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
b9238976491622ad75a67ab0c12edf99e36212b9th if (svp->sv_flags & SV4_NOTINUSE) {
b9238976491622ad75a67ab0c12edf99e36212b9th nfs_rw_exit(&svp->sv_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th nfs_rw_exit(&svp->sv_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* check if the server is responding */
b9238976491622ad75a67ab0c12edf99e36212b9th status = nfs4_trigger_ping_server(svp, nointr);
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert if (status == RPC_INTR) {
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert kmem_free(hostlist, MAXPATHLEN);
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert nfs4_trigger_esi_destroy(esi_first, vp);
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert nargs = nargs_head;
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert while (nargs != NULL) {
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert next = nargs->nfs_ext_u.nfs_extB.next;
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert nfs4_trigger_nargs_destroy(nargs);
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert nargs = next;
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert }
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert return (EINTR);
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert } else if (status != RPC_SUCCESS) {
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert /* if the server did not respond, ignore it */
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert }
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi = nfs4_trigger_esi_create(vp, svp, cr);
b9238976491622ad75a67ab0c12edf99e36212b9th if (esi == NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If the original current server (mi_curr_serv)
b9238976491622ad75a67ab0c12edf99e36212b9th * was down when when we first tried it,
b9238976491622ad75a67ab0c12edf99e36212b9th * (i.e. esi_first == NULL),
b9238976491622ad75a67ab0c12edf99e36212b9th * we select this new server (svp) to be the server
b9238976491622ad75a67ab0c12edf99e36212b9th * that we will actually contact (esi_first).
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Note that it's possible that mi_curr_serv == svp,
b9238976491622ad75a67ab0c12edf99e36212b9th * if that mi_curr_serv was down but has now recovered.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th next = nfs4_trigger_nargs_create(mi, svp, esi);
b9238976491622ad75a67ab0c12edf99e36212b9th if (esi_first == NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(nargs == NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(nargs_head == NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th nargs_head = next;
b9238976491622ad75a67ab0c12edf99e36212b9th esi_first = esi;
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strlcpy(hostlist,
b9238976491622ad75a67ab0c12edf99e36212b9th esi_first->esi_hostname, MAXPATHLEN);
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(nargs_head != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->nfs_ext_u.nfs_extB.next = next;
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strlcat(hostlist, ",", MAXPATHLEN);
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strlcat(hostlist, esi->esi_hostname,
b9238976491622ad75a67ab0c12edf99e36212b9th MAXPATHLEN);
b9238976491622ad75a67ab0c12edf99e36212b9th /* esi was only needed for hostname & nargs */
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_esi_destroy(esi, vp);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nargs = next;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* if we've had no response at all, wait a second */
b9238976491622ad75a67ab0c12edf99e36212b9th if (esi_first == NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th delay(drv_usectohz(1000000));
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th } while (esi_first == NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(nargs_head != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th dma = kmem_zalloc(sizeof (domount_args_t), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th dma->dma_esi = esi_first;
b9238976491622ad75a67ab0c12edf99e36212b9th dma->dma_hostlist = hostlist;
b9238976491622ad75a67ab0c12edf99e36212b9th dma->dma_nargs = nargs_head;
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert *dmap = dma;
b9238976491622ad75a67ab0c12edf99e36212b9th
d16da3206f378fcb1a1de6d0cfc66f08a489d63eSimon Klinkert return (0);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_domount_args_destroy(domount_args_t *dma, vnode_t *vp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th if (dma != NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th if (dma->dma_esi != NULL && vp != NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_esi_destroy(dma->dma_esi, vp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (dma->dma_hostlist != NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(dma->dma_hostlist, MAXPATHLEN);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (dma->dma_nargs != NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th struct nfs_args *nargs = dma->dma_nargs;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th do {
b9238976491622ad75a67ab0c12edf99e36212b9th struct nfs_args *next =
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->nfs_ext_u.nfs_extB.next;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_nargs_destroy(nargs);
b9238976491622ad75a67ab0c12edf99e36212b9th nargs = next;
b9238976491622ad75a67ab0c12edf99e36212b9th } while (nargs != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(dma, sizeof (domount_args_t));
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * The ephemeral_servinfo_t struct contains basic information we will need to
b9238976491622ad75a67ab0c12edf99e36212b9th * perform the mount. Whilst the structure is generic across different
b9238976491622ad75a67ab0c12edf99e36212b9th * types of ephemeral mount, the way we gather its contents differs.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic ephemeral_servinfo_t *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_trigger_esi_create(vnode_t *vp, servinfo4_t *svp, cred_t *cr)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th ephemeral_servinfo_t *esi;
b9238976491622ad75a67ab0c12edf99e36212b9th rnode4_t *rp = VTOR4(vp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(RP_ISSTUB(rp));
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* Call the ephemeral type-specific routine */
b9238976491622ad75a67ab0c12edf99e36212b9th if (RP_ISSTUB_MIRRORMOUNT(rp))
b9238976491622ad75a67ab0c12edf99e36212b9th esi = nfs4_trigger_esi_create_mirrormount(vp, svp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow else if (RP_ISSTUB_REFERRAL(rp))
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi = nfs4_trigger_esi_create_referral(vp, cr);
b9238976491622ad75a67ab0c12edf99e36212b9th else
b9238976491622ad75a67ab0c12edf99e36212b9th esi = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th return (esi);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_esi_destroy(ephemeral_servinfo_t *esi, vnode_t *vp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th rnode4_t *rp = VTOR4(vp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(RP_ISSTUB(rp));
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* Currently, no need for an ephemeral type-specific routine */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * The contents of ephemeral_servinfo_t goes into nfs_args,
b9238976491622ad75a67ab0c12edf99e36212b9th * and will be handled by nfs4_trigger_nargs_destroy().
b9238976491622ad75a67ab0c12edf99e36212b9th * We need only free the structure itself.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (esi != NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(esi, sizeof (ephemeral_servinfo_t));
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Some of this may turn out to be common with other ephemeral types,
b9238976491622ad75a67ab0c12edf99e36212b9th * in which case it should be moved to nfs4_trigger_esi_create(), or a
b9238976491622ad75a67ab0c12edf99e36212b9th * common function called.
b9238976491622ad75a67ab0c12edf99e36212b9th */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow/*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Mirror mounts case - should have all data available
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic ephemeral_servinfo_t *
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_esi_create_mirrormount(vnode_t *vp, servinfo4_t *svp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th char *stubpath;
b9238976491622ad75a67ab0c12edf99e36212b9th struct knetconfig *sikncp, *svkncp;
b9238976491622ad75a67ab0c12edf99e36212b9th struct netbuf *bufp;
b9238976491622ad75a67ab0c12edf99e36212b9th ephemeral_servinfo_t *esi;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th esi = kmem_zalloc(sizeof (ephemeral_servinfo_t), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* initially set to be our type of ephemeral mount; may be added to */
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_mount_flags = NFSMNT_MIRRORMOUNT;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We're copying info from the stub rnode's servinfo4, but
b9238976491622ad75a67ab0c12edf99e36212b9th * we must create new copies, not pointers, since this information
b9238976491622ad75a67ab0c12edf99e36212b9th * is to be associated with the new mount, which will be
b9238976491622ad75a67ab0c12edf99e36212b9th * unmounted (and its structures freed) separately
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Sizes passed to kmem_[z]alloc here must match those freed
b9238976491622ad75a67ab0c12edf99e36212b9th * in nfs4_free_args()
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We hold sv_lock across kmem_zalloc() calls that may sleep, but this
b9238976491622ad75a67ab0c12edf99e36212b9th * is difficult to avoid: as we need to read svp to calculate the
b9238976491622ad75a67ab0c12edf99e36212b9th * sizes to be allocated.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th (void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_hostname = kmem_zalloc(strlen(svp->sv_hostname) + 1, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strcat(esi->esi_hostname, svp->sv_hostname);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_addr = kmem_zalloc(sizeof (struct netbuf), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th bufp = esi->esi_addr;
b9238976491622ad75a67ab0c12edf99e36212b9th bufp->len = svp->sv_addr.len;
b9238976491622ad75a67ab0c12edf99e36212b9th bufp->maxlen = svp->sv_addr.maxlen;
b9238976491622ad75a67ab0c12edf99e36212b9th bufp->buf = kmem_zalloc(bufp->len, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th bcopy(svp->sv_addr.buf, bufp->buf, bufp->len);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_knconf = kmem_zalloc(sizeof (*esi->esi_knconf), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th sikncp = esi->esi_knconf;
b9238976491622ad75a67ab0c12edf99e36212b9th svkncp = svp->sv_knconf;
b9238976491622ad75a67ab0c12edf99e36212b9th sikncp->knc_semantics = svkncp->knc_semantics;
b9238976491622ad75a67ab0c12edf99e36212b9th sikncp->knc_protofmly = (caddr_t)kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strcat((char *)sikncp->knc_protofmly,
b9238976491622ad75a67ab0c12edf99e36212b9th (char *)svkncp->knc_protofmly);
b9238976491622ad75a67ab0c12edf99e36212b9th sikncp->knc_proto = (caddr_t)kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strcat((char *)sikncp->knc_proto, (char *)svkncp->knc_proto);
b9238976491622ad75a67ab0c12edf99e36212b9th sikncp->knc_rdev = svkncp->knc_rdev;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Used when AUTH_DH is negotiated.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * This is ephemeral mount-type specific, since it contains the
b9238976491622ad75a67ab0c12edf99e36212b9th * server's time-sync syncaddr.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (svp->sv_dhsec) {
b9238976491622ad75a67ab0c12edf99e36212b9th struct netbuf *bufp;
b9238976491622ad75a67ab0c12edf99e36212b9th sec_data_t *sdata;
b9238976491622ad75a67ab0c12edf99e36212b9th dh_k4_clntdata_t *data;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th sdata = svp->sv_dhsec;
b9238976491622ad75a67ab0c12edf99e36212b9th data = (dh_k4_clntdata_t *)sdata->data;
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(sdata->rpcflavor == AUTH_DH);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th bufp = kmem_zalloc(sizeof (struct netbuf), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th bufp->len = data->syncaddr.len;
b9238976491622ad75a67ab0c12edf99e36212b9th bufp->maxlen = data->syncaddr.maxlen;
b9238976491622ad75a67ab0c12edf99e36212b9th bufp->buf = kmem_zalloc(bufp->len, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th bcopy(data->syncaddr.buf, bufp->buf, bufp->len);
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_syncaddr = bufp;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (data->netname != NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th int nmlen = data->netnamelen;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We need to copy from a dh_k4_clntdata_t
b9238976491622ad75a67ab0c12edf99e36212b9th * netname/netnamelen pair to a NUL-terminated
b9238976491622ad75a67ab0c12edf99e36212b9th * netname string suitable for putting in nfs_args,
b9238976491622ad75a67ab0c12edf99e36212b9th * where the latter has no netnamelen field.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_netname = kmem_zalloc(nmlen + 1, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th bcopy(data->netname, esi->esi_netname, nmlen);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_syncaddr = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_netname = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th stubpath = fn_path(VTOSV(vp)->sv_name);
b9238976491622ad75a67ab0c12edf99e36212b9th /* step over initial '.', to avoid e.g. sv_path: "/tank./ws" */
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(*stubpath == '.');
b9238976491622ad75a67ab0c12edf99e36212b9th stubpath += 1;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* for nfs_args->fh */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_path_len = strlen(stubpath) + 1;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (strcmp(svp->sv_path, "/") != 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_path_len += strlen(svp->sv_path);
b9238976491622ad75a67ab0c12edf99e36212b9th esi->esi_path = kmem_zalloc(esi->esi_path_len, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (strcmp(svp->sv_path, "/") != 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) strcat(esi->esi_path, svp->sv_path);
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strcat(esi->esi_path, stubpath);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th stubpath -= 1;
b9238976491622ad75a67ab0c12edf99e36212b9th /* stubpath allocated by fn_path() */
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(stubpath, strlen(stubpath) + 1);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs_rw_exit(&svp->sv_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (esi);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow/*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Makes an upcall to NFSMAPID daemon to resolve hostname of NFS server to
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * get network information required to do the mount call.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowint
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_callmapid(utf8string *server, struct nfs_fsl_info *resp)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_arg_t door_args;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_handle_t dh;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow XDR xdr;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow refd_door_args_t *xdr_argsp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow refd_door_res_t *orig_resp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow k_sigset_t smask;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int xdr_len = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int res_len = 16; /* length of an ip adress */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int orig_reslen = res_len;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int error = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct nfsidmap_globals *nig;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (ECONNREFUSED);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nig = zone_getspecific(nfsidmap_zone_key, nfs_zone());
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow ASSERT(nig != NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_enter(&nig->nfsidmap_daemon_lock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow dh = nig->nfsidmap_daemon_dh;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (dh == NULL) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_exit(&nig->nfsidmap_daemon_lock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow cmn_err(CE_NOTE,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow "nfs4_callmapid: nfsmapid daemon not " \
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow "running unable to resolve host name\n");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (EINVAL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_ki_hold(dh);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_exit(&nig->nfsidmap_daemon_lock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow xdr_len = xdr_sizeof(&(xdr_utf8string), server);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow xdr_argsp = kmem_zalloc(xdr_len + sizeof (*xdr_argsp), KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow xdr_argsp->xdr_len = xdr_len;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow xdr_argsp->cmd = NFSMAPID_SRV_NETINFO;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow xdrmem_create(&xdr, (char *)&xdr_argsp->xdr_arg,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow xdr_len, XDR_ENCODE);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (!xdr_utf8string(&xdr, server)) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_ki_rele(dh);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (1);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (orig_reslen)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow orig_resp = kmem_alloc(orig_reslen, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_args.data_ptr = (char *)xdr_argsp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_args.data_size = sizeof (*xdr_argsp) + xdr_argsp->xdr_len;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_args.desc_ptr = NULL;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_args.desc_num = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_args.rbuf = orig_resp ? (char *)orig_resp : NULL;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_args.rsize = res_len;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sigintr(&smask, 1);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow error = door_ki_upcall(dh, &door_args);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sigunintr(&smask);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_ki_rele(dh);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (error) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(orig_resp, orig_reslen);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * There is no door to connect to. The referral daemon
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * must not be running yet.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow cmn_err(CE_WARN,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow "nfsmapid not running cannot resolve host name");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow goto out;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * If the results buffer passed back are not the same as
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * what was sent free the old buffer and use the new one.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (orig_resp && orig_reslen) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow refd_door_res_t *door_resp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_resp = (refd_door_res_t *)door_args.rbuf;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if ((void *)door_args.rbuf != orig_resp)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(orig_resp, orig_reslen);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (door_resp->res_status == 0) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow xdrmem_create(&xdr, (char *)&door_resp->xdr_res,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow door_resp->xdr_len, XDR_DECODE);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bzero(resp, sizeof (struct nfs_fsl_info));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (!xdr_nfs_fsl_info(&xdr, resp)) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4clnt__debug__referral__upcall__xdrfail,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct nfs_fsl_info *, resp,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *, "nfs4_callmapid");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow error = EINVAL;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow } else {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4clnt__debug__referral__upcall__badstatus,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int, door_resp->res_status,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *, "nfs4_callmapid");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow error = door_resp->res_status;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(door_args.rbuf, door_args.rsize);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowout:
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(nfs4clnt__func__referral__upcall,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *, server, int, error);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (error);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow}
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow/*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Fetches the fs_locations attribute. Typically called
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * from a Replication/Migration/Referrals/Mirror-mount context
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Fills in the attributes in garp. The caller is assumed
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * to have allocated memory for garp.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * lock: if set do not lock s_recovlock and mi_recovlock mutex,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * it's already done by caller. Otherwise lock these mutexes
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * before doing the rfs4call().
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Returns
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * 1 for success
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * 0 for failure
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowint
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_fetch_locations(mntinfo4_t *mi, nfs4_sharedfh_t *sfh, char *nm,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow cred_t *cr, nfs4_ga_res_t *garp, COMPOUND4res_clnt *callres, bool_t lock)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow COMPOUND4args_clnt args;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow COMPOUND4res_clnt res;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_argop4 *argop;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int argoplist_size = 3 * sizeof (nfs_argop4);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_server_t *sp = NULL;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int doqueue = 1;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int retval = 1;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct nfs4_clnt *nfscl;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (lock == TRUE)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_READER, 0);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow else
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow ASSERT(nfs_rw_lock_held(&mi->mi_recovlock, RW_READER) ||
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_rw_lock_held(&mi->mi_recovlock, RW_WRITER));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sp = find_nfs4_server(mi);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (lock == TRUE)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_rw_exit(&mi->mi_recovlock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (sp != NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_exit(&sp->s_lock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (lock == TRUE) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (sp != NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) nfs_rw_enter_sig(&sp->s_recovlock,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow RW_WRITER, 0);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_WRITER, 0);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow } else {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (sp != NULL) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow ASSERT(nfs_rw_lock_held(&sp->s_recovlock, RW_READER) ||
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_rw_lock_held(&sp->s_recovlock, RW_WRITER));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Do we want to do the setup for recovery here?
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * We know that the server responded to a null ping a very
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * short time ago, and we know that we intend to do a
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * single stateless operation - we want to fetch attributes,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * so we know we can't encounter errors about state. If
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * something goes wrong with the GETATTR, like not being
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * able to get a response from the server or getting any
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * kind of FH error, we should fail the mount.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * We may want to re-visited this at a later time.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow argop = kmem_alloc(argoplist_size, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow args.ctag = TAG_GETATTR_FSLOCATION;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* PUTFH LOOKUP GETATTR */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow args.array_len = 3;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow args.array = argop;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* 0. putfh file */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow argop[0].argop = OP_CPUTFH;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow argop[0].nfs_argop4_u.opcputfh.sfh = sfh;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* 1. lookup name, can't be dotdot */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow argop[1].argop = OP_CLOOKUP;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow argop[1].nfs_argop4_u.opclookup.cname = nm;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* 2. file attrs */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow argop[2].argop = OP_GETATTR;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow argop[2].nfs_argop4_u.opgetattr.attr_request =
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow FATTR4_FSID_MASK | FATTR4_FS_LOCATIONS_MASK |
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow FATTR4_MOUNTED_ON_FILEID_MASK;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow argop[2].nfs_argop4_u.opgetattr.mi = mi;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow rfs4call(mi, &args, &res, cr, &doqueue, 0, &e);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (lock == TRUE) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_rw_exit(&mi->mi_recovlock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (sp != NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_rw_exit(&sp->s_recovlock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfscl = zone_getspecific(nfs4clnt_zone_key, nfs_zone());
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfscl->nfscl_stat.referrals.value.ui64++;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE3(nfs4clnt__func__referral__fsloc,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_sharedfh_t *, sfh, char *, nm, nfs4_error_t *, &e);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (e.error != 0) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (sp != NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_server_rele(sp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(argop, argoplist_size);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (0);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Check for all possible error conditions.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * For valid replies without an ops array or for illegal
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * replies, return a failure.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (res.status != NFS4_OK || res.array_len < 3 ||
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow res.array[2].nfs_resop4_u.opgetattr.status != NFS4_OK) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow retval = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow goto exit;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * There isn't much value in putting the attributes
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * in the attr cache since fs_locations4 aren't
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * encountered very frequently, so just make them
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * available to the caller.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *garp = res.array[2].nfs_resop4_u.opgetattr.ga_res;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(nfs4clnt__debug__referral__fsloc,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ga_res_t *, garp, char *, "nfs4_fetch_locations");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* No fs_locations? -- return a failure */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (garp->n4g_ext_res == NULL ||
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow garp->n4g_ext_res->n4g_fslocations.locations_val == NULL) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow retval = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow goto exit;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (!garp->n4g_fsid_valid)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow retval = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowexit:
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (retval == 0) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* the call was ok but failed validating the call results */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow } else {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow ASSERT(callres != NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *callres = res;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (sp != NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_server_rele(sp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(argop, argoplist_size);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (retval);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow}
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow/* tunable to disable referral mounts */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowint nfs4_no_referrals = 0;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow/*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Returns NULL if the vnode cannot be created or found.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowvnode_t *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowfind_referral_stubvp(vnode_t *dvp, char *nm, cred_t *cr)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_fh4 *stub_fh, *dfh;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_sharedfh_t *sfhp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *newfhval;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vnode_t *vp = NULL;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow fattr4_mounted_on_fileid mnt_on_fileid;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ga_res_t garp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mntinfo4_t *mi;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow COMPOUND4res_clnt callres;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow hrtime_t t;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (nfs4_no_referrals)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Get the mounted_on_fileid, unique on that server::fsid
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mi = VTOMI4(dvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (nfs4_fetch_locations(mi, VTOR4(dvp)->r_fh, nm, cr,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow &garp, &callres, FALSE) == 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mnt_on_fileid = garp.n4g_mon_fid;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&callres);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Build a fake filehandle from the dir FH and the mounted_on_fileid
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow dfh = &VTOR4(dvp)->r_fh->sfh_fh;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow stub_fh = kmem_alloc(sizeof (nfs_fh4), KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow stub_fh->nfs_fh4_val = kmem_alloc(dfh->nfs_fh4_len +
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sizeof (fattr4_mounted_on_fileid), KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow newfhval = stub_fh->nfs_fh4_val;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* copy directory's file handle */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bcopy(dfh->nfs_fh4_val, newfhval, dfh->nfs_fh4_len);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow stub_fh->nfs_fh4_len = dfh->nfs_fh4_len;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow newfhval = newfhval + dfh->nfs_fh4_len;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* Add mounted_on_fileid. Use bcopy to avoid alignment problem */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bcopy((char *)&mnt_on_fileid, newfhval,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sizeof (fattr4_mounted_on_fileid));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow stub_fh->nfs_fh4_len += sizeof (fattr4_mounted_on_fileid);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sfhp = sfh4_put(stub_fh, VTOMI4(dvp), NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(stub_fh->nfs_fh4_val, dfh->nfs_fh4_len +
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sizeof (fattr4_mounted_on_fileid));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(stub_fh, sizeof (nfs_fh4));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (sfhp == NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow t = gethrtime();
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow garp.n4g_va.va_type = VDIR;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vp = makenfs4node(sfhp, NULL, dvp->v_vfsp, t,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow cr, dvp, fn_get(VTOSV(dvp)->sv_name, nm, sfhp));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (vp != NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vp->v_type = VDIR;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sfh4_rele(&sfhp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (vp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow}
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowint
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_setup_referral(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vnode_t *nvp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow rnode4_t *rp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if ((nvp = find_referral_stubvp(dvp, nm, cr)) == NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (EINVAL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow rp = VTOR4(nvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_enter(&rp->r_statelock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow r4_stub_referral(rp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_exit(&rp->r_statelock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow dnlc_enter(dvp, nm, nvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (*vpp != NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow VN_RELE(*vpp); /* no longer need this vnode */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *vpp = nvp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (0);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow}
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow/*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Fetch the location information and resolve the new server.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Caller needs to free up the XDR data which is returned.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Input: mount info, shared filehandle, nodename
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Return: Index to the result or Error(-1)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Output: FsLocations Info, Resolved Server Info.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowint
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_process_referral(mntinfo4_t *mi, nfs4_sharedfh_t *sfh,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *nm, cred_t *cr, nfs4_ga_res_t *grp, COMPOUND4res_clnt *res,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct nfs_fsl_info *fsloc)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow fs_location4 *fsp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct nfs_fsl_info nfsfsloc;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int ret, i, error;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ga_res_t garp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow COMPOUND4res_clnt callres;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct knetconfig *knc;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow ret = nfs4_fetch_locations(mi, sfh, nm, cr, &garp, &callres, TRUE);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (ret == 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (-1);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * As a lame attempt to figuring out if we're
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * handling a migration event or a referral,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * look for rnodes with this fsid in the rnode
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * cache.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * If we can find one or more such rnodes, it
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * means we're handling a migration event and
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * we want to bail out in that case.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (r4find_by_fsid(mi, &garp.n4g_fsid)) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE3(nfs4clnt__debug__referral__migration,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mntinfo4_t *, mi, nfs4_ga_res_t *, &garp,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *, "nfs4_process_referral");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&callres);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (-1);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Find the first responsive server to mount. When we find
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * one, fsp will point to it.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow for (i = 0; i < garp.n4g_ext_res->n4g_fslocations.locations_len; i++) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow fsp = &garp.n4g_ext_res->n4g_fslocations.locations_val[i];
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (fsp->server_len == 0 || fsp->server_val == NULL)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow continue;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow error = nfs4_callmapid(fsp->server_val, &nfsfsloc);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (error != 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow continue;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow error = nfs4_ping_server_common(nfsfsloc.knconf,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfsfsloc.addr, !(mi->mi_flags & MI4_INT));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (error == RPC_SUCCESS)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow break;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(nfs4clnt__debug__referral__srvaddr,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sockaddr_in *, (struct sockaddr_in *)nfsfsloc.addr->buf,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *, "nfs4_process_referral");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_nfs_fsl_info, (char *)&nfsfsloc);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow knc = nfsfsloc.knconf;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if ((i >= garp.n4g_ext_res->n4g_fslocations.locations_len) ||
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (knc->knc_protofmly == NULL) || (knc->knc_proto == NULL)) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(nfs4clnt__debug__referral__nofsloc,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ga_res_t *, &garp, char *, "nfs4_process_referral");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&callres);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (-1);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* Send the results back */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *fsloc = nfsfsloc;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *grp = garp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *res = callres;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (i);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow}
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow/*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Referrals case - need to fetch referral data and then upcall to
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * user-level to get complete mount data.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowstatic ephemeral_servinfo_t *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_trigger_esi_create_referral(vnode_t *vp, cred_t *cr)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct knetconfig *sikncp, *svkncp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct netbuf *bufp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow ephemeral_servinfo_t *esi;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow vnode_t *dvp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow rnode4_t *drp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow fs_location4 *fsp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct nfs_fsl_info nfsfsloc;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ga_res_t garp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *p;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char fn[MAXNAMELEN];
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int i, index = -1;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mntinfo4_t *mi;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow COMPOUND4res_clnt callres;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * If we're passed in a stub vnode that
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * isn't a "referral" stub, bail out
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * and return a failure
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (!RP_ISSTUB_REFERRAL(VTOR4(vp)))
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (vtodv(vp, &dvp, CRED(), TRUE) != 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow drp = VTOR4(dvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (nfs_rw_enter_sig(&drp->r_rwlock, RW_READER, INTR4(dvp))) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow VN_RELE(dvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (vtoname(vp, fn, MAXNAMELEN) != 0) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_rw_exit(&drp->r_rwlock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow VN_RELE(dvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mi = VTOMI4(dvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow index = nfs4_process_referral(mi, drp->r_fh, fn, cr,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow &garp, &callres, &nfsfsloc);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs_rw_exit(&drp->r_rwlock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow VN_RELE(dvp);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (index < 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow fsp = &garp.n4g_ext_res->n4g_fslocations.locations_val[index];
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi = kmem_zalloc(sizeof (ephemeral_servinfo_t), KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* initially set to be our type of ephemeral mount; may be added to */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_mount_flags = NFSMNT_REFERRAL;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_hostname =
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_zalloc(fsp->server_val->utf8string_len + 1, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bcopy(fsp->server_val->utf8string_val, esi->esi_hostname,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow fsp->server_val->utf8string_len);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_hostname[fsp->server_val->utf8string_len] = '\0';
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bufp = kmem_alloc(sizeof (struct netbuf), KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bufp->len = nfsfsloc.addr->len;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bufp->maxlen = nfsfsloc.addr->maxlen;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bufp->buf = kmem_zalloc(bufp->len, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bcopy(nfsfsloc.addr->buf, bufp->buf, bufp->len);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_addr = bufp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_knconf = kmem_zalloc(sizeof (*esi->esi_knconf), KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sikncp = esi->esi_knconf;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(nfs4clnt__debug__referral__nfsfsloc,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct nfs_fsl_info *, &nfsfsloc,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *, "nfs4_trigger_esi_create_referral");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow svkncp = nfsfsloc.knconf;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sikncp->knc_semantics = svkncp->knc_semantics;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sikncp->knc_protofmly = (caddr_t)kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) strlcat((char *)sikncp->knc_protofmly,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (char *)svkncp->knc_protofmly, KNC_STRSIZE);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sikncp->knc_proto = (caddr_t)kmem_zalloc(KNC_STRSIZE, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) strlcat((char *)sikncp->knc_proto, (char *)svkncp->knc_proto,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow KNC_STRSIZE);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow sikncp->knc_rdev = svkncp->knc_rdev;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_PROBE2(nfs4clnt__debug__referral__knetconf,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow struct knetconfig *, sikncp,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow char *, "nfs4_trigger_esi_create_referral");
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_netname = kmem_zalloc(nfsfsloc.netnm_len, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bcopy(nfsfsloc.netname, esi->esi_netname, nfsfsloc.netnm_len);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_syncaddr = NULL;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_path = p = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_path_len = MAXPATHLEN;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *p++ = '/';
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow for (i = 0; i < fsp->rootpath.pathname4_len; i++) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow component4 *comp;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow comp = &fsp->rootpath.pathname4_val[i];
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* If no space, null the string and bail */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if ((p - esi->esi_path) + comp->utf8string_len + 1 > MAXPATHLEN)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow goto err;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bcopy(comp->utf8string_val, p, comp->utf8string_len);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow p += comp->utf8string_len;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *p++ = '/';
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (fsp->rootpath.pathname4_len != 0)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *(p - 1) = '\0';
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow else
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *p = '\0';
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow p = esi->esi_path;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_path = strdup(p);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow esi->esi_path_len = strlen(p) + 1;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(p, MAXPATHLEN);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* Allocated in nfs4_process_referral() */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_nfs_fsl_info, (char *)&nfsfsloc);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&callres);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (esi);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowerr:
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi->esi_path, esi->esi_path_len);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi->esi_hostname, fsp->server_val->utf8string_len + 1);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi->esi_addr->buf, esi->esi_addr->len);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi->esi_addr, sizeof (struct netbuf));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi->esi_knconf->knc_protofmly, KNC_STRSIZE);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi->esi_knconf->knc_proto, KNC_STRSIZE);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi->esi_knconf, sizeof (*esi->esi_knconf));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi->esi_netname, nfsfsloc.netnm_len);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow kmem_free(esi, sizeof (ephemeral_servinfo_t));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_nfs_fsl_info, (char *)&nfsfsloc);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow (void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&callres);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (NULL);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow}
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Assemble the args, and call the generic VFS mount function to
b9238976491622ad75a67ab0c12edf99e36212b9th * finally perform the ephemeral mount.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_domount(vnode_t *stubvp, domount_args_t *dma, vfs_t **vfsp,
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes cred_t *cr, vnode_t **newvpp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th struct mounta *uap;
b9238976491622ad75a67ab0c12edf99e36212b9th char *mntpt, *orig_path, *path;
b9238976491622ad75a67ab0c12edf99e36212b9th const char *orig_mntpt;
b9238976491622ad75a67ab0c12edf99e36212b9th int retval;
b9238976491622ad75a67ab0c12edf99e36212b9th int mntpt_len;
b9238976491622ad75a67ab0c12edf99e36212b9th int spec_len;
b9238976491622ad75a67ab0c12edf99e36212b9th zone_t *zone = curproc->p_zone;
b9238976491622ad75a67ab0c12edf99e36212b9th bool_t has_leading_slash;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes int i;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th vfs_t *stubvfsp = stubvp->v_vfsp;
b9238976491622ad75a67ab0c12edf99e36212b9th ephemeral_servinfo_t *esi = dma->dma_esi;
b9238976491622ad75a67ab0c12edf99e36212b9th struct nfs_args *nargs = dma->dma_nargs;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* first, construct the mount point for the ephemeral mount */
b9238976491622ad75a67ab0c12edf99e36212b9th orig_path = path = fn_path(VTOSV(stubvp)->sv_name);
b9238976491622ad75a67ab0c12edf99e36212b9th orig_mntpt = (char *)refstr_value(stubvfsp->vfs_mntpt);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (*orig_path == '.')
b9238976491622ad75a67ab0c12edf99e36212b9th orig_path++;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Get rid of zone's root path
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (zone != global_zone) {
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * -1 for trailing '/' and -1 for EOS.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (strncmp(zone->zone_rootpath, orig_mntpt,
b9238976491622ad75a67ab0c12edf99e36212b9th zone->zone_rootpathlen - 1) == 0) {
b9238976491622ad75a67ab0c12edf99e36212b9th orig_mntpt += (zone->zone_rootpathlen - 2);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mntpt_len = strlen(orig_mntpt) + strlen(orig_path);
b9238976491622ad75a67ab0c12edf99e36212b9th mntpt = kmem_zalloc(mntpt_len + 1, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strcat(mntpt, orig_mntpt);
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strcat(mntpt, orig_path);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(path, strlen(path) + 1);
b9238976491622ad75a67ab0c12edf99e36212b9th path = esi->esi_path;
b9238976491622ad75a67ab0c12edf99e36212b9th if (*path == '.')
b9238976491622ad75a67ab0c12edf99e36212b9th path++;
b9238976491622ad75a67ab0c12edf99e36212b9th if (path[0] == '/' && path[1] == '/')
b9238976491622ad75a67ab0c12edf99e36212b9th path++;
b9238976491622ad75a67ab0c12edf99e36212b9th has_leading_slash = (*path == '/');
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th spec_len = strlen(dma->dma_hostlist);
b9238976491622ad75a67ab0c12edf99e36212b9th spec_len += strlen(path);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* We are going to have to add this in */
b9238976491622ad75a67ab0c12edf99e36212b9th if (!has_leading_slash)
b9238976491622ad75a67ab0c12edf99e36212b9th spec_len++;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* We need to get the ':' for dma_hostlist:esi_path */
b9238976491622ad75a67ab0c12edf99e36212b9th spec_len++;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th uap = kmem_zalloc(sizeof (struct mounta), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th uap->spec = kmem_zalloc(spec_len + 1, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th (void) snprintf(uap->spec, spec_len + 1, "%s:%s%s", dma->dma_hostlist,
b9238976491622ad75a67ab0c12edf99e36212b9th has_leading_slash ? "" : "/", path);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th uap->dir = mntpt;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th uap->flags = MS_SYSSPACE | MS_DATA;
b9238976491622ad75a67ab0c12edf99e36212b9th /* fstype-independent mount options not covered elsewhere */
b9238976491622ad75a67ab0c12edf99e36212b9th /* copy parent's mount(1M) "-m" flag */
b9238976491622ad75a67ab0c12edf99e36212b9th if (stubvfsp->vfs_flag & VFS_NOMNTTAB)
b9238976491622ad75a67ab0c12edf99e36212b9th uap->flags |= MS_NOMNTTAB;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th uap->fstype = MNTTYPE_NFS4;
b9238976491622ad75a67ab0c12edf99e36212b9th uap->dataptr = (char *)nargs;
b9238976491622ad75a67ab0c12edf99e36212b9th /* not needed for MS_SYSSPACE */
b9238976491622ad75a67ab0c12edf99e36212b9th uap->datalen = 0;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* use optptr to pass in extra mount options */
b9238976491622ad75a67ab0c12edf99e36212b9th uap->flags |= MS_OPTIONSTR;
b9238976491622ad75a67ab0c12edf99e36212b9th uap->optptr = nfs4_trigger_create_mntopts(stubvfsp);
b9238976491622ad75a67ab0c12edf99e36212b9th if (uap->optptr == NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th retval = EINVAL;
b9238976491622ad75a67ab0c12edf99e36212b9th goto done;
b9238976491622ad75a67ab0c12edf99e36212b9th }
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th /* domount() expects us to count the trailing NUL */
b9238976491622ad75a67ab0c12edf99e36212b9th uap->optlen = strlen(uap->optptr) + 1;
b9238976491622ad75a67ab0c12edf99e36212b9th
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes /*
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes * If we get EBUSY, we try again once to see if we can perform
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes * the mount. We do this because of a spurious race condition.
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes */
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes for (i = 0; i < 2; i++) {
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes int error;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes bool_t was_mounted;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes retval = domount(NULL, uap, stubvp, cr, vfsp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes if (retval == 0) {
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes retval = VFS_ROOT(*vfsp, newvpp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes VFS_RELE(*vfsp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes break;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes } else if (retval != EBUSY) {
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes break;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes }
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes /*
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes * We might find it mounted by the other racer...
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes */
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes error = nfs4_trigger_mounted_already(stubvp,
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes newvpp, &was_mounted, vfsp);
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes if (error) {
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes goto done;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes } else if (was_mounted) {
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes retval = 0;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes break;
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes }
6962f5b8ab9112ea1e951c076b3eb4583ef37612Thomas Haynes }
546a399722fe82dc300c308a8fb86a11d2ca3ba3Thomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9thdone:
b9238976491622ad75a67ab0c12edf99e36212b9th if (uap->optptr)
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_destroy_mntopts(uap->optptr);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(uap->spec, spec_len + 1);
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(uap, sizeof (struct mounta));
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(mntpt, mntpt_len + 1);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (retval);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Build an nfs_args structure for passing to domount().
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Ephemeral mount-type specific data comes from the ephemeral_servinfo_t;
b9238976491622ad75a67ab0c12edf99e36212b9th * generic data - common to all ephemeral mount types - is read directly
b9238976491622ad75a67ab0c12edf99e36212b9th * from the parent mount's servinfo4_t and mntinfo4_t, via the stub vnode.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic struct nfs_args *
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_nargs_create(mntinfo4_t *mi, servinfo4_t *svp,
b9238976491622ad75a67ab0c12edf99e36212b9th ephemeral_servinfo_t *esi)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th sec_data_t *secdata;
b9238976491622ad75a67ab0c12edf99e36212b9th struct nfs_args *nargs;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* setup the nfs args */
b9238976491622ad75a67ab0c12edf99e36212b9th nargs = kmem_zalloc(sizeof (struct nfs_args), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th (void) nfs_rw_enter_sig(&svp->sv_lock, RW_READER, 0);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->addr = esi->esi_addr;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* for AUTH_DH by negotiation */
b9238976491622ad75a67ab0c12edf99e36212b9th if (esi->esi_syncaddr || esi->esi_netname) {
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_SECURE;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->syncaddr = esi->esi_syncaddr;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->netname = esi->esi_netname;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_KNCONF;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->knconf = esi->esi_knconf;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_HOSTNAME;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->hostname = esi->esi_hostname;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->fh = esi->esi_path;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* general mount settings, all copied from parent mount */
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (!(mi->mi_flags & MI4_HARD))
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_SOFT;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_TIMEO |
b9238976491622ad75a67ab0c12edf99e36212b9th NFSMNT_RETRANS;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->wsize = mi->mi_stsize;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->rsize = mi->mi_tsize;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->timeo = mi->mi_timeo;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->retrans = mi->mi_retrans;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_flags & MI4_INT)
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_INT;
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_flags & MI4_NOAC)
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_NOAC;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_ACREGMIN | NFSMNT_ACREGMAX | NFSMNT_ACDIRMIN |
b9238976491622ad75a67ab0c12edf99e36212b9th NFSMNT_ACDIRMAX;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->acregmin = HR2SEC(mi->mi_acregmin);
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->acregmax = HR2SEC(mi->mi_acregmax);
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->acdirmin = HR2SEC(mi->mi_acdirmin);
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->acdirmax = HR2SEC(mi->mi_acdirmax);
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* add any specific flags for this type of ephemeral mount */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nargs->flags |= esi->esi_mount_flags;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_flags & MI4_NOCTO)
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_NOCTO;
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_flags & MI4_GRPID)
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_GRPID;
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_flags & MI4_LLOCK)
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_LLOCK;
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_flags & MI4_NOPRINT)
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_NOPRINT;
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_flags & MI4_DIRECTIO)
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_DIRECTIO;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (mi->mi_flags & MI4_PUBLIC && nargs->flags & NFSMNT_MIRRORMOUNT)
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_PUBLIC;
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* Do some referral-specific option tweaking */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (nargs->flags & NFSMNT_REFERRAL) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nargs->flags &= ~NFSMNT_DORDMA;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nargs->flags |= NFSMNT_TRYRDMA;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow }
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_exit(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Security data & negotiation policy.
b9238976491622ad75a67ab0c12edf99e36212b9th *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * For mirror mounts, we need to preserve the parent mount's
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * preference for security negotiation, translating SV4_TRYSECDEFAULT
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * to NFSMNT_SECDEFAULT if present.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * For referrals, we always want security negotiation and will
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * set NFSMNT_SECDEFAULT and we will not copy current secdata.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * The reason is that we can't negotiate down from a parent's
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Kerberos flavor to AUTH_SYS.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * If SV4_TRYSECDEFAULT is not set, that indicates that a specific
b9238976491622ad75a67ab0c12edf99e36212b9th * security flavour was requested, with data in sv_secdata, and that
b9238976491622ad75a67ab0c12edf99e36212b9th * no negotiation should occur. If this specified flavour fails, that's
b9238976491622ad75a67ab0c12edf99e36212b9th * it. We will copy sv_secdata, and not set NFSMNT_SECDEFAULT.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * If SV4_TRYSECDEFAULT is set, then we start with a passed-in
b9238976491622ad75a67ab0c12edf99e36212b9th * default flavour, in sv_secdata, but then negotiate a new flavour.
b9238976491622ad75a67ab0c12edf99e36212b9th * Possible flavours are recorded in an array in sv_secinfo, with
b9238976491622ad75a67ab0c12edf99e36212b9th * currently in-use flavour pointed to by sv_currsec.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * If sv_currsec is set, i.e. if negotiation has already occurred,
b9238976491622ad75a67ab0c12edf99e36212b9th * we will copy sv_currsec. Otherwise, copy sv_secdata. Regardless,
b9238976491622ad75a67ab0c12edf99e36212b9th * we will set NFSMNT_SECDEFAULT, to enable negotiation.
b9238976491622ad75a67ab0c12edf99e36212b9th */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (nargs->flags & NFSMNT_REFERRAL) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* enable negotiation for referral mount */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nargs->flags |= NFSMNT_SECDEFAULT;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow secdata = kmem_alloc(sizeof (sec_data_t), KM_SLEEP);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow secdata->secmod = secdata->rpcflavor = AUTH_SYS;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow secdata->data = NULL;
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes } else if (svp->sv_flags & SV4_TRYSECDEFAULT) {
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /* enable negotiation for mirror mount */
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_SECDEFAULT;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * As a starting point for negotiation, copy parent
b9238976491622ad75a67ab0c12edf99e36212b9th * mount's negotiated flavour (sv_currsec) if available,
b9238976491622ad75a67ab0c12edf99e36212b9th * or its passed-in flavour (sv_secdata) if not.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (svp->sv_currsec != NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th secdata = copy_sec_data(svp->sv_currsec);
b9238976491622ad75a67ab0c12edf99e36212b9th else if (svp->sv_secdata != NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th secdata = copy_sec_data(svp->sv_secdata);
b9238976491622ad75a67ab0c12edf99e36212b9th else
b9238976491622ad75a67ab0c12edf99e36212b9th secdata = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th /* do not enable negotiation; copy parent's passed-in flavour */
b9238976491622ad75a67ab0c12edf99e36212b9th if (svp->sv_secdata != NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th secdata = copy_sec_data(svp->sv_secdata);
b9238976491622ad75a67ab0c12edf99e36212b9th else
b9238976491622ad75a67ab0c12edf99e36212b9th secdata = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs_rw_exit(&svp->sv_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->flags |= NFSMNT_NEWARGS;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->nfs_args_ext = NFS_ARGS_EXTB;
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->nfs_ext_u.nfs_extB.secdata = secdata;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* for NFS RO failover; caller will set if necessary */
b9238976491622ad75a67ab0c12edf99e36212b9th nargs->nfs_ext_u.nfs_extB.next = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (nargs);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_nargs_destroy(struct nfs_args *nargs)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Either the mount failed, in which case the data is not needed, or
b9238976491622ad75a67ab0c12edf99e36212b9th * nfs4_mount() has either taken copies of what it needs or,
b9238976491622ad75a67ab0c12edf99e36212b9th * where it has merely copied the ptr, it has set *our* ptr to NULL,
b9238976491622ad75a67ab0c12edf99e36212b9th * whereby nfs4_free_args() will ignore it.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_free_args(nargs);
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(nargs, sizeof (struct nfs_args));
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * When we finally get into the mounting, we need to add this
b9238976491622ad75a67ab0c12edf99e36212b9th * node to the ephemeral tree.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * This is called from nfs4_mount().
b9238976491622ad75a67ab0c12edf99e36212b9th */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynesint
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_record_ephemeral_mount(mntinfo4_t *mi, vnode_t *mvp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th mntinfo4_t *mi_parent;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *eph;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *net;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *prior;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *child;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *peer;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_globals_t *ntg;
b9238976491622ad75a67ab0c12edf99e36212b9th zone_t *zone = curproc->p_zone;
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes int rc = 0;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th mi_parent = VTOMI4(mvp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Get this before grabbing anything else!
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th ntg = zone_getspecific(nfs4_ephemeral_key, zone);
b9238976491622ad75a67ab0c12edf99e36212b9th if (!ntg->ntg_thread_started) {
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_start_harvester(ntg);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&mi_parent->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes net = mi->mi_ephemeral_tree =
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mi_parent->mi_ephemeral_tree;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * If the mi_ephemeral_tree is NULL, then it
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * means that either the harvester or a manual
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * umount has cleared the tree out right before
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * we got here.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes *
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * There is nothing we can do here, so return
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * to the caller and let them decide whether they
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * try again.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (net == NULL) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&mi->mi_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&mi_parent->mi_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes return (EBUSY);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes }
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * We've just tied the mntinfo to the tree, so
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * now we bump the refcnt and hold it there until
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * this mntinfo is removed from the tree.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes nfs4_ephemeral_tree_hold(net);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We need to tack together the ephemeral mount
b9238976491622ad75a67ab0c12edf99e36212b9th * with this new mntinfo.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th eph = kmem_zalloc(sizeof (*eph), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th eph->ne_mount = mi;
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes MI4_HOLD(mi);
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes VFS_HOLD(mi->mi_vfsp);
b9238976491622ad75a67ab0c12edf99e36212b9th eph->ne_ref_time = gethrestime_sec();
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We need to tell the ephemeral mount when
b9238976491622ad75a67ab0c12edf99e36212b9th * to time out.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th eph->ne_mount_to = ntg->ntg_mount_to;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mi->mi_ephemeral = eph;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If the enclosing mntinfo4 is also ephemeral,
b9238976491622ad75a67ab0c12edf99e36212b9th * then we need to point to its enclosing parent.
b9238976491622ad75a67ab0c12edf99e36212b9th * Else the enclosing mntinfo4 is the enclosing parent.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * We also need to weave this ephemeral node
b9238976491622ad75a67ab0c12edf99e36212b9th * into the tree.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi_parent->mi_flags & MI4_EPHEMERAL) {
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We need to decide if we are
b9238976491622ad75a67ab0c12edf99e36212b9th * the root node of this branch
b9238976491622ad75a67ab0c12edf99e36212b9th * or if we are a sibling of this
b9238976491622ad75a67ab0c12edf99e36212b9th * branch.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th prior = mi_parent->mi_ephemeral;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (prior == NULL) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * Race condition, clean up, and
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * let caller handle mntinfo.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mi->mi_flags &= ~MI4_EPHEMERAL;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mi->mi_ephemeral = NULL;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes kmem_free(eph, sizeof (*eph));
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes VFS_RELE(mi->mi_vfsp);
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes MI4_RELE(mi);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_tree_rele(net);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes rc = EBUSY;
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (prior->ne_child == NULL) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes prior->ne_child = eph;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes } else {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes child = prior->ne_child;
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes prior->ne_child = eph;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes eph->ne_peer = child;
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes child->ne_prior = eph;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes }
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes eph->ne_prior = prior;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes }
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * The parent mntinfo4 is the non-ephemeral
b9238976491622ad75a67ab0c12edf99e36212b9th * root of the ephemeral tree. We
b9238976491622ad75a67ab0c12edf99e36212b9th * need to decide if we are the root
b9238976491622ad75a67ab0c12edf99e36212b9th * node of that tree or if we are a
b9238976491622ad75a67ab0c12edf99e36212b9th * sibling of the root node.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * We are the root if there is no
b9238976491622ad75a67ab0c12edf99e36212b9th * other node.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (net->net_root == NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_root = eph;
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th eph->ne_peer = peer = net->net_root;
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(peer != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_root = eph;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th peer->ne_prior = eph;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th eph->ne_prior = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&mi_parent->mi_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes return (rc);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Commit the changes to the ephemeral tree for removing this node.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_umount_cleanup(nfs4_ephemeral_t *eph)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *e = eph;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *peer;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *prior;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th peer = eph->ne_peer;
b9238976491622ad75a67ab0c12edf99e36212b9th prior = e->ne_prior;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If this branch root was not the
b9238976491622ad75a67ab0c12edf99e36212b9th * tree root, then we need to fix back pointers.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior) {
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior->ne_child == e) {
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_child = peer;
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_peer = peer;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (peer)
b9238976491622ad75a67ab0c12edf99e36212b9th peer->ne_prior = prior;
b9238976491622ad75a67ab0c12edf99e36212b9th } else if (peer) {
b9238976491622ad75a67ab0c12edf99e36212b9th peer->ne_mount->mi_ephemeral_tree->net_root = peer;
b9238976491622ad75a67ab0c12edf99e36212b9th peer->ne_prior = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_mount->mi_ephemeral_tree->net_root = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * We want to avoid recursion at all costs. So we need to
b9238976491622ad75a67ab0c12edf99e36212b9th * unroll the tree. We do this by a depth first traversal to
b9238976491622ad75a67ab0c12edf99e36212b9th * leaf nodes. We blast away the leaf and work our way back
b9238976491622ad75a67ab0c12edf99e36212b9th * up and down the tree.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_unmount_engine(nfs4_ephemeral_t *eph,
b9238976491622ad75a67ab0c12edf99e36212b9th int isTreeRoot, int flag, cred_t *cr)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *e = eph;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *prior;
b9238976491622ad75a67ab0c12edf99e36212b9th mntinfo4_t *mi;
b9238976491622ad75a67ab0c12edf99e36212b9th vfs_t *vfsp;
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We use the loop while unrolling the ephemeral tree.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th for (;;) {
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * First we walk down the child.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (e->ne_child) {
b9238976491622ad75a67ab0c12edf99e36212b9th prior = e;
b9238976491622ad75a67ab0c12edf99e36212b9th e = e->ne_child;
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If we are the root of the branch we are removing,
b9238976491622ad75a67ab0c12edf99e36212b9th * we end it here. But if the branch is the root of
b9238976491622ad75a67ab0c12edf99e36212b9th * the tree, we have to forge on. We do not consider
b9238976491622ad75a67ab0c12edf99e36212b9th * the peer list for the root because while it may
b9238976491622ad75a67ab0c12edf99e36212b9th * be okay to remove, it is both extra work and a
b9238976491622ad75a67ab0c12edf99e36212b9th * potential for a false-positive error to stall the
b9238976491622ad75a67ab0c12edf99e36212b9th * unmount attempt.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (e == eph && isTreeRoot == FALSE)
b9238976491622ad75a67ab0c12edf99e36212b9th return (0);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Next we walk down the peer list.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (e->ne_peer) {
b9238976491622ad75a67ab0c12edf99e36212b9th prior = e;
b9238976491622ad75a67ab0c12edf99e36212b9th e = e->ne_peer;
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We can only remove the node passed in by the
b9238976491622ad75a67ab0c12edf99e36212b9th * caller if it is the root of the ephemeral tree.
b9238976491622ad75a67ab0c12edf99e36212b9th * Otherwise, the caller will remove it.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (e == eph && isTreeRoot == FALSE)
b9238976491622ad75a67ab0c12edf99e36212b9th return (0);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Okay, we have a leaf node, time
b9238976491622ad75a67ab0c12edf99e36212b9th * to prune it!
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Note that prior can only be NULL if
b9238976491622ad75a67ab0c12edf99e36212b9th * and only if it is the root of the
b9238976491622ad75a67ab0c12edf99e36212b9th * ephemeral tree.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th prior = e->ne_prior;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mi = e->ne_mount;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th vfsp = mi->mi_vfsp;
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes ASSERT(vfsp != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Cleared by umount2_engine.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th VFS_HOLD(vfsp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Inform nfs4_unmount to not recursively
b9238976491622ad75a67ab0c12edf99e36212b9th * descend into this node's children when it
b9238976491622ad75a67ab0c12edf99e36212b9th * gets processed.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th mi->mi_flags |= MI4_EPHEMERAL_RECURSED;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th error = umount2_engine(vfsp, flag, cr, FALSE);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error) {
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * We need to reenable nfs4_unmount's ability
b9238976491622ad75a67ab0c12edf99e36212b9th * to recursively descend on this node.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th mi->mi_flags &= ~MI4_EPHEMERAL_RECURSED;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If we are the current node, we do not want to
b9238976491622ad75a67ab0c12edf99e36212b9th * touch anything else. At this point, the only
b9238976491622ad75a67ab0c12edf99e36212b9th * way the current node can have survived to here
b9238976491622ad75a67ab0c12edf99e36212b9th * is if it is the root of the ephemeral tree and
b9238976491622ad75a67ab0c12edf99e36212b9th * we are unmounting the enclosing mntinfo4.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (e == eph) {
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(prior == NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th return (0);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Stitch up the prior node. Note that since
b9238976491622ad75a67ab0c12edf99e36212b9th * we have handled the root of the tree, prior
b9238976491622ad75a67ab0c12edf99e36212b9th * must be non-NULL.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(prior != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior->ne_child == e) {
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_child = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th } else {
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(prior->ne_peer == e);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_peer = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th e = prior;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* NOTREACHED */
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Common code to safely release net_cnt_lock and net_tree_lock
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thvoid
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_umount_unlock(bool_t *pmust_unlock,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_tree_t **pnet)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *net = *pnet;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (*pmust_unlock) {
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status &= ~NFS4_EPHEMERAL_TREE_UMOUNTING;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th *pmust_unlock = FALSE;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * While we may have removed any child or sibling nodes of this
b9238976491622ad75a67ab0c12edf99e36212b9th * ephemeral node, we can not nuke it until we know that there
b9238976491622ad75a67ab0c12edf99e36212b9th * were no actived vnodes on it. This will do that final
b9238976491622ad75a67ab0c12edf99e36212b9th * work once we know it is not busy.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thvoid
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_umount_activate(mntinfo4_t *mi, bool_t *pmust_unlock,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_tree_t **pnet)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Now we need to get rid of the ephemeral data if it exists.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th if (mi->mi_ephemeral) {
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If we are the root node of an ephemeral branch
b9238976491622ad75a67ab0c12edf99e36212b9th * which is being removed, then we need to fixup
b9238976491622ad75a67ab0c12edf99e36212b9th * pointers into and out of the node.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (!(mi->mi_flags & MI4_EPHEMERAL_RECURSED))
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_umount_cleanup(mi->mi_ephemeral);
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_tree_rele(*pnet);
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(mi->mi_ephemeral != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(mi->mi_ephemeral, sizeof (*mi->mi_ephemeral));
b9238976491622ad75a67ab0c12edf99e36212b9th mi->mi_ephemeral = NULL;
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes VFS_RELE(mi->mi_vfsp);
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes MI4_RELE(mi);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_umount_unlock(pmust_unlock, pnet);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Unmount an ephemeral node.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Note that if this code fails, then it must unlock.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * If it succeeds, then the caller must be prepared to do so.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thint
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_umount(mntinfo4_t *mi, int flag, cred_t *cr,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow bool_t *pmust_unlock, nfs4_ephemeral_tree_t **pnet)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error = 0;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *eph;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *net;
b9238976491622ad75a67ab0c12edf99e36212b9th int is_derooting = FALSE;
b9238976491622ad75a67ab0c12edf99e36212b9th int is_recursed = FALSE;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes int was_locked = FALSE;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * Make sure to set the default state for cleaning
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * up the tree in the caller (and on the way out).
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow *pmust_unlock = FALSE;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * The active vnodes on this file system may be ephemeral
b9238976491622ad75a67ab0c12edf99e36212b9th * children. We need to check for and try to unmount them
b9238976491622ad75a67ab0c12edf99e36212b9th * here. If any can not be unmounted, we are going
b9238976491622ad75a67ab0c12edf99e36212b9th * to return EBUSY.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If an ephemeral tree, we need to check to see if
b9238976491622ad75a67ab0c12edf99e36212b9th * the lock is already held. If it is, then we need
b9238976491622ad75a67ab0c12edf99e36212b9th * to see if we are being called as a result of
b9238976491622ad75a67ab0c12edf99e36212b9th * the recursive removal of some node of the tree or
b9238976491622ad75a67ab0c12edf99e36212b9th * if we are another attempt to remove the tree.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * mi_flags & MI4_EPHEMERAL indicates an ephemeral
b9238976491622ad75a67ab0c12edf99e36212b9th * node. mi_ephemeral being non-NULL also does this.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * mi_ephemeral_tree being non-NULL is sufficient
b9238976491622ad75a67ab0c12edf99e36212b9th * to also indicate either it is an ephemeral node
b9238976491622ad75a67ab0c12edf99e36212b9th * or the enclosing mntinfo4.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Do we need MI4_EPHEMERAL? Yes, it is useful for
b9238976491622ad75a67ab0c12edf99e36212b9th * when we delete the ephemeral node and need to
b9238976491622ad75a67ab0c12edf99e36212b9th * differentiate from an ephemeral node and the
b9238976491622ad75a67ab0c12edf99e36212b9th * enclosing root node.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th *pnet = net = mi->mi_ephemeral_tree;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (net == NULL) {
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&mi->mi_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth return (0);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth }
b9238976491622ad75a67ab0c12edf99e36212b9th
eabd0450c0ea06b7993daac8f9545c7061ae7caeth eph = mi->mi_ephemeral;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth is_recursed = mi->mi_flags & MI4_EPHEMERAL_RECURSED;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth is_derooting = (eph == NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_enter(&net->net_cnt_lock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
eabd0450c0ea06b7993daac8f9545c7061ae7caeth /*
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * If this is not recursion, then we need to
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * check to see if a harvester thread has
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * already grabbed the lock.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * After we exit this branch, we may not
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * blindly return, we need to jump to
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * is_busy!
eabd0450c0ea06b7993daac8f9545c7061ae7caeth */
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (!is_recursed) {
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (net->net_status &
eabd0450c0ea06b7993daac8f9545c7061ae7caeth NFS4_EPHEMERAL_TREE_LOCKED) {
b9238976491622ad75a67ab0c12edf99e36212b9th /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * If the tree is locked, we need
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * to decide whether we are the
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * harvester or some explicit call
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * for a umount. The only way that
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * we are the harvester is if
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * MS_SYSSPACE is set.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes *
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * We only let the harvester through
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * at this point.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth *
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * We return EBUSY so that the
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * caller knows something is
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * going on. Note that by that
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * time, the umount in the other
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * thread may have already occured.
b9238976491622ad75a67ab0c12edf99e36212b9th */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (!(flag & MS_SYSSPACE)) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&mi->mi_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes return (EBUSY);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes }
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes was_locked = TRUE;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes }
eabd0450c0ea06b7993daac8f9545c7061ae7caeth }
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow mutex_exit(&net->net_cnt_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_exit(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
eabd0450c0ea06b7993daac8f9545c7061ae7caeth /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * If we are not the harvester, we need to check
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * to see if we need to grab the tree lock.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (was_locked == FALSE) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * If we grab the lock, it means that no other
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * operation is working on the tree. If we don't
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * grab it, we need to decide if this is because
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * we are a recursive call or a new operation.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (mutex_tryenter(&net->net_tree_lock)) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes *pmust_unlock = TRUE;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes } else {
b9238976491622ad75a67ab0c12edf99e36212b9th /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * If we are a recursive call, we can
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * proceed without the lock.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * Otherwise we have to wait until
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * the lock becomes free.
b9238976491622ad75a67ab0c12edf99e36212b9th */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (!is_recursed) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_enter(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (net->net_status &
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes (NFS4_EPHEMERAL_TREE_DEROOTING
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes | NFS4_EPHEMERAL_TREE_INVALID)) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes goto is_busy;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes }
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * We can't hold any other locks whilst
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * we wait on this to free up.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_enter(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * Note that while mi->mi_ephemeral
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * may change and thus we have to
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * update eph, it is the case that
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * we have tied down net and
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * do not care if mi->mi_ephemeral_tree
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * has changed.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_enter(&mi->mi_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes eph = mi->mi_ephemeral;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&mi->mi_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * Okay, we need to see if either the
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * tree got nuked or the current node
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * got nuked. Both of which will cause
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * an error.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes *
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * Note that a subsequent retry of the
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * umount shall work.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_enter(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (net->net_status &
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes NFS4_EPHEMERAL_TREE_INVALID ||
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes (!is_derooting && eph == NULL)) {
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_tree_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes goto is_busy;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes }
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_exit(&net->net_cnt_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes *pmust_unlock = TRUE;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth }
eabd0450c0ea06b7993daac8f9545c7061ae7caeth }
eabd0450c0ea06b7993daac8f9545c7061ae7caeth }
eabd0450c0ea06b7993daac8f9545c7061ae7caeth
eabd0450c0ea06b7993daac8f9545c7061ae7caeth /*
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * Only once we have grabbed the lock can we mark what we
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * are planning on doing to the ephemeral tree.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth */
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (*pmust_unlock) {
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_enter(&net->net_cnt_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth net->net_status |= NFS4_EPHEMERAL_TREE_UMOUNTING;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth
eabd0450c0ea06b7993daac8f9545c7061ae7caeth /*
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * Check to see if we are nuking the root.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth */
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (is_derooting)
eabd0450c0ea06b7993daac8f9545c7061ae7caeth net->net_status |=
eabd0450c0ea06b7993daac8f9545c7061ae7caeth NFS4_EPHEMERAL_TREE_DEROOTING;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_exit(&net->net_cnt_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth }
eabd0450c0ea06b7993daac8f9545c7061ae7caeth
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (!is_derooting) {
eabd0450c0ea06b7993daac8f9545c7061ae7caeth /*
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * Only work on children if the caller has not already
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * done so.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth */
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (!is_recursed) {
eabd0450c0ea06b7993daac8f9545c7061ae7caeth ASSERT(eph != NULL);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth
eabd0450c0ea06b7993daac8f9545c7061ae7caeth error = nfs4_ephemeral_unmount_engine(eph,
eabd0450c0ea06b7993daac8f9545c7061ae7caeth FALSE, flag, cr);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (error)
eabd0450c0ea06b7993daac8f9545c7061ae7caeth goto is_busy;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth }
eabd0450c0ea06b7993daac8f9545c7061ae7caeth } else {
eabd0450c0ea06b7993daac8f9545c7061ae7caeth eph = net->net_root;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth
eabd0450c0ea06b7993daac8f9545c7061ae7caeth /*
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * Only work if there is something there.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth */
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (eph) {
eabd0450c0ea06b7993daac8f9545c7061ae7caeth error = nfs4_ephemeral_unmount_engine(eph, TRUE,
eabd0450c0ea06b7993daac8f9545c7061ae7caeth flag, cr);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth if (error) {
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_enter(&net->net_cnt_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth net->net_status &=
eabd0450c0ea06b7993daac8f9545c7061ae7caeth ~NFS4_EPHEMERAL_TREE_DEROOTING;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_exit(&net->net_cnt_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth goto is_busy;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * Nothing else which goes wrong will
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * invalidate the blowing away of the
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * ephmeral tree.
b9238976491622ad75a67ab0c12edf99e36212b9th */
eabd0450c0ea06b7993daac8f9545c7061ae7caeth net->net_root = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th }
eabd0450c0ea06b7993daac8f9545c7061ae7caeth
eabd0450c0ea06b7993daac8f9545c7061ae7caeth /*
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * We have derooted and we have caused the tree to be
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * invalidated.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth */
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_enter(&net->net_cnt_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth net->net_status &= ~NFS4_EPHEMERAL_TREE_DEROOTING;
eabd0450c0ea06b7993daac8f9545c7061ae7caeth net->net_status |= NFS4_EPHEMERAL_TREE_INVALID;
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow DTRACE_NFSV4_1(nfs4clnt__dbg__ephemeral__tree__derooting,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow uint_t, net->net_refcnt);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow /*
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * We will not finalize this node, so safe to
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * release it.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow */
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_tree_decr(net);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_exit(&net->net_cnt_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes if (was_locked == FALSE)
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes mutex_exit(&net->net_tree_lock);
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * We have just blown away any notation of this
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * tree being locked or having a refcnt.
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * We can't let the caller try to clean things up.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes */
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes *pmust_unlock = FALSE;
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes
eabd0450c0ea06b7993daac8f9545c7061ae7caeth /*
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes * At this point, the tree should no longer be
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes * associated with the mntinfo4. We need to pull
d708af7468d704bef75d63291c115c0909f1da5dThomas Haynes * it off there and let the harvester take
eabd0450c0ea06b7993daac8f9545c7061ae7caeth * care of it once the refcnt drops.
eabd0450c0ea06b7993daac8f9545c7061ae7caeth */
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mutex_enter(&mi->mi_lock);
eabd0450c0ea06b7993daac8f9545c7061ae7caeth mi->mi_ephemeral_tree = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&mi->mi_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (0);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9this_busy:
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_umount_unlock(pmust_unlock, pnet);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (error);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Do the umount and record any error in the parent.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_record_umount(vfs_t *vfsp, int flag,
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *e, nfs4_ephemeral_t *prior)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th int error;
b9238976491622ad75a67ab0c12edf99e36212b9th
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes /*
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes * Only act on if the fs is still mounted.
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes */
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes if (vfsp == NULL)
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes return;
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th error = umount2_engine(vfsp, flag, kcred, FALSE);
b9238976491622ad75a67ab0c12edf99e36212b9th if (error) {
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior) {
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior->ne_child == e)
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_state |=
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_CHILD_ERROR;
b9238976491622ad75a67ab0c12edf99e36212b9th else
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_state |=
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_PEER_ERROR;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * For each tree in the forest (where the forest is in
b9238976491622ad75a67ab0c12edf99e36212b9th * effect all of the ephemeral trees for this zone),
b9238976491622ad75a67ab0c12edf99e36212b9th * scan to see if a node can be unmounted. Note that
b9238976491622ad75a67ab0c12edf99e36212b9th * unlike nfs4_ephemeral_unmount_engine(), we do
b9238976491622ad75a67ab0c12edf99e36212b9th * not process the current node before children or
b9238976491622ad75a67ab0c12edf99e36212b9th * siblings. I.e., if a node can be unmounted, we
b9238976491622ad75a67ab0c12edf99e36212b9th * do not recursively check to see if the nodes
b9238976491622ad75a67ab0c12edf99e36212b9th * hanging off of it can also be unmounted.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Instead, we delve down deep to try and remove the
b9238976491622ad75a67ab0c12edf99e36212b9th * children first. Then, because we share code with
b9238976491622ad75a67ab0c12edf99e36212b9th * nfs4_ephemeral_unmount_engine(), we will try
b9238976491622ad75a67ab0c12edf99e36212b9th * them again. This could be a performance issue in
b9238976491622ad75a67ab0c12edf99e36212b9th * the future.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Also note that unlike nfs4_ephemeral_unmount_engine(),
b9238976491622ad75a67ab0c12edf99e36212b9th * we do not halt on an error. We will not remove the
b9238976491622ad75a67ab0c12edf99e36212b9th * current node, but we will keep on trying to remove
b9238976491622ad75a67ab0c12edf99e36212b9th * the others.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * force indicates that we want the unmount to occur
b9238976491622ad75a67ab0c12edf99e36212b9th * even if there is something blocking it.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * time_check indicates that we want to see if the
b9238976491622ad75a67ab0c12edf99e36212b9th * mount has expired past mount_to or not. Typically
b9238976491622ad75a67ab0c12edf99e36212b9th * we want to do this and only on a shutdown of the
b9238976491622ad75a67ab0c12edf99e36212b9th * zone would we want to ignore the check.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_harvest_forest(nfs4_trigger_globals_t *ntg,
b9238976491622ad75a67ab0c12edf99e36212b9th bool_t force, bool_t time_check)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *net;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *prev = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *next;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *e;
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_t *prior;
b9238976491622ad75a67ab0c12edf99e36212b9th time_t now = gethrestime_sec();
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_tree_t *harvest = NULL;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th int flag;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mntinfo4_t *mi;
b9238976491622ad75a67ab0c12edf99e36212b9th vfs_t *vfsp;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (force)
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes flag = MS_FORCE | MS_SYSSPACE;
b9238976491622ad75a67ab0c12edf99e36212b9th else
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes flag = MS_SYSSPACE;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&ntg->ntg_forest_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th for (net = ntg->ntg_forest; net != NULL; net = next) {
b9238976491622ad75a67ab0c12edf99e36212b9th next = net->net_next;
b9238976491622ad75a67ab0c12edf99e36212b9th
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes nfs4_ephemeral_tree_hold(net);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Let the unmount code know that the
b9238976491622ad75a67ab0c12edf99e36212b9th * tree is already locked!
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status |= NFS4_EPHEMERAL_TREE_LOCKED;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If the intent is force all ephemeral nodes to
b9238976491622ad75a67ab0c12edf99e36212b9th * be unmounted in this zone, we can short circuit a
b9238976491622ad75a67ab0c12edf99e36212b9th * lot of tree traversal and simply zap the root node.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (force) {
b9238976491622ad75a67ab0c12edf99e36212b9th if (net->net_root) {
b9238976491622ad75a67ab0c12edf99e36212b9th mi = net->net_root->ne_mount;
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th vfsp = mi->mi_vfsp;
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes ASSERT(vfsp != NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Cleared by umount2_engine.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th VFS_HOLD(vfsp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th (void) umount2_engine(vfsp, flag,
b9238976491622ad75a67ab0c12edf99e36212b9th kcred, FALSE);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th goto check_done;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th e = net->net_root;
b9238976491622ad75a67ab0c12edf99e36212b9th if (e)
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_state = NFS4_EPHEMERAL_VISIT_CHILD;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th while (e) {
b9238976491622ad75a67ab0c12edf99e36212b9th if (e->ne_state == NFS4_EPHEMERAL_VISIT_CHILD) {
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_state = NFS4_EPHEMERAL_VISIT_SIBLING;
b9238976491622ad75a67ab0c12edf99e36212b9th if (e->ne_child) {
b9238976491622ad75a67ab0c12edf99e36212b9th e = e->ne_child;
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_state =
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_VISIT_CHILD;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th } else if (e->ne_state ==
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_VISIT_SIBLING) {
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_state = NFS4_EPHEMERAL_PROCESS_ME;
b9238976491622ad75a67ab0c12edf99e36212b9th if (e->ne_peer) {
b9238976491622ad75a67ab0c12edf99e36212b9th e = e->ne_peer;
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_state =
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_VISIT_CHILD;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th } else if (e->ne_state ==
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_CHILD_ERROR) {
b9238976491622ad75a67ab0c12edf99e36212b9th prior = e->ne_prior;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * If a child reported an error, do
b9238976491622ad75a67ab0c12edf99e36212b9th * not bother trying to unmount.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * If your prior node is a parent,
b9238976491622ad75a67ab0c12edf99e36212b9th * pass the error up such that they
b9238976491622ad75a67ab0c12edf99e36212b9th * also do not try to unmount.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * However, if your prior is a sibling,
b9238976491622ad75a67ab0c12edf99e36212b9th * let them try to unmount if they can.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior) {
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior->ne_child == e)
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_state |=
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_CHILD_ERROR;
b9238976491622ad75a67ab0c12edf99e36212b9th else
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_state |=
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_PEER_ERROR;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Clear the error and if needed, process peers.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Once we mask out the error, we know whether
b9238976491622ad75a67ab0c12edf99e36212b9th * or we have to process another node.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_state &= ~NFS4_EPHEMERAL_CHILD_ERROR;
b9238976491622ad75a67ab0c12edf99e36212b9th if (e->ne_state == NFS4_EPHEMERAL_PROCESS_ME)
b9238976491622ad75a67ab0c12edf99e36212b9th e = prior;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th } else if (e->ne_state ==
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_PEER_ERROR) {
b9238976491622ad75a67ab0c12edf99e36212b9th prior = e->ne_prior;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior) {
b9238976491622ad75a67ab0c12edf99e36212b9th if (prior->ne_child == e)
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_state =
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_CHILD_ERROR;
b9238976491622ad75a67ab0c12edf99e36212b9th else
b9238976491622ad75a67ab0c12edf99e36212b9th prior->ne_state =
b9238976491622ad75a67ab0c12edf99e36212b9th NFS4_EPHEMERAL_PEER_ERROR;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Clear the error from this node and do the
b9238976491622ad75a67ab0c12edf99e36212b9th * correct processing.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_state &= ~NFS4_EPHEMERAL_PEER_ERROR;
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th prior = e->ne_prior;
b9238976491622ad75a67ab0c12edf99e36212b9th e->ne_state = NFS4_EPHEMERAL_OK;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * It must be the case that we need to process
b9238976491622ad75a67ab0c12edf99e36212b9th * this node.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (!time_check ||
b9238976491622ad75a67ab0c12edf99e36212b9th now - e->ne_ref_time > e->ne_mount_to) {
b9238976491622ad75a67ab0c12edf99e36212b9th mi = e->ne_mount;
b9238976491622ad75a67ab0c12edf99e36212b9th vfsp = mi->mi_vfsp;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Cleared by umount2_engine.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes if (vfsp != NULL)
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes VFS_HOLD(vfsp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Note that we effectively work down to the
b9238976491622ad75a67ab0c12edf99e36212b9th * leaf nodes first, try to unmount them,
b9238976491622ad75a67ab0c12edf99e36212b9th * then work our way back up into the leaf
b9238976491622ad75a67ab0c12edf99e36212b9th * nodes.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Also note that we deal with a lot of
b9238976491622ad75a67ab0c12edf99e36212b9th * complexity by sharing the work with
b9238976491622ad75a67ab0c12edf99e36212b9th * the manual unmount code.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_record_umount(vfsp, flag,
b9238976491622ad75a67ab0c12edf99e36212b9th e, prior);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th e = prior;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thcheck_done:
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * At this point we are done processing this tree.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * If the tree is invalid and we were the only reference
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * to it, then we push it on the local linked list
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * to remove it at the end. We avoid that action now
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes * to keep the tree processing going along at a fair clip.
d3a1459128b677cee1a84512ca49eef4bffd392dThomas Haynes *
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * Else, even if we were the only reference, we
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow * allow it to be reused as needed.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&net->net_cnt_lock);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow nfs4_ephemeral_tree_decr(net);
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (net->net_refcnt == 0 &&
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status & NFS4_EPHEMERAL_TREE_INVALID) {
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status &= ~NFS4_EPHEMERAL_TREE_LOCKED;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (prev)
b9238976491622ad75a67ab0c12edf99e36212b9th prev->net_next = net->net_next;
b9238976491622ad75a67ab0c12edf99e36212b9th else
b9238976491622ad75a67ab0c12edf99e36212b9th ntg->ntg_forest = net->net_next;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_next = harvest;
b9238976491622ad75a67ab0c12edf99e36212b9th harvest = net;
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes VFS_RELE(net->net_mount->mi_vfsp);
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes MI4_RELE(net->net_mount);
b87f76ed1ee637bbd9c4bb45fb6d05f3ae647b07Thomas Haynes
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th net->net_status &= ~NFS4_EPHEMERAL_TREE_LOCKED;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th prev = net;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&ntg->ntg_forest_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th for (net = harvest; net != NULL; net = next) {
b9238976491622ad75a67ab0c12edf99e36212b9th next = net->net_next;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_destroy(&net->net_tree_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_destroy(&net->net_cnt_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(net, sizeof (*net));
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * This is the thread which decides when the harvesting
b9238976491622ad75a67ab0c12edf99e36212b9th * can proceed and when to kill it off for this zone.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_harvester(nfs4_trigger_globals_t *ntg)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th clock_t timeleft;
b9238976491622ad75a67ab0c12edf99e36212b9th zone_t *zone = curproc->p_zone;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th for (;;) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni timeleft = zone_status_timedwait(zone, ddi_get_lbolt() +
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_thread_timer * hz, ZONE_IS_SHUTTING_DOWN);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * zone is exiting...
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (timeleft != -1) {
b9238976491622ad75a67ab0c12edf99e36212b9th ASSERT(zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN);
b9238976491622ad75a67ab0c12edf99e36212b9th zthread_exit();
b9238976491622ad75a67ab0c12edf99e36212b9th /* NOTREACHED */
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Only bother scanning if there is potential
b9238976491622ad75a67ab0c12edf99e36212b9th * work to be done.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (ntg->ntg_forest == NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Now scan the list and get rid of everything which
b9238976491622ad75a67ab0c12edf99e36212b9th * is old.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_harvest_forest(ntg, FALSE, TRUE);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* NOTREACHED */
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * The zone specific glue needed to start the unmount harvester.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Note that we want to avoid holding the mutex as long as possible,
b9238976491622ad75a67ab0c12edf99e36212b9th * hence the multiple checks.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * The caller should avoid us getting down here in the first
b9238976491622ad75a67ab0c12edf99e36212b9th * place.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_start_harvester(nfs4_trigger_globals_t *ntg)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * It got started before we got here...
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (ntg->ntg_thread_started)
b9238976491622ad75a67ab0c12edf99e36212b9th return;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_enter(&nfs4_ephemeral_thread_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (ntg->ntg_thread_started) {
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&nfs4_ephemeral_thread_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th return;
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * Start the unmounter harvester thread for this zone.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th (void) zthread_create(NULL, 0, nfs4_ephemeral_harvester,
b9238976491622ad75a67ab0c12edf99e36212b9th ntg, 0, minclsyspri);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ntg->ntg_thread_started = TRUE;
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_exit(&nfs4_ephemeral_thread_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*ARGSUSED*/
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void *
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_zsd_create(zoneid_t zoneid)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_globals_t *ntg;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ntg = kmem_zalloc(sizeof (*ntg), KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th ntg->ntg_thread_started = FALSE;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * This is the default....
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th ntg->ntg_mount_to = nfs4_trigger_thread_timer;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_init(&ntg->ntg_forest_lock, NULL,
b9238976491622ad75a67ab0c12edf99e36212b9th MUTEX_DEFAULT, NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (ntg);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Try a nice gentle walk down the forest and convince
b9238976491622ad75a67ab0c12edf99e36212b9th * all of the trees to gracefully give it up.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th/*ARGSUSED*/
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_zsd_shutdown(zoneid_t zoneid, void *arg)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_globals_t *ntg = arg;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (!ntg)
b9238976491622ad75a67ab0c12edf99e36212b9th return;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_harvest_forest(ntg, FALSE, FALSE);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Race along the forest and rip all of the trees out by
b9238976491622ad75a67ab0c12edf99e36212b9th * their rootballs!
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th/*ARGSUSED*/
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_zsd_destroy(zoneid_t zoneid, void *arg)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_globals_t *ntg = arg;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (!ntg)
b9238976491622ad75a67ab0c12edf99e36212b9th return;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_harvest_forest(ntg, TRUE, FALSE);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_destroy(&ntg->ntg_forest_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(ntg, sizeof (*ntg));
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * This is the zone independent cleanup needed for
b9238976491622ad75a67ab0c12edf99e36212b9th * emphemeral mount processing.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thvoid
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_fini(void)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th (void) zone_key_delete(nfs4_ephemeral_key);
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_destroy(&nfs4_ephemeral_thread_lock);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * This is the zone independent initialization needed for
b9238976491622ad75a67ab0c12edf99e36212b9th * emphemeral mount processing.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thvoid
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_init(void)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th mutex_init(&nfs4_ephemeral_thread_lock, NULL, MUTEX_DEFAULT,
b9238976491622ad75a67ab0c12edf99e36212b9th NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th zone_key_create(&nfs4_ephemeral_key, nfs4_ephemeral_zsd_create,
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_ephemeral_zsd_shutdown, nfs4_ephemeral_zsd_destroy);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * nfssys() calls this function to set the per-zone
b9238976491622ad75a67ab0c12edf99e36212b9th * value of mount_to to drive when an ephemeral mount is
b9238976491622ad75a67ab0c12edf99e36212b9th * timed out. Each mount will grab a copy of this value
b9238976491622ad75a67ab0c12edf99e36212b9th * when mounted.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thvoid
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_ephemeral_set_mount_to(uint_t mount_to)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_globals_t *ntg;
b9238976491622ad75a67ab0c12edf99e36212b9th zone_t *zone = curproc->p_zone;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ntg = zone_getspecific(nfs4_ephemeral_key, zone);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th ntg->ntg_mount_to = mount_to;
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Walk the list of v4 mount options; if they are currently set in vfsp,
b9238976491622ad75a67ab0c12edf99e36212b9th * append them to a new comma-separated mount option string, and return it.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Caller should free by calling nfs4_trigger_destroy_mntopts().
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic char *
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_create_mntopts(vfs_t *vfsp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th uint_t i;
b9238976491622ad75a67ab0c12edf99e36212b9th char *mntopts;
b9238976491622ad75a67ab0c12edf99e36212b9th struct vfssw *vswp;
b9238976491622ad75a67ab0c12edf99e36212b9th mntopts_t *optproto;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th mntopts = kmem_zalloc(MAX_MNTOPT_STR, KM_SLEEP);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* get the list of applicable mount options for v4; locks *vswp */
b9238976491622ad75a67ab0c12edf99e36212b9th vswp = vfs_getvfssw(MNTTYPE_NFS4);
b9238976491622ad75a67ab0c12edf99e36212b9th optproto = &vswp->vsw_optproto;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th for (i = 0; i < optproto->mo_count; i++) {
b9238976491622ad75a67ab0c12edf99e36212b9th struct mntopt *mop = &optproto->mo_list[i];
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (mop->mo_flags & MO_EMPTY)
b9238976491622ad75a67ab0c12edf99e36212b9th continue;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (nfs4_trigger_add_mntopt(mntopts, mop->mo_name, vfsp)) {
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(mntopts, MAX_MNTOPT_STR);
b9238976491622ad75a67ab0c12edf99e36212b9th vfs_unrefvfssw(vswp);
b9238976491622ad75a67ab0c12edf99e36212b9th return (NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th vfs_unrefvfssw(vswp);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /*
b9238976491622ad75a67ab0c12edf99e36212b9th * MNTOPT_XATTR is not in the v4 mount opt proto list,
b9238976491622ad75a67ab0c12edf99e36212b9th * and it may only be passed via MS_OPTIONSTR, so we
b9238976491622ad75a67ab0c12edf99e36212b9th * must handle it here.
b9238976491622ad75a67ab0c12edf99e36212b9th *
b9238976491622ad75a67ab0c12edf99e36212b9th * Ideally, it would be in the list, but NFS does not specify its
b9238976491622ad75a67ab0c12edf99e36212b9th * own opt proto list, it uses instead the default one. Since
b9238976491622ad75a67ab0c12edf99e36212b9th * not all filesystems support extended attrs, it would not be
b9238976491622ad75a67ab0c12edf99e36212b9th * appropriate to add it there.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9th if (nfs4_trigger_add_mntopt(mntopts, MNTOPT_XATTR, vfsp) ||
b9238976491622ad75a67ab0c12edf99e36212b9th nfs4_trigger_add_mntopt(mntopts, MNTOPT_NOXATTR, vfsp)) {
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(mntopts, MAX_MNTOPT_STR);
b9238976491622ad75a67ab0c12edf99e36212b9th return (NULL);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (mntopts);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic void
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_destroy_mntopts(char *mntopts)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th if (mntopts)
b9238976491622ad75a67ab0c12edf99e36212b9th kmem_free(mntopts, MAX_MNTOPT_STR);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th/*
b9238976491622ad75a67ab0c12edf99e36212b9th * Check a single mount option (optname). Add to mntopts if it is set in VFS.
b9238976491622ad75a67ab0c12edf99e36212b9th */
b9238976491622ad75a67ab0c12edf99e36212b9thstatic int
b9238976491622ad75a67ab0c12edf99e36212b9thnfs4_trigger_add_mntopt(char *mntopts, char *optname, vfs_t *vfsp)
b9238976491622ad75a67ab0c12edf99e36212b9th{
b9238976491622ad75a67ab0c12edf99e36212b9th if (mntopts == NULL || optname == NULL || vfsp == NULL)
b9238976491622ad75a67ab0c12edf99e36212b9th return (EINVAL);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (vfs_optionisset(vfsp, optname, NULL)) {
b9238976491622ad75a67ab0c12edf99e36212b9th size_t mntoptslen = strlen(mntopts);
b9238976491622ad75a67ab0c12edf99e36212b9th size_t optnamelen = strlen(optname);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* +1 for ',', +1 for NUL */
b9238976491622ad75a67ab0c12edf99e36212b9th if (mntoptslen + optnamelen + 2 > MAX_MNTOPT_STR)
b9238976491622ad75a67ab0c12edf99e36212b9th return (EOVERFLOW);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* first or subsequent mount option? */
b9238976491622ad75a67ab0c12edf99e36212b9th if (*mntopts != '\0')
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strcat(mntopts, ",");
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th (void) strcat(mntopts, optname);
b9238976491622ad75a67ab0c12edf99e36212b9th }
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (0);
b9238976491622ad75a67ab0c12edf99e36212b9th}
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9thstatic enum clnt_stat
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_ping_server_common(struct knetconfig *knc, struct netbuf *addr, int nointr)
b9238976491622ad75a67ab0c12edf99e36212b9th{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow int retries;
b9238976491622ad75a67ab0c12edf99e36212b9th uint_t max_msgsize;
b9238976491622ad75a67ab0c12edf99e36212b9th enum clnt_stat status;
b9238976491622ad75a67ab0c12edf99e36212b9th CLIENT *cl;
b9238976491622ad75a67ab0c12edf99e36212b9th struct timeval timeout;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th /* as per recov_newserver() */
b9238976491622ad75a67ab0c12edf99e36212b9th max_msgsize = 0;
b9238976491622ad75a67ab0c12edf99e36212b9th retries = 1;
b9238976491622ad75a67ab0c12edf99e36212b9th timeout.tv_sec = 2;
b9238976491622ad75a67ab0c12edf99e36212b9th timeout.tv_usec = 0;
b9238976491622ad75a67ab0c12edf99e36212b9th
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow if (clnt_tli_kcreate(knc, addr, NFS_PROGRAM, NFS_V4,
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow max_msgsize, retries, CRED(), &cl) != 0)
b9238976491622ad75a67ab0c12edf99e36212b9th return (RPC_FAILED);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th if (nointr)
b9238976491622ad75a67ab0c12edf99e36212b9th cl->cl_nosignal = TRUE;
b9238976491622ad75a67ab0c12edf99e36212b9th status = CLNT_CALL(cl, RFS_NULL, xdr_void, NULL, xdr_void, NULL,
b9238976491622ad75a67ab0c12edf99e36212b9th timeout);
b9238976491622ad75a67ab0c12edf99e36212b9th if (nointr)
b9238976491622ad75a67ab0c12edf99e36212b9th cl->cl_nosignal = FALSE;
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th AUTH_DESTROY(cl->cl_auth);
b9238976491622ad75a67ab0c12edf99e36212b9th CLNT_DESTROY(cl);
b9238976491622ad75a67ab0c12edf99e36212b9th
b9238976491622ad75a67ab0c12edf99e36212b9th return (status);
b9238976491622ad75a67ab0c12edf99e36212b9th}
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlowstatic enum clnt_stat
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlownfs4_trigger_ping_server(servinfo4_t *svp, int nointr)
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow{
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow return (nfs4_ping_server_common(svp->sv_knconf, &svp->sv_addr, nointr));
2f172c55ef76964744bc62b4500ece87f3089b4dRobert Thurlow}