auto_vnops.c revision ffc349ab772a8ab3ac82d192827e2777ab45d0be
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER START
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The contents of this file are subject to the terms of the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Common Development and Distribution License (the "License").
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You may not use this file except in compliance with the License.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * or http://www.opensolaris.org/os/licensing.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * See the License for the specific language governing permissions
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and limitations under the License.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens * When distributing Covered Code, include this CDDL HEADER in each
5f7a8e6d750cb070a3347f045201c6206caee6aaDan McDonald * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If applicable, add the following below this CDDL HEADER, with the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * fields enclosed by brackets "[]" replaced with your own identifying
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * information: Portions Copyright [yyyy] [name of copyright owner]
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER END
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Use is subject to license terms.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma ident "%Z%%M% %I% %E% SMI"
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/param.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/systm.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/errno.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/proc.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/vnode.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/vfs.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/vfs_opreg.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/uio.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/cred.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/pathname.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/dirent.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/debug.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/sysmacros.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/tiuser.h>
7b1753e64ab6c8c68e7cd79acbedfdfba12bd7f8John Wren Kennedy#include <sys/cmn_err.h>
7b1753e64ab6c8c68e7cd79acbedfdfba12bd7f8John Wren Kennedy#include <sys/stat.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/mode.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/policy.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <rpc/types.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <rpc/auth.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <rpc/clnt.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/fs/autofs.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <rpcsvc/autofs_prot.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <fs/fs_subr.h>
7b1753e64ab6c8c68e7cd79acbedfdfba12bd7f8John Wren Kennedy
7b1753e64ab6c8c68e7cd79acbedfdfba12bd7f8John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Vnode ops for autofs
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int auto_open(vnode_t **, int, cred_t *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int auto_close(vnode_t *, int, int, offset_t, cred_t *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int auto_getattr(vnode_t *, vattr_t *, int, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_setattr(vnode_t *, vattr_t *, int, cred_t *,
c029eafbb040b81649027c5ae5a38e92d214461bHans Rosenfeld caller_context_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_access(vnode_t *, int, int, cred_t *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int auto_lookup(vnode_t *, char *, vnode_t **,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pathname_t *, int, vnode_t *, cred_t *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int auto_create(vnode_t *, char *, vattr_t *, vcexcl_t,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy int, vnode_t **, cred_t *, int);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_remove(vnode_t *, char *, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_link(vnode_t *, vnode_t *, char *, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_rename(vnode_t *, char *, vnode_t *, char *, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_mkdir(vnode_t *, char *, vattr_t *, vnode_t **, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_rmdir(vnode_t *, char *, vnode_t *, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_readdir(vnode_t *, uio_t *, cred_t *, int *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_symlink(vnode_t *, char *, vattr_t *, char *, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_readlink(vnode_t *, struct uio *, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int auto_fsync(vnode_t *, int, cred_t *);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic void auto_inactive(vnode_t *, cred_t *);
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankovstatic int auto_rwlock(vnode_t *, int, caller_context_t *);
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankovstatic void auto_rwunlock(vnode_t *vp, int, caller_context_t *);
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankovstatic int auto_seek(vnode_t *vp, offset_t, offset_t *);
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankov
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankovstatic int auto_trigger_mount(vnode_t *, cred_t *, vnode_t **);
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankov
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankovvnodeops_t *auto_vnodeops;
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankov
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankovconst fs_operation_def_t auto_vnodeops_template[] = {
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens VOPNAME_OPEN, { .vop_open = auto_open },
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens VOPNAME_CLOSE, { .vop_close = auto_close },
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens VOPNAME_GETATTR, { .vop_getattr = auto_getattr },
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens VOPNAME_SETATTR, { .vop_setattr = auto_setattr },
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens VOPNAME_ACCESS, { .vop_access = auto_access },
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VOPNAME_LOOKUP, { .vop_lookup = auto_lookup },
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VOPNAME_CREATE, { .vop_create = auto_create },
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VOPNAME_REMOVE, { .vop_remove = auto_remove },
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VOPNAME_LINK, { .vop_link = auto_link },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_RENAME, { .vop_rename = auto_rename },
c5d1600c3eb0a58e493be9019c5fb8eaec72cb81Matthew Ahrens VOPNAME_MKDIR, { .vop_mkdir = auto_mkdir },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_RMDIR, { .vop_rmdir = auto_rmdir },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_READDIR, { .vop_readdir = auto_readdir },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_SYMLINK, { .vop_symlink = auto_symlink },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_READLINK, { .vop_readlink = auto_readlink },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_FSYNC, { .vop_fsync = auto_fsync },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_INACTIVE, { .vop_inactive = auto_inactive },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_RWLOCK, { .vop_rwlock = auto_rwlock },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_RWUNLOCK, { .vop_rwunlock = auto_rwunlock },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_SEEK, { .vop_seek = auto_seek },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_FRLOCK, { .error = fs_error },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_DISPOSE, { .error = fs_error },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_SHRLOCK, { .error = fs_error },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy NULL, NULL
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyauto_open(vnode_t **vpp, int flag, cred_t *cred)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vnode_t *newvp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int error;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((4, "auto_open: *vpp=%p\n", (void *)*vpp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = auto_trigger_mount(*vpp, cred, &newvp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (error)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy goto done;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (newvp != NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Node is now mounted on.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VN_RELE(*vpp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *vpp = newvp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = VOP_ACCESS(*vpp, VREAD, 0, cred);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!error)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = VOP_OPEN(vpp, flag, cred);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedydone:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((5, "auto_open: *vpp=%p error=%d\n", (void *)*vpp,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyauto_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cred)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedyauto_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cred)
5878fad70d76d8711f6608c1f80b0447601261c6Dan McDonald{
5f7a8e6d750cb070a3347f045201c6206caee6aaDan McDonald fnnode_t *fnp = vntofn(vp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vnode_t *newvp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vfs_t *vfsp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int error;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((4, "auto_getattr vp %p\n", (void *)vp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Recursive auto_getattr/mount; go to the vfsp == NULL
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * case.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (vn_vfswlock_held(vp))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy goto defattr;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error = vn_vfsrlock_wait(vp))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vfsp = vn_mountedvfs(vp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (vfsp != NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Node is mounted on.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = VFS_ROOT(vfsp, &newvp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vn_vfsunlock(vp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (error)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&fnp->fn_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (fnp->fn_seen == newvp && fnp->fn_thread == curthread) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Recursive auto_getattr(); just release newvp and drop
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * into the vfsp == NULL case.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&fnp->fn_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VN_RELE(newvp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while (fnp->fn_thread && fnp->fn_thread != curthread) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fnp->fn_flags |= MF_ATTR_WAIT;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_wait(&fnp->fn_cv_mount, &fnp->fn_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy fnp->fn_thread = curthread;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy fnp->fn_seen = newvp;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_exit(&fnp->fn_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = VOP_GETATTR(newvp, vap, flags, cred);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VN_RELE(newvp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&fnp->fn_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fnp->fn_seen = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fnp->fn_thread = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (fnp->fn_flags & MF_ATTR_WAIT) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fnp->fn_flags &= ~MF_ATTR_WAIT;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_broadcast(&fnp->fn_cv_mount);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&fnp->fn_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vn_vfsunlock(vp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedydefattr:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(vp->v_type == VDIR || vp->v_type == VLNK);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_uid = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_gid = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_nlink = fnp->fn_linkcnt;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_nodeid = (u_longlong_t)fnp->fn_nodeid;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_size = fnp->fn_size;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_atime = fnp->fn_atime;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_mtime = fnp->fn_mtime;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_ctime = fnp->fn_ctime;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_type = vp->v_type;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_mode = fnp->fn_mode;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_fsid = vp->v_vfsp->vfs_dev;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_rdev = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_blksize = MAXBSIZE;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vap->va_seq = 0;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (0);
4eab410fb63816fe2c0ad0fd18b4c948613f6616Matthew Ahrens}
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy/*ARGSUSED4*/
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyauto_setattr(
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vnode_t *vp,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct vattr *vap,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int flags,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cred_t *cred,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy caller_context_t *ct)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vnode_t *newvp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int error;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((4, "auto_setattr vp %p\n", (void *)vp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (error = auto_trigger_mount(vp, cred, &newvp))
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy goto done;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (newvp != NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Node is mounted on.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (vn_is_readonly(newvp))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = EROFS;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = VOP_SETATTR(newvp, vap, flags, cred, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VN_RELE(newvp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = ENOSYS;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedydone:
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy AUTOFS_DPRINT((5, "auto_setattr: error=%d\n", error));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (error);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy}
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyauto_access(vnode_t *vp, int mode, int flags, cred_t *cred)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fnnode_t *fnp = vntofn(vp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vnode_t *newvp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int error;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((4, "auto_access: vp=%p\n", (void *)vp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (error = auto_trigger_mount(vp, cred, &newvp))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy goto done;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (newvp != NULL) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Node is mounted on.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = VOP_ACCESS(newvp, mode, 0, cred);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VN_RELE(newvp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int shift = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * really interested in the autofs node, check the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * access on it
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(error == 0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (crgetuid(cred) != fnp->fn_uid) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy shift += 3;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (groupmember(fnp->fn_gid, cred) == 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy shift += 3;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mode &= ~(fnp->fn_mode << shift);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mode != 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = secpolicy_vnode_access(cred, vp, fnp->fn_uid,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mode);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedydone:
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy AUTOFS_DPRINT((5, "auto_access: error=%d\n", error));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (error);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy}
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedystatic int
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedyauto_lookup(
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vnode_t *dvp,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy char *nm,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vnode_t **vpp,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy pathname_t *pnp,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy int flags,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vnode_t *rdir,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy cred_t *cred)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy{
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy int error = 0;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vnode_t *newvp = NULL;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vfs_t *vfsp;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy fninfo_t *dfnip;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy fnnode_t *dfnp = NULL;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy fnnode_t *fnp = NULL;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy char *searchnm;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy int operation; /* either AUTOFS_LOOKUP or AUTOFS_MOUNT */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy dfnip = vfstofni(dvp->v_vfsp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy AUTOFS_DPRINT((3, "auto_lookup: dvp=%p (%s) name=%s\n",
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy (void *)dvp, dfnip->fi_map, nm));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (nm[0] == 0) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VN_HOLD(dvp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy *vpp = dvp;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (0);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error = VOP_ACCESS(dvp, VEXEC, 0, cred))
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (error);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (nm[0] == '.' && nm[1] == 0) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VN_HOLD(dvp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy *vpp = dvp;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (0);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy fnnode_t *pdfnp;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy pdfnp = (vntofn(dvp))->fn_parent;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy ASSERT(pdfnp != NULL);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Since it is legitimate to have the VROOT flag set for the
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * subdirectories of the indirect map in autofs filesystem,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * rootfnnodep is checked against fnnode of dvp instead of
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * just checking whether VROOT flag is set in dvp
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (pdfnp == pdfnp->fn_globals->fng_rootfnnodep) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vnode_t *vp;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vfs_rlock_wait(dvp->v_vfsp);
633aa8079184298dfc2ae6966d0d9cc897712b57Yuri Pankov if (dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) {
633aa8079184298dfc2ae6966d0d9cc897712b57Yuri Pankov vfs_unlock(dvp->v_vfsp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (EIO);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vp = dvp->v_vfsp->vfs_vnodecovered;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VN_HOLD(vp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vfs_unlock(dvp->v_vfsp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = VOP_LOOKUP(vp, nm, vpp, pnp, flags, rdir, cred);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy VN_RELE(vp);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy return (error);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy } else {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy *vpp = fntovn(pdfnp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VN_HOLD(*vpp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (0);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
4eab410fb63816fe2c0ad0fd18b4c948613f6616Matthew Ahrens
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedytop:
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy dfnp = vntofn(dvp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy searchnm = nm;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy operation = 0;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy ASSERT(vn_matchops(dvp, auto_vnodeops));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy AUTOFS_DPRINT((3, "auto_lookup: dvp=%p dfnp=%p\n", (void *)dvp,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy (void *)dfnp));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * If a lookup or mount of this node is in progress, wait for it
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * to finish, and return whatever result it got.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_enter(&dfnp->fn_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (dfnp->fn_flags & (MF_LOOKUP | MF_INPROG)) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_exit(&dfnp->fn_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = auto_wait4mount(dfnp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error == AUTOFS_SHUTDOWN)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = ENOENT;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error == EAGAIN)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy goto top;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (error);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy } else
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_exit(&dfnp->fn_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = vn_vfsrlock_wait(dvp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (error);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vfsp = vn_mountedvfs(dvp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (vfsp != NULL) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = VFS_ROOT(vfsp, &newvp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vn_vfsunlock(dvp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (!error) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = VOP_LOOKUP(newvp, nm, vpp, pnp,
7d46dc6ca63a6f3f0d51aa655bfcf10cf2405a9eMatthew Ahrens flags, rdir, cred);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VN_RELE(newvp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vn_vfsunlock(dvp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy rw_enter(&dfnp->fn_rwlock, RW_READER);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = auto_search(dfnp, nm, &fnp, cred);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (dfnip->fi_flags & MF_DIRECT) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * direct map.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (dfnp->fn_dirents) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Mount previously triggered.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * 'nm' not found
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = ENOENT;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy } else {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * I need to contact the daemon to trigger
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * the mount. 'dfnp' will be the mountpoint.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy operation = AUTOFS_MOUNT;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VN_HOLD(fntovn(dfnp));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy fnp = dfnp;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = 0;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy } else if (dvp == dfnip->fi_rootvp) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * 'dfnp' is the root of the indirect AUTOFS.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (rw_tryupgrade(&dfnp->fn_rwlock) == 0) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Could not acquire writer lock, release
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * reader, and wait until available. We
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * need to search for 'nm' again, since we
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * had to release the lock before reacquiring
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * it.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy rw_exit(&dfnp->fn_rwlock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy rw_enter(&dfnp->fn_rwlock, RW_WRITER);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = auto_search(dfnp, nm, &fnp, cred);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * create node being looked-up and request
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * mount on it.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = auto_enter(dfnp, nm, &fnp, kcred);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (!error)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy operation = AUTOFS_LOOKUP;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy } else if ((dfnp->fn_dirents == NULL) &&
9c3fd1216fa7fb02cfbc78a2518a686d54b48ab8Matthew Ahrens ((dvp->v_flag & VROOT) == 0) &&
9c3fd1216fa7fb02cfbc78a2518a686d54b48ab8Matthew Ahrens ((fntovn(dfnp->fn_parent))->v_flag & VROOT)) {
9c3fd1216fa7fb02cfbc78a2518a686d54b48ab8Matthew Ahrens /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * dfnp is the actual 'mountpoint' of indirect map,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * it is the equivalent of a direct mount,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * ie, /home/'user1'
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy operation = AUTOFS_MOUNT;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VN_HOLD(fntovn(dfnp));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy fnp = dfnp;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = 0;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy searchnm = dfnp->fn_name;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error == EAGAIN) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy rw_exit(&dfnp->fn_rwlock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy goto top;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy rw_exit(&dfnp->fn_rwlock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (error);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * We now have the actual fnnode we're interested in.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * The 'MF_LOOKUP' indicates another thread is currently
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * performing a daemon lookup of this node, therefore we
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * wait for its completion.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * The 'MF_INPROG' indicates another thread is currently
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * performing a daemon mount of this node, we wait for it
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * to be done if we are performing a MOUNT. We don't
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * wait for it if we are performing a LOOKUP.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * We can release the reader/writer lock as soon as we acquire
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * the mutex, since the state of the lock can only change by
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * first acquiring the mutex.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_enter(&fnp->fn_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy rw_exit(&dfnp->fn_rwlock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if ((fnp->fn_flags & MF_LOOKUP) ||
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy ((operation == AUTOFS_MOUNT) && (fnp->fn_flags & MF_INPROG))) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_exit(&fnp->fn_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = auto_wait4mount(fnp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VN_RELE(fntovn(fnp));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error == AUTOFS_SHUTDOWN)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = ENOENT;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error && error != EAGAIN)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (error);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy goto top;
215198a6ad15cf4832370e2f19247abeb36b951aJoe Stein }
215198a6ad15cf4832370e2f19247abeb36b951aJoe Stein
215198a6ad15cf4832370e2f19247abeb36b951aJoe Stein if (operation == 0) {
215198a6ad15cf4832370e2f19247abeb36b951aJoe Stein /*
215198a6ad15cf4832370e2f19247abeb36b951aJoe Stein * got the fnnode, check for any errors
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * on the previous operation on that node.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = fnp->fn_error;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if ((error == EINTR) || (error == EAGAIN)) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * previous operation on this node was
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * not completed, do a lookup now.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy operation = AUTOFS_LOOKUP;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy } else {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy /*
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * previous operation completed. Return
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * a pointer to the node only if there was
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * no error.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_exit(&fnp->fn_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (!error)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy *vpp = fntovn(fnp);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy else
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy VN_RELE(fntovn(fnp));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (error);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
bde3d612a7c090234c60e6e4578821237a5db135Simon Klinkert }
bde3d612a7c090234c60e6e4578821237a5db135Simon Klinkert
bde3d612a7c090234c60e6e4578821237a5db135Simon Klinkert /*
bde3d612a7c090234c60e6e4578821237a5db135Simon Klinkert * Since I got to this point, it means I'm the one
bde3d612a7c090234c60e6e4578821237a5db135Simon Klinkert * responsible for triggering the mount/look-up of this node.
*/
switch (operation) {
case AUTOFS_LOOKUP:
AUTOFS_BLOCK_OTHERS(fnp, MF_LOOKUP);
fnp->fn_error = 0;
mutex_exit(&fnp->fn_lock);
error = auto_lookup_aux(fnp, searchnm, cred);
if (!error) {
/*
* Return this vnode
*/
*vpp = fntovn(fnp);
} else {
/*
* release our reference to this vnode
* and return error
*/
VN_RELE(fntovn(fnp));
}
break;
case AUTOFS_MOUNT:
AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG);
fnp->fn_error = 0;
mutex_exit(&fnp->fn_lock);
/*
* auto_new_mount_thread fires up a new thread which
* calls automountd finishing up the work
*/
auto_new_mount_thread(fnp, searchnm, cred);
/*
* At this point, we are simply another thread
* waiting for the mount to complete
*/
error = auto_wait4mount(fnp);
if (error == AUTOFS_SHUTDOWN)
error = ENOENT;
/*
* now release our reference to this vnode
*/
VN_RELE(fntovn(fnp));
if (!error)
goto top;
break;
default:
auto_log(dfnp->fn_globals->fng_verbose,
dfnp->fn_globals->fng_zoneid, CE_WARN,
"auto_lookup: unknown "
"operation %d", operation);
}
AUTOFS_DPRINT((5, "auto_lookup: name=%s *vpp=%p return=%d\n",
nm, (void *)*vpp, error));
return (error);
}
static int
auto_create(
vnode_t *dvp,
char *nm,
vattr_t *va,
vcexcl_t excl,
int mode,
vnode_t **vpp,
cred_t *cred,
int flag)
{
vnode_t *newvp;
int error;
AUTOFS_DPRINT((4, "auto_create dvp %p nm %s\n", (void *)dvp, nm));
if (error = auto_trigger_mount(dvp, cred, &newvp))
goto done;
if (newvp != NULL) {
/*
* Node is now mounted on.
*/
if (vn_is_readonly(newvp))
error = EROFS;
else
error = VOP_CREATE(newvp, nm, va, excl,
mode, vpp, cred, flag);
VN_RELE(newvp);
} else
error = ENOSYS;
done:
AUTOFS_DPRINT((5, "auto_create: error=%d\n", error));
return (error);
}
static int
auto_remove(vnode_t *dvp, char *nm, cred_t *cred)
{
vnode_t *newvp;
int error;
AUTOFS_DPRINT((4, "auto_remove dvp %p nm %s\n", (void *)dvp, nm));
if (error = auto_trigger_mount(dvp, cred, &newvp))
goto done;
if (newvp != NULL) {
/*
* Node is now mounted on.
*/
if (vn_is_readonly(newvp))
error = EROFS;
else
error = VOP_REMOVE(newvp, nm, cred);
VN_RELE(newvp);
} else
error = ENOSYS;
done:
AUTOFS_DPRINT((5, "auto_remove: error=%d\n", error));
return (error);
}
static int
auto_link(vnode_t *tdvp, vnode_t *svp, char *nm, cred_t *cred)
{
vnode_t *newvp;
int error;
AUTOFS_DPRINT((4, "auto_link tdvp %p svp %p nm %s\n", (void *)tdvp,
(void *)svp, nm));
if (error = auto_trigger_mount(tdvp, cred, &newvp))
goto done;
if (newvp == NULL) {
/*
* an autonode can not be a link to another node
*/
error = ENOSYS;
goto done;
}
if (vn_is_readonly(newvp)) {
error = EROFS;
VN_RELE(newvp);
goto done;
}
if (vn_matchops(svp, auto_vnodeops)) {
/*
* source vp can't be an autonode
*/
error = ENOSYS;
VN_RELE(newvp);
goto done;
}
error = VOP_LINK(newvp, svp, nm, cred);
VN_RELE(newvp);
done:
AUTOFS_DPRINT((5, "auto_link error=%d\n", error));
return (error);
}
static int
auto_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr)
{
vnode_t *o_newvp, *n_newvp;
int error;
AUTOFS_DPRINT((4, "auto_rename odvp %p onm %s to ndvp %p nnm %s\n",
(void *)odvp, onm, (void *)ndvp, nnm));
/*
* we know odvp is an autonode, otherwise this function
* could not have ever been called.
*/
ASSERT(vn_matchops(odvp, auto_vnodeops));
if (error = auto_trigger_mount(odvp, cr, &o_newvp))
goto done;
if (o_newvp == NULL) {
/*
* can't rename an autonode
*/
error = ENOSYS;
goto done;
}
if (vn_matchops(ndvp, auto_vnodeops)) {
/*
* directory is AUTOFS, need to trigger the
* mount of the real filesystem.
*/
if (error = auto_trigger_mount(ndvp, cr, &n_newvp)) {
VN_RELE(o_newvp);
goto done;
}
if (n_newvp == NULL) {
/*
* target can't be an autonode
*/
error = ENOSYS;
VN_RELE(o_newvp);
goto done;
}
} else {
/*
* destination directory mount had been
* triggered prior to the call to this function.
*/
n_newvp = ndvp;
}
ASSERT(!vn_matchops(n_newvp, auto_vnodeops));
if (vn_is_readonly(n_newvp)) {
error = EROFS;
VN_RELE(o_newvp);
if (n_newvp != ndvp)
VN_RELE(n_newvp);
goto done;
}
error = VOP_RENAME(o_newvp, onm, n_newvp, nnm, cr);
VN_RELE(o_newvp);
if (n_newvp != ndvp)
VN_RELE(n_newvp);
done:
AUTOFS_DPRINT((5, "auto_rename error=%d\n", error));
return (error);
}
static int
auto_mkdir(vnode_t *dvp, char *nm, vattr_t *va, vnode_t **vpp, cred_t *cred)
{
vnode_t *newvp;
int error;
AUTOFS_DPRINT((4, "auto_mkdir dvp %p nm %s\n", (void *)dvp, nm));
if (error = auto_trigger_mount(dvp, cred, &newvp))
goto done;
if (newvp != NULL) {
/*
* Node is now mounted on.
*/
if (vn_is_readonly(newvp))
error = EROFS;
else
error = VOP_MKDIR(newvp, nm, va, vpp, cred);
VN_RELE(newvp);
} else
error = ENOSYS;
done:
AUTOFS_DPRINT((5, "auto_mkdir: error=%d\n", error));
return (error);
}
static int
auto_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cred)
{
vnode_t *newvp;
int error;
AUTOFS_DPRINT((4, "auto_rmdir: vp=%p nm=%s\n", (void *)dvp, nm));
if (error = auto_trigger_mount(dvp, cred, &newvp))
goto done;
if (newvp != NULL) {
/*
* Node is now mounted on.
*/
if (vn_is_readonly(newvp))
error = EROFS;
else
error = VOP_RMDIR(newvp, nm, cdir, cred);
VN_RELE(newvp);
} else
error = ENOSYS;
done:
AUTOFS_DPRINT((5, "auto_rmdir: error=%d\n", error));
return (error);
}
static int autofs_nobrowse = 0;
#ifdef nextdp
#undef nextdp
#endif
#define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
static int
auto_readdir(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp)
{
struct autofs_rddirargs rda;
autofs_rddirres rd;
fnnode_t *fnp = vntofn(vp);
fnnode_t *cfnp, *nfnp;
dirent64_t *dp;
ulong_t offset;
ulong_t outcount = 0, count = 0;
size_t namelen;
ulong_t alloc_count;
void *outbuf = NULL;
fninfo_t *fnip = vfstofni(vp->v_vfsp);
struct iovec *iovp;
int error = 0;
int reached_max = 0;
int myeof = 0;
int this_reclen;
struct autofs_globals *fngp = vntofn(fnip->fi_rootvp)->fn_globals;
AUTOFS_DPRINT((4, "auto_readdir vp=%p offset=%lld\n",
(void *)vp, uiop->uio_loffset));
if (eofp != NULL)
*eofp = 0;
if (uiop->uio_iovcnt != 1)
return (EINVAL);
iovp = uiop->uio_iov;
alloc_count = iovp->iov_len;
gethrestime(&fnp->fn_atime);
fnp->fn_ref_time = fnp->fn_atime.tv_sec;
dp = outbuf = kmem_zalloc(alloc_count, KM_SLEEP);
/*
* Held when getdents calls VOP_RWLOCK....
*/
ASSERT(RW_READ_HELD(&fnp->fn_rwlock));
if (uiop->uio_offset >= AUTOFS_DAEMONCOOKIE) {
again:
/*
* Do readdir of daemon contents only
* Drop readers lock and reacquire after reply.
*/
rw_exit(&fnp->fn_rwlock);
bzero(&rd, sizeof (struct autofs_rddirres));
count = 0;
rda.rda_map = fnip->fi_map;
rda.rda_offset = (uint_t)uiop->uio_offset;
rd.rd_rddir.rddir_entries = dp;
rda.rda_count = rd.rd_rddir.rddir_size = (uint_t)alloc_count;
rda.uid = crgetuid(cred);
error = auto_calldaemon(fngp->fng_zoneid,
AUTOFS_READDIR,
xdr_autofs_rddirargs,
&rda,
xdr_autofs_rddirres,
(void *)&rd,
sizeof (autofs_rddirres),
TRUE);
/*
* reacquire previously dropped lock
*/
rw_enter(&fnp->fn_rwlock, RW_READER);
if (!error) {
error = rd.rd_status;
dp = rd.rd_rddir.rddir_entries;
}
if (error) {
if (error == AUTOFS_SHUTDOWN) {
/*
* treat as empty directory
*/
error = 0;
myeof = 1;
if (eofp)
*eofp = 1;
}
goto done;
}
if (rd.rd_rddir.rddir_size) {
dirent64_t *odp = dp; /* next in output buffer */
dirent64_t *cdp = dp; /* current examined entry */
/*
* Check for duplicates here
*/
do {
this_reclen = cdp->d_reclen;
if (auto_search(fnp, cdp->d_name,
NULL, cred)) {
/*
* entry not found in kernel list,
* include it in readdir output.
*
* If we are skipping entries. then
* we need to copy this entry to the
* correct position in the buffer
* to be copied out.
*/
if (cdp != odp)
bcopy(cdp, odp,
(size_t)this_reclen);
odp = nextdp(odp);
outcount += this_reclen;
} else {
/*
* Entry was found in the kernel
* list. If it is the first entry
* in this buffer, then just skip it
*/
if (odp == dp) {
dp = nextdp(dp);
odp = dp;
}
}
count += this_reclen;
cdp = (struct dirent64 *)
((char *)cdp + this_reclen);
} while (count < rd.rd_rddir.rddir_size);
if (outcount)
error = uiomove(dp, outcount, UIO_READ, uiop);
uiop->uio_offset = rd.rd_rddir.rddir_offset;
} else {
if (rd.rd_rddir.rddir_eof == 0) {
/*
* alloc_count not large enough for one
* directory entry
*/
error = EINVAL;
}
}
if (rd.rd_rddir.rddir_eof && !error) {
myeof = 1;
if (eofp)
*eofp = 1;
}
if (!error && !myeof && outcount == 0) {
/*
* call daemon with new cookie, all previous
* elements happened to be duplicates
*/
dp = outbuf;
goto again;
}
goto done;
}
if (uiop->uio_offset == 0) {
/*
* first time: so fudge the . and ..
*/
this_reclen = DIRENT64_RECLEN(1);
if (alloc_count < this_reclen) {
error = EINVAL;
goto done;
}
dp->d_ino = (ino64_t)fnp->fn_nodeid;
dp->d_off = (off64_t)1;
dp->d_reclen = (ushort_t)this_reclen;
/* use strncpy(9f) to zero out uninitialized bytes */
(void) strncpy(dp->d_name, ".",
DIRENT64_NAMELEN(this_reclen));
outcount += dp->d_reclen;
dp = nextdp(dp);
this_reclen = DIRENT64_RECLEN(2);
if (alloc_count < outcount + this_reclen) {
error = EINVAL;
goto done;
}
dp->d_reclen = (ushort_t)this_reclen;
dp->d_ino = (ino64_t)fnp->fn_parent->fn_nodeid;
dp->d_off = (off64_t)2;
/* use strncpy(9f) to zero out uninitialized bytes */
(void) strncpy(dp->d_name, "..",
DIRENT64_NAMELEN(this_reclen));
outcount += dp->d_reclen;
dp = nextdp(dp);
}
offset = 2;
cfnp = fnp->fn_dirents;
while (cfnp != NULL) {
nfnp = cfnp->fn_next;
offset = cfnp->fn_offset;
if ((offset >= uiop->uio_offset) &&
(!(cfnp->fn_flags & MF_LOOKUP))) {
int reclen;
/*
* include node only if its offset is greater or
* equal to the one required and it is not in
* transient state (not being looked-up)
*/
namelen = strlen(cfnp->fn_name);
reclen = (int)DIRENT64_RECLEN(namelen);
if (outcount + reclen > alloc_count) {
reached_max = 1;
break;
}
dp->d_reclen = (ushort_t)reclen;
dp->d_ino = (ino64_t)cfnp->fn_nodeid;
if (nfnp != NULL) {
/*
* get the offset of the next element
*/
dp->d_off = (off64_t)nfnp->fn_offset;
} else {
/*
* This is the last element, make
* offset one plus the current
*/
dp->d_off = (off64_t)cfnp->fn_offset + 1;
}
/* use strncpy(9f) to zero out uninitialized bytes */
(void) strncpy(dp->d_name, cfnp->fn_name,
DIRENT64_NAMELEN(reclen));
outcount += dp->d_reclen;
dp = nextdp(dp);
}
cfnp = nfnp;
}
if (outcount)
error = uiomove(outbuf, outcount, UIO_READ, uiop);
if (!error) {
if (reached_max) {
/*
* This entry did not get added to the buffer on this,
* call. We need to add it on the next call therefore
* set uio_offset to this entry's offset. If there
* wasn't enough space for one dirent, return EINVAL.
*/
uiop->uio_offset = offset;
if (outcount == 0)
error = EINVAL;
} else if (autofs_nobrowse ||
auto_nobrowse_option(fnip->fi_opts) ||
(fnip->fi_flags & MF_DIRECT) ||
(fnp->fn_trigger != NULL) ||
(((vp->v_flag & VROOT) == 0) &&
((fntovn(fnp->fn_parent))->v_flag & VROOT) &&
(fnp->fn_dirents == NULL))) {
/*
* done reading directory entries
*/
uiop->uio_offset = offset + 1;
if (eofp)
*eofp = 1;
} else {
/*
* Need to get the rest of the entries from the daemon.
*/
uiop->uio_offset = AUTOFS_DAEMONCOOKIE;
}
}
done:
kmem_free(outbuf, alloc_count);
AUTOFS_DPRINT((5, "auto_readdir vp=%p offset=%lld eof=%d\n",
(void *)vp, uiop->uio_loffset, myeof));
return (error);
}
static int
auto_symlink(
vnode_t *dvp,
char *lnknm, /* new entry */
vattr_t *tva,
char *tnm, /* existing entry */
cred_t *cred)
{
vnode_t *newvp;
int error;
AUTOFS_DPRINT((4, "auto_symlink: dvp=%p lnknm=%s tnm=%s\n",
(void *)dvp, lnknm, tnm));
if (error = auto_trigger_mount(dvp, cred, &newvp))
goto done;
if (newvp != NULL) {
/*
* Node is mounted on.
*/
if (vn_is_readonly(newvp))
error = EROFS;
else
error = VOP_SYMLINK(newvp, lnknm, tva, tnm, cred);
VN_RELE(newvp);
} else
error = ENOSYS;
done:
AUTOFS_DPRINT((5, "auto_symlink: error=%d\n", error));
return (error);
}
/* ARGSUSED */
static int
auto_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr)
{
fnnode_t *fnp = vntofn(vp);
int error;
timestruc_t now;
AUTOFS_DPRINT((4, "auto_readlink: vp=%p\n", (void *)vp));
gethrestime(&now);
fnp->fn_ref_time = now.tv_sec;
if (vp->v_type != VLNK)
error = EINVAL;
else {
ASSERT(!(fnp->fn_flags & (MF_INPROG | MF_LOOKUP)));
fnp->fn_atime = now;
error = uiomove(fnp->fn_symlink, MIN(fnp->fn_symlinklen,
uiop->uio_resid), UIO_READ, uiop);
}
AUTOFS_DPRINT((5, "auto_readlink: error=%d\n", error));
return (error);
}
/* ARGSUSED */
static int
auto_fsync(vnode_t *cp, int syncflag, cred_t *cred)
{
return (0);
}
/* ARGSUSED */
static void
auto_inactive(vnode_t *vp, cred_t *cred)
{
fnnode_t *fnp = vntofn(vp);
fnnode_t *dfnp = fnp->fn_parent;
int count;
AUTOFS_DPRINT((4, "auto_inactive: vp=%p v_count=%u fn_link=%d\n",
(void *)vp, vp->v_count, fnp->fn_linkcnt));
/*
* The rwlock should not be already held by this thread.
* The assert relies on the fact that the owner field is cleared
* when the lock is released.
*/
ASSERT(dfnp != NULL);
ASSERT(rw_owner(&dfnp->fn_rwlock) != curthread);
rw_enter(&dfnp->fn_rwlock, RW_WRITER);
mutex_enter(&vp->v_lock);
ASSERT(vp->v_count > 0);
count = --vp->v_count;
mutex_exit(&vp->v_lock);
if (count == 0) {
/*
* Free only if node has no subdirectories.
*/
if (fnp->fn_linkcnt == 1) {
auto_disconnect(dfnp, fnp);
rw_exit(&dfnp->fn_rwlock);
auto_freefnnode(fnp);
AUTOFS_DPRINT((5, "auto_inactive: (exit) vp=%p freed\n",
(void *)vp));
return;
}
}
rw_exit(&dfnp->fn_rwlock);
AUTOFS_DPRINT((5, "auto_inactive: (exit) vp=%p v_count=%u fn_link=%d\n",
(void *)vp, vp->v_count, fnp->fn_linkcnt));
}
/* ARGSUSED2 */
static int
auto_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct)
{
fnnode_t *fnp = vntofn(vp);
if (write_lock)
rw_enter(&fnp->fn_rwlock, RW_WRITER);
else
rw_enter(&fnp->fn_rwlock, RW_READER);
return (write_lock);
}
/* ARGSUSED */
static void
auto_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct)
{
fnnode_t *fnp = vntofn(vp);
rw_exit(&fnp->fn_rwlock);
}
/* ARGSUSED */
static int
auto_seek(struct vnode *vp, offset_t ooff, offset_t *noffp)
{
/*
* Return 0 unconditionally, since we expect
* a VDIR all the time
*/
return (0);
}
/*
* Triggers the mount if needed. If the mount has been triggered by
* another thread, it will wait for its return status, and return it.
* Whether the mount is triggered by this thread, another thread, or
* if the vnode was already covered, '*newvp' is a
* VN_HELD vnode pointing to the root of the filesystem covering 'vp'.
* If the node is not mounted on, and should not be mounted on, '*newvp'
* will be NULL.
* The calling routine may use '*newvp' to do the filesystem jump.
*/
static int
auto_trigger_mount(vnode_t *vp, cred_t *cred, vnode_t **newvp)
{
fnnode_t *fnp = vntofn(vp);
fninfo_t *fnip = vfstofni(vp->v_vfsp);
vnode_t *dvp;
vfs_t *vfsp;
int delayed_ind;
char name[AUTOFS_MAXPATHLEN];
int error;
AUTOFS_DPRINT((4, "auto_trigger_mount: vp=%p\n", (void *)vp));
*newvp = NULL;
/*
* Cross-zone mount triggering is disallowed.
*/
if (fnip->fi_zoneid != getzoneid())
return (EPERM); /* Not owner of mount */
retry:
error = 0;
delayed_ind = 0;
mutex_enter(&fnp->fn_lock);
while (fnp->fn_flags & (MF_LOOKUP | MF_INPROG)) {
/*
* Mount or lookup in progress,
* wait for it before proceeding.
*/
mutex_exit(&fnp->fn_lock);
error = auto_wait4mount(fnp);
if (error == AUTOFS_SHUTDOWN) {
error = 0;
goto done;
}
if (error && error != EAGAIN)
goto done;
error = 0;
mutex_enter(&fnp->fn_lock);
}
/*
* If the vfslock can't be acquired for the first time.
* drop the fn_lock and retry next time in blocking mode.
*/
if (vn_vfswlock(vp)) {
/*
* Lock held by another thread.
* Perform blocking by dropping the
* fn_lock.
*/
mutex_exit(&fnp->fn_lock);
error = vn_vfswlock_wait(vp);
if (error)
goto done;
/*
* Because fn_lock wasn't held, the state
* of the trigger node might have changed.
* Need to run through the checks on trigger
* node again.
*/
vn_vfsunlock(vp);
goto retry;
}
vfsp = vn_mountedvfs(vp);
if (vfsp != NULL) {
mutex_exit(&fnp->fn_lock);
error = VFS_ROOT(vfsp, newvp);
vn_vfsunlock(vp);
goto done;
} else {
vn_vfsunlock(vp);
if ((fnp->fn_flags & MF_MOUNTPOINT) &&
fnp->fn_trigger != NULL) {
ASSERT(fnp->fn_dirents == NULL);
/*
* The filesystem that used to sit here has been
* forcibly unmounted.
*/
mutex_exit(&fnp->fn_lock);
error = EIO;
goto done;
}
}
ASSERT(vp->v_type == VDIR);
dvp = fntovn(fnp->fn_parent);
if ((fnp->fn_dirents == NULL) &&
((fnip->fi_flags & MF_DIRECT) == 0) &&
((vp->v_flag & VROOT) == 0) &&
(dvp->v_flag & VROOT)) {
/*
* If the parent of this node is the root of an indirect
* AUTOFS filesystem, this node is remountable.
*/
delayed_ind = 1;
}
if (delayed_ind ||
((fnip->fi_flags & MF_DIRECT) && (fnp->fn_dirents == NULL))) {
/*
* Trigger mount since:
* direct mountpoint with no subdirs or
* delayed indirect.
*/
AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG);
fnp->fn_error = 0;
mutex_exit(&fnp->fn_lock);
if (delayed_ind)
(void) strcpy(name, fnp->fn_name);
else
(void) strcpy(name, ".");
fnp->fn_ref_time = gethrestime_sec();
auto_new_mount_thread(fnp, name, cred);
/*
* At this point we're simply another thread waiting
* for the mount to finish.
*/
error = auto_wait4mount(fnp);
if (error == EAGAIN)
goto retry;
if (error == AUTOFS_SHUTDOWN) {
error = 0;
goto done;
}
if (error == 0) {
if (error = vn_vfsrlock_wait(vp))
goto done;
/* Reacquire after dropping locks */
vfsp = vn_mountedvfs(vp);
if (vfsp != NULL) {
error = VFS_ROOT(vfsp, newvp);
vn_vfsunlock(vp);
} else {
vn_vfsunlock(vp);
goto retry;
}
}
} else
mutex_exit(&fnp->fn_lock);
done:
AUTOFS_DPRINT((5, "auto_trigger_mount: error=%d\n", error));
return (error);
}