opensolaris_lookup.c revision 185029
11541Srgrimes/*-
21541Srgrimes * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
31541Srgrimes * All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes *
141541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
151541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
181541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241541Srgrimes * SUCH DAMAGE.
251541Srgrimes */
261541Srgrimes
271541Srgrimes#include <sys/cdefs.h>
281541Srgrimes__FBSDID("$FreeBSD: head/sys/cddl/compat/opensolaris/kern/opensolaris_lookup.c 185029 2008-11-17 20:49:29Z pjd $");
291541Srgrimes
301541Srgrimes#include <sys/param.h>
311541Srgrimes#include <sys/kernel.h>
321541Srgrimes#include <sys/systm.h>
331541Srgrimes#include <sys/pathname.h>
341541Srgrimes#include <sys/vfs.h>
351541Srgrimes#include <sys/vnode.h>
3636503Speter
371541Srgrimesint
381541Srgrimeslookupname(char *dirname, enum uio_seg seg, enum symfollow follow,
3983651Speter    vnode_t **dirvpp, vnode_t **compvpp)
4083651Speter{
4183651Speter
421541Srgrimes	return (lookupnameat(dirname, seg, follow, dirvpp, compvpp, NULL));
431541Srgrimes}
441541Srgrimes
451541Srgrimesint
461541Srgrimeslookupnameat(char *dirname, enum uio_seg seg, enum symfollow follow,
4783651Speter    vnode_t **dirvpp, vnode_t **compvpp, vnode_t *startvp)
481541Srgrimes{
4948274Speter	struct nameidata nd;
5048274Speter	int error, ltype;
5160041Sphk
5231886Sbde	ASSERT(dirvpp == NULL);
531541Srgrimes
541541Srgrimes	vref(startvp);
551541Srgrimes	ltype = VOP_ISLOCKED(startvp);
561541Srgrimes	VOP_UNLOCK(startvp, 0);
571541Srgrimes	NDINIT_ATVP(&nd, LOOKUP, LOCKLEAF | MPSAFE | follow, seg, dirname,
581541Srgrimes	    startvp, curthread);
591541Srgrimes	error = namei(&nd);
609336Sdfr	*compvpp = nd.ni_vp;
612997Swollman	NDFREE(&nd, NDF_ONLY_PNBUF);
622997Swollman	vn_lock(startvp, ltype | LK_RETRY);
6383651Speter	return (error);
641541Srgrimes}
653305Sphk
6612662Sdgint
6712662Sdgtraverse(vnode_t **cvpp, int lktype)
6892783Sjeff{
693305Sphk	kthread_t *td = curthread;
701541Srgrimes	vnode_t *cvp;
719336Sdfr	vnode_t *tvp;
7283651Speter	vfs_t *vfsp;
7383651Speter	int error;
741541Srgrimes
7583651Speter	cvp = *cvpp;
7683651Speter	tvp = NULL;
771541Srgrimes
781541Srgrimes	/*
791541Srgrimes	 * If this vnode is mounted on, then we transparently indirect
801541Srgrimes	 * to the vnode which is the root of the mounted file system.
811541Srgrimes	 * Before we do this we must check that an unmount is not in
821541Srgrimes	 * progress on this vnode.
831541Srgrimes	 */
8483651Speter
8583651Speter	for (;;) {
8683651Speter		/*
8783651Speter		 * Reached the end of the mount chain?
881541Srgrimes		 */
891541Srgrimes		vfsp = vn_mountedvfs(cvp);
9036541Speter		if (vfsp == NULL)
9112911Sphk			break;
9283651Speter		/*
9312911Sphk		 * tvp is NULL for *cvpp vnode, which we can't unlock.
9412911Sphk		 */
9583651Speter		if (tvp != NULL)
9683651Speter			vput(cvp);
979336Sdfr		else
9883651Speter			vrele(cvp);
9983651Speter
1009759Sbde		/*
10183651Speter		 * The read lock must be held across the call to VFS_ROOT() to
10283651Speter		 * prevent a concurrent unmount from destroying the vfs.
10338894Sbde		 */
1049336Sdfr		error = VFS_ROOT(vfsp, lktype, &tvp, td);
1059336Sdfr		if (error != 0)
1069336Sdfr			return (error);
1079336Sdfr		cvp = tvp;
1089336Sdfr	}
1099336Sdfr
1109336Sdfr	*cvpp = cvp;
1119336Sdfr	return (0);
1129336Sdfr}
1139336Sdfr