auto_vnops.c revision ffc349ab772a8ab3ac82d192827e2777ab45d0be
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER START
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 * 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.
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 * CDDL HEADER END
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Use is subject to license terms.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma ident "%Z%%M% %I% %E% SMI"
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Vnode ops for autofs
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 *,
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 Kennedystatic int auto_create(vnode_t *, char *, vattr_t *, vcexcl_t,
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 Pankovstatic int auto_trigger_mount(vnode_t *, cred_t *, vnode_t **);
d7e7cb9c207e40874f6a4b61ca8ea1526b5555bdYuri Pankovconst fs_operation_def_t auto_vnodeops_template[] = {
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 },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy VOPNAME_RENAME, { .vop_rename = auto_rename },
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 Kennedyauto_open(vnode_t **vpp, int flag, cred_t *cred)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((4, "auto_open: *vpp=%p\n", (void *)*vpp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = auto_trigger_mount(*vpp, cred, &newvp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Node is now mounted on.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((5, "auto_open: *vpp=%p error=%d\n", (void *)*vpp,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyauto_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cred)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedyauto_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cred)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((4, "auto_getattr vp %p\n", (void *)vp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Recursive auto_getattr/mount; go to the vfsp == NULL
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Node is mounted on.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (fnp->fn_seen == newvp && fnp->fn_thread == curthread) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Recursive auto_getattr(); just release newvp and drop
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * into the vfsp == NULL case.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while (fnp->fn_thread && fnp->fn_thread != curthread) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_wait(&fnp->fn_cv_mount, &fnp->fn_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = VOP_GETATTR(newvp, vap, flags, cred);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(vp->v_type == VDIR || vp->v_type == VLNK);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy vap->va_nodeid = (u_longlong_t)fnp->fn_nodeid;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((4, "auto_setattr vp %p\n", (void *)vp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (error = auto_trigger_mount(vp, cred, &newvp))
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Node is mounted on.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = VOP_SETATTR(newvp, vap, flags, cred, NULL);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy AUTOFS_DPRINT((5, "auto_setattr: error=%d\n", error));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyauto_access(vnode_t *vp, int mode, int flags, cred_t *cred)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy AUTOFS_DPRINT((4, "auto_access: vp=%p\n", (void *)vp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (error = auto_trigger_mount(vp, cred, &newvp))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Node is mounted on.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * really interested in the autofs node, check the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * access on it
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = secpolicy_vnode_access(cred, vp, fnp->fn_uid,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy AUTOFS_DPRINT((5, "auto_access: error=%d\n", error));
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy int operation; /* either AUTOFS_LOOKUP or AUTOFS_MOUNT */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy AUTOFS_DPRINT((3, "auto_lookup: dvp=%p (%s) name=%s\n",
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (nm[0] == 0) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (error = VOP_ACCESS(dvp, VEXEC, 0, cred))
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) {
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 if (pdfnp == pdfnp->fn_globals->fng_rootfnnodep) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = VOP_LOOKUP(vp, nm, vpp, pnp, flags, rdir, cred);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy AUTOFS_DPRINT((3, "auto_lookup: dvp=%p dfnp=%p\n", (void *)dvp,
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 if (dfnp->fn_flags & (MF_LOOKUP | MF_INPROG)) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = auto_search(dfnp, nm, &fnp, cred);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * Mount previously triggered.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * 'nm' not found
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * I need to contact the daemon to trigger
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * the mount. 'dfnp' will be the mountpoint.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * 'dfnp' is the root of the indirect AUTOFS.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (rw_tryupgrade(&dfnp->fn_rwlock) == 0) {
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 error = auto_search(dfnp, nm, &fnp, cred);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * create node being looked-up and request
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * mount on it.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy error = auto_enter(dfnp, nm, &fnp, kcred);
9c3fd1216fa7fb02cfbc78a2518a686d54b48ab8Matthew Ahrens ((fntovn(dfnp->fn_parent))->v_flag & VROOT)) {
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 * 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 ((operation == AUTOFS_MOUNT) && (fnp->fn_flags & MF_INPROG))) {
215198a6ad15cf4832370e2f19247abeb36b951aJoe Stein * got the fnnode, check for any errors
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * on the previous operation on that node.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if ((error == EINTR) || (error == EAGAIN)) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * previous operation on this node was
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * not completed, do a lookup now.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * previous operation completed. Return
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy * a pointer to the node only if there was
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:
if (!error) {
case AUTOFS_MOUNT:
if (!error)
goto top;
return (error);
char *nm,
int mode,
int flag)
int error;
goto done;
done:
return (error);
int error;
goto done;
done:
return (error);
int error;
goto done;
goto done;
goto done;
goto done;
done:
return (error);
int error;
goto done;
goto done;
goto done;
goto done;
goto done;
done:
return (error);
int error;
goto done;
done:
return (error);
int error;
goto done;
done:
return (error);
static int autofs_nobrowse = 0;
#ifdef nextdp
int error = 0;
int reached_max = 0;
int myeof = 0;
int this_reclen;
*eofp = 0;
return (EINVAL);
count = 0;
&rda,
(void *)&rd,
sizeof (autofs_rddirres),
TRUE);
if (!error) {
if (error) {
error = 0;
if (eofp)
goto done;
if (outcount)
if (eofp)
goto again;
goto done;
goto done;
goto done;
int reclen;
if (outcount)
if (!error) {
if (reached_max) {
if (outcount == 0)
} else if (autofs_nobrowse ||
if (eofp)
done:
return (error);
int error;
goto done;
done:
return (error);
int error;
return (error);
int count;
if (count == 0) {
(void *)vp));
if (write_lock)
return (write_lock);
int delayed_ind;
int error;
error = 0;
delayed_ind = 0;
error = 0;
goto done;
goto done;
error = 0;
if (error)
goto done;
goto retry;
goto done;
goto done;
if (delayed_ind ||
if (delayed_ind)
goto retry;
error = 0;
goto done;
if (error == 0) {
goto done;
goto retry;
done:
return (error);