* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.85.2.9 2002/09/24 08:11:41 mdodd Exp $
- * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.30 2006/09/11 20:24:59 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.31 2006/10/27 04:56:28 dillon Exp $
*/
#include "opt_compat.h"
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
if (error)
goto cleanup;
/*
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/compat/linux/linux_stats.c,v 1.22.2.3 2001/11/05 19:08:23 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.23 2006/09/10 01:26:38 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_stats.c,v 1.24 2006/10/27 04:56:28 dillon Exp $
*/
#include <sys/param.h>
if (error == 0)
error = kern_statfs(&nd, &statfs);
if (error == 0) {
- if (nd.nl_ncp->nc_vp != NULL)
- error = vn_get_namelen(nd.nl_ncp->nc_vp, &namelen);
+ if (nd.nl_nch.ncp->nc_vp != NULL)
+ error = vn_get_namelen(nd.nl_nch.ncp->nc_vp, &namelen);
else
error = EINVAL;
}
*
* from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp
* $FreeBSD: src/sys/compat/linux/linux_util.c,v 1.12.2.2 2001/11/05 19:08:23 marcel Exp $
- * $DragonFly: src/sys/emulation/linux/linux_util.c,v 1.13 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_util.c,v 1.14 2006/10/27 04:56:28 dillon Exp $
*/
#include <sys/param.h>
error = nlookup(&nd);
vp = NULL;
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error)
goto dont_translate;
error = nlookup(&ndroot);
vproot = NULL;
if (error == 0) {
- error = cache_vref(ndroot.nl_ncp, ndroot.nl_cred,
+ error = cache_vref(&ndroot.nl_nch, ndroot.nl_cred,
&vproot);
}
nlookup_done(&ndroot);
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/kern/imgact_elf.c,v 1.73.2.13 2002/12/28 19:49:41 dillon Exp $
- * $DragonFly: src/sys/kern/imgact_elf.c,v 1.42 2006/09/11 20:25:01 dillon Exp $
+ * $DragonFly: src/sys/kern/imgact_elf.c,v 1.43 2006/10/27 04:56:31 dillon Exp $
*/
#include <sys/param.h>
if (error == 0)
error = nlookup(nd);
if (error == 0)
- error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &imgp->vp);
+ error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &imgp->vp);
nlookup_done(nd);
if (error)
goto fail;
*
* @(#)init_main.c 8.9 (Berkeley) 1/21/94
* $FreeBSD: src/sys/kern/init_main.c,v 1.134.2.8 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/kern/init_main.c,v 1.64 2006/09/19 11:47:35 corecode Exp $
+ * $DragonFly: src/sys/kern/init_main.c,v 1.65 2006/10/27 04:56:31 dillon Exp $
*/
#include "opt_init_path.h"
mp = mountlist_boot_getfirst();
if (VFS_ROOT(mp, &vp))
panic("cannot find root vnode");
- if (mp->mnt_ncp == NULL) {
- mp->mnt_ncp = cache_allocroot(mp, vp);
- cache_unlock(mp->mnt_ncp); /* leave ref intact */
+ if (mp->mnt_ncmountpt.ncp == NULL) {
+ cache_allocroot(&mp->mnt_ncmountpt, mp, vp);
+ cache_unlock(&mp->mnt_ncmountpt); /* leave ref intact */
}
p->p_fd->fd_cdir = vp;
vref(p->p_fd->fd_cdir);
p->p_fd->fd_rdir = vp;
vref(p->p_fd->fd_rdir);
- vfs_cache_setroot(vp, cache_hold(mp->mnt_ncp));
+ vfs_cache_setroot(vp, cache_hold(&mp->mnt_ncmountpt));
vn_unlock(vp); /* leave ref intact */
- p->p_fd->fd_ncdir = cache_hold(mp->mnt_ncp);
- p->p_fd->fd_nrdir = cache_hold(mp->mnt_ncp);
+ cache_copy(&mp->mnt_ncmountpt, &p->p_fd->fd_ncdir);
+ cache_copy(&mp->mnt_ncmountpt, &p->p_fd->fd_nrdir);
/*
* Need just enough stack to hold the faked-up "execve()" arguments.
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/kern/kern_acl.c,v 1.2.2.1 2000/07/28 18:48:16 rwatson Exp $
- * $DragonFly: src/sys/kern/kern_acl.c,v 1.15 2006/08/12 00:26:20 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_acl.c,v 1.16 2006/10/27 04:56:31 dillon Exp $
*/
/*
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
error = vacl_get_acl(vp, uap->type, uap->aclp);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
error = vacl_set_acl(vp, uap->type, uap->aclp);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
*
* @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94
* $FreeBSD: src/sys/kern/kern_descrip.c,v 1.81.2.19 2004/02/28 00:43:31 tegge Exp $
- * $DragonFly: src/sys/kern/kern_descrip.c,v 1.74 2006/09/19 11:47:35 corecode Exp $
+ * $DragonFly: src/sys/kern/kern_descrip.c,v 1.75 2006/10/27 04:56:31 dillon Exp $
*/
#include "opt_compat.h"
nfiles--;
spin_unlock_wr(&filehead_spin);
crfree(fp->f_cred);
- if (fp->f_ncp) {
- cache_drop(fp->f_ncp);
- fp->f_ncp = NULL;
- }
+ if (fp->f_nchandle.ncp)
+ cache_drop(&fp->f_nchandle);
kfree(fp, M_FILE);
}
if (fdp->fd_cdir) {
newfdp->fd_cdir = fdp->fd_cdir;
vref(newfdp->fd_cdir);
- newfdp->fd_ncdir = cache_hold(fdp->fd_ncdir);
+ cache_copy(&fdp->fd_ncdir, &newfdp->fd_ncdir);
}
/*
if (fdp->fd_rdir) {
newfdp->fd_rdir = fdp->fd_rdir;
vref(newfdp->fd_rdir);
- newfdp->fd_nrdir = cache_hold(fdp->fd_nrdir);
+ cache_copy(&fdp->fd_nrdir, &newfdp->fd_nrdir);
}
if (fdp->fd_jdir) {
newfdp->fd_jdir = fdp->fd_jdir;
vref(newfdp->fd_jdir);
- newfdp->fd_njdir = cache_hold(fdp->fd_njdir);
+ cache_copy(&fdp->fd_njdir, &newfdp->fd_njdir);
}
spin_unlock_rd(&fdp->fd_spin);
*/
if ((newfdp->fd_cdir = fdp->fd_cdir) != NULL) {
vref(newfdp->fd_cdir);
- newfdp->fd_ncdir = cache_hold(fdp->fd_ncdir);
+ cache_copy(&fdp->fd_ncdir, &newfdp->fd_ncdir);
}
/*
* We must check for fd_rdir here, at least for now because
*/
if ((newfdp->fd_rdir = fdp->fd_rdir) != NULL) {
vref(newfdp->fd_rdir);
- newfdp->fd_nrdir = cache_hold(fdp->fd_nrdir);
+ cache_copy(&fdp->fd_nrdir, &newfdp->fd_nrdir);
}
if ((newfdp->fd_jdir = fdp->fd_jdir) != NULL) {
vref(newfdp->fd_jdir);
- newfdp->fd_njdir = cache_hold(fdp->fd_njdir);
+ cache_copy(&fdp->fd_njdir, &newfdp->fd_njdir);
}
newfdp->fd_refcnt = 1;
newfdp->fd_nfiles = i;
if (fdp->fd_files != fdp->fd_builtin_files)
kfree(fdp->fd_files, M_FILEDESC);
if (fdp->fd_cdir) {
- cache_drop(fdp->fd_ncdir);
+ cache_drop(&fdp->fd_ncdir);
vrele(fdp->fd_cdir);
}
if (fdp->fd_rdir) {
- cache_drop(fdp->fd_nrdir);
+ cache_drop(&fdp->fd_nrdir);
vrele(fdp->fd_rdir);
}
if (fdp->fd_jdir) {
- cache_drop(fdp->fd_njdir);
+ cache_drop(&fdp->fd_njdir);
vrele(fdp->fd_jdir);
}
if (fdp->fd_knlist)
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/kern/kern_exec.c,v 1.107.2.15 2002/07/30 15:40:46 nectar Exp $
- * $DragonFly: src/sys/kern/kern_exec.c,v 1.47 2006/10/20 17:02:16 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_exec.c,v 1.48 2006/10/27 04:56:31 dillon Exp $
*/
#include <sys/param.h>
*/
if ((error = nlookup(nd)) != 0)
goto exec_fail;
- error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &imgp->vp);
+ error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &imgp->vp);
KKASSERT(nd->nl_flags & NLC_NCPISLOCKED);
nd->nl_flags &= ~NLC_NCPISLOCKED;
- cache_unlock(nd->nl_ncp);
+ cache_unlock(&nd->nl_nch);
if (error)
goto exec_fail;
execsigs(p);
/* name this process - nameiexec(p, ndp) */
- len = min(nd->nl_ncp->nc_nlen, MAXCOMLEN);
- bcopy(nd->nl_ncp->nc_name, p->p_comm, len);
+ len = min(nd->nl_nch.ncp->nc_nlen, MAXCOMLEN);
+ bcopy(nd->nl_nch.ncp->nc_name, p->p_comm, len);
p->p_comm[len] = 0;
bcopy(p->p_comm, p->p_lwp.lwp_thread->td_comm, MAXCOMLEN+1);
* ----------------------------------------------------------------------------
*
* $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $
- * $DragonFly: src/sys/kern/kern_jail.c,v 1.12 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_jail.c,v 1.13 2006/10/27 04:56:31 dillon Exp $
*
*/
if (pr == NULL)
return(EINVAL);
- error = kern_chroot(pr->pr_root);
+ error = kern_chroot(&pr->pr_root);
if (error)
return(error);
error = nlookup(&nd);
if (error)
goto nlookup_init_clean;
- pr->pr_root = cache_hold(nd.nl_ncp);
+ cache_copy(&nd.nl_nch, &pr->pr_root);
pr->pr_ip = j.ip_number;
varsymset_init(&pr->pr_varsymset, NULL);
char *fullpath, *freepath;
xp->pr_version = KINFO_PRISON_VERSION;
xp->pr_id = pr->pr_id;
- error = cache_fullpath(p, pr->pr_root, &fullpath, &freepath);
+ error = cache_fullpath(p, &pr->pr_root, &fullpath, &freepath);
if (error == 0) {
strlcpy(xp->pr_path, fullpath, sizeof(xp->pr_path));
kfree(freepath, M_TEMP);
if (pr->pr_linux != NULL)
kfree(pr->pr_linux, M_PRISON);
varsymset_clean(&pr->pr_varsymset);
- cache_drop(pr->pr_root);
+ cache_drop(&pr->pr_root);
kfree(pr, M_PRISON);
}
*
* @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94
* $FreeBSD: src/sys/kern/kern_shutdown.c,v 1.72.2.12 2002/02/21 19:15:10 dillon Exp $
- * $DragonFly: src/sys/kern/kern_shutdown.c,v 1.39 2006/10/20 17:02:16 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_shutdown.c,v 1.40 2006/10/27 04:56:31 dillon Exp $
*/
#include "opt_ddb.h"
if ((fdp = p->p_fd) != NULL) {
kern_closefrom(0);
if (fdp->fd_cdir) {
- cache_drop(fdp->fd_ncdir);
+ cache_drop(&fdp->fd_ncdir);
vrele(fdp->fd_cdir);
fdp->fd_cdir = NULL;
- fdp->fd_ncdir = NULL;
}
if (fdp->fd_rdir) {
- cache_drop(fdp->fd_nrdir);
+ cache_drop(&fdp->fd_nrdir);
vrele(fdp->fd_rdir);
fdp->fd_rdir = NULL;
- fdp->fd_nrdir = NULL;
}
if (fdp->fd_jdir) {
- cache_drop(fdp->fd_njdir);
+ cache_drop(&fdp->fd_njdir);
vrele(fdp->fd_jdir);
fdp->fd_jdir = NULL;
- fdp->fd_njdir = NULL;
}
}
if (p->p_vkernel)
*
* From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
* $FreeBSD: src/sys/kern/uipc_usrreq.c,v 1.54.2.10 2003/03/04 17:28:09 nectar Exp $
- * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.29 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.30 2006/10/27 04:56:31 dillon Exp $
*/
#include <sys/param.h>
error = nlookup_init(&nd, buf, UIO_SYSSPACE, NLC_LOCKVP|NLC_CREATE);
if (error == 0)
error = nlookup(&nd);
- if (error == 0 && nd.nl_ncp->nc_vp != NULL)
+ if (error == 0 && nd.nl_nch.ncp->nc_vp != NULL)
error = EADDRINUSE;
if (error)
goto done;
VATTR_NULL(&vattr);
vattr.va_type = VSOCK;
vattr.va_mode = (ACCESSPERMS & ~p->p_fd->fd_cmask);
- error = VOP_NCREATE(nd.nl_ncp, &vp, nd.nl_cred, &vattr);
+ error = VOP_NCREATE(&nd.nl_nch, &vp, nd.nl_cred, &vattr);
if (error == 0) {
vp->v_socket = unp->unp_socket;
unp->unp_vnode = vp;
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
nlookup_done(&nd);
if (error)
return (error);
*
* @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
* $FreeBSD: src/sys/kern/vfs_cache.c,v 1.42.2.6 2001/10/05 20:07:03 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_cache.c,v 1.78 2006/10/26 02:27:19 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_cache.c,v 1.79 2006/10/27 04:56:31 dillon Exp $
*/
#include <sys/param.h>
SYSCTL_INT(_debug, OID_AUTO, vnsize, CTLFLAG_RD, 0, sizeof(struct vnode), "");
SYSCTL_INT(_debug, OID_AUTO, ncsize, CTLFLAG_RD, 0, sizeof(struct namecache), "");
-static int cache_resolve_mp(struct namecache *ncp);
-static void cache_rehash(struct namecache *ncp);
+static int cache_resolve_mp(struct mount *mp);
+static void _cache_rehash(struct namecache *ncp);
+static void _cache_lock(struct namecache *ncp);
+static void _cache_setunresolved(struct namecache *ncp);
/*
* The new name cache statistics
TAILQ_EMPTY(&ncp->nc_list)
) {
KKASSERT(ncp->nc_exlocks == 0);
- cache_lock(ncp);
+ _cache_lock(ncp);
cache_zap(ncp);
} else {
atomic_subtract_int(&ncp->nc_refs, 1);
if ((par = ncp->nc_parent) != NULL) {
ncp->nc_parent = NULL;
- par = cache_hold(par);
+ par = _cache_hold(par);
TAILQ_REMOVE(&par->nc_list, ncp, nc_entry);
if (par->nc_vp && TAILQ_EMPTY(&par->nc_list))
vdrop(par->nc_vp);
- cache_drop(par);
+ _cache_drop(par);
}
}
*/
ncp->nc_fsmid = cache_getnewfsmid();
TAILQ_INIT(&ncp->nc_list);
- cache_lock(ncp);
+ _cache_lock(ncp);
return(ncp);
}
static void
-cache_free(struct namecache *ncp)
+_cache_free(struct namecache *ncp)
{
KKASSERT(ncp->nc_refs == 1 && ncp->nc_exlocks == 1);
if (ncp->nc_name)
kfree(ncp, M_VFSCACHE);
}
+void
+cache_zero(struct nchandle *nch)
+{
+ nch->ncp = NULL;
+ nch->mount = NULL;
+}
+
/*
* Ref and deref a namecache structure.
*
* Warning: caller may hold an unrelated read spinlock, which means we can't
* use read spinlocks here.
*/
-struct namecache *
-cache_hold(struct namecache *ncp)
+struct nchandle *
+cache_hold(struct nchandle *nch)
{
- return(_cache_hold(ncp));
+ _cache_hold(nch->ncp);
+ ++nch->mount->mnt_refs;
+ return(nch);
}
void
-cache_drop(struct namecache *ncp)
+cache_copy(struct nchandle *nch, struct nchandle *target)
{
- _cache_drop(ncp);
+ *target = *nch;
+ _cache_hold(target->ncp);
+ ++nch->mount->mnt_refs;
+}
+
+void
+cache_changemount(struct nchandle *nch, struct mount *mp)
+{
+ --nch->mount->mnt_refs;
+ nch->mount = mp;
+ ++nch->mount->mnt_refs;
+}
+
+void
+cache_drop(struct nchandle *nch)
+{
+ --nch->mount->mnt_refs;
+ _cache_drop(nch->ncp);
+ nch->ncp = NULL;
+ nch->mount = NULL;
}
/*
* is handled). Or, alternatively, make an unconditional call to
* cache_validate() or cache_resolve() after cache_lock() returns.
*/
+static
void
-cache_lock(struct namecache *ncp)
+_cache_lock(struct namecache *ncp)
{
thread_t td;
int didwarn;
continue;
didwarn = 1;
printf("[diagnostic] cache_lock: blocked on %p", ncp);
- if ((ncp->nc_flag & NCF_MOUNTPT) && ncp->nc_mount)
- printf(" [MOUNTFROM %s]\n", ncp->nc_mount->mnt_stat.f_mntfromname);
- else
- printf(" \"%*.*s\"\n",
- ncp->nc_nlen, ncp->nc_nlen,
- ncp->nc_name);
+ printf(" \"%*.*s\"\n",
+ ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name);
}
}
}
}
+void
+cache_lock(struct nchandle *nch)
+{
+ _cache_lock(nch->ncp);
+}
+
+static
int
-cache_lock_nonblock(struct namecache *ncp)
+_cache_lock_nonblock(struct namecache *ncp)
{
thread_t td;
}
}
+int
+cache_lock_nonblock(struct nchandle *nch)
+{
+ return(_cache_lock_nonblock(nch->ncp));
+}
+
+static
void
-cache_unlock(struct namecache *ncp)
+_cache_unlock(struct namecache *ncp)
{
thread_t td = curthread;
}
}
+void
+cache_unlock(struct nchandle *nch)
+{
+ _cache_unlock(nch->ncp);
+}
+
/*
* ref-and-lock, unlock-and-deref functions.
*
* initiated a recyclement. We want cache_get() to return a definitively
* usable vnode or a definitively unresolved ncp.
*/
+static
struct namecache *
-cache_get(struct namecache *ncp)
+_cache_get(struct namecache *ncp)
{
_cache_hold(ncp);
- cache_lock(ncp);
+ _cache_lock(ncp);
if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
- cache_setunresolved(ncp);
+ _cache_setunresolved(ncp);
return(ncp);
}
-int
-cache_get_nonblock(struct namecache *ncp)
+/*
+ * note: the same nchandle can be passed for both arguments.
+ */
+void
+cache_get(struct nchandle *nch, struct nchandle *target)
+{
+ target->mount = nch->mount;
+ target->ncp = _cache_get(nch->ncp);
+ ++target->mount->mnt_refs;
+}
+
+static int
+_cache_get_nonblock(struct namecache *ncp)
{
/* XXX MP */
if (ncp->nc_exlocks == 0 || ncp->nc_locktd == curthread) {
_cache_hold(ncp);
- cache_lock(ncp);
+ _cache_lock(ncp);
if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
- cache_setunresolved(ncp);
+ _cache_setunresolved(ncp);
return(0);
}
return(EWOULDBLOCK);
}
+int
+cache_get_nonblock(struct nchandle *nch)
+{
+ return(_cache_get_nonblock(nch->ncp));
+}
+
+static __inline
void
-cache_put(struct namecache *ncp)
+_cache_put(struct namecache *ncp)
{
- cache_unlock(ncp);
+ _cache_unlock(ncp);
_cache_drop(ncp);
}
+void
+cache_put(struct nchandle *nch)
+{
+ --nch->mount->mnt_refs;
+ _cache_put(nch->ncp);
+ nch->ncp = NULL;
+ nch->mount = NULL;
+}
+
/*
* Resolve an unresolved ncp by associating a vnode with it. If the
* vnode is NULL, a negative cache entry is created.
*
* The ncp should be locked on entry and will remain locked on return.
*/
+static
void
-cache_setvp(struct namecache *ncp, struct vnode *vp)
+_cache_setvp(struct namecache *ncp, struct vnode *vp)
{
KKASSERT(ncp->nc_flag & NCF_UNRESOLVED);
ncp->nc_vp = vp;
}
void
-cache_settimeout(struct namecache *ncp, int nticks)
+cache_setvp(struct nchandle *nch, struct vnode *vp)
{
+ _cache_setvp(nch->ncp, vp);
+}
+
+void
+cache_settimeout(struct nchandle *nch, int nticks)
+{
+ struct namecache *ncp = nch->ncp;
+
if ((ncp->nc_timeout = ticks + nticks) == 0)
ncp->nc_timeout = 1;
}
* NOTE: NCF_FSMID must be cleared so a refurbishment of the ncp, such as
* in a create, properly propogates flag up the chain.
*/
+static
void
-cache_setunresolved(struct namecache *ncp)
+_cache_setunresolved(struct namecache *ncp)
{
struct vnode *vp;
}
}
-/*
- * Mark the namecache node as containing a mount point.
- *
- * XXX called with a ref'd but unlocked ncp.
- */
void
-cache_setmountpt(struct namecache *ncp, struct mount *mp)
+cache_setunresolved(struct nchandle *nch)
{
- ncp->nc_mount = mp;
- ncp->nc_flag |= NCF_MOUNTPT;
- ncp->nc_parent->nc_flag |= NCF_MOUNTEDHERE;
+ _cache_setunresolved(nch->ncp);
}
/*
- * Clean up a mount point in the namecache topology after an unmount.
- *
- * XXX we probably need to traverse the entire topology and clear
- * the nc_mount pointer.
+ * Determine if we can clear NCF_ISMOUNTPT by scanning the mountlist
+ * looking for matches. This flag tells the lookup code when it must
+ * check for a mount linkage and also prevents the directories in question
+ * from being deleted or renamed.
*/
+static
+int
+cache_clrmountpt_callback(struct mount *mp, void *data)
+{
+ struct nchandle *nch = data;
+
+ if (mp->mnt_ncmounton.ncp == nch->ncp)
+ return(1);
+ if (mp->mnt_ncmountpt.ncp == nch->ncp)
+ return(1);
+ return(0);
+}
+
void
-cache_clrmountpt(struct namecache *ncp)
+cache_clrmountpt(struct nchandle *nch)
{
- if (ncp->nc_parent)
- ncp->nc_parent->nc_flag &= ~NCF_MOUNTEDHERE;
- ncp->nc_mount = NULL;
+ int count;
+
+ count = mountlist_scan(cache_clrmountpt_callback, nch,
+ MNTSCAN_FORWARD|MNTSCAN_NOBUSY);
+ if (count == 0)
+ nch->ncp->nc_flag &= ~NCF_ISMOUNTPT;
}
/*
int depth;
};
-static int cache_inval_internal(struct namecache *, int, struct cinvtrack *);
+static int _cache_inval_internal(struct namecache *, int, struct cinvtrack *);
+static
int
-cache_inval(struct namecache *ncp, int flags)
+_cache_inval(struct namecache *ncp, int flags)
{
struct cinvtrack track;
struct namecache *ncp2;
track.resume_ncp = NULL;
for (;;) {
- r = cache_inval_internal(ncp, flags, &track);
+ r = _cache_inval_internal(ncp, flags, &track);
if (track.resume_ncp == NULL)
break;
printf("Warning: deep namecache recursion at %s\n",
ncp->nc_name);
- cache_unlock(ncp);
+ _cache_unlock(ncp);
while ((ncp2 = track.resume_ncp) != NULL) {
track.resume_ncp = NULL;
- cache_lock(ncp2);
- cache_inval_internal(ncp2, flags & ~CINV_DESTROY,
+ _cache_lock(ncp2);
+ _cache_inval_internal(ncp2, flags & ~CINV_DESTROY,
&track);
- cache_put(ncp2);
+ _cache_put(ncp2);
}
- cache_lock(ncp);
+ _cache_lock(ncp);
}
return(r);
}
+int
+cache_inval(struct nchandle *nch, int flags)
+{
+ return(_cache_inval(nch->ncp, flags));
+}
+
static int
-cache_inval_internal(struct namecache *ncp, int flags, struct cinvtrack *track)
+_cache_inval_internal(struct namecache *ncp, int flags, struct cinvtrack *track)
{
struct namecache *kid;
struct namecache *nextkid;
KKASSERT(ncp->nc_exlocks);
- cache_setunresolved(ncp);
+ _cache_setunresolved(ncp);
if (flags & CINV_DESTROY)
ncp->nc_flag |= NCF_DESTROYED;
) {
if (++track->depth > MAX_RECURSION_DEPTH) {
track->resume_ncp = ncp;
- cache_hold(ncp);
+ _cache_hold(ncp);
++rcnt;
}
- cache_hold(kid);
- cache_unlock(ncp);
+ _cache_hold(kid);
+ _cache_unlock(ncp);
while (kid) {
if (track->resume_ncp) {
- cache_drop(kid);
+ _cache_drop(kid);
break;
}
if ((nextkid = TAILQ_NEXT(kid, nc_entry)) != NULL)
- cache_hold(nextkid);
+ _cache_hold(nextkid);
if ((kid->nc_flag & NCF_UNRESOLVED) == 0 ||
TAILQ_FIRST(&kid->nc_list)
) {
- cache_lock(kid);
- rcnt += cache_inval_internal(kid, flags & ~CINV_DESTROY, track);
- cache_unlock(kid);
+ _cache_lock(kid);
+ rcnt += _cache_inval_internal(kid, flags & ~CINV_DESTROY, track);
+ _cache_unlock(kid);
}
- cache_drop(kid);
+ _cache_drop(kid);
kid = nextkid;
}
--track->depth;
- cache_lock(ncp);
+ _cache_lock(ncp);
}
/*
restart:
ncp = TAILQ_FIRST(&vp->v_namecache);
if (ncp)
- cache_hold(ncp);
+ _cache_hold(ncp);
while (ncp) {
/* loop entered with ncp held */
if ((next = TAILQ_NEXT(ncp, nc_vnode)) != NULL)
- cache_hold(next);
- cache_lock(ncp);
+ _cache_hold(next);
+ _cache_lock(ncp);
if (ncp->nc_vp != vp) {
printf("Warning: cache_inval_vp: race-A detected on "
"%s\n", ncp->nc_name);
- cache_put(ncp);
+ _cache_put(ncp);
if (next)
- cache_drop(next);
+ _cache_drop(next);
goto restart;
}
- cache_inval(ncp, flags);
- cache_put(ncp); /* also releases reference */
+ _cache_inval(ncp, flags);
+ _cache_put(ncp); /* also releases reference */
ncp = next;
if (ncp && ncp->nc_vp != vp) {
printf("Warning: cache_inval_vp: race-B detected on "
"%s\n", ncp->nc_name);
- cache_drop(ncp);
+ _cache_drop(ncp);
goto restart;
}
}
* back out. An rm -rf can cause this situation to occur.
*/
void
-cache_rename(struct namecache *fncp, struct namecache *tncp)
+cache_rename(struct nchandle *fnch, struct nchandle *tnch)
{
+ struct namecache *fncp = fnch->ncp;
+ struct namecache *tncp = tnch->ncp;
struct namecache *scan;
int didwarn = 0;
- cache_setunresolved(fncp);
- cache_setunresolved(tncp);
- while (cache_inval(tncp, CINV_CHILDREN) != 0) {
+ _cache_setunresolved(fncp);
+ _cache_setunresolved(tncp);
+ while (_cache_inval(tncp, CINV_CHILDREN) != 0) {
if (didwarn++ % 10 == 0) {
printf("Warning: cache_rename: race during "
"rename %s->%s\n",
fncp->nc_name, tncp->nc_name);
}
tsleep(tncp, 0, "mvrace", hz / 10);
- cache_setunresolved(tncp);
+ _cache_setunresolved(tncp);
}
while ((scan = TAILQ_FIRST(&fncp->nc_list)) != NULL) {
- cache_hold(scan);
+ _cache_hold(scan);
cache_unlink_parent(scan);
cache_link_parent(scan, tncp);
if (scan->nc_flag & NCF_HASHED)
- cache_rehash(scan);
- cache_drop(scan);
+ _cache_rehash(scan);
+ _cache_drop(scan);
}
}
* contents of ncp->nc_vp.
*/
int
-cache_vget(struct namecache *ncp, struct ucred *cred,
+cache_vget(struct nchandle *nch, struct ucred *cred,
int lk_type, struct vnode **vpp)
{
+ struct namecache *ncp;
struct vnode *vp;
int error;
+ ncp = nch->ncp;
again:
vp = NULL;
if (ncp->nc_flag & NCF_UNRESOLVED) {
- cache_lock(ncp);
- error = cache_resolve(ncp, cred);
- cache_unlock(ncp);
+ _cache_lock(ncp);
+ error = cache_resolve(nch, cred);
+ _cache_unlock(ncp);
} else {
error = 0;
}
*/
if (vp->v_flag & VRECLAIMED) {
printf("Warning: vnode reclaim race detected in cache_vget on %p (%s)\n", vp, ncp->nc_name);
- cache_lock(ncp);
- cache_setunresolved(ncp);
- cache_unlock(ncp);
+ _cache_lock(ncp);
+ _cache_setunresolved(ncp);
+ _cache_unlock(ncp);
goto again;
}
error = vget(vp, lk_type);
}
int
-cache_vref(struct namecache *ncp, struct ucred *cred, struct vnode **vpp)
+cache_vref(struct nchandle *nch, struct ucred *cred, struct vnode **vpp)
{
+ struct namecache *ncp;
struct vnode *vp;
int error;
+ ncp = nch->ncp;
+
again:
vp = NULL;
if (ncp->nc_flag & NCF_UNRESOLVED) {
- cache_lock(ncp);
- error = cache_resolve(ncp, cred);
- cache_unlock(ncp);
+ _cache_lock(ncp);
+ error = cache_resolve(nch, cred);
+ _cache_unlock(ncp);
} else {
error = 0;
}
*/
if (vp->v_flag & VRECLAIMED) {
printf("Warning: vnode reclaim race detected on cache_vref %p (%s)\n", vp, ncp->nc_name);
- cache_lock(ncp);
- cache_setunresolved(ncp);
- cache_unlock(ncp);
+ _cache_lock(ncp);
+ _cache_setunresolved(ncp);
+ _cache_unlock(ncp);
goto again;
}
vref_initial(vp, 1);
* hierarchy.
*/
void
-cache_update_fsmid(struct namecache *ncp)
+cache_update_fsmid(struct nchandle *nch)
{
- struct vnode *vp;
+ struct namecache *ncp;
struct namecache *scan;
+ struct vnode *vp;
+
+ ncp = nch->ncp;
/*
* Warning: even if we get a non-NULL vp it could still be in the
* the makeit variable.
*/
-static int cache_inefficient_scan(struct namecache *ncp, struct ucred *cred,
+static int cache_inefficient_scan(struct nchandle *nch, struct ucred *cred,
struct vnode *dvp);
static int cache_fromdvp_try(struct vnode *dvp, struct ucred *cred,
struct vnode **saved_dvp);
-struct namecache *
-cache_fromdvp(struct vnode *dvp, struct ucred *cred, int makeit)
+int
+cache_fromdvp(struct vnode *dvp, struct ucred *cred, int makeit,
+ struct nchandle *nch)
{
- struct namecache *ncp;
struct vnode *saved_dvp;
struct vnode *pvp;
int error;
- ncp = NULL;
+ nch->ncp = NULL;
+ nch->mount = dvp->v_mount;
saved_dvp = NULL;
/*
* to be exercised.
*/
if (ncvp_debug >= 3 && makeit && TAILQ_FIRST(&dvp->v_namecache)) {
- ncp = TAILQ_FIRST(&dvp->v_namecache);
- printf("cache_fromdvp: forcing %s\n", ncp->nc_name);
+ nch->ncp = TAILQ_FIRST(&dvp->v_namecache);
+ printf("cache_fromdvp: forcing %s\n", nch->ncp->nc_name);
goto force;
}
/*
* Loop until resolution, inside code will break out on error.
*/
- while ((ncp = TAILQ_FIRST(&dvp->v_namecache)) == NULL && makeit) {
+ while ((nch->ncp = TAILQ_FIRST(&dvp->v_namecache)) == NULL && makeit) {
force:
/*
* If dvp is the root of its filesystem it should already
* effect of the mount, but it may have been disassociated.
*/
if (dvp->v_flag & VROOT) {
- ncp = cache_get(dvp->v_mount->mnt_ncp);
- error = cache_resolve_mp(ncp);
- cache_put(ncp);
+ nch->ncp = _cache_get(nch->mount->mnt_ncmountpt.ncp);
+ error = cache_resolve_mp(nch->mount);
+ _cache_put(nch->ncp);
if (ncvp_debug) {
printf("cache_fromdvp: resolve root of mount %p error %d",
dvp->v_mount, error);
if (error) {
if (ncvp_debug)
printf(" failed\n");
- ncp = NULL;
+ nch->ncp = NULL;
break;
}
if (ncvp_debug)
/*
* Reuse makeit as a recursion depth counter.
*/
- ncp = cache_fromdvp(pvp, cred, makeit + 1);
+ cache_fromdvp(pvp, cred, makeit + 1, nch);
vrele(pvp);
- if (ncp == NULL)
+ if (nch->ncp == NULL)
break;
/*
*
* ncp and dvp are both held but not locked.
*/
- error = cache_inefficient_scan(ncp, cred, dvp);
- cache_drop(ncp);
+ error = cache_inefficient_scan(nch, cred, dvp);
+ _cache_drop(nch->ncp);
if (error) {
printf("cache_fromdvp: scan %p (%s) failed on dvp=%p\n",
- pvp, ncp->nc_name, dvp);
- ncp = NULL;
+ pvp, nch->ncp->nc_name, dvp);
+ nch->ncp = NULL;
break;
}
if (ncvp_debug) {
printf("cache_fromdvp: scan %p (%s) succeeded\n",
- pvp, ncp->nc_name);
+ pvp, nch->ncp->nc_name);
}
}
- if (ncp)
- cache_hold(ncp);
+
+ /*
+ * hold it for real so the mount gets a ref
+ */
+ if (nch->ncp)
+ cache_hold(nch);
if (saved_dvp)
vrele(saved_dvp);
- return (ncp);
+ if (nch->ncp)
+ return (0);
+ return (EINVAL);
}
/*
cache_fromdvp_try(struct vnode *dvp, struct ucred *cred,
struct vnode **saved_dvp)
{
- struct namecache *ncp;
+ struct nchandle nch;
struct vnode *pvp;
int error;
static time_t last_fromdvp_report;
* can resolve in the namecache.
*/
vref(dvp);
+ nch.mount = dvp->v_mount;
+
for (;;) {
error = vop_nlookupdotdot(*dvp->v_ops, dvp, &pvp, cred);
if (error) {
return (error);
}
vn_unlock(pvp);
- if ((ncp = TAILQ_FIRST(&pvp->v_namecache)) != NULL) {
- cache_hold(ncp);
+ if ((nch.ncp = TAILQ_FIRST(&pvp->v_namecache)) != NULL) {
+ _cache_hold(nch.ncp);
vrele(pvp);
break;
}
if (pvp->v_flag & VROOT) {
- ncp = cache_get(pvp->v_mount->mnt_ncp);
- error = cache_resolve_mp(ncp);
- cache_unlock(ncp);
+ nch.ncp = _cache_get(pvp->v_mount->mnt_ncmountpt.ncp);
+ error = cache_resolve_mp(nch.mount);
+ _cache_unlock(nch.ncp);
vrele(pvp);
if (error) {
- cache_drop(ncp);
+ _cache_drop(nch.ncp);
vrele(dvp);
return (error);
}
if (last_fromdvp_report != time_second) {
last_fromdvp_report = time_second;
printf("Warning: extremely inefficient path resolution on %s\n",
- ncp->nc_name);
+ nch.ncp->nc_name);
}
- error = cache_inefficient_scan(ncp, cred, dvp);
+ error = cache_inefficient_scan(&nch, cred, dvp);
/*
* Hopefully dvp now has a namecache record associated with it.
* algorithms.
*/
static int
-cache_inefficient_scan(struct namecache *ncp, struct ucred *cred,
+cache_inefficient_scan(struct nchandle *nch, struct ucred *cred,
struct vnode *dvp)
{
struct nlcomponent nlc;
- struct namecache *rncp;
+ struct nchandle rncp;
struct dirent *den;
struct vnode *pvp;
struct vattr vat;
vat.va_blocksize = 0;
if ((error = VOP_GETATTR(dvp, &vat)) != 0)
return (error);
- if ((error = cache_vref(ncp, cred, &pvp)) != 0)
+ if ((error = cache_vref(nch, cred, &pvp)) != 0)
return (error);
if (ncvp_debug)
printf("inefficient_scan: directory iosize %ld vattr fileid = %ld\n", vat.va_blocksize, (long)vat.va_fileid);
if ((blksize = vat.va_blocksize) == 0)
blksize = DEV_BSIZE;
rbuf = kmalloc(blksize, M_TEMP, M_WAITOK);
- rncp = NULL;
+ rncp.ncp = NULL;
eofflag = 0;
uio.uio_offset = 0;
if (ncvp_debug) {
printf("cache_inefficient_scan: "
"MATCHED inode %ld path %s/%*.*s\n",
- vat.va_fileid, ncp->nc_name,
+ vat.va_fileid, nch->ncp->nc_name,
den->d_namlen, den->d_namlen,
den->d_name);
}
nlc.nlc_nameptr = den->d_name;
nlc.nlc_namelen = den->d_namlen;
- rncp = cache_nlookup(ncp, &nlc);
- KKASSERT(rncp != NULL);
+ rncp = cache_nlookup(nch, &nlc);
+ KKASSERT(rncp.ncp != NULL);
break;
}
bytes -= _DIRENT_DIRSIZ(den);
den = _DIRENT_NEXT(den);
}
- if (rncp == NULL && eofflag == 0 && uio.uio_resid != blksize)
+ if (rncp.ncp == NULL && eofflag == 0 && uio.uio_resid != blksize)
goto again;
}
vrele(pvp);
- if (rncp) {
- if (rncp->nc_flag & NCF_UNRESOLVED) {
- cache_setvp(rncp, dvp);
+ if (rncp.ncp) {
+ if (rncp.ncp->nc_flag & NCF_UNRESOLVED) {
+ _cache_setvp(rncp.ncp, dvp);
if (ncvp_debug >= 2) {
printf("cache_inefficient_scan: setvp %s/%s = %p\n",
- ncp->nc_name, rncp->nc_name, dvp);
+ nch->ncp->nc_name, rncp.ncp->nc_name, dvp);
}
} else {
if (ncvp_debug >= 2) {
printf("cache_inefficient_scan: setvp %s/%s already set %p/%p\n",
- ncp->nc_name, rncp->nc_name, dvp,
- rncp->nc_vp);
+ nch->ncp->nc_name, rncp.ncp->nc_name, dvp,
+ rncp.ncp->nc_vp);
}
}
- if (rncp->nc_vp == NULL)
- error = rncp->nc_error;
- cache_put(rncp);
+ if (rncp.ncp->nc_vp == NULL)
+ error = rncp.ncp->nc_error;
+ _cache_put(rncp.ncp);
} else {
printf("cache_inefficient_scan: dvp %p NOT FOUND in %s\n",
- dvp, ncp->nc_name);
+ dvp, nch->ncp->nc_name);
error = ENOENT;
}
kfree(rbuf, M_TEMP);
/*
* Disassociate the vnode or negative cache ref and set NCF_UNRESOLVED.
*/
- cache_setunresolved(ncp);
+ _cache_setunresolved(ncp);
/*
* Try to scrap the entry and possibly tail-recurse on its parent.
LIST_REMOVE(ncp, nc_hash);
}
if ((par = ncp->nc_parent) != NULL) {
- par = cache_hold(par);
+ par = _cache_hold(par);
TAILQ_REMOVE(&par->nc_list, ncp, nc_entry);
ncp->nc_parent = NULL;
if (par->nc_vp && TAILQ_EMPTY(&par->nc_list))
*/
KKASSERT(ncp->nc_refs == 1);
--numunres;
- /* cache_unlock(ncp) not required */
+ /* _cache_unlock(ncp) not required */
ncp->nc_refs = -1; /* safety */
if (ncp->nc_name)
kfree(ncp->nc_name, M_VFSCACHE);
if (ncp == NULL)
return;
if (ncp->nc_refs != 1) {
- cache_drop(ncp);
+ _cache_drop(ncp);
return;
}
KKASSERT(par->nc_exlocks == 0);
- cache_lock(ncp);
+ _cache_lock(ncp);
}
done:
- cache_unlock(ncp);
+ _cache_unlock(ncp);
atomic_subtract_int(&ncp->nc_refs, 1);
}
* Lookup an entry in the cache. A locked, referenced, non-NULL
* entry is *always* returned, even if the supplied component is illegal.
* The resulting namecache entry should be returned to the system with
- * cache_put() or cache_unlock() + cache_drop().
+ * cache_put() or _cache_unlock() + cache_drop().
*
* namecache locks are recursive but care must be taken to avoid lock order
* reversals.
* responsible for resolving the namecache chain top-down. This API
* specifically allows whole chains to be created in an unresolved state.
*/
-struct namecache *
-cache_nlookup(struct namecache *par, struct nlcomponent *nlc)
+struct nchandle
+cache_nlookup(struct nchandle *par_nch, struct nlcomponent *nlc)
{
+ struct nchandle nch;
struct namecache *ncp;
struct namecache *new_ncp;
struct nchashhead *nchpp;
* Try to locate an existing entry
*/
hash = fnv_32_buf(nlc->nlc_nameptr, nlc->nlc_namelen, FNV1_32_INIT);
- hash = fnv_32_buf(&par, sizeof(par), hash);
+ hash = fnv_32_buf(&par_nch->ncp, sizeof(par_nch->ncp), hash);
new_ncp = NULL;
restart:
LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
(ncp->nc_flag & NCF_UNRESOLVED) == 0 &&
ncp->nc_exlocks == 0
) {
- cache_zap(cache_get(ncp));
+ cache_zap(_cache_get(ncp));
goto restart;
}
* UNRESOLVED entries may match, but DESTROYED entries
* do not.
*/
- if (ncp->nc_parent == par &&
+ if (ncp->nc_parent == par_nch->ncp &&
ncp->nc_nlen == nlc->nlc_namelen &&
bcmp(ncp->nc_name, nlc->nlc_nameptr, ncp->nc_nlen) == 0 &&
(ncp->nc_flag & NCF_DESTROYED) == 0
) {
- if (cache_get_nonblock(ncp) == 0) {
+ if (_cache_get_nonblock(ncp) == 0) {
if (new_ncp)
- cache_free(new_ncp);
+ _cache_free(new_ncp);
goto found;
}
- cache_get(ncp);
- cache_put(ncp);
+ _cache_get(ncp);
+ _cache_put(ncp);
goto restart;
}
}
* Initialize as a new UNRESOLVED entry, lock (non-blocking),
* and link to the parent. The mount point is usually inherited
* from the parent unless this is a special case such as a mount
- * point where nlc_namelen is 0. The caller is responsible for
- * setting nc_mount in that case. If nlc_namelen is 0 nc_name will
+ * point where nlc_namelen is 0. If nlc_namelen is 0 nc_name will
* be NULL.
*/
if (nlc->nlc_namelen) {
bcopy(nlc->nlc_nameptr, ncp->nc_name, nlc->nlc_namelen);
ncp->nc_name[nlc->nlc_namelen] = 0;
- ncp->nc_mount = par->nc_mount;
}
nchpp = NCHHASH(hash);
LIST_INSERT_HEAD(nchpp, ncp, nc_hash);
ncp->nc_flag |= NCF_HASHED;
- cache_link_parent(ncp, par);
+ cache_link_parent(ncp, par_nch->ncp);
found:
/*
* stats and namecache size management
else
++gd->gd_nchstats->ncs_neghits;
cache_hysteresis();
- return(ncp);
+ nch.mount = par_nch->mount;
+ nch.ncp = ncp;
+ ++nch.mount->mnt_refs;
+ return(nch);
}
/*
- * Locate the mount point under a namecache entry. We locate a special
- * child ncp with a 0-length name and retrieve the mount point from it.
+ * The namecache entry is marked as being used as a mount point.
+ * Locate the mount if it is visible to the caller.
*/
-struct mount *
-cache_findmount(struct namecache *par)
+struct findmount_info {
+ struct mount *result;
+ struct mount *nch_mount;
+ struct namecache *nch_ncp;
+};
+
+static
+int
+cache_findmount_callback(struct mount *mp, void *data)
{
- struct namecache *ncp;
- u_int32_t hash;
+ struct findmount_info *info = data;
- hash = FNV1_32_INIT; /* special 0-length name */
- hash = fnv_32_buf(&par, sizeof(par), hash);
- LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
- if (ncp->nc_nlen == 0 && (ncp->nc_flag & NCF_MOUNTPT))
- return(ncp->nc_mount);
+ /*
+ * Check the mount's mounted-on point against the passed nch.
+ */
+ if (mp->mnt_ncmounton.mount == info->nch_mount &&
+ mp->mnt_ncmounton.ncp == info->nch_ncp
+ ) {
+ info->result = mp;
+ return(-1);
}
- return(NULL);
+ return(0);
}
-/*
- * Given a locked ncp, validate that the vnode, if present, is actually
- * usable. If it is not usable set the ncp to an unresolved state.
- */
-void
-cache_validate(struct namecache *ncp)
+struct mount *
+cache_findmount(struct nchandle *nch)
{
- if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
- if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
- cache_setunresolved(ncp);
- }
+ struct findmount_info info;
+
+ info.result = NULL;
+ info.nch_mount = nch->mount;
+ info.nch_ncp = nch->ncp;
+ mountlist_scan(cache_findmount_callback, &info,
+ MNTSCAN_FORWARD|MNTSCAN_NOBUSY);
+ return(info.result);
}
/*
* will be returned.
*/
int
-cache_resolve(struct namecache *ncp, struct ucred *cred)
+cache_resolve(struct nchandle *nch, struct ucred *cred)
{
struct namecache *par;
+ struct namecache *ncp;
+ struct nchandle nctmp;
+ struct mount *mp;
int error;
+ ncp = nch->ncp;
+ mp = nch->mount;
restart:
/*
* If the ncp is already resolved we have nothing to do. However,
*/
if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
- cache_setunresolved(ncp);
+ _cache_setunresolved(ncp);
if ((ncp->nc_flag & NCF_UNRESOLVED) == 0)
return (ncp->nc_error);
}
* Mount points need special handling because the parent does not
* belong to the same filesystem as the ncp.
*/
- if (ncp->nc_flag & NCF_MOUNTPT)
- return (cache_resolve_mp(ncp));
+ if (ncp == mp->mnt_ncmountpt.ncp)
+ return (cache_resolve_mp(mp));
/*
* We expect an unbroken chain of ncps to at least the mount point,
* be one of its parents. We resolve it anyway, the loop
* will handle any moves.
*/
- cache_get(par);
- if (par->nc_flag & NCF_MOUNTPT) {
- cache_resolve_mp(par);
+ _cache_get(par);
+ if (par == nch->mount->mnt_ncmountpt.ncp) {
+ cache_resolve_mp(nch->mount);
} else if (par->nc_parent->nc_vp == NULL) {
printf("[diagnostic] cache_resolve: raced on %*.*s\n", par->nc_nlen, par->nc_nlen, par->nc_name);
- cache_put(par);
+ _cache_put(par);
continue;
} else if (par->nc_flag & NCF_UNRESOLVED) {
- par->nc_error = VOP_NRESOLVE(par, cred);
+ nctmp.mount = mp;
+ nctmp.ncp = par;
+ par->nc_error = VOP_NRESOLVE(&nctmp, cred);
}
if ((error = par->nc_error) != 0) {
if (par->nc_error != EAGAIN) {
printf("EXDEV case 3 %*.*s error %d\n",
par->nc_nlen, par->nc_nlen, par->nc_name,
par->nc_error);
- cache_put(par);
+ _cache_put(par);
return(error);
}
printf("[diagnostic] cache_resolve: EAGAIN par %p %*.*s\n",
par, par->nc_nlen, par->nc_nlen, par->nc_name);
}
- cache_put(par);
+ _cache_put(par);
/* loop */
}
* NOTE: in order to call VOP_NRESOLVE(), the parent of the passed
* ncp must already be resolved.
*/
- KKASSERT((ncp->nc_flag & NCF_MOUNTPT) == 0);
- ncp->nc_error = VOP_NRESOLVE(ncp, cred);
+ nctmp.mount = mp;
+ nctmp.ncp = ncp;
+ ncp->nc_error = VOP_NRESOLVE(&nctmp, cred);
/*vop_nresolve(*ncp->nc_parent->nc_vp->v_ops, ncp, cred);*/
if (ncp->nc_error == EAGAIN) {
printf("[diagnostic] cache_resolve: EAGAIN ncp %p %*.*s\n",
* the unlock we have to recheck the flags after we relock.
*/
static int
-cache_resolve_mp(struct namecache *ncp)
+cache_resolve_mp(struct mount *mp)
{
+ struct namecache *ncp = mp->mnt_ncmountpt.ncp;
struct vnode *vp;
- struct mount *mp = ncp->nc_mount;
int error;
KKASSERT(mp != NULL);
*/
if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
if (ncp->nc_vp && (ncp->nc_vp->v_flag & VRECLAIMED))
- cache_setunresolved(ncp);
+ _cache_setunresolved(ncp);
}
if (ncp->nc_flag & NCF_UNRESOLVED) {
- cache_unlock(ncp);
+ _cache_unlock(ncp);
while (vfs_busy(mp, 0))
;
error = VFS_ROOT(mp, &vp);
- cache_lock(ncp);
+ _cache_lock(ncp);
/*
* recheck the ncp state after relocking.
if (ncp->nc_flag & NCF_UNRESOLVED) {
ncp->nc_error = error;
if (error == 0) {
- cache_setvp(ncp, vp);
+ _cache_setvp(ncp, vp);
vput(vp);
} else {
printf("[diagnostic] cache_resolve_mp: failed to resolve mount %p\n", mp);
- cache_setvp(ncp, NULL);
+ _cache_setvp(ncp, NULL);
}
} else if (error == 0) {
vput(vp);
}
TAILQ_REMOVE(&ncneglist, ncp, nc_vnode);
TAILQ_INSERT_TAIL(&ncneglist, ncp, nc_vnode);
- if (cache_get_nonblock(ncp) == 0)
+ if (_cache_get_nonblock(ncp) == 0)
cache_zap(ncp);
--count;
}
* unhash the ncp if the ncp is no longer hashable.
*/
static void
-cache_rehash(struct namecache *ncp)
+_cache_rehash(struct namecache *ncp)
{
struct nchashhead *nchpp;
u_int32_t hash;
* Called from start_init() to bootstrap the root filesystem. Returns
* a referenced, unlocked namecache record.
*/
-struct namecache *
-cache_allocroot(struct mount *mp, struct vnode *vp)
+void
+cache_allocroot(struct nchandle *nch, struct mount *mp, struct vnode *vp)
{
- struct namecache *ncp = cache_alloc(0);
-
- ncp->nc_flag |= NCF_MOUNTPT | NCF_ROOT;
- ncp->nc_mount = mp;
- cache_setvp(ncp, vp);
- return(ncp);
+ nch->ncp = cache_alloc(0);
+ nch->mount = mp;
+ ++mp->mnt_refs;
+ if (vp)
+ _cache_setvp(nch->ncp, vp);
}
/*
* it must cache_hold() it.
*/
void
-vfs_cache_setroot(struct vnode *nvp, struct namecache *ncp)
+vfs_cache_setroot(struct vnode *nvp, struct nchandle *nch)
{
struct vnode *ovp;
- struct namecache *oncp;
+ struct nchandle onch;
ovp = rootvnode;
- oncp = rootncp;
+ onch = rootnch;
rootvnode = nvp;
- rootncp = ncp;
-
+ if (nch)
+ rootnch = *nch;
+ else
+ cache_zero(&rootnch);
if (ovp)
vrele(ovp);
- if (oncp)
- cache_drop(oncp);
+ if (onch.ncp)
+ cache_drop(&onch);
}
/*
* Since we need to check it anyway, we will flush all the invalid
* entries at the same time.
*/
+#if 0
+
void
cache_purgevfs(struct mount *mp)
{
for (nchpp = &nchashtbl[nchash]; nchpp >= nchashtbl; nchpp--) {
ncp = LIST_FIRST(nchpp);
if (ncp)
- cache_hold(ncp);
+ _cache_hold(ncp);
while (ncp) {
nnp = LIST_NEXT(ncp, nc_hash);
if (nnp)
- cache_hold(nnp);
+ _cache_hold(nnp);
if (ncp->nc_mount == mp) {
- cache_lock(ncp);
+ _cache_lock(ncp);
cache_zap(ncp);
} else {
- cache_drop(ncp);
+ _cache_drop(ncp);
}
ncp = nnp;
}
}
}
+#endif
+
/*
* Create a new (theoretically) unique fsmid
*/
char *bp;
int i, slash_prefixed;
struct filedesc *fdp;
- struct namecache *ncp;
+ struct nchandle nch;
numcwdcalls++;
bp = buf;
fdp = p->p_fd;
slash_prefixed = 0;
- ncp = fdp->fd_ncdir;
- while (ncp && ncp != fdp->fd_nrdir && (ncp->nc_flag & NCF_ROOT) == 0) {
- if (ncp->nc_flag & NCF_MOUNTPT) {
- if (ncp->nc_mount == NULL) {
- *error = EBADF; /* forced unmount? */
- return(NULL);
- }
- ncp = ncp->nc_parent;
+ nch = fdp->fd_ncdir;
+ while (nch.ncp && (nch.ncp != fdp->fd_nrdir.ncp ||
+ nch.mount != fdp->fd_nrdir.mount)
+ ) {
+ /*
+ * While traversing upwards if we encounter the root
+ * of the current mount we have to skip to the mount point
+ * in the underlying filesystem.
+ */
+ if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
+ nch = nch.mount->mnt_ncmounton;
continue;
}
- for (i = ncp->nc_nlen - 1; i >= 0; i--) {
+
+ /*
+ * Prepend the path segment
+ */
+ for (i = nch.ncp->nc_nlen - 1; i >= 0; i--) {
if (bp == buf) {
numcwdfail4++;
*error = ENOMEM;
return(NULL);
}
- *--bp = ncp->nc_name[i];
+ *--bp = nch.ncp->nc_name[i];
}
if (bp == buf) {
numcwdfail4++;
}
*--bp = '/';
slash_prefixed = 1;
- ncp = ncp->nc_parent;
+
+ /*
+ * Go up a directory. This isn't a mount point so we don't
+ * have to check again.
+ */
+ nch.ncp = nch.ncp->nc_parent;
}
- if (ncp == NULL) {
+ if (nch.ncp == NULL) {
numcwdfail2++;
*error = ENOENT;
return(NULL);
STATNODE(numfullpathfound);
int
-cache_fullpath(struct proc *p, struct namecache *ncp, char **retbuf, char **freebuf)
+cache_fullpath(struct proc *p, struct nchandle *nchp, char **retbuf, char **freebuf)
{
char *bp, *buf;
int i, slash_prefixed;
- struct namecache *fd_nrdir;
+ struct nchandle fd_nrdir;
+ struct nchandle nch;
numfullpathcalls--;
+ *retbuf = NULL;
+ *freebuf = NULL;
+
buf = kmalloc(MAXPATHLEN, M_TEMP, M_WAITOK);
bp = buf + MAXPATHLEN - 1;
*bp = '\0';
if (p != NULL)
fd_nrdir = p->p_fd->fd_nrdir;
else
- fd_nrdir = NULL;
+ fd_nrdir = rootnch;
slash_prefixed = 0;
- while (ncp && ncp != fd_nrdir && (ncp->nc_flag & NCF_ROOT) == 0) {
- if (ncp->nc_flag & NCF_MOUNTPT) {
- if (ncp->nc_mount == NULL) {
- kfree(buf, M_TEMP);
- return(EBADF);
- }
- ncp = ncp->nc_parent;
+ nch = *nchp;
+
+ while (nch.ncp &&
+ (nch.ncp != fd_nrdir.ncp || nch.mount != fd_nrdir.mount)
+ ) {
+ /*
+ * While traversing upwards if we encounter the root
+ * of the current mount we have to skip to the mount point.
+ */
+ if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
+ nch = nch.mount->mnt_ncmounton;
continue;
}
- for (i = ncp->nc_nlen - 1; i >= 0; i--) {
+
+ /*
+ * Prepend the path segment
+ */
+ for (i = nch.ncp->nc_nlen - 1; i >= 0; i--) {
if (bp == buf) {
numfullpathfail4++;
kfree(buf, M_TEMP);
return(ENOMEM);
}
- *--bp = ncp->nc_name[i];
+ *--bp = nch.ncp->nc_name[i];
}
if (bp == buf) {
numfullpathfail4++;
}
*--bp = '/';
slash_prefixed = 1;
- ncp = ncp->nc_parent;
+
+ /*
+ * Go up a directory. This isn't a mount point so we don't
+ * have to check again.
+ */
+ nch.ncp = nch.ncp->nc_parent;
}
- if (ncp == NULL) {
+ if (nch.ncp == NULL) {
numfullpathfail2++;
kfree(buf, M_TEMP);
return(ENOENT);
}
- if (p != NULL && (ncp->nc_flag & NCF_ROOT) && ncp != fd_nrdir) {
- bp = buf + MAXPATHLEN - 1;
- *bp = '\0';
- slash_prefixed = 0;
- }
+
if (!slash_prefixed) {
if (bp == buf) {
numfullpathfail4++;
vn_fullpath(struct proc *p, struct vnode *vn, char **retbuf, char **freebuf)
{
struct namecache *ncp;
+ struct nchandle nch;
numfullpathcalls++;
if (disablefullpath)
return (EINVAL);
numfullpathcalls--;
- return(cache_fullpath(p, ncp, retbuf, freebuf));
+ nch.ncp = ncp;;
+ nch.mount = vn->v_mount;
+ return(cache_fullpath(p, &nch, retbuf, freebuf));
}
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/kern/vfs_conf.c,v 1.49.2.5 2003/01/07 11:56:53 joerg Exp $
- * $DragonFly: src/sys/kern/vfs_conf.c,v 1.20 2006/09/10 01:26:39 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_conf.c,v 1.21 2006/10/27 04:56:31 dillon Exp $
*/
/*
#define ROOTNAME "root_device"
struct vnode *rootvnode;
-struct namecache *rootncp;
+struct nchandle rootnch;
/*
* The root specifiers we will try if RB_CDROM is specified. Note that
*
*
* $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
- * $DragonFly: src/sys/kern/vfs_default.c,v 1.44 2006/10/26 02:27:19 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_default.c,v 1.45 2006/10/27 04:56:31 dillon Exp $
*/
#include <sys/param.h>
}
/*
- * vop_compat_resolve { struct namecache *a_ncp } XXX STOPGAP FUNCTION
+ * vop_compat_resolve { struct nchandle *a_nch } XXX STOPGAP FUNCTION
*
* XXX OLD API ROUTINE! WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
* WILL BE REMOVED. This procedure exists for all VFSs which have not
int error;
struct vnode *dvp;
struct vnode *vp;
+ struct nchandle *nch;
struct namecache *ncp;
struct componentname cnp;
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
vrele(vp);
} else if (error == 0) {
KKASSERT(vp != NULL);
- cache_setvp(ncp, vp);
+ cache_setvp(nch, vp);
vrele(vp);
} else if (error == ENOENT) {
KKASSERT(vp == NULL);
if (cnp.cn_flags & CNP_ISWHITEOUT)
ncp->nc_flag |= NCF_WHITEOUT;
- cache_setvp(ncp, NULL);
+ cache_setvp(nch, NULL);
}
vrele(dvp);
return (error);
}
/*
- * vop_compat_ncreate { struct namecache *a_ncp, XXX STOPGAP FUNCTION
+ * vop_compat_ncreate { struct nchandle *a_nch, XXX STOPGAP FUNCTION
* struct vnode *a_vpp,
* struct ucred *a_cred,
* struct vattr *a_vap }
{
struct thread *td = curthread;
struct componentname cnp;
+ struct nchandle *nch;
struct namecache *ncp;
struct vnode *dvp;
int error;
/*
* Sanity checks, get a locked directory vnode.
*/
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
if (error == 0) {
- cache_setunresolved(ncp);
- cache_setvp(ncp, *ap->a_vpp);
+ cache_setunresolved(nch);
+ cache_setvp(nch, *ap->a_vpp);
}
} else {
if (error == 0) {
}
/*
- * vop_compat_nmkdir { struct namecache *a_ncp, XXX STOPGAP FUNCTION
+ * vop_compat_nmkdir { struct nchandle *a_nch, XXX STOPGAP FUNCTION
* struct vnode *a_vpp,
* struct ucred *a_cred,
* struct vattr *a_vap }
{
struct thread *td = curthread;
struct componentname cnp;
+ struct nchandle *nch;
struct namecache *ncp;
struct vnode *dvp;
int error;
/*
* Sanity checks, get a locked directory vnode.
*/
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
if (error == 0) {
- cache_setunresolved(ncp);
- cache_setvp(ncp, *ap->a_vpp);
+ cache_setunresolved(nch);
+ cache_setvp(nch, *ap->a_vpp);
}
} else {
if (error == 0) {
}
/*
- * vop_compat_nmknod { struct namecache *a_ncp, XXX STOPGAP FUNCTION
+ * vop_compat_nmknod { struct nchandle *a_nch, XXX STOPGAP FUNCTION
* struct vnode *a_vpp,
* struct ucred *a_cred,
* struct vattr *a_vap }
{
struct thread *td = curthread;
struct componentname cnp;
+ struct nchandle *nch;
struct namecache *ncp;
struct vnode *dvp;
int error;
/*
* Sanity checks, get a locked directory vnode.
*/
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
if (error == 0) {
- cache_setunresolved(ncp);
- cache_setvp(ncp, *ap->a_vpp);
+ cache_setunresolved(nch);
+ cache_setvp(nch, *ap->a_vpp);
}
} else {
if (error == 0) {
}
/*
- * vop_compat_nlink { struct namecache *a_ncp, XXX STOPGAP FUNCTION
+ * vop_compat_nlink { struct nchandle *a_nch, XXX STOPGAP FUNCTION
* struct vnode *a_vp,
* struct ucred *a_cred }
*
{
struct thread *td = curthread;
struct componentname cnp;
+ struct nchandle *nch;
struct namecache *ncp;
struct vnode *dvp;
struct vnode *tvp;
/*
* Sanity checks, get a locked directory vnode.
*/
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
if (error == 0) {
- cache_setunresolved(ncp);
- cache_setvp(ncp, ap->a_vp);
+ cache_setunresolved(nch);
+ cache_setvp(nch, ap->a_vp);
}
} else {
if (error == 0) {
{
struct thread *td = curthread;
struct componentname cnp;
+ struct nchandle *nch;
struct namecache *ncp;
struct vnode *dvp;
struct vnode *vp;
* Sanity checks, get a locked directory vnode.
*/
*ap->a_vpp = NULL;
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
if (error == 0) {
- cache_setunresolved(ncp);
- cache_setvp(ncp, vp);
+ cache_setunresolved(nch);
+ cache_setvp(nch, vp);
*ap->a_vpp = vp;
}
} else {
}
/*
- * vop_compat_nwhiteout { struct namecache *a_ncp, XXX STOPGAP FUNCTION
+ * vop_compat_nwhiteout { struct nchandle *a_nch, XXX STOPGAP FUNCTION
* struct ucred *a_cred,
* int a_flags }
*
{
struct thread *td = curthread;
struct componentname cnp;
+ struct nchandle *nch;
struct namecache *ncp;
struct vnode *dvp;
struct vnode *vp;
/*
* Sanity checks, get a locked directory vnode.
*/
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
if (error == 0)
- cache_setunresolved(ncp);
+ cache_setunresolved(nch);
} else {
if (error == 0) {
vput(vp);
/*
- * vop_compat_nremove { struct namecache *a_ncp, XXX STOPGAP FUNCTION
+ * vop_compat_nremove { struct nchandle *a_nch, XXX STOPGAP FUNCTION
* struct ucred *a_cred }
*/
int
{
struct thread *td = curthread;
struct componentname cnp;
+ struct nchandle *nch;
struct namecache *ncp;
struct vnode *dvp;
struct vnode *vp;
/*
* Sanity checks, get a locked directory vnode.
*/
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_REMOVE(dvp, vp, &cnp);
if (error == 0) {
- cache_setunresolved(ncp);
- cache_setvp(ncp, NULL);
+ cache_setunresolved(nch);
+ cache_setvp(nch, NULL);
cache_inval_vp(vp, CINV_DESTROY);
}
}
}
/*
- * vop_compat_nrmdir { struct namecache *a_ncp, XXX STOPGAP FUNCTION
+ * vop_compat_nrmdir { struct nchandle *a_nch, XXX STOPGAP FUNCTION
* struct ucred *a_cred }
*/
int
{
struct thread *td = curthread;
struct componentname cnp;
+ struct nchandle *nch;
struct namecache *ncp;
struct vnode *dvp;
struct vnode *vp;
/*
* Sanity checks, get a locked directory vnode.
*/
- ncp = ap->a_ncp; /* locked namecache node */
- if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ nch = ap->a_nch; /* locked namecache node */
+ ncp = nch->ncp;
if (ncp->nc_parent == NULL)
return(EPERM);
if ((dvp = ncp->nc_parent->nc_vp) == NULL)
* back out.
*/
if (error == 0) {
- cache_inval(ncp, CINV_DESTROY);
+ cache_inval(nch, CINV_DESTROY);
cache_inval_vp(vp, CINV_DESTROY);
}
}
}
/*
- * vop_compat_nrename { struct namecache *a_fncp, XXX STOPGAP FUNCTION
- * struct namecache *a_tncp,
+ * vop_compat_nrename { struct nchandle *a_fnch, XXX STOPGAP FUNCTION
+ * struct nchandle *a_tnch,
* struct ucred *a_cred }
*
* This is a fairly difficult procedure. The old VOP_OLD_RENAME requires that
struct thread *td = curthread;
struct componentname fcnp;
struct componentname tcnp;
+ struct nchandle *fnch;
+ struct nchandle *tnch;
struct namecache *fncp;
struct namecache *tncp;
struct vnode *fdvp, *fvp;
/*
* Sanity checks, get referenced vnodes representing the source.
*/
- fncp = ap->a_fncp; /* locked namecache node */
- if (fncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- return(EPERM);
+ fnch = ap->a_fnch; /* locked namecache node */
+ fncp = fnch->ncp;
if (fncp->nc_parent == NULL)
return(EPERM);
if ((fdvp = fncp->nc_parent->nc_vp) == NULL)
* in CREATE mode so it places the required information in the
* directory inode.
*/
- tncp = ap->a_tncp; /* locked namecache node */
- if (tncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
- error = EPERM;
+ tnch = ap->a_tnch; /* locked namecache node */
+ tncp = tnch->ncp;
if (tncp->nc_parent == NULL)
error = EPERM;
if ((tdvp = tncp->nc_parent->nc_vp) == NULL)
KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
if (error == 0) {
- cache_rename(fncp, tncp);
- cache_setvp(tncp, fvp);
+ cache_rename(fnch, tnch);
+ cache_setvp(tnch, fvp);
}
} else if (error == 0) {
/*
KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
if (error == 0) {
- cache_rename(fncp, tncp);
- cache_setvp(tncp, fvp);
+ cache_rename(fnch, tnch);
+ cache_setvp(tnch, fvp);
}
} else {
vrele(fdvp);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_jops.c,v 1.31 2006/09/30 21:10:19 swildner Exp $
+ * $DragonFly: src/sys/kern/vfs_jops.c,v 1.32 2006/10/27 04:56:31 dillon Exp $
*/
/*
* Each mount point may have zero or more independantly configured journals
}
/*
- * Journal vop_ncreate { a_ncp, a_vpp, a_cred, a_vap }
+ * Journal vop_ncreate { a_nch, a_vpp, a_cred, a_vap }
*/
static
int
if (error == 0) {
TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
jrecord_write_cred(jrec, NULL, ap->a_cred);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
if (*ap->a_vpp)
jrecord_write_vnode_ref(jrec, *ap->a_vpp);
save = jrecord_push(jrec, JTYPE_REDO);
}
/*
- * Journal vop_nmknod { a_ncp, a_vpp, a_cred, a_vap }
+ * Journal vop_nmknod { a_nch, a_vpp, a_cred, a_vap }
*/
static
int
if (error == 0) {
TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
jrecord_write_cred(jrec, NULL, ap->a_cred);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
save = jrecord_push(jrec, JTYPE_REDO);
jrecord_write_vattr(jrec, ap->a_vap);
jrecord_pop(jrec, save);
}
/*
- * Journal vop_nlink { a_ncp, a_vp, a_cred }
+ * Journal vop_nlink { a_nch, a_vp, a_cred }
*/
static
int
if (error == 0) {
TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
jrecord_write_cred(jrec, NULL, ap->a_cred);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
/* XXX PATH to VP and inode number */
/* XXX this call may not record the correct path when
* multiple paths are available */
save = jrecord_push(jrec, JTYPE_REDO);
- jrecord_write_vnode_link(jrec, ap->a_vp, ap->a_ncp);
+ jrecord_write_vnode_link(jrec, ap->a_vp, ap->a_nch->ncp);
jrecord_pop(jrec, save);
}
}
}
/*
- * Journal vop_symlink { a_ncp, a_vpp, a_cred, a_vap, a_target }
+ * Journal vop_symlink { a_nch, a_vpp, a_cred, a_vap, a_target }
*/
static
int
if (error == 0) {
TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
jrecord_write_cred(jrec, NULL, ap->a_cred);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
save = jrecord_push(jrec, JTYPE_REDO);
jrecord_leaf(jrec, JLEAF_SYMLINKDATA,
ap->a_target, strlen(ap->a_target));
}
/*
- * Journal vop_nwhiteout { a_ncp, a_cred, a_flags }
+ * Journal vop_nwhiteout { a_nch, a_cred, a_flags }
*/
static
int
if (error == 0) {
TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
jrecord_write_cred(jrec, NULL, ap->a_cred);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
}
}
jreclist_done(mp, &jreclist, error);
}
/*
- * Journal vop_nremove { a_ncp, a_cred }
+ * Journal vop_nremove { a_nch, a_cred }
*/
static
int
mp = ap->a_head.a_ops->head.vv_mount;
if (jreclist_init(mp, &jreclist, &jreccache, JTYPE_REMOVE) &&
- ap->a_ncp->nc_vp
+ ap->a_nch->ncp->nc_vp
) {
- jreclist_undo_file(&jreclist, ap->a_ncp->nc_vp,
+ jreclist_undo_file(&jreclist, ap->a_nch->ncp->nc_vp,
JRUNDO_ALL|JRUNDO_GETVP|JRUNDO_CONDLINK, 0, -1);
}
error = vop_journal_operate_ap(&ap->a_head);
if (error == 0) {
TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
jrecord_write_cred(jrec, NULL, ap->a_cred);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
}
}
jreclist_done(mp, &jreclist, error);
}
/*
- * Journal vop_nmkdir { a_ncp, a_vpp, a_cred, a_vap }
+ * Journal vop_nmkdir { a_nch, a_vpp, a_cred, a_vap }
*/
static
int
jrecord_write_audit(jrec);
}
#endif
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
jrecord_write_cred(jrec, NULL, ap->a_cred);
jrecord_write_vattr(jrec, ap->a_vap);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
if (*ap->a_vpp)
jrecord_write_vnode_ref(jrec, *ap->a_vpp);
}
}
/*
- * Journal vop_nrmdir { a_ncp, a_cred }
+ * Journal vop_nrmdir { a_nch, a_cred }
*/
static
int
mp = ap->a_head.a_ops->head.vv_mount;
if (jreclist_init(mp, &jreclist, &jreccache, JTYPE_RMDIR)) {
- jreclist_undo_file(&jreclist, ap->a_ncp->nc_vp,
+ jreclist_undo_file(&jreclist, ap->a_nch->ncp->nc_vp,
JRUNDO_VATTR|JRUNDO_GETVP, 0, 0);
}
error = vop_journal_operate_ap(&ap->a_head);
if (error == 0) {
TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
jrecord_write_cred(jrec, NULL, ap->a_cred);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_ncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_nch->ncp);
}
}
jreclist_done(mp, &jreclist, error);
}
/*
- * Journal vop_nrename { a_fncp, a_tncp, a_cred }
+ * Journal vop_nrename { a_fnch, a_tnch, a_cred }
*/
static
int
mp = ap->a_head.a_ops->head.vv_mount;
if (jreclist_init(mp, &jreclist, &jreccache, JTYPE_RENAME) &&
- ap->a_tncp->nc_vp
+ ap->a_tnch->ncp->nc_vp
) {
- jreclist_undo_file(&jreclist, ap->a_tncp->nc_vp,
+ jreclist_undo_file(&jreclist, ap->a_tnch->ncp->nc_vp,
JRUNDO_ALL|JRUNDO_GETVP|JRUNDO_CONDLINK, 0, -1);
}
error = vop_journal_operate_ap(&ap->a_head);
if (error == 0) {
TAILQ_FOREACH(jrec, &jreclist.list, user_entry) {
jrecord_write_cred(jrec, NULL, ap->a_cred);
- jrecord_write_path(jrec, JLEAF_PATH1, ap->a_fncp);
- jrecord_write_path(jrec, JLEAF_PATH2, ap->a_tncp);
+ jrecord_write_path(jrec, JLEAF_PATH1, ap->a_fnch->ncp);
+ jrecord_write_path(jrec, JLEAF_PATH2, ap->a_tnch->ncp);
}
}
jreclist_done(mp, &jreclist, error);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_journal.c,v 1.28 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_journal.c,v 1.29 2006/10/27 04:56:31 dillon Exp $
*/
/*
* The journaling protocol is intended to evolve into a two-way stream
/*
* Pass 1 - figure out the number of bytes required. Include terminating
* \0 on last element and '/' separator on other elements.
+ *
+ * The namecache topology terminates at the root of the filesystem
+ * (the normal lookup code would then continue by using the mount
+ * structure to figure out what it was mounted on).
*/
again:
pathlen = 0;
- for (scan = ncp;
- scan && (scan->nc_flag & NCF_MOUNTPT) == 0;
- scan = scan->nc_parent
- ) {
+ for (scan = ncp; scan; scan = scan->nc_parent) {
pathlen += scan->nc_nlen + 1;
}
* Pass 2 - generate the path buffer
*/
index = pathlen;
- for (scan = ncp;
- scan && (scan->nc_flag & NCF_MOUNTPT) == 0;
- scan = scan->nc_parent
- ) {
+ for (scan = ncp; scan; scan = scan->nc_parent) {
if (scan->nc_nlen >= index) {
if (base != buf)
kfree(base, M_TEMP);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_nlookup.c,v 1.19 2006/09/19 16:06:11 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_nlookup.c,v 1.20 2006/10/27 04:56:31 dillon Exp $
*/
/*
* nlookup() is the 'new' namei interface. Rather then return directory and
if (error == 0) {
if (p && p->p_fd) {
- nd->nl_ncp = cache_hold(p->p_fd->fd_ncdir);
- nd->nl_rootncp = cache_hold(p->p_fd->fd_nrdir);
- if (p->p_fd->fd_njdir)
- nd->nl_jailncp = cache_hold(p->p_fd->fd_njdir);
+ cache_copy(&p->p_fd->fd_ncdir, &nd->nl_nch);
+ cache_copy(&p->p_fd->fd_nrdir, &nd->nl_rootnch);
+ if (p->p_fd->fd_njdir.ncp)
+ cache_copy(&p->p_fd->fd_njdir, &nd->nl_jailnch);
nd->nl_cred = crhold(p->p_ucred);
} else {
- nd->nl_ncp = cache_hold(rootncp);
- nd->nl_rootncp = cache_hold(nd->nl_ncp);
- nd->nl_jailncp = cache_hold(nd->nl_ncp);
+ cache_copy(&rootnch, &nd->nl_nch);
+ cache_copy(&nd->nl_nch, &nd->nl_rootnch);
+ cache_copy(&nd->nl_nch, &nd->nl_jailnch);
nd->nl_cred = crhold(proc0.p_ucred);
}
nd->nl_td = td;
/*
* This works similarly to nlookup_init() but does not assume a process
- * context. rootncp is always chosen for the root directory and the cred
+ * context. rootnch is always chosen for the root directory and the cred
* and starting directory are supplied in arguments.
*/
int
nlookup_init_raw(struct nlookupdata *nd,
const char *path, enum uio_seg seg, int flags,
- struct ucred *cred, struct namecache *ncstart)
+ struct ucred *cred, struct nchandle *ncstart)
{
size_t pathlen;
thread_t td;
error = ENOENT;
if (error == 0) {
- nd->nl_ncp = cache_hold(ncstart);
- nd->nl_rootncp = cache_hold(rootncp);
- nd->nl_jailncp = cache_hold(rootncp);
+ cache_copy(ncstart, &nd->nl_nch);
+ cache_copy(&rootnch, &nd->nl_rootnch);
+ cache_copy(&rootnch, &nd->nl_jailnch);
nd->nl_cred = crhold(cred);
nd->nl_td = td;
nd->nl_flags |= flags;
void
nlookup_done(struct nlookupdata *nd)
{
- if (nd->nl_ncp) {
+ if (nd->nl_nch.ncp) {
if (nd->nl_flags & NLC_NCPISLOCKED) {
nd->nl_flags &= ~NLC_NCPISLOCKED;
- cache_unlock(nd->nl_ncp);
+ cache_unlock(&nd->nl_nch);
}
- cache_drop(nd->nl_ncp);
- nd->nl_ncp = NULL;
- }
- if (nd->nl_rootncp) {
- cache_drop(nd->nl_rootncp);
- nd->nl_rootncp = NULL;
- }
- if (nd->nl_jailncp) {
- cache_drop(nd->nl_jailncp);
- nd->nl_jailncp = NULL;
+ cache_drop(&nd->nl_nch);
}
+ if (nd->nl_rootnch.ncp)
+ cache_drop(&nd->nl_rootnch);
+ if (nd->nl_jailnch.ncp)
+ cache_drop(&nd->nl_jailnch);
if ((nd->nl_flags & NLC_HASBUF) && nd->nl_path) {
objcache_put(namei_oc, nd->nl_path);
nd->nl_path = NULL;
* is checked on the directory path leading up to the result. The caller
* must call naccess() to check the permissions of the returned leaf.
*/
-struct namecache *
+struct nchandle
nlookup_simple(const char *str, enum uio_seg seg,
int niflags, int *error)
{
struct nlookupdata nd;
- struct namecache *ncp;
+ struct nchandle nch;
*error = nlookup_init(&nd, str, seg, niflags);
if (*error == 0) {
if ((*error = nlookup(&nd)) == 0) {
- ncp = nd.nl_ncp; /* keep hold ref from structure */
- nd.nl_ncp = NULL; /* and NULL out */
+ nch = nd.nl_nch; /* keep hold ref from structure */
+ cache_zero(&nd.nl_nch); /* and NULL out */
} else {
- ncp = NULL;
+ cache_zero(&nch);
}
nlookup_done(&nd);
} else {
- ncp = NULL;
+ cache_zero(&nch);
}
- return(ncp);
+ return(nch);
}
/*
* Do a generic nlookup. Note that the passed nd is not nlookup_done()'d
* on return, even if an error occurs. If no error occurs the returned
- * nl_ncp is always referenced and locked, otherwise it may or may not be.
+ * nl_nch is always referenced and locked, otherwise it may or may not be.
*
* Intermediate directory elements, including the current directory, require
* execute (search) permission. nlookup does not examine the access
nlookup(struct nlookupdata *nd)
{
struct nlcomponent nlc;
- struct namecache *ncp;
+ struct nchandle nch;
+ struct mount *mp;
int wasdotordotdot;
char *ptr;
char *xptr;
* Setup for the loop. The current working namecache element must
* be in a refd + unlocked state. This typically the case on entry except
* when stringing nlookup()'s along in a chain, since nlookup() always
- * returns nl_ncp in a locked state.
+ * returns nl_nch in a locked state.
*/
nd->nl_loopcnt = 0;
if (nd->nl_flags & NLC_NCPISLOCKED) {
nd->nl_flags &= ~NLC_NCPISLOCKED;
- cache_unlock(nd->nl_ncp);
+ cache_unlock(&nd->nl_nch);
}
ptr = nd->nl_path;
/*
- * Loop on the path components. At the top of the loop nd->nl_ncp
+ * Loop on the path components. At the top of the loop nd->nl_nch
* is ref'd and unlocked and represents our current position.
*/
for (;;) {
do {
++ptr;
} while (*ptr == '/');
- ncp = cache_hold(nd->nl_rootncp);
- cache_drop(nd->nl_ncp);
- nd->nl_ncp = ncp;
+ cache_copy(&nd->nl_rootnch, &nch);
+ cache_drop(&nd->nl_nch);
+ nd->nl_nch = nch;
if (*ptr == 0) {
- cache_lock(nd->nl_ncp);
+ cache_lock(&nd->nl_nch);
nd->nl_flags |= NLC_NCPISLOCKED;
error = 0;
break;
}
/*
- * Check directory search permissions
+ * Check directory search permissions.
*/
- if ((error = naccess(nd->nl_ncp, VEXEC, nd->nl_cred)) != 0)
+ if ((error = naccess(&nd->nl_nch, VEXEC, nd->nl_cred)) != 0)
break;
/*
* cases.
*
* When handling ".." we have to detect a traversal back through a
- * mount point and skip the mount-under node. If we are at the root
- * ".." just returns the root.
+ * mount point. If we are at the root, ".." just returns the root.
*
- * This subsection returns a locked, refd 'ncp' unless it errors out.
+ * This subsection returns a locked, refd 'nch' unless it errors out.
* The namecache topology is not allowed to be disconnected, so
* encountering a NULL parent will generate EINVAL. This typically
* occurs when a directory is removed out from under a process.
* of a path.
*/
if (nlc.nlc_namelen == 1 && nlc.nlc_nameptr[0] == '.') {
- ncp = cache_get(nd->nl_ncp);
+ cache_get(&nd->nl_nch, &nch);
wasdotordotdot = 1;
} else if (nlc.nlc_namelen == 2 &&
nlc.nlc_nameptr[0] == '.' && nlc.nlc_nameptr[1] == '.') {
- ncp = nd->nl_ncp;
- if (ncp == nd->nl_rootncp) {
- ncp = cache_get(ncp);
+ if (nd->nl_nch.mount == nd->nl_rootnch.mount &&
+ nd->nl_nch.ncp == nd->nl_rootnch.ncp
+ ) {
+ /*
+ * ".." at the root returns the root
+ */
+ cache_get(&nd->nl_nch, &nch);
} else {
- while ((ncp->nc_flag & NCF_MOUNTPT) && ncp != nd->nl_rootncp) {
- if (ncp->nc_parent->nc_flag & NCF_DESTROYED)
- break;
- ncp = ncp->nc_parent; /* get to underlying node */
- KKASSERT(ncp != NULL && 1);
- }
- if (ncp != nd->nl_rootncp) {
- if (ncp->nc_parent->nc_flag & NCF_DESTROYED) {
- error = EINVAL;
- break;
- }
- ncp = ncp->nc_parent;
- if (ncp == NULL) {
- error = EINVAL;
- break;
- }
- }
- ncp = cache_get(ncp);
+ /*
+ * Locate the parent ncp. If we are at the root of a
+ * filesystem mount we have to skip to the mounted-on
+ * point in the underlying filesystem.
+ */
+ nch = nd->nl_nch;
+ while (nch.ncp == nch.mount->mnt_ncmountpt.ncp)
+ nch = nd->nl_nch.mount->mnt_ncmounton;
+ nch.ncp = nch.ncp->nc_parent;
+ KKASSERT(nch.ncp != NULL);
+ cache_get(&nch, &nch);
}
wasdotordotdot = 1;
} else {
- ncp = cache_nlookup(nd->nl_ncp, &nlc);
- while ((error = cache_resolve(ncp, nd->nl_cred)) == EAGAIN) {
+ nch = cache_nlookup(&nd->nl_nch, &nlc);
+ while ((error = cache_resolve(&nch, nd->nl_cred)) == EAGAIN) {
printf("[diagnostic] nlookup: relookup %*.*s\n",
- ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name);
- cache_put(ncp);
- ncp = cache_nlookup(nd->nl_ncp, &nlc);
+ nch.ncp->nc_nlen, nch.ncp->nc_nlen, nch.ncp->nc_name);
+ cache_put(&nch);
+ nch = cache_nlookup(&nd->nl_nch, &nlc);
}
wasdotordotdot = 0;
}
/*
- * [end of subsection] ncp is locked and ref'd. nd->nl_ncp is ref'd
+ * [end of subsection] ncp is locked and ref'd. nd->nl_nch is ref'd
*/
/*
* XXX neither '.' nor '..' should return EAGAIN since they were
* previously resolved and thus cannot be newly created ncp's.
*/
- if (ncp->nc_flag & NCF_UNRESOLVED) {
- error = cache_resolve(ncp, nd->nl_cred);
+ if (nch.ncp->nc_flag & NCF_UNRESOLVED) {
+ error = cache_resolve(&nch, nd->nl_cred);
KKASSERT(error != EAGAIN);
} else {
- error = ncp->nc_error;
+ error = nch.ncp->nc_error;
}
/*
;
if (*xptr == 0) {
if (error == ENOENT && (nd->nl_flags & NLC_CREATE))
- error = naccess(ncp, VCREATE, nd->nl_cred);
+ error = naccess(&nch, VCREATE, nd->nl_cred);
if (error == 0 && wasdotordotdot && (nd->nl_flags & NLC_DELETE))
error = EINVAL;
}
* Early completion on error.
*/
if (error) {
- cache_put(ncp);
+ cache_put(&nch);
break;
}
* element or it is the last element and we are allowed to
* follow symlinks, resolve the symlink.
*/
- if ((ncp->nc_flag & NCF_ISSYMLINK) &&
+ if ((nch.ncp->nc_flag & NCF_ISSYMLINK) &&
(*ptr || (nd->nl_flags & NLC_FOLLOW))
) {
if (nd->nl_loopcnt++ >= MAXSYMLINKS) {
error = ELOOP;
- cache_put(ncp);
+ cache_put(&nch);
break;
}
- error = nreadsymlink(nd, ncp, &nlc);
- cache_put(ncp);
+ error = nreadsymlink(nd, &nch, &nlc);
+ cache_put(&nch);
if (error)
break;
/*
* If the element is a directory and we are crossing a mount point,
- * retrieve the root of the mounted filesystem from mnt_ncp and
- * resolve it if necessary.
- *
- * XXX mnt_ncp should really be resolved in the mount code.
- * NOTE! the normal nresolve() code cannot resolve mount point ncp's!
- *
- * XXX NOCROSSMOUNT
+ * Locate the mount.
*/
- while ((ncp->nc_flag & NCF_ISDIR) && (ncp->nc_flag & NCF_MOUNTEDHERE)
- && (nd->nl_flags & NLC_NOCROSSMOUNT) == 0
+ while ((nch.ncp->nc_flag & NCF_ISMOUNTPT) &&
+ (nd->nl_flags & NLC_NOCROSSMOUNT) == 0 &&
+ (mp = cache_findmount(&nch)) != NULL
) {
- struct mount *mp;
struct vnode *tdp;
- if ((mp = cache_findmount(ncp)) == NULL) {
- printf("warning: nlookup(): ncp marked as a mount point which isn't one at %p %s\n", ncp, ncp->nc_name);
- ncp->nc_flag &= ~NCF_MOUNTEDHERE;
- break;
- }
- cache_put(ncp);
- ncp = cache_get(mp->mnt_ncp);
+ cache_put(&nch);
+ cache_get(&mp->mnt_ncmountpt, &nch);
- if (ncp->nc_flag & NCF_UNRESOLVED) {
+ if (nch.ncp->nc_flag & NCF_UNRESOLVED) {
while (vfs_busy(mp, 0))
;
error = VFS_ROOT(mp, &tdp);
vfs_unbusy(mp);
if (error)
break;
- cache_setvp(ncp, tdp);
+ cache_setvp(&nch, tdp);
vput(tdp);
}
}
if (error) {
- cache_put(ncp);
+ cache_put(&nch);
break;
}
* to the failure case below.
*/
while (*ptr == '/') {
- if ((ncp->nc_flag & NCF_ISDIR) == 0 &&
+ if ((nch.ncp->nc_flag & NCF_ISDIR) == 0 &&
!(nd->nl_flags & NLC_WILLBEDIR)
) {
break;
* Continuation case: additional elements and the current
* element is a directory.
*/
- if (*ptr && (ncp->nc_flag & NCF_ISDIR)) {
- cache_drop(nd->nl_ncp);
- cache_unlock(ncp);
- nd->nl_ncp = ncp;
+ if (*ptr && (nch.ncp->nc_flag & NCF_ISDIR)) {
+ cache_drop(&nd->nl_nch);
+ cache_unlock(&nch);
+ nd->nl_nch = nch;
continue;
}
* is not a directory
*/
if (*ptr) {
- cache_put(ncp);
+ cache_put(&nch);
error = ENOTDIR;
break;
}
* Check directory permissions if a deletion is specified.
*/
if (*ptr == 0 && (nd->nl_flags & NLC_DELETE)) {
- if ((error = naccess(ncp, VDELETE, nd->nl_cred)) != 0) {
- cache_put(ncp);
+ if ((error = naccess(&nch, VDELETE, nd->nl_cred)) != 0) {
+ cache_put(&nch);
break;
}
}
* ncp may represent a negative hit (ncp->nc_error will be ENOENT),
* but we still return an error code of 0.
*/
- cache_drop(nd->nl_ncp);
- nd->nl_ncp = ncp;
+ cache_drop(&nd->nl_nch);
+ nd->nl_nch = nch;
nd->nl_flags |= NLC_NCPISLOCKED;
error = 0;
break;
* If no error occured a locked, ref'd ncp is stored in *ncpp.
*/
int
-nlookup_mp(struct mount *mp, struct namecache **ncpp)
+nlookup_mp(struct mount *mp, struct nchandle *nch)
{
- struct namecache *ncp;
struct vnode *vp;
int error;
error = 0;
- ncp = mp->mnt_ncp;
- cache_get(ncp);
- if (ncp->nc_flag & NCF_UNRESOLVED) {
+ cache_get(&mp->mnt_ncmountpt, nch);
+ if (nch->ncp->nc_flag & NCF_UNRESOLVED) {
while (vfs_busy(mp, 0))
;
error = VFS_ROOT(mp, &vp);
vfs_unbusy(mp);
if (error) {
- cache_put(ncp);
- ncp = NULL;
+ cache_put(nch);
} else {
- cache_setvp(ncp, vp);
+ cache_setvp(nch, vp);
vput(vp);
}
}
- *ncpp = ncp;
return(error);
}
* If an error occurs no buffer will be allocated or returned in the nlc.
*/
int
-nreadsymlink(struct nlookupdata *nd, struct namecache *ncp,
+nreadsymlink(struct nlookupdata *nd, struct nchandle *nch,
struct nlcomponent *nlc)
{
struct vnode *vp;
nlc->nlc_nameptr = NULL;
nlc->nlc_namelen = 0;
- if (ncp->nc_vp == NULL)
+ if (nch->ncp->nc_vp == NULL)
return(ENOENT);
- if ((error = cache_vget(ncp, nd->nl_cred, LK_SHARED, &vp)) != 0)
+ if ((error = cache_vget(nch, nd->nl_cred, LK_SHARED, &vp)) != 0)
return(error);
cp = objcache_get(namei_oc, M_WAITOK);
aiov.iov_base = cp;
* checks.
*/
int
-naccess(struct namecache *ncp, int vmode, struct ucred *cred)
+naccess(struct nchandle *nch, int vmode, struct ucred *cred)
{
- struct namecache *par;
+ struct nchandle par;
struct vnode *vp;
struct vattr va;
int error;
- if (ncp->nc_flag & NCF_UNRESOLVED) {
- cache_lock(ncp);
- cache_resolve(ncp, cred);
- cache_unlock(ncp);
+ if (nch->ncp->nc_flag & NCF_UNRESOLVED) {
+ cache_lock(nch);
+ cache_resolve(nch, cred);
+ cache_unlock(nch);
}
- error = ncp->nc_error;
+ error = nch->ncp->nc_error;
if (vmode & (VDELETE|VCREATE|VEXCL)) {
- if (((vmode & VCREATE) && ncp->nc_vp == NULL) ||
- ((vmode & VDELETE) && ncp->nc_vp != NULL)
+ if (((vmode & VCREATE) && nch->ncp->nc_vp == NULL) ||
+ ((vmode & VDELETE) && nch->ncp->nc_vp != NULL)
) {
- if ((par = ncp->nc_parent) == NULL) {
+ if ((par.ncp = nch->ncp->nc_parent) == NULL) {
if (error != EAGAIN)
error = EINVAL;
} else {
- cache_hold(par);
- error = naccess(par, VWRITE, cred);
- cache_drop(par);
+ par.mount = nch->mount;
+ cache_hold(&par);
+ error = naccess(&par, VWRITE, cred);
+ cache_drop(&par);
}
}
- if ((vmode & VEXCL) && ncp->nc_vp != NULL)
+ if ((vmode & VEXCL) && nch->ncp->nc_vp != NULL)
error = EEXIST;
}
if (error == 0) {
- error = cache_vget(ncp, cred, LK_SHARED, &vp);
+ error = cache_vget(nch, cred, LK_SHARED, &vp);
if (error == ENOENT) {
if (vmode & VCREATE)
error = 0;
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
* $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.106 2006/09/19 18:17:46 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.107 2006/10/27 04:56:31 dillon Exp $
*/
#include <sys/param.h>
#include <sys/spinlock.h>
#include <sys/kern_syscall.h>
#include <sys/objcache.h>
-
-#include <machine/limits.h>
-#include <vfs/union/union.h>
#include <sys/sysctl.h>
+#include <sys/file2.h>
+#include <sys/spinlock2.h>
+
#include <vm/vm.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
-#include <sys/file2.h>
-#include <sys/spinlock2.h>
+#include <machine/limits.h>
+#include <machine/stdarg.h>
+
+#include <vfs/union/union.h>
+static void mount_warning(struct mount *mp, const char *ctl, ...);
static int checkvp_chdir (struct vnode *vn, struct thread *td);
-static void checkdirs (struct vnode *olddp, struct namecache *ncp);
+static void checkdirs (struct vnode *olddp, struct nchandle *nch);
static int chroot_refuse_vdir_fds (struct filedesc *fdp);
static int chroot_visible_mnt(struct mount *mp, struct proc *p);
static int getutimes (const struct timeval *, struct timespec *);
struct thread *td = curthread;
struct proc *p = td->td_proc;
struct vnode *vp;
- struct namecache *ncp;
+ struct nchandle nch;
struct mount *mp;
struct vfsconf *vfsp;
int error, flag = 0, flag2 = 0;
struct vattr va;
struct nlookupdata nd;
char fstypename[MFSNAMELEN];
- struct nlcomponent nlc;
struct ucred *cred = p->p_ucred;
KKASSERT(p);
uap->flags |= MNT_NOSUID | MNT_NODEV;
/*
- * Lookup the requested path and extract the ncp and vnode.
+ * Lookup the requested path and extract the nch and vnode.
*/
error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
if (error == 0) {
if ((error = nlookup(&nd)) == 0) {
- if (nd.nl_ncp->nc_vp == NULL)
+ if (nd.nl_nch.ncp->nc_vp == NULL)
error = ENOENT;
}
}
/*
* Extract the locked+refd ncp and cleanup the nd structure
*/
- ncp = nd.nl_ncp;
- nd.nl_ncp = NULL;
+ nch = nd.nl_nch;
+ cache_zero(&nd.nl_nch);
nlookup_done(&nd);
- if ((ncp->nc_flag & NCF_MOUNTEDHERE) && cache_findmount(ncp))
+ if ((nch.ncp->nc_flag & NCF_ISMOUNTPT) && cache_findmount(&nch))
hasmount = 1;
else
hasmount = 0;
/*
- * now we have the locked ref'd ncp and unreferenced vnode.
+ * now we have the locked ref'd nch and unreferenced vnode.
*/
- vp = ncp->nc_vp;
+ vp = nch.ncp->nc_vp;
if ((error = vget(vp, LK_EXCLUSIVE)) != 0) {
- cache_put(ncp);
+ cache_put(&nch);
return (error);
}
- cache_unlock(ncp);
+ cache_unlock(&nch);
/*
- * Now we have an unlocked ref'd ncp and a locked ref'd vp
+ * Now we have an unlocked ref'd nch and a locked ref'd vp
*/
if (uap->flags & MNT_UPDATE) {
if ((vp->v_flag & VROOT) == 0) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (EINVAL);
}
*/
if ((uap->flags & MNT_RELOAD) &&
((mp->mnt_flag & MNT_RDONLY) == 0)) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (EOPNOTSUPP); /* Needs translation */
}
*/
if (mp->mnt_stat.f_owner != cred->cr_uid &&
(error = suser(td))) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (error);
}
if (vfs_busy(mp, LK_NOWAIT)) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (EBUSY);
}
if ((vp->v_flag & VMOUNT) != 0 || hasmount) {
- cache_drop(ncp);
+ cache_drop(&nch);
vfs_unbusy(mp);
vput(vp);
return (EBUSY);
*/
if ((error = VOP_GETATTR(vp, &va)) ||
(va.va_uid != cred->cr_uid && (error = suser(td)))) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (error);
}
if ((error = vinvalbuf(vp, V_SAVE, 0, 0)) != 0) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (error);
}
if (vp->v_type != VDIR) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (ENOTDIR);
}
if ((error = copyinstr(uap->type, fstypename, MFSNAMELEN, NULL)) != 0) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (error);
}
/* Only load modules for root (very important!) */
if ((error = suser(td)) != 0) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return error;
}
error = linker_load_file(fstypename, &lf);
if (error || lf == NULL) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
if (lf == NULL)
error = ENODEV;
if (vfsp == NULL) {
lf->userrefs--;
linker_file_unload(lf);
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (ENODEV);
}
}
if ((vp->v_flag & VMOUNT) != 0 || hasmount) {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
return (EBUSY);
}
vfs_unbusy(mp);
vp->v_flag &= ~VMOUNT;
vrele(vp);
- cache_drop(ncp);
+ cache_drop(&nch);
return (error);
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
/*
* Put the new filesystem on the mount list after root. The mount
- * point gets its own mnt_ncp which is a special ncp linking the
- * vnode-under to the root of the new mount. The lookup code
- * detects the mount point going forward and detects the special
- * mnt_ncp via NCP_MOUNTPT going backwards.
+ * point gets its own mnt_ncmountpt (unless the VFS already set one
+ * up) which represents the root of the mount. The lookup code
+ * detects the mount point going forward and checks the root of
+ * the mount going backwards.
*
* It is not necessary to invalidate or purge the vnode underneath
* because elements under the mount will be given their own glue
* namecache record.
*/
if (!error) {
- nlc.nlc_nameptr = "";
- nlc.nlc_namelen = 0;
- mp->mnt_ncp = cache_nlookup(ncp, &nlc);
- cache_setunresolved(mp->mnt_ncp);
- cache_setmountpt(mp->mnt_ncp, mp);
- cache_drop(ncp);
- /* XXX get the root of the fs and cache_setvp(mnt_ncp...) */
+ if (mp->mnt_ncmountpt.ncp == NULL) {
+ /*
+ * allocate, then unlock, but leave the ref intact
+ */
+ cache_allocroot(&mp->mnt_ncmountpt, mp, NULL);
+ cache_unlock(&mp->mnt_ncmountpt);
+ }
+ mp->mnt_ncmounton = nch; /* inherits ref */
+ nch.ncp->nc_flag |= NCF_ISMOUNTPT;
+
+ /* XXX get the root of the fs and cache_setvp(mnt_ncmountpt...) */
vp->v_flag &= ~VMOUNT;
mountlist_insert(mp, MNTINS_LAST);
- checkdirs(vp, mp->mnt_ncp);
- cache_unlock(mp->mnt_ncp); /* leave ref intact */
+ checkdirs(vp, &mp->mnt_ncmounton);
vn_unlock(vp);
error = vfs_allocate_syncvnode(mp);
vfs_unbusy(mp);
mp->mnt_vfc->vfc_refcount--;
vfs_unbusy(mp);
kfree(mp, M_MOUNT);
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
}
return (error);
struct checkdirs_info {
struct vnode *olddp;
struct vnode *newdp;
- struct namecache *ncp;
+ struct nchandle nch;
};
static int checkdirs_callback(struct proc *p, void *data);
static void
-checkdirs(struct vnode *olddp, struct namecache *ncp)
+checkdirs(struct vnode *olddp, struct nchandle *nch)
{
struct checkdirs_info info;
struct vnode *newdp;
if (olddp->v_usecount == 1)
return;
- mp = ncp->nc_mount;
+ mp = nch->mount;
if (VFS_ROOT(mp, &newdp))
panic("mount: lost mount");
- cache_setvp(ncp, newdp);
+ cache_setvp(nch, newdp);
if (rootvnode == olddp) {
vref(newdp);
- vfs_cache_setroot(newdp, cache_hold(ncp));
+ vfs_cache_setroot(newdp, cache_hold(nch));
}
info.olddp = olddp;
info.newdp = newdp;
- info.ncp = ncp;
+ info.nch = *nch;
allproc_scan(checkdirs_callback, &info);
vput(newdp);
}
{
struct checkdirs_info *info = data;
struct filedesc *fdp;
- struct namecache *ncdrop1;
- struct namecache *ncdrop2;
+ struct nchandle ncdrop1;
+ struct nchandle ncdrop2;
struct vnode *vprele1;
struct vnode *vprele2;
if ((fdp = p->p_fd) != NULL) {
- ncdrop1 = NULL;
- ncdrop2 = NULL;
+ cache_zero(&ncdrop1);
+ cache_zero(&ncdrop2);
vprele1 = NULL;
vprele2 = NULL;
vref(info->newdp);
fdp->fd_cdir = info->newdp;
ncdrop1 = fdp->fd_ncdir;
- fdp->fd_ncdir = cache_hold(info->ncp);
+ cache_copy(&info->nch, &fdp->fd_ncdir);
}
if (fdp->fd_rdir == info->olddp) {
vprele2 = fdp->fd_rdir;
vref(info->newdp);
fdp->fd_rdir = info->newdp;
ncdrop2 = fdp->fd_nrdir;
- fdp->fd_nrdir = cache_hold(info->ncp);
+ cache_copy(&info->nch, &fdp->fd_nrdir);
}
spin_unlock_wr(&fdp->fd_spin);
- if (ncdrop1)
- cache_drop(ncdrop1);
- if (ncdrop2)
- cache_drop(ncdrop2);
+ if (ncdrop1.ncp)
+ cache_drop(&ncdrop1);
+ if (ncdrop2.ncp)
+ cache_drop(&ncdrop2);
if (vprele1)
vrele(vprele1);
if (vprele2)
if (error)
goto out;
- mp = nd.nl_ncp->nc_mount;
+ mp = nd.nl_nch.mount;
/*
* Only root, or the user that did the original mount is
/*
* Must be the root of the filesystem
*/
- if (!(nd.nl_ncp->nc_flag & NCF_MOUNTPT)) {
+ if (nd.nl_nch.ncp != mp->mnt_ncmountpt.ncp) {
error = EINVAL;
goto out;
}
dounmount(struct mount *mp, int flags)
{
struct namecache *ncp;
+ struct nchandle nch;
int error;
int async_flag;
int lflags;
+ int freeok = 1;
/*
* Exclusive access for unmounting purposes
mp->mnt_flag &=~ MNT_ASYNC;
/*
- * remove cache entries for this file sys and determine if anyone
- * other then us is still holding onto any namecache references.
- *
- * XXX need separate ref counter on mount structure to delay
- * kfree()ing it.
+ * If this filesystem isn't aliasing other filesystems,
+ * try to invalidate any remaining namecache entries and
+ * check the count afterwords.
*/
- cache_purgevfs(mp);
- if ((ncp = mp->mnt_ncp) != NULL) {
- if (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list)) {
- char *ptr;
- char *buf;
+ if ((mp->mnt_kern_flag & MNTK_NCALIASED) == 0) {
+ cache_lock(&mp->mnt_ncmountpt);
+ cache_inval(&mp->mnt_ncmountpt, CINV_DESTROY|CINV_CHILDREN);
+ cache_unlock(&mp->mnt_ncmountpt);
+
+ if ((ncp = mp->mnt_ncmountpt.ncp) != NULL &&
+ (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list))) {
if ((flags & MNT_FORCE) == 0) {
error = EBUSY;
- } else if (cache_fullpath(NULL, ncp, &ptr, &buf)) {
- printf("Warning: forced unmount - "
- "namecache references still present\n");
+ mount_warning(mp, "Cannot unmount: "
+ "%d namecache "
+ "references still "
+ "present",
+ ncp->nc_refs - 1);
} else {
- printf("Warning: forced unmount of %s - "
- "namecache references still present\n",
- ptr
- );
- kfree(buf, M_TEMP);
+ mount_warning(mp, "Forced unmount: "
+ "%d namecache "
+ "references still "
+ "present",
+ ncp->nc_refs - 1);
+ freeok = 0;
}
}
}
+ /*
+ * nchandle records ref the mount structure. Expect a count of 1
+ * (our mount->mnt_ncmountpt).
+ */
+ if (mp->mnt_refs != 1) {
+ if ((flags & MNT_FORCE) == 0) {
+ mount_warning(mp, "Cannot unmount: "
+ "%d process references still "
+ "present", mp->mnt_refs);
+ error = EBUSY;
+ } else {
+ mount_warning(mp, "Forced unmount: "
+ "%d process references still "
+ "present", mp->mnt_refs);
+ freeok = 0;
+ }
+ }
+
if (error == 0) {
if (mp->mnt_syncer != NULL)
vrele(mp->mnt_syncer);
vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_spec_ops);
vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_fifo_ops);
- if ((ncp = mp->mnt_ncp) != NULL) {
- cache_clrmountpt(ncp);
- cache_drop(ncp);
- mp->mnt_ncp = NULL;
+ if (mp->mnt_ncmountpt.ncp != NULL) {
+ nch = mp->mnt_ncmountpt;
+ cache_zero(&mp->mnt_ncmountpt);
+ cache_clrmountpt(&nch);
+ cache_drop(&nch);
+ }
+ if (mp->mnt_ncmounton.ncp != NULL) {
+ nch = mp->mnt_ncmounton;
+ cache_zero(&mp->mnt_ncmounton);
+ cache_clrmountpt(&nch);
+ cache_drop(&nch);
}
mp->mnt_vfc->vfc_refcount--;
lockmgr(&mp->mnt_lock, LK_RELEASE);
if (mp->mnt_kern_flag & MNTK_MWAIT)
wakeup(mp);
- kfree(mp, M_MOUNT);
+ if (freeok)
+ kfree(mp, M_MOUNT);
return (0);
}
+static
+void
+mount_warning(struct mount *mp, const char *ctl, ...)
+{
+ char *ptr;
+ char *buf;
+ __va_list va;
+
+ __va_start(va, ctl);
+ if (cache_fullpath(NULL, &mp->mnt_ncmounton, &ptr, &buf) == 0) {
+ printf("unmount(%s): ", ptr);
+ vprintf(ctl, va);
+ printf("\n");
+ kfree(buf, M_TEMP);
+ } else {
+ printf("unmount(%p): ", mp);
+ vprintf(ctl, va);
+ printf("\n");
+ }
+ __va_end(va);
+}
+
/*
* Sync each mounted filesystem.
*/
if (error == 0)
error = nlookup(&nd);
if (error == 0) {
- mp = nd.nl_ncp->nc_mount;
+ mp = nd.nl_nch.mount;
error = VFS_QUOTACTL(mp, uap->cmd, uap->uid,
uap->arg, nd.nl_cred);
}
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
nlookup_done(&nd);
if (error)
return (error);
if ((error = nlookup(nd)) != 0)
return (error);
- mp = nd->nl_ncp->nc_mount;
+ mp = nd->nl_nch.mount;
sp = &mp->mnt_stat;
if ((error = VFS_STATFS(mp, sp, nd->nl_cred)) != 0)
return (error);
- error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath);
+ error = cache_fullpath(p, &mp->mnt_ncmountpt, &fullpath, &freepath);
if (error)
return(error);
bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
if ((error = VFS_STATFS(mp, sp, fp->f_cred)) != 0)
goto done;
- if ((error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath)) != 0)
+ if ((error = cache_fullpath(p, &mp->mnt_ncmountpt, &fullpath, &freepath)) != 0)
goto done;
bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
long maxcount;
int error;
int flags;
- int is_chrooted;
struct proc *p;
};
struct getfsstat_info info;
bzero(&info, sizeof(info));
- if (p != NULL && (p->p_fd->fd_nrdir->nc_flag & NCF_ROOT) == 0)
- info.is_chrooted = 1;
- else
- info.is_chrooted = 0;
info.maxcount = uap->bufsize / sizeof(struct statfs);
info.sfsp = uap->buf;
int error;
if (info->sfsp && info->count < info->maxcount) {
- if (info->is_chrooted && !chroot_visible_mnt(mp, info->p))
+ if (info->p && !chroot_visible_mnt(mp, info->p))
return(0);
sp = &mp->mnt_stat;
}
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- error = cache_fullpath(info->p, mp->mnt_ncp,
+ error = cache_fullpath(info->p, &mp->mnt_ncmountpt,
&fullpath, &freepath);
if (error) {
info->error = error;
struct vnode *vp, *ovp;
struct mount *mp;
struct file *fp;
- struct namecache *ncp, *oncp;
- struct namecache *nct;
+ struct nchandle nch, onch, tnch;
int error;
if ((error = holdvnode(fdp, uap->fd, &fp)) != 0)
vp = (struct vnode *)fp->f_data;
vref(vp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- if (vp->v_type != VDIR || fp->f_ncp == NULL)
+ if (vp->v_type != VDIR || fp->f_nchandle.ncp == NULL)
error = ENOTDIR;
else
error = VOP_ACCESS(vp, VEXEC, p->p_ucred);
fdrop(fp);
return (error);
}
- ncp = cache_hold(fp->f_ncp);
+ cache_copy(&fp->f_nchandle, &nch);
/*
* If the ncp has become a mount point, traverse through
* the mount point.
*/
- while (!error && (ncp->nc_flag & NCF_MOUNTEDHERE) &&
- (mp = cache_findmount(ncp)) != NULL
+ while (!error && (nch.ncp->nc_flag & NCF_ISMOUNTPT) &&
+ (mp = cache_findmount(&nch)) != NULL
) {
- error = nlookup_mp(mp, &nct);
+ error = nlookup_mp(mp, &tnch);
if (error == 0) {
- cache_unlock(nct); /* leave ref intact */
+ cache_unlock(&tnch); /* leave ref intact */
vput(vp);
- vp = nct->nc_vp;
+ vp = tnch.ncp->nc_vp;
error = vget(vp, LK_SHARED);
KKASSERT(error == 0);
- cache_drop(ncp);
- ncp = nct;
+ cache_drop(&nch);
+ nch = tnch;
}
}
if (error == 0) {
ovp = fdp->fd_cdir;
- oncp = fdp->fd_ncdir;
+ onch = fdp->fd_ncdir;
vn_unlock(vp); /* leave ref intact */
fdp->fd_cdir = vp;
- fdp->fd_ncdir = ncp;
- cache_drop(oncp);
+ fdp->fd_ncdir = nch;
+ cache_drop(&onch);
vrele(ovp);
} else {
- cache_drop(ncp);
+ cache_drop(&nch);
vput(vp);
}
fdrop(fp);
struct proc *p = td->td_proc;
struct filedesc *fdp = p->p_fd;
struct vnode *vp, *ovp;
- struct namecache *oncp;
+ struct nchandle onch;
int error;
if ((error = nlookup(nd)) != 0)
return (error);
- if ((vp = nd->nl_ncp->nc_vp) == NULL)
+ if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
return (ENOENT);
if ((error = vget(vp, LK_SHARED)) != 0)
return (error);
vn_unlock(vp);
if (error == 0) {
ovp = fdp->fd_cdir;
- oncp = fdp->fd_ncdir;
- cache_unlock(nd->nl_ncp); /* leave reference intact */
- fdp->fd_ncdir = nd->nl_ncp;
+ onch = fdp->fd_ncdir;
+ cache_unlock(&nd->nl_nch); /* leave reference intact */
+ fdp->fd_ncdir = nd->nl_nch;
fdp->fd_cdir = vp;
- cache_drop(oncp);
+ cache_drop(&onch);
vrele(ovp);
- nd->nl_ncp = NULL;
+ cache_zero(&nd->nl_nch);
} else {
vrele(vp);
}
* remain locked and referenced on return.
*/
int
-kern_chroot(struct namecache *ncp)
+kern_chroot(struct nchandle *nch)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
if ((error = chroot_refuse_vdir_fds(fdp)) != 0)
return (error);
}
- if ((vp = ncp->nc_vp) == NULL)
+ if ((vp = nch->ncp->nc_vp) == NULL)
return (ENOENT);
if ((error = vget(vp, LK_SHARED)) != 0)
if (error == 0) {
vrele(fdp->fd_rdir);
fdp->fd_rdir = vp; /* reference inherited by fd_rdir */
- cache_drop(fdp->fd_nrdir);
- fdp->fd_nrdir = cache_hold(ncp);
+ cache_drop(&fdp->fd_nrdir);
+ cache_copy(nch, &fdp->fd_nrdir);
if (fdp->fd_jdir == NULL) {
fdp->fd_jdir = vp;
vref(fdp->fd_jdir);
- fdp->fd_njdir = cache_hold(ncp);
+ cache_copy(nch, &fdp->fd_njdir);
}
} else {
vrele(vp);
}
error = nlookup(&nd);
if (error == 0)
- error = kern_chroot(nd.nl_ncp);
+ error = kern_chroot(&nd.nl_nch);
nlookup_done(&nd);
return(error);
}
int
kern_mknod(struct nlookupdata *nd, int mode, int dev)
{
- struct namecache *ncp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
struct vnode *vp;
nd->nl_flags |= NLC_CREATE;
if ((error = nlookup(nd)) != 0)
return (error);
- ncp = nd->nl_ncp;
- if (ncp->nc_vp)
+ if (nd->nl_nch.ncp->nc_vp)
return (EEXIST);
- if ((error = ncp_writechk(ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
VATTR_NULL(&vattr);
}
if (error == 0) {
if (whiteout) {
- error = VOP_NWHITEOUT(ncp, nd->nl_cred, NAMEI_CREATE);
+ error = VOP_NWHITEOUT(&nd->nl_nch, nd->nl_cred, NAMEI_CREATE);
} else {
vp = NULL;
- error = VOP_NMKNOD(ncp, &vp, nd->nl_cred, &vattr);
+ error = VOP_NMKNOD(&nd->nl_nch, &vp, nd->nl_cred, &vattr);
if (error == 0)
vput(vp);
}
int
kern_mkfifo(struct nlookupdata *nd, int mode)
{
- struct namecache *ncp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
struct vattr vattr;
nd->nl_flags |= NLC_CREATE;
if ((error = nlookup(nd)) != 0)
return (error);
- ncp = nd->nl_ncp;
- if (ncp->nc_vp)
+ if (nd->nl_nch.ncp->nc_vp)
return (EEXIST);
- if ((error = ncp_writechk(ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
VATTR_NULL(&vattr);
vattr.va_type = VFIFO;
vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
vp = NULL;
- error = VOP_NMKNOD(ncp, &vp, nd->nl_cred, &vattr);
+ error = VOP_NMKNOD(&nd->nl_nch, &vp, nd->nl_cred, &vattr);
if (error == 0)
vput(vp);
return (error);
bwillwrite();
if ((error = nlookup(nd)) != 0)
return (error);
- vp = nd->nl_ncp->nc_vp;
+ vp = nd->nl_nch.ncp->nc_vp;
KKASSERT(vp != NULL);
if (vp->v_type == VDIR)
return (EPERM); /* POSIX */
- if ((error = ncp_writechk(nd->nl_ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
if ((error = vget(vp, LK_EXCLUSIVE)) != 0)
return (error);
*/
KKASSERT(nd->nl_flags & NLC_NCPISLOCKED);
nd->nl_flags &= ~NLC_NCPISLOCKED;
- cache_unlock(nd->nl_ncp);
+ cache_unlock(&nd->nl_nch);
linknd->nl_flags |= NLC_CREATE;
if ((error = nlookup(linknd)) != 0) {
vput(vp);
return (error);
}
- if (linknd->nl_ncp->nc_vp) {
+ if (linknd->nl_nch.ncp->nc_vp) {
vput(vp);
return (EEXIST);
}
*/
error = can_hardlink(vp, td, td->td_proc->p_ucred);
if (error == 0)
- error = VOP_NLINK(linknd->nl_ncp, vp, linknd->nl_cred);
+ error = VOP_NLINK(&linknd->nl_nch, vp, linknd->nl_cred);
vput(vp);
return (error);
}
int
kern_symlink(struct nlookupdata *nd, char *path, int mode)
{
- struct namecache *ncp;
struct vattr vattr;
struct vnode *vp;
int error;
nd->nl_flags |= NLC_CREATE;
if ((error = nlookup(nd)) != 0)
return (error);
- ncp = nd->nl_ncp;
- if (ncp->nc_vp)
+ if (nd->nl_nch.ncp->nc_vp)
return (EEXIST);
- if ((error = ncp_writechk(ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
VATTR_NULL(&vattr);
vattr.va_mode = mode;
- error = VOP_NSYMLINK(ncp, &vp, nd->nl_cred, &vattr, path);
+ error = VOP_NSYMLINK(&nd->nl_nch, &vp, nd->nl_cred, &vattr, path);
if (error == 0)
vput(vp);
return (error);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = ncp_writechk(nd.nl_ncp);
+ error = ncp_writechk(&nd.nl_nch);
if (error == 0)
- error = VOP_NWHITEOUT(nd.nl_ncp, nd.nl_cred, NAMEI_DELETE);
+ error = VOP_NWHITEOUT(&nd.nl_nch, nd.nl_cred, NAMEI_DELETE);
nlookup_done(&nd);
return (error);
}
int
kern_unlink(struct nlookupdata *nd)
{
- struct namecache *ncp;
int error;
bwillwrite();
nd->nl_flags |= NLC_DELETE;
if ((error = nlookup(nd)) != 0)
return (error);
- ncp = nd->nl_ncp;
- if ((error = ncp_writechk(ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
- error = VOP_NREMOVE(ncp, nd->nl_cred);
+ error = VOP_NREMOVE(&nd->nl_nch, nd->nl_cred);
return (error);
}
if ((error = nlookup(nd)) != 0)
return (error);
retry:
- error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &vp);
if (error)
return (error);
if (aflags & X_OK)
flags |= VEXEC;
if ((flags & VWRITE) == 0 ||
- (error = vn_writechk(vp, nd->nl_ncp)) == 0)
+ (error = vn_writechk(vp, &nd->nl_nch)) == 0)
error = VOP_ACCESS(vp, flags, nd->nl_cred);
/*
* entry. This is a hack at the moment.
*/
if (error == ESTALE) {
- cache_setunresolved(nd->nl_ncp);
- error = cache_resolve(nd->nl_ncp, nd->nl_cred);
+ cache_setunresolved(&nd->nl_nch);
+ error = cache_resolve(&nd->nl_nch, nd->nl_cred);
if (error == 0) {
vput(vp);
vp = NULL;
if ((error = nlookup(nd)) != 0)
return (error);
again:
- if ((vp = nd->nl_ncp->nc_vp) == NULL)
+ if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
return (ENOENT);
td = curthread;
* is a hack at the moment.
*/
if (error == ESTALE) {
- cache_setunresolved(nd->nl_ncp);
- error = cache_resolve(nd->nl_ncp, nd->nl_cred);
+ cache_setunresolved(&nd->nl_nch);
+ error = cache_resolve(&nd->nl_nch, nd->nl_cred);
if (error == 0) {
vput(vp);
goto again;
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
nlookup_done(&nd);
if (error == 0) {
error = VOP_PATHCONF(vp, uap->name, uap->sysmsg_fds);
if ((error = nlookup(nd)) != 0)
return (error);
- error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &vp);
if (error)
return (error);
if (vp->v_type != VLNK) {
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = ncp_writechk(nd.nl_ncp);
+ error = ncp_writechk(&nd.nl_nch);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
error = setfflags(vp, uap->flags);
if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
return (error);
- if (fp->f_ncp)
- error = ncp_writechk(fp->f_ncp);
+ if (fp->f_nchandle.ncp)
+ error = ncp_writechk(&fp->f_nchandle);
if (error == 0)
error = setfflags((struct vnode *) fp->f_data, uap->flags);
fdrop(fp);
/* XXX Add NLC flag indicating modifying operation? */
if ((error = nlookup(nd)) != 0)
return (error);
- if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0)
+ if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
return (error);
- if ((error = ncp_writechk(nd->nl_ncp)) == 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) == 0)
error = setfmode(vp, mode);
vrele(vp);
return (error);
if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
return (error);
- if (fp->f_ncp)
- error = ncp_writechk(fp->f_ncp);
+ if (fp->f_nchandle.ncp)
+ error = ncp_writechk(&fp->f_nchandle);
if (error == 0)
error = setfmode((struct vnode *)fp->f_data, uap->mode);
fdrop(fp);
/* XXX Add NLC flag indicating modifying operation? */
if ((error = nlookup(nd)) != 0)
return (error);
- if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0)
+ if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
return (error);
- if ((error = ncp_writechk(nd->nl_ncp)) == 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) == 0)
error = setfown(vp, uid, gid);
vrele(vp);
return (error);
if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
return (error);
- if (fp->f_ncp)
- error = ncp_writechk(fp->f_ncp);
+ if (fp->f_nchandle.ncp)
+ error = ncp_writechk(&fp->f_nchandle);
if (error == 0)
error = setfown((struct vnode *)fp->f_data, uap->uid, uap->gid);
fdrop(fp);
/* XXX Add NLC flag indicating modifying operation? */
if ((error = nlookup(nd)) != 0)
return (error);
- if ((error = ncp_writechk(nd->nl_ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
- if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0)
+ if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
return (error);
error = setutimes(vp, ts, tptr == NULL);
vrele(vp);
return (error);
if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
return (error);
- if (fp->f_ncp)
- error = ncp_writechk(fp->f_ncp);
+ if (fp->f_nchandle.ncp)
+ error = ncp_writechk(&fp->f_nchandle);
if (error == 0)
error = setutimes((struct vnode *)fp->f_data, ts, tptr == NULL);
fdrop(fp);
/* XXX Add NLC flag indicating modifying operation? */
if ((error = nlookup(nd)) != 0)
return (error);
- if ((error = ncp_writechk(nd->nl_ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
- if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0)
+ if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
return (error);
if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) {
vrele(vp);
}
if (vp->v_type == VDIR) {
error = EISDIR;
- } else if ((error = vn_writechk(vp, nd->nl_ncp)) == 0 &&
+ } else if ((error = vn_writechk(vp, &nd->nl_nch)) == 0 &&
(error = VOP_ACCESS(vp, VWRITE, nd->nl_cred)) == 0) {
VATTR_NULL(&vattr);
vattr.va_size = length;
return(EINVAL);
if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
return (error);
- if (fp->f_ncp) {
- error = ncp_writechk(fp->f_ncp);
+ if (fp->f_nchandle.ncp) {
+ error = ncp_writechk(&fp->f_nchandle);
if (error)
goto done;
}
int
kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
{
- struct namecache *fncpd;
- struct namecache *tncpd;
+ struct nchandle fnchd;
+ struct nchandle tnchd;
struct namecache *ncp;
struct mount *mp;
int error;
bwillwrite();
if ((error = nlookup(fromnd)) != 0)
return (error);
- if ((fncpd = fromnd->nl_ncp->nc_parent) == NULL)
+ if ((fnchd.ncp = fromnd->nl_nch.ncp->nc_parent) == NULL)
return (ENOENT);
- cache_hold(fncpd);
+ fnchd.mount = fromnd->nl_nch.mount;
+ cache_hold(&fnchd);
/*
- * unlock the source ncp so we can lookup the target ncp without
+ * unlock the source nch so we can lookup the target nch without
* deadlocking. The target may or may not exist so we do not check
* for a target vp like kern_mkdir() and other creation functions do.
*
*/
KKASSERT(fromnd->nl_flags & NLC_NCPISLOCKED);
fromnd->nl_flags &= ~NLC_NCPISLOCKED;
- cache_unlock(fromnd->nl_ncp);
+ cache_unlock(&fromnd->nl_nch);
tond->nl_flags |= NLC_CREATE;
if ((error = nlookup(tond)) != 0) {
- cache_drop(fncpd);
+ cache_drop(&fnchd);
return (error);
}
- if ((tncpd = tond->nl_ncp->nc_parent) == NULL) {
- cache_drop(fncpd);
+ if ((tnchd.ncp = tond->nl_nch.ncp->nc_parent) == NULL) {
+ cache_drop(&fnchd);
return (ENOENT);
}
- cache_hold(tncpd);
+ tnchd.mount = tond->nl_nch.mount;
+ cache_hold(&tnchd);
/*
* If the source and target are the same there is nothing to do
*/
- if (fromnd->nl_ncp == tond->nl_ncp) {
- cache_drop(fncpd);
- cache_drop(tncpd);
+ if (fromnd->nl_nch.ncp == tond->nl_nch.ncp) {
+ cache_drop(&fnchd);
+ cache_drop(&tnchd);
return (0);
}
/*
* Mount points cannot be renamed or overwritten
*/
- if ((fromnd->nl_ncp->nc_flag | tond->nl_ncp->nc_flag) &
- (NCF_MOUNTPT|NCF_MOUNTEDHERE)
+ if ((fromnd->nl_nch.ncp->nc_flag | tond->nl_nch.ncp->nc_flag) &
+ NCF_ISMOUNTPT
) {
- cache_drop(fncpd);
- cache_drop(tncpd);
+ cache_drop(&fnchd);
+ cache_drop(&tnchd);
return (EINVAL);
}
* may have become invalid while it was unlocked, nc_vp and nc_mount
* could be NULL.
*/
- if (cache_lock_nonblock(fromnd->nl_ncp) == 0) {
- cache_resolve(fromnd->nl_ncp, fromnd->nl_cred);
- } else if (fromnd->nl_ncp > tond->nl_ncp) {
- cache_lock(fromnd->nl_ncp);
- cache_resolve(fromnd->nl_ncp, fromnd->nl_cred);
+ if (cache_lock_nonblock(&fromnd->nl_nch) == 0) {
+ cache_resolve(&fromnd->nl_nch, fromnd->nl_cred);
+ } else if (fromnd->nl_nch.ncp > tond->nl_nch.ncp) {
+ cache_lock(&fromnd->nl_nch);
+ cache_resolve(&fromnd->nl_nch, fromnd->nl_cred);
} else {
- cache_unlock(tond->nl_ncp);
- cache_lock(fromnd->nl_ncp);
- cache_resolve(fromnd->nl_ncp, fromnd->nl_cred);
- cache_lock(tond->nl_ncp);
- cache_resolve(tond->nl_ncp, tond->nl_cred);
+ cache_unlock(&tond->nl_nch);
+ cache_lock(&fromnd->nl_nch);
+ cache_resolve(&fromnd->nl_nch, fromnd->nl_cred);
+ cache_lock(&tond->nl_nch);
+ cache_resolve(&tond->nl_nch, tond->nl_cred);
}
fromnd->nl_flags |= NLC_NCPISLOCKED;
/*
* make sure the parent directories linkages are the same
*/
- if (fncpd != fromnd->nl_ncp->nc_parent ||
- tncpd != tond->nl_ncp->nc_parent) {
- cache_drop(fncpd);
- cache_drop(tncpd);
+ if (fnchd.ncp != fromnd->nl_nch.ncp->nc_parent ||
+ tnchd.ncp != tond->nl_nch.ncp->nc_parent) {
+ cache_drop(&fnchd);
+ cache_drop(&tnchd);
return (ENOENT);
}
*
* NOTE: fromnd's nc_mount or nc_vp could be NULL.
*/
- mp = fncpd->nc_mount;
- if (mp != tncpd->nc_mount || mp != fromnd->nl_ncp->nc_mount ||
- mp != tond->nl_ncp->nc_mount) {
- cache_drop(fncpd);
- cache_drop(tncpd);
+ mp = fnchd.mount;
+ if (mp != tnchd.mount || mp != fromnd->nl_nch.mount ||
+ mp != tond->nl_nch.mount) {
+ cache_drop(&fnchd);
+ cache_drop(&tnchd);
return (EXDEV);
}
/*
* Make sure the mount point is writable
*/
- if ((error = ncp_writechk(tond->nl_ncp)) != 0) {
- cache_drop(fncpd);
- cache_drop(tncpd);
+ if ((error = ncp_writechk(&tond->nl_nch)) != 0) {
+ cache_drop(&fnchd);
+ cache_drop(&tnchd);
return (error);
}
* If the target exists and either the source or target is a directory,
* then both must be directories.
*
- * Due to relocking of the source, fromnd->nl_ncp->nc_vp might have
- * become NULL.
+ * Due to relocking of the source, fromnd->nl_nch.ncp->nc_vp might h
+ * have become NULL.
*/
- if (tond->nl_ncp->nc_vp) {
- if (fromnd->nl_ncp->nc_vp == NULL) {
+ if (tond->nl_nch.ncp->nc_vp) {
+ if (fromnd->nl_nch.ncp->nc_vp == NULL) {
error = ENOENT;
- } else if (fromnd->nl_ncp->nc_vp->v_type == VDIR) {
- if (tond->nl_ncp->nc_vp->v_type != VDIR)
+ } else if (fromnd->nl_nch.ncp->nc_vp->v_type == VDIR) {
+ if (tond->nl_nch.ncp->nc_vp->v_type != VDIR)
error = ENOTDIR;
- } else if (tond->nl_ncp->nc_vp->v_type == VDIR) {
+ } else if (tond->nl_nch.ncp->nc_vp->v_type == VDIR) {
error = EISDIR;
}
}
* for a match against the source.
*/
if (error == 0) {
- for (ncp = tncpd; ncp; ncp = ncp->nc_parent) {
- if (fromnd->nl_ncp == ncp) {
+ for (ncp = tnchd.ncp; ncp; ncp = ncp->nc_parent) {
+ if (fromnd->nl_nch.ncp == ncp) {
error = EINVAL;
break;
}
}
}
- cache_drop(fncpd);
- cache_drop(tncpd);
+ cache_drop(&fnchd);
+ cache_drop(&tnchd);
/*
* Even though the namespaces are different, they may still represent
* when we detect the situation.
*/
if (error == 0) {
- if (fromnd->nl_ncp->nc_vp == tond->nl_ncp->nc_vp) {
- error = VOP_NREMOVE(fromnd->nl_ncp, fromnd->nl_cred);
+ if (fromnd->nl_nch.ncp->nc_vp == tond->nl_nch.ncp->nc_vp) {
+ error = VOP_NREMOVE(&fromnd->nl_nch, fromnd->nl_cred);
} else {
- error = VOP_NRENAME(fromnd->nl_ncp, tond->nl_ncp,
+ error = VOP_NRENAME(&fromnd->nl_nch, &tond->nl_nch,
tond->nl_cred);
}
}
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
- struct namecache *ncp;
struct vnode *vp;
struct vattr vattr;
int error;
if ((error = nlookup(nd)) != 0)
return (error);
- ncp = nd->nl_ncp;
- if (ncp->nc_vp)
+ if (nd->nl_nch.ncp->nc_vp)
return (EEXIST);
- if ((error = ncp_writechk(ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
VATTR_NULL(&vattr);
vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
vp = NULL;
- error = VOP_NMKDIR(ncp, &vp, p->p_ucred, &vattr);
+ error = VOP_NMKDIR(&nd->nl_nch, &vp, p->p_ucred, &vattr);
if (error == 0)
vput(vp);
return (error);
int
kern_rmdir(struct nlookupdata *nd)
{
- struct namecache *ncp;
int error;
bwillwrite();
* deleted, even if empty. Check write perms on mount point
* in case the vnode is aliased (aka nullfs).
*/
- if (nd->nl_ncp->nc_flag & (NCF_MOUNTEDHERE|NCF_MOUNTPT))
+ if (nd->nl_nch.ncp->nc_flag & (NCF_ISMOUNTPT))
return (EINVAL);
- if ((error = ncp_writechk(nd->nl_ncp)) != 0)
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
- ncp = nd->nl_ncp;
- error = VOP_NRMDIR(ncp, nd->nl_cred);
+ error = VOP_NRMDIR(&nd->nl_nch, nd->nl_cred);
return (error);
}
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
cred = crhold(nd.nl_cred);
nlookup_done(&nd);
if (error == 0) {
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
nlookup_done(&nd);
if (error == 0) {
bzero(&fh, sizeof(fh));
* VOP_OPEN needs the file pointer so it can potentially override
* it.
*
- * WARNING! no f_ncp will be associated when fhopen()ing a directory.
- * XXX
+ * WARNING! no f_nchandle will be associated when fhopen()ing a
+ * directory. XXX
*/
if ((error = falloc(p, &nfp, &indx)) != 0)
goto bad;
if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
return (ESTALE);
- if (p != NULL && (p->p_fd->fd_nrdir->nc_flag & NCF_ROOT) == 0 &&
- !chroot_visible_mnt(mp, p))
+ if (p != NULL && !chroot_visible_mnt(mp, p))
return (ESTALE);
if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
if ((error = VFS_STATFS(mp, sp, p->p_ucred)) != 0)
return (error);
- error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath);
+ error = cache_fullpath(p, &mp->mnt_ncmountpt, &fullpath, &freepath);
if (error)
return(error);
bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
if (error == 0)
error = nlookup(&nd);
if (error == 0) {
- mp = nd.nl_ncp->nc_mount;
+ mp = nd.nl_nch.mount;
error = VFS_EXTATTRCTL(mp, uap->cmd,
uap->attrname, uap->arg,
nd.nl_cred);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = ncp_writechk(nd.nl_ncp);
+ error = ncp_writechk(&nd.nl_nch);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
if (error) {
nlookup_done(&nd);
return (error);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
if (error) {
nlookup_done(&nd);
return (error);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = ncp_writechk(nd.nl_ncp);
+ error = ncp_writechk(&nd.nl_nch);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
if (error) {
nlookup_done(&nd);
return (error);
return(error);
}
+/*
+ * Determine if the mount is visible to the process.
+ */
static int
chroot_visible_mnt(struct mount *mp, struct proc *p)
{
- struct namecache *ncp;
+ struct nchandle nch;
+
/*
- * First check if this file system is below
- * the chroot path.
+ * Traverse from the mount point upwards. If we hit the process
+ * root then the mount point is visible to the process.
*/
- ncp = mp->mnt_ncp;
- while (ncp != NULL && ncp != p->p_fd->fd_nrdir)
- ncp = ncp->nc_parent;
- if (ncp == NULL) {
- /*
- * This is not below the chroot path.
- *
- * Check if the chroot path is on the same filesystem,
- * by determing if we have to cross a mount point
- * before reaching mp->mnt_ncp.
- */
- ncp = p->p_fd->fd_nrdir;
- while (ncp != NULL && ncp != mp->mnt_ncp) {
- if (ncp->nc_flag & NCF_MOUNTPT) {
- ncp = NULL;
- break;
- }
- ncp = ncp->nc_parent;
+ nch = mp->mnt_ncmountpt;
+ while (nch.ncp) {
+ if (nch.mount == p->p_fd->fd_nrdir.mount &&
+ nch.ncp == p->p_fd->fd_nrdir.ncp) {
+ return(1);
+ }
+ if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
+ nch = nch.mount->mnt_ncmounton;
+ } else {
+ nch.ncp = nch.ncp->nc_parent;
}
}
- return(ncp != NULL);
+ return(0);
}
+
*
* @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94
* $FreeBSD: src/sys/kern/vfs_vnops.c,v 1.87.2.13 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.48 2006/09/18 18:19:33 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.49 2006/10/27 04:56:31 dillon Exp $
*/
#include <sys/param.h>
struct ucred *cred = nd->nl_cred;
struct vattr vat;
struct vattr *vap = &vat;
- struct namecache *ncp;
int mode, error;
/*
* Lookup the path and create or obtain the vnode. After a
- * successful lookup a locked nd->nl_ncp will be returned.
+ * successful lookup a locked nd->nl_nch will be returned.
*
* The result of this section should be a locked vnode.
*
if (error)
return (error);
- ncp = nd->nl_ncp;
/*
* split case to allow us to re-resolve and retry the ncp in case
*/
again:
if (fmode & O_CREAT) {
- if (ncp->nc_vp == NULL) {
- if ((error = ncp_writechk(ncp)) != 0)
+ if (nd->nl_nch.ncp->nc_vp == NULL) {
+ if ((error = ncp_writechk(&nd->nl_nch)) != 0)
return (error);
VATTR_NULL(vap);
vap->va_type = VREG;
vap->va_mode = cmode;
if (fmode & O_EXCL)
vap->va_vaflags |= VA_EXCLUSIVE;
- error = VOP_NCREATE(ncp, &vp, nd->nl_cred, vap);
+ error = VOP_NCREATE(&nd->nl_nch, &vp, nd->nl_cred, vap);
if (error)
return (error);
fmode &= ~O_TRUNC;
if (fmode & O_EXCL) {
error = EEXIST;
} else {
- error = cache_vget(ncp, cred,
+ error = cache_vget(&nd->nl_nch, cred,
LK_EXCLUSIVE, &vp);
}
if (error)
fmode &= ~O_CREAT;
}
} else {
- error = cache_vget(ncp, cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd->nl_nch, cred, LK_EXCLUSIVE, &vp);
if (error)
return (error);
}
/*
* We have a locked vnode and ncp now. Note that the ncp will
- * be cleaned up by the caller if nd->nl_ncp is left intact.
+ * be cleaned up by the caller if nd->nl_nch is left intact.
*/
if (vp->v_type == VLNK) {
error = EMLINK;
error = EISDIR;
goto bad;
}
- error = vn_writechk(vp, ncp);
+ error = vn_writechk(vp, &nd->nl_nch);
if (error) {
/*
* Special stale handling, re-resolve the
if (error == ESTALE) {
vput(vp);
vp = NULL;
- cache_setunresolved(ncp);
- error = cache_resolve(ncp, cred);
+ cache_setunresolved(&nd->nl_nch);
+ error = cache_resolve(&nd->nl_nch, cred);
if (error == 0)
goto again;
}
if (error == ESTALE) {
vput(vp);
vp = NULL;
- cache_setunresolved(ncp);
- error = cache_resolve(ncp, cred);
+ cache_setunresolved(&nd->nl_nch);
+ error = cache_resolve(&nd->nl_nch, cred);
if (error == 0)
goto again;
}
* Setup the fp so VOP_OPEN can override it. No descriptor has been
* associated with the fp yet so we own it clean.
*
- * f_ncp inherits nl_ncp. This used to be necessary only for
+ * f_nchandle inherits nl_nch. This used to be necessary only for
* directories but now we do it unconditionally so f*() ops
* such as fchmod() can access the actual namespace that was
* used to open the file.
*/
if (fp) {
- fp->f_ncp = nd->nl_ncp;
- nd->nl_ncp = NULL;
- cache_unlock(fp->f_ncp);
+ fp->f_nchandle = nd->nl_nch;
+ cache_zero(&nd->nl_nch);
+ cache_unlock(&fp->f_nchandle);
}
/*
- * Get rid of nl_ncp. vn_open does not return it (it returns the
- * vnode or the file pointer). Note: we can't leave nl_ncp locked
+ * Get rid of nl_nch. vn_open does not return it (it returns the
+ * vnode or the file pointer). Note: we can't leave nl_nch locked
* through the VOP_OPEN anyway since the VOP_OPEN may block, e.g.
* on /dev/ttyd0
*/
- if (nd->nl_ncp) {
- cache_put(nd->nl_ncp);
- nd->nl_ncp = NULL;
- }
+ if (nd->nl_nch.ncp)
+ cache_put(&nd->nl_nch);
error = VOP_OPEN(vp, fmode, cred, fp);
if (error) {
}
/*
- * Check for write permissions on the specified vnode.
+ * Check for write permissions on the specified vnode. nch may be NULL.
*/
int
-vn_writechk(struct vnode *vp, struct namecache *ncp)
+vn_writechk(struct vnode *vp, struct nchandle *nch)
{
/*
* If there's shared text associated with
/*
* If the vnode represents a regular file, check the mount
- * point via the ncp. This may be a different mount point
+ * point via the nch. This may be a different mount point
* then the one embedded in the vnode (e.g. nullfs).
*
* We can still write to non-regular files (e.g. devices)
* via read-only mounts.
*/
- if (ncp && vp->v_type == VREG)
- return (ncp_writechk(ncp));
+ if (nch && nch->ncp && vp->v_type == VREG)
+ return (ncp_writechk(nch));
return (0);
}
* check is needed.
*/
int
-ncp_writechk(struct namecache *ncp)
+ncp_writechk(struct nchandle *nch)
{
- if (ncp->nc_mount && (ncp->nc_mount->mnt_flag & MNT_RDONLY))
+ if (nch->mount && (nch->mount->mnt_flag & MNT_RDONLY))
return (EROFS);
return(0);
}
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.32 2006/08/12 00:26:20 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.33 2006/10/27 04:56:31 dillon Exp $
*/
#include <sys/param.h>
* is left locked on return.
*/
int
-vop_nresolve(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred)
+vop_nresolve(struct vop_ops *ops, struct nchandle *nch, struct ucred *cred)
{
struct vop_nresolve_args ap;
int error;
ap.a_head.a_desc = &vop_nresolve_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_cred = cred;
DO_OPS(ops, error, &ap, vop_nresolve);
* is left locked on return.
*/
int
-vop_ncreate(struct vop_ops *ops, struct namecache *ncp,
+vop_ncreate(struct vop_ops *ops, struct nchandle *nch,
struct vnode **vpp, struct ucred *cred, struct vattr *vap)
{
struct vop_ncreate_args ap;
ap.a_head.a_desc = &vop_ncreate_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_vpp = vpp;
ap.a_cred = cred;
ap.a_vap = vap;
* is left locked on return.
*/
int
-vop_nmkdir(struct vop_ops *ops, struct namecache *ncp,
+vop_nmkdir(struct vop_ops *ops, struct nchandle *nch,
struct vnode **vpp, struct ucred *cred, struct vattr *vap)
{
struct vop_nmkdir_args ap;
ap.a_head.a_desc = &vop_nmkdir_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_vpp = vpp;
ap.a_cred = cred;
ap.a_vap = vap;
* is left locked on return.
*/
int
-vop_nmknod(struct vop_ops *ops, struct namecache *ncp,
+vop_nmknod(struct vop_ops *ops, struct nchandle *nch,
struct vnode **vpp, struct ucred *cred, struct vattr *vap)
{
struct vop_nmknod_args ap;
ap.a_head.a_desc = &vop_nmknod_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_vpp = vpp;
ap.a_cred = cred;
ap.a_vap = vap;
* is left locked on return.
*/
int
-vop_nlink(struct vop_ops *ops, struct namecache *ncp,
+vop_nlink(struct vop_ops *ops, struct nchandle *nch,
struct vnode *vp, struct ucred *cred)
{
struct vop_nlink_args ap;
ap.a_head.a_desc = &vop_nlink_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_vp = vp;
ap.a_cred = cred;
DO_OPS(ops, error, &ap, vop_nlink);
if (error == 0)
- cache_update_fsmid(ncp);
+ cache_update_fsmid(nch);
return(error);
}
* is left locked on return.
*/
int
-vop_nsymlink(struct vop_ops *ops, struct namecache *ncp,
+vop_nsymlink(struct vop_ops *ops, struct nchandle *nch,
struct vnode **vpp, struct ucred *cred,
struct vattr *vap, char *target)
{
ap.a_head.a_desc = &vop_nsymlink_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_vpp = vpp;
ap.a_cred = cred;
ap.a_vap = vap;
DO_OPS(ops, error, &ap, vop_nsymlink);
if (error == 0)
- cache_update_fsmid(ncp);
+ cache_update_fsmid(nch);
return(error);
}
* is left locked on return.
*/
int
-vop_nwhiteout(struct vop_ops *ops, struct namecache *ncp,
+vop_nwhiteout(struct vop_ops *ops, struct nchandle *nch,
struct ucred *cred, int flags)
{
struct vop_nwhiteout_args ap;
ap.a_head.a_desc = &vop_nwhiteout_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_cred = cred;
ap.a_flags = flags;
DO_OPS(ops, error, &ap, vop_nwhiteout);
if (error == 0)
- cache_update_fsmid(ncp);
+ cache_update_fsmid(nch);
return(error);
}
* is left locked on return.
*/
int
-vop_nremove(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred)
+vop_nremove(struct vop_ops *ops, struct nchandle *nch, struct ucred *cred)
{
struct vop_nremove_args ap;
int error;
ap.a_head.a_desc = &vop_nremove_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_cred = cred;
DO_OPS(ops, error, &ap, vop_nremove);
if (error == 0)
- cache_update_fsmid(ncp);
+ cache_update_fsmid(nch);
return(error);
}
* is left locked on return.
*/
int
-vop_nrmdir(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred)
+vop_nrmdir(struct vop_ops *ops, struct nchandle *nch, struct ucred *cred)
{
struct vop_nrmdir_args ap;
int error;
ap.a_head.a_desc = &vop_nrmdir_desc;
ap.a_head.a_ops = ops;
- ap.a_ncp = ncp;
+ ap.a_nch = nch;
ap.a_cred = cred;
DO_OPS(ops, error, &ap, vop_nrmdir);
if (error == 0)
- cache_update_fsmid(ncp);
+ cache_update_fsmid(nch);
return(error);
}
* source ncp's underlying file.
*/
int
-vop_nrename(struct vop_ops *ops, struct namecache *fncp,
- struct namecache *tncp, struct ucred *cred)
+vop_nrename(struct vop_ops *ops, struct nchandle *fnch,
+ struct nchandle *tnch, struct ucred *cred)
{
struct vop_nrename_args ap;
int error;
ap.a_head.a_desc = &vop_nrename_desc;
ap.a_head.a_ops = ops;
- ap.a_fncp = fncp;
- ap.a_tncp = tncp;
+ ap.a_fnch = fnch;
+ ap.a_tnch = tnch;
ap.a_cred = cred;
DO_OPS(ops, error, &ap, vop_nrename);
if (error == 0) {
- cache_update_fsmid(fncp);
- cache_update_fsmid(tncp);
+ cache_update_fsmid(fnch);
+ cache_update_fsmid(tnch);
}
return(error);
}
*
* @(#)file.h 8.3 (Berkeley) 1/9/95
* $FreeBSD: src/sys/sys/file.h,v 1.22.2.7 2002/11/21 23:39:24 sam Exp $
- * $DragonFly: src/sys/sys/file.h,v 1.23 2006/08/06 18:56:46 dillon Exp $
+ * $DragonFly: src/sys/sys/file.h,v 1.24 2006/10/27 04:56:33 dillon Exp $
*/
#ifndef _SYS_FILE_H_
#ifndef _SYS_SPINLOCK_H_
#include <sys/spinlock.h>
#endif
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
struct stat;
struct proc;
void *f_data; /* vnode, pipe, socket, or kqueue */
int f_count; /* reference count */
int f_msgcount; /* (U) reference count from message queue */
- struct namecache *f_ncp; /* ncp (required for directories) */
+ struct nchandle f_nchandle; /* namecache reference */
struct spinlock f_spin;
};
*
* @(#)filedesc.h 8.1 (Berkeley) 6/2/93
* $FreeBSD: src/sys/sys/filedesc.h,v 1.19.2.5 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/sys/filedesc.h,v 1.19 2006/05/26 02:26:26 dillon Exp $
+ * $DragonFly: src/sys/sys/filedesc.h,v 1.20 2006/10/27 04:56:33 dillon Exp $
*/
#ifndef _SYS_FILEDESC_H_
#ifndef _SYS_SPINLOCK_H_
#include <sys/spinlock.h>
#endif
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
/*
* This structure is used for the management of descriptors. It may be
struct file;
struct klist;
-struct namecache;
struct fdnode {
struct file *fp;
struct vnode *fd_cdir; /* current directory (phaseout) */
struct vnode *fd_rdir; /* root directory (phaseout) */
struct vnode *fd_jdir; /* jail root directory (phaseout) */
- struct namecache *fd_ncdir; /* current directory */
- struct namecache *fd_nrdir; /* root directory */
- struct namecache *fd_njdir; /* jail directory */
+ struct nchandle fd_ncdir; /* current directory */
+ struct nchandle fd_nrdir; /* root directory */
+ struct nchandle fd_njdir; /* jail directory */
int fd_nfiles; /* number of open files allocated */
int fd_lastfile; /* high-water mark of fd_files */
int fd_freefile; /* approx. next free file */
* ----------------------------------------------------------------------------
*
* $FreeBSD: src/sys/sys/jail.h,v 1.8.2.2 2000/11/01 17:58:06 rwatson Exp $
- * $DragonFly: src/sys/sys/jail.h,v 1.7 2006/05/20 02:42:13 dillon Exp $
+ * $DragonFly: src/sys/sys/jail.h,v 1.8 2006/10/27 04:56:33 dillon Exp $
*
*/
#else /* _KERNEL */
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
+#ifndef _SYS_VARSYM_H_
#include <sys/varsym.h>
+#endif
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_PRISON);
LIST_ENTRY(prison) pr_list; /* all prisons */
int pr_id; /* prison id */
int pr_ref; /* reference count */
- struct namecache *pr_root; /* namecache entry of root */
+ struct nchandle pr_root; /* namecache entry of root */
char pr_host[MAXHOSTNAMELEN]; /* host name */
uint32_t pr_ip; /* IP address */
void *pr_linux; /* Linux ABI emulation */
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/kern_syscall.h,v 1.33 2006/09/17 21:09:39 dillon Exp $
+ * $DragonFly: src/sys/sys/kern_syscall.h,v 1.34 2006/10/27 04:56:33 dillon Exp $
*/
#ifndef _SYS_KERN_SYSCALL_H_
struct mbuf;
struct msghdr;
struct namecache;
+struct nchandle;
struct nlookupdata;
struct rlimit;
struct rusage;
int kern_chdir(struct nlookupdata *nd);
int kern_chmod(struct nlookupdata *nd, int mode);
int kern_chown(struct nlookupdata *nd, int uid, int gid);
-int kern_chroot(struct namecache *ncp);
+int kern_chroot(struct nchandle *nch);
int kern_fstatfs(int fd, struct statfs *buf);
int kern_ftruncate(int fd, off_t length);
int kern_futimes(int fd, struct timeval *tptr);
*
* @(#)mount.h 8.21 (Berkeley) 5/20/95
* $FreeBSD: src/sys/sys/mount.h,v 1.89.2.7 2003/04/04 20:35:57 tegge Exp $
- * $DragonFly: src/sys/sys/mount.h,v 1.29 2006/09/19 16:06:12 dillon Exp $
+ * $DragonFly: src/sys/sys/mount.h,v 1.30 2006/10/27 04:56:33 dillon Exp $
*/
#ifndef _SYS_MOUNT_H_
#ifndef _SYS_LOCK_H_
#include <sys/lock.h>
#endif
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
#endif
struct thread;
struct vop_ops *mnt_vn_norm_ops; /* for use by the VFS */
struct vop_ops *mnt_vn_spec_ops; /* for use by the VFS */
struct vop_ops *mnt_vn_fifo_ops; /* for use by the VFS */
- struct namecache *mnt_ncp; /* NCF_MNTPT ncp */
+ struct nchandle mnt_ncmountpt; /* mount point */
+ struct nchandle mnt_ncmounton; /* mounted on */
+ int mnt_refs; /* nchandle references */
struct journallst mnt_jlist; /* list of active journals */
u_int8_t *mnt_jbitmap; /* streamid bitmap */
* with the unmount attempt (used by NFS).
*/
#define MNTK_UNMOUNTF 0x00000001 /* forced unmount in progress */
+#define MNTK_NCALIASED 0x00800000 /* namecached aliased */
#define MNTK_UNMOUNT 0x01000000 /* unmount in progress */
#define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */
#define MNTK_WANTRDWR 0x04000000 /* upgrade to read/write requested */
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/namecache.h,v 1.27 2006/09/19 16:06:12 dillon Exp $
+ * $DragonFly: src/sys/sys/namecache.h,v 1.28 2006/10/27 04:56:33 dillon Exp $
*/
#ifndef _SYS_NAMECACHE_H_
int nc_timeout; /* compared against ticks, or 0 */
int nc_exlocks; /* namespace locking */
struct thread *nc_locktd; /* namespace locking */
- struct mount *nc_mount; /* associated mount for vopops */
int64_t nc_fsmid; /* filesystem modified id */
};
-typedef struct namecache *namecache_t;
+/*
+ * Namecache handles include a mount reference allowing topologies
+ * to be replicated with mount overlays (nullfs mounts).
+ */
+struct nchandle {
+ struct namecache *ncp; /* ncp in underlying filesystem */
+ struct mount *mount; /* mount pt (possible overlay) */
+};
/*
* Flags in namecache.nc_flag (u_char)
#define NCF_LOCKED 0x0001 /* locked namespace */
#define NCF_WHITEOUT 0x0002 /* negative entry corresponds to whiteout */
#define NCF_UNRESOLVED 0x0004 /* invalid or unresolved entry */
-#define NCF_MOUNTPT 0x0008 /* mount point */
-#define NCF_ROOT 0x0010 /* namecache root (static) */
+#define NCF_ISMOUNTPT 0x0008 /* someone may have mounted on us here */
+#define NCF_UNUSED10 0x0010
#define NCF_HASHED 0x0020 /* namecache entry in hash table */
#define NCF_LOCKREQ 0x0040
-#define NCF_MOUNTEDHERE 0x0080 /* has child marked NCF_MOUNTPT */
+#define NCF_UNUSED20 0x0080
#define NCF_ISSYMLINK 0x0100 /* represents a symlink */
#define NCF_ISDIR 0x0200 /* represents a directory */
#define NCF_DESTROYED 0x0400 /* name association is considered destroyed */
struct nlcomponent;
struct mount;
-void cache_lock(struct namecache *ncp);
-int cache_lock_nonblock(struct namecache *ncp);
-void cache_unlock(struct namecache *ncp);
-void cache_setvp(struct namecache *ncp, struct vnode *vp);
-void cache_settimeout(struct namecache *ncp, int nticks);
-void cache_setunresolved(struct namecache *ncp);
-void cache_setmountpt(struct namecache *ncp, struct mount *mp);
-void cache_clrmountpt(struct namecache *ncp);
-struct namecache *cache_nlookup(struct namecache *par, struct nlcomponent *nlc);
-struct namecache *cache_allocroot(struct mount *mp, struct vnode *vp);
-struct mount *cache_findmount(struct namecache *par);
-int cache_inval(struct namecache *ncp, int flags);
+void cache_lock(struct nchandle *nch);
+int cache_lock_nonblock(struct nchandle *nch);
+void cache_unlock(struct nchandle *nch);
+void cache_setvp(struct nchandle *nch, struct vnode *vp);
+void cache_settimeout(struct nchandle *nch, int nticks);
+void cache_setunresolved(struct nchandle *nch);
+void cache_clrmountpt(struct nchandle *nch);
+struct nchandle cache_nlookup(struct nchandle *nch, struct nlcomponent *nlc);
+void cache_allocroot(struct nchandle *nch, struct mount *mp, struct vnode *vp);
+struct mount *cache_findmount(struct nchandle *nch);
+int cache_inval(struct nchandle *nch, int flags);
int cache_inval_vp(struct vnode *vp, int flags);
-void vfs_cache_setroot(struct vnode *vp, struct namecache *ncp);
-
+void vfs_cache_setroot(struct vnode *vp, struct nchandle *nch);
-int cache_resolve(struct namecache *ncp, struct ucred *cred);
+int cache_resolve(struct nchandle *nch, struct ucred *cred);
void cache_purge(struct vnode *vp);
void cache_purgevfs (struct mount *mp);
-void cache_validate(struct namecache *ncp);
-int cache_get_nonblock(struct namecache *ncp);
+int cache_get_nonblock(struct nchandle *nch);
void cache_cleanneg(int count);
-struct namecache *cache_get(struct namecache *ncp);
-struct namecache *cache_hold(struct namecache *ncp);
-void cache_put(struct namecache *ncp);
-void cache_drop(struct namecache *ncp);
-void cache_rename(struct namecache *fncp, struct namecache *tncp);
-int cache_vget(struct namecache *, struct ucred *, int, struct vnode **);
-int cache_vref(struct namecache *, struct ucred *, struct vnode **);
-struct namecache *cache_fromdvp(struct vnode *, struct ucred *, int);
-int cache_fullpath(struct proc *, struct namecache *, char **, char **);
-void cache_update_fsmid(struct namecache *);
+void cache_get(struct nchandle *nch, struct nchandle *target);
+struct nchandle *cache_hold(struct nchandle *nch);
+void cache_copy(struct nchandle *nch, struct nchandle *target);
+void cache_changemount(struct nchandle *nch, struct mount *mp);
+void cache_put(struct nchandle *nch);
+void cache_drop(struct nchandle *nch);
+void cache_zero(struct nchandle *nch);
+void cache_rename(struct nchandle *fnch, struct nchandle *tnch);
+int cache_vget(struct nchandle *, struct ucred *, int, struct vnode **);
+int cache_vref(struct nchandle *, struct ucred *, struct vnode **);
+int cache_fromdvp(struct vnode *, struct ucred *, int, struct nchandle *);
+int cache_fullpath(struct proc *, struct nchandle *, char **, char **);
+void cache_update_fsmid(struct nchandle *);
void cache_update_fsmid_vp(struct vnode *);
int64_t cache_sync_fsmid_vp(struct vnode *);
int cache_check_fsmid_vp(struct vnode *, int64_t *);
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/nlookup.h,v 1.4 2005/03/09 06:11:22 hmp Exp $
+ * $DragonFly: src/sys/sys/nlookup.h,v 1.5 2006/10/27 04:56:33 dillon Exp $
*/
#ifndef _SYS_NLOOKUP_H_
#ifndef _SYS_UIO_H_
#include <sys/uio.h>
#endif
+#ifndef _SYS_NAMECACHE_H_
+#include <sys/namecache.h>
+#endif
struct vnode;
struct vattr;
struct mount;
-struct namecache;
struct thread;
struct ucred;
*/
struct nlookupdata {
/*
- * These fields are setup by nlookup_init() with nl_ncp set to
+ * These fields are setup by nlookup_init() with nl_nch set to
* the current directory if a process or the root directory if
* a pure thread. The result from nlookup() will be returned in
- * nl_ncp.
+ * nl_nch.
*/
- struct namecache *nl_ncp; /* start-point and result */
- struct namecache *nl_rootncp; /* root directory */
- struct namecache *nl_jailncp; /* jail directory */
+ struct nchandle nl_nch; /* start-point and result */
+ struct nchandle nl_rootnch; /* root directory */
+ struct nchandle nl_jailnch; /* jail directory */
char *nl_path; /* path buffer */
struct thread *nl_td; /* thread requesting the nlookup */
#ifdef _KERNEL
int nlookup_init(struct nlookupdata *, const char *, enum uio_seg, int);
-int nlookup_init_raw(struct nlookupdata *, const char *, enum uio_seg, int, struct ucred *, struct namecache *);
+int nlookup_init_raw(struct nlookupdata *, const char *, enum uio_seg, int, struct ucred *, struct nchandle *);
void nlookup_set_cred(struct nlookupdata *nd, struct ucred *cred);
void nlookup_zero(struct nlookupdata *);
void nlookup_done(struct nlookupdata *);
-struct namecache *nlookup_simple(const char *str, enum uio_seg seg,
+struct nchandle nlookup_simple(const char *str, enum uio_seg seg,
int niflags, int *error);
-int nlookup_mp(struct mount *mp, struct namecache **ncpp);
+int nlookup_mp(struct mount *mp, struct nchandle *nch);
int nlookup(struct nlookupdata *);
-int nreadsymlink(struct nlookupdata *nd, struct namecache *ncp,
+int nreadsymlink(struct nlookupdata *nd, struct nchandle *nch,
struct nlcomponent *nlc);
-int naccess(struct namecache *ncp, int vmode, struct ucred *cred);
+int naccess(struct nchandle *nch, int vmode, struct ucred *cred);
int naccess_va(struct vattr *va, int vmode, struct ucred *cred);
#endif
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/vfsops.h,v 1.26 2006/08/12 00:26:20 dillon Exp $
+ * $DragonFly: src/sys/sys/vfsops.h,v 1.27 2006/10/27 04:56:33 dillon Exp $
*/
/*
struct syslink_desc;
struct vnode;
struct thread;
-struct namecache;
+struct nchandle;
struct componentname;
struct vattr;
struct ucred;
*/
struct vop_nresolve_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp;
+ struct nchandle *a_nch;
struct ucred *a_cred;
};
struct vop_ncreate_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp; /* locked namespace */
+ struct nchandle *a_nch; /* locked namespace */
struct vnode **a_vpp; /* returned refd & locked */
struct ucred *a_cred;
struct vattr *a_vap;
struct vop_nmkdir_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp; /* locked namespace */
+ struct nchandle *a_nch; /* locked namespace */
struct vnode **a_vpp; /* returned refd & locked */
struct ucred *a_cred;
struct vattr *a_vap;
struct vop_nmknod_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp;
+ struct nchandle *a_nch;
struct vnode **a_vpp;
struct ucred *a_cred;
struct vattr *a_vap;
struct vop_nlink_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp;
+ struct nchandle *a_nch;
struct vnode *a_vp;
struct ucred *a_cred;
};
struct vop_nsymlink_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp;
+ struct nchandle *a_nch;
struct vnode **a_vpp;
struct ucred *a_cred;
struct vattr *a_vap;
struct vop_nwhiteout_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp;
+ struct nchandle *a_nch;
struct ucred *a_cred;
int a_flags;
};
struct vop_nremove_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp; /* locked namespace */
+ struct nchandle *a_nch; /* locked namespace */
struct ucred *a_cred;
};
struct vop_nrmdir_args {
struct vop_generic_args a_head;
- struct namecache *a_ncp; /* locked namespace */
+ struct nchandle *a_nch; /* locked namespace */
struct ucred *a_cred;
};
struct vop_nrename_args {
struct vop_generic_args a_head;
- struct namecache *a_fncp; /* locked namespace / from */
- struct namecache *a_tncp; /* locked namespace / to */
+ struct nchandle *a_fnch; /* locked namespace / from */
+ struct nchandle *a_tnch; /* locked namespace / to */
struct ucred *a_cred;
};
struct uio *uio, struct ucred *cred);
int vop_mountctl(struct vop_ops *ops, int op, struct file *fp,
const void *ctl, int ctllen, void *buf, int buflen, int *res);
-int vop_nresolve(struct vop_ops *ops, struct namecache *ncp,
+int vop_nresolve(struct vop_ops *ops, struct nchandle *nch,
struct ucred *cred);
int vop_nlookupdotdot(struct vop_ops *ops, struct vnode *dvp,
struct vnode **vpp, struct ucred *cred);
-int vop_ncreate(struct vop_ops *ops, struct namecache *ncp,
+int vop_ncreate(struct vop_ops *ops, struct nchandle *nch,
struct vnode **vpp, struct ucred *cred, struct vattr *vap);
-int vop_nmkdir(struct vop_ops *ops, struct namecache *ncp,
+int vop_nmkdir(struct vop_ops *ops, struct nchandle *nch,
struct vnode **vpp, struct ucred *cred, struct vattr *vap);
-int vop_nmknod(struct vop_ops *ops, struct namecache *ncp,
+int vop_nmknod(struct vop_ops *ops, struct nchandle *nch,
struct vnode **vpp, struct ucred *cred, struct vattr *vap);
-int vop_nlink(struct vop_ops *ops, struct namecache *ncp, struct vnode *vp,
+int vop_nlink(struct vop_ops *ops, struct nchandle *nch, struct vnode *vp,
struct ucred *cred);
-int vop_nsymlink(struct vop_ops *ops, struct namecache *ncp,
+int vop_nsymlink(struct vop_ops *ops, struct nchandle *nch,
struct vnode **vpp, struct ucred *cred,
struct vattr *vap, char *target);
-int vop_nwhiteout(struct vop_ops *ops, struct namecache *ncp,
+int vop_nwhiteout(struct vop_ops *ops, struct nchandle *nch,
struct ucred *cred, int flags);
-int vop_nremove(struct vop_ops *ops, struct namecache *ncp,
+int vop_nremove(struct vop_ops *ops, struct nchandle *nch,
struct ucred *cred);
-int vop_nrmdir(struct vop_ops *ops, struct namecache *ncp,
+int vop_nrmdir(struct vop_ops *ops, struct nchandle *nch,
struct ucred *cred);
-int vop_nrename(struct vop_ops *ops, struct namecache *fncp,
- struct namecache *tncp, struct ucred *cred);
+int vop_nrename(struct vop_ops *ops, struct nchandle *fnch,
+ struct nchandle *tnch, struct ucred *cred);
/*
* Kernel VOP forwarding wrappers. These are called when a VFS such as
* code in kern/vfs_default which does the magic required to call the old
* routines.
*/
-#define VOP_NRESOLVE(ncp, cred) \
- vop_nresolve((ncp)->nc_mount->mnt_vn_use_ops, ncp, cred)
-#define VOP_NCREATE(ncp, vpp, cred, vap) \
- vop_ncreate((ncp)->nc_mount->mnt_vn_use_ops, ncp, vpp, cred, vap)
-#define VOP_NMKDIR(ncp, vpp, cred, vap) \
- vop_nmkdir((ncp)->nc_mount->mnt_vn_use_ops, ncp, vpp, cred, vap)
-#define VOP_NMKNOD(ncp, vpp, cred, vap) \
- vop_nmknod((ncp)->nc_mount->mnt_vn_use_ops, ncp, vpp, cred, vap)
-#define VOP_NLINK(ncp, vp, cred) \
- vop_nlink((ncp)->nc_mount->mnt_vn_use_ops, ncp, vp, cred)
-#define VOP_NSYMLINK(ncp, vpp, cred, vap, target) \
- vop_nsymlink((ncp)->nc_mount->mnt_vn_use_ops, ncp, vpp, cred, vap, target)
-#define VOP_NWHITEOUT(ncp, cred, flags) \
- vop_nwhiteout((ncp)->nc_mount->mnt_vn_use_ops, ncp, cred, flags)
-#define VOP_NRENAME(fncp, tncp, cred) \
- vop_nrename((fncp)->nc_mount->mnt_vn_use_ops, fncp, tncp, cred)
-#define VOP_NRMDIR(ncp, cred) \
- vop_nrmdir((ncp)->nc_mount->mnt_vn_use_ops, ncp, cred)
-#define VOP_NREMOVE(ncp, cred) \
- vop_nremove((ncp)->nc_mount->mnt_vn_use_ops, ncp, cred)
+#define VOP_NRESOLVE(nch, cred) \
+ vop_nresolve((nch)->mount->mnt_vn_use_ops, nch, cred)
+#define VOP_NCREATE(nch, vpp, cred, vap) \
+ vop_ncreate((nch)->mount->mnt_vn_use_ops, nch, vpp, cred, vap)
+#define VOP_NMKDIR(nch, vpp, cred, vap) \
+ vop_nmkdir((nch)->mount->mnt_vn_use_ops, nch, vpp, cred, vap)
+#define VOP_NMKNOD(nch, vpp, cred, vap) \
+ vop_nmknod((nch)->mount->mnt_vn_use_ops, nch, vpp, cred, vap)
+#define VOP_NLINK(nch, vp, cred) \
+ vop_nlink((nch)->mount->mnt_vn_use_ops, nch, vp, cred)
+#define VOP_NSYMLINK(nch, vpp, cred, vap, target) \
+ vop_nsymlink((nch)->mount->mnt_vn_use_ops, nch, vpp, cred, vap, target)
+#define VOP_NWHITEOUT(nch, cred, flags) \
+ vop_nwhiteout((nch)->mount->mnt_vn_use_ops, nch, cred, flags)
+#define VOP_NRENAME(fnch, tnch, cred) \
+ vop_nrename((fnch)->mount->mnt_vn_use_ops, fnch, tnch, cred)
+#define VOP_NRMDIR(nch, cred) \
+ vop_nrmdir((nch)->mount->mnt_vn_use_ops, nch, cred)
+#define VOP_NREMOVE(nch, cred) \
+ vop_nremove((nch)->mount->mnt_vn_use_ops, nch, cred)
#endif
*
* @(#)vnode.h 8.7 (Berkeley) 2/4/94
* $FreeBSD: src/sys/sys/vnode.h,v 1.111.2.19 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/sys/vnode.h,v 1.71 2006/09/19 16:06:12 dillon Exp $
+ * $DragonFly: src/sys/sys/vnode.h,v 1.72 2006/10/27 04:56:33 dillon Exp $
*/
#ifndef _SYS_VNODE_H_
struct objcache;
extern struct vnode *rootvnode; /* root (i.e. "/") vnode */
-extern struct namecache *rootncp; /* root (i.e. "/") namecache */
+extern struct nchandle rootnch; /* root (i.e. "/") namecache */
extern int desiredvnodes; /* number of vnodes desired */
extern time_t syncdelay; /* max time to delay syncing data */
extern time_t filedelay; /* time to delay syncing files */
int vn_stat (struct vnode *vp, struct stat *sb, struct ucred *cred);
cdev_t vn_todev (struct vnode *vp);
void vfs_timestamp (struct timespec *);
-int vn_writechk (struct vnode *vp, struct namecache *ncp);
-int ncp_writechk(struct namecache *ncp);
+int vn_writechk (struct vnode *vp, struct nchandle *nch);
+int ncp_writechk(struct nchandle *nch);
int vop_stdopen (struct vop_open_args *ap);
int vop_stdclose (struct vop_close_args *ap);
int vop_nopoll (struct vop_poll_args *ap);
*
* @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
* $FreeBSD: src/sys/gnu/ext2fs/ext2_vfsops.c,v 1.63.2.7 2002/07/01 00:18:51 iedowse Exp $
- * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.50 2006/09/10 01:26:40 dillon Exp $
+ * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.51 2006/10/27 04:56:33 dillon Exp $
*/
#include "opt_quota.h"
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
nlookup_done(&nd);
if (error)
return (error);
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/fs/hpfs/hpfs_vfsops.c,v 1.3.2.2 2001/12/25 01:44:45 dillon Exp $
- * $DragonFly: src/sys/vfs/hpfs/hpfs_vfsops.c,v 1.38 2006/09/10 01:26:40 dillon Exp $
+ * $DragonFly: src/sys/vfs/hpfs/hpfs_vfsops.c,v 1.39 2006/10/27 04:56:34 dillon Exp $
*/
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
nlookup_done(&nd);
if (error)
goto error_1;
*
* @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94
* $FreeBSD: src/sys/isofs/cd9660/cd9660_rrip.c,v 1.17 1999/08/28 00:46:06 peter Exp $
- * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_rrip.c,v 1.11 2006/09/05 00:55:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_rrip.c,v 1.12 2006/10/27 04:56:34 dillon Exp $
*/
#include <sys/param.h>
/* same as above */
outbuf -= len;
len = 0;
- error = cache_fullpath(NULL, ana->imp->im_mountp->mnt_ncp,
+ error = cache_fullpath(NULL, &ana->imp->im_mountp->mnt_ncmountpt,
&inbuf, &freebuf);
if (error)
goto bad;
*
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
* $FreeBSD: src/sys/isofs/cd9660/cd9660_vfsops.c,v 1.74.2.7 2002/04/08 09:39:29 bde Exp $
- * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v 1.41 2006/09/10 01:26:41 dillon Exp $
+ * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vfsops.c,v 1.42 2006/10/27 04:56:34 dillon Exp $
*/
#include <sys/param.h>
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
nlookup_done(&nd);
if (error)
return (error);
/* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/msdosfs/Attic/msdosfs_vfsops.c,v 1.60.2.8 2004/03/02 09:43:04 tjr Exp $ */
-/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.41 2006/10/03 01:32:41 swildner Exp $ */
+/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.42 2006/10/27 04:56:34 dillon Exp $ */
/* $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $ */
/*-
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
nlookup_done(&nd);
if (error)
return (error);
*
* @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
* $FreeBSD: src/sys/nfs/nfs_serv.c,v 1.93.2.6 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.40 2006/09/19 16:06:14 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.41 2006/10/27 04:56:34 dillon Exp $
*/
/*
struct nlookupdata nd;
struct vnode *vp;
struct vnode *dirp;
- struct namecache *ncp;
+ struct nchandle nch;
nfsfh_t nfh;
fhandle_t *fhp;
caddr_t cp;
* via the original nd. Confused? You aren't alone!
*/
vn_unlock(vp);
- ncp = cache_hold(nd.nl_ncp);
+ cache_copy(&nd.nl_nch, &nch);
nlookup_done(&nd);
error = nlookup_init_raw(&nd, nfs_pub.np_index,
- UIO_SYSSPACE, 0, cred, ncp);
- cache_drop(ncp);
+ UIO_SYSSPACE, 0, cred, &nch);
+ cache_drop(&nch);
if (error == 0)
error = nlookup(&nd);
vrele(dirp);
dirp = vp;
vp = NULL;
- error = cache_vget(nd.nl_ncp, nd.nl_cred,
+ error = cache_vget(&nd.nl_nch, nd.nl_cred,
LK_EXCLUSIVE, &vp);
KKASSERT(error == 0);
}
if (vap->va_type == VREG || vap->va_type == VSOCK) {
vput(dvp);
dvp = NULL;
- error = VOP_NCREATE(nd.nl_ncp, &vp, nd.nl_cred, vap);
+ error = VOP_NCREATE(&nd.nl_nch, &vp, nd.nl_cred, vap);
if (error == 0) {
if (exclusive_flag) {
exclusive_flag = 0;
vput(dvp);
dvp = NULL;
- error = VOP_NMKNOD(nd.nl_ncp, &vp, nd.nl_cred, vap);
+ error = VOP_NMKNOD(&nd.nl_nch, &vp, nd.nl_cred, vap);
if (error)
goto nfsmreply0;
#if 0
if (vap->va_mode == (mode_t)VNOVAL)
vap->va_mode = 0;
if (vtyp == VSOCK) {
- error = VOP_NCREATE(nd.nl_ncp, &vp, nd.nl_cred, vap);
+ error = VOP_NCREATE(&nd.nl_nch, &vp, nd.nl_cred, vap);
} else {
if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
goto out;
- error = VOP_NMKNOD(nd.nl_ncp, &vp, nd.nl_cred, vap);
+ error = VOP_NMKNOD(&nd.nl_nch, &vp, nd.nl_cred, vap);
if (error)
goto out;
vput(vp);
vp = NULL;
}
- error = VOP_NREMOVE(nd.nl_ncp, nd.nl_cred);
+ error = VOP_NREMOVE(&nd.nl_nch, nd.nl_cred);
}
}
if (dirp && v3)
* the target ncp.
*/
KKASSERT(fromnd.nl_flags & NLC_NCPISLOCKED);
- cache_unlock(fromnd.nl_ncp);
+ cache_unlock(&fromnd.nl_nch);
fromnd.nl_flags &= ~NLC_NCPISLOCKED;
nfsm_srvmtofh(tfhp);
nfsm_strsiz(len2, NFS_MAXNAMLEN);
/*
* relock the source
*/
- if (cache_lock_nonblock(fromnd.nl_ncp) == 0) {
- cache_resolve(fromnd.nl_ncp, fromnd.nl_cred);
- } else if (fromnd.nl_ncp > tond.nl_ncp) {
- cache_lock(fromnd.nl_ncp);
- cache_resolve(fromnd.nl_ncp, fromnd.nl_cred);
+ if (cache_lock_nonblock(&fromnd.nl_nch) == 0) {
+ cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
+ } else if (fromnd.nl_nch.ncp > tond.nl_nch.ncp) {
+ cache_lock(&fromnd.nl_nch);
+ cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
} else {
- cache_unlock(tond.nl_ncp);
- cache_lock(fromnd.nl_ncp);
- cache_resolve(fromnd.nl_ncp, fromnd.nl_cred);
- cache_lock(tond.nl_ncp);
- cache_resolve(tond.nl_ncp, tond.nl_cred);
+ cache_unlock(&tond.nl_nch);
+ cache_lock(&fromnd.nl_nch);
+ cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
+ cache_lock(&tond.nl_nch);
+ cache_resolve(&tond.nl_nch, tond.nl_cred);
}
fromnd.nl_flags |= NLC_NCPISLOCKED;
- tvp = tond.nl_ncp->nc_vp;
- fvp = fromnd.nl_ncp->nc_vp;
+ tvp = tond.nl_nch.ncp->nc_vp;
+ fvp = fromnd.nl_nch.ncp->nc_vp;
if (tvp != NULL) {
if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
error = ENOTDIR;
goto out;
}
- if (tvp->v_type == VDIR && (tond.nl_ncp->nc_flag & NCF_MOUNTPT)) {
+ if (tvp->v_type == VDIR && (tond.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
if (v3)
error = EXDEV;
else
goto out;
}
}
- if (fvp->v_type == VDIR && (fromnd.nl_ncp->nc_flag & NCF_MOUNTPT)) {
+ if (fvp->v_type == VDIR && (fromnd.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
if (v3)
error = EXDEV;
else
error = ENOTEMPTY;
goto out;
}
- if (fromnd.nl_ncp->nc_mount != tond.nl_ncp->nc_mount) {
+ if (fromnd.nl_nch.mount != tond.nl_nch.mount) {
if (v3)
error = EXDEV;
else
error = ENOTEMPTY;
goto out;
}
- if (fromnd.nl_ncp == tond.nl_ncp->nc_parent) {
+ if (fromnd.nl_nch.ncp == tond.nl_nch.ncp->nc_parent) {
if (v3)
error = EINVAL;
else
* for a match against the source.
*/
if (error == 0) {
- for (ncp = tond.nl_ncp; ncp; ncp = ncp->nc_parent) {
- if (fromnd.nl_ncp == ncp) {
+ for (ncp = tond.nl_nch.ncp; ncp; ncp = ncp->nc_parent) {
+ if (fromnd.nl_nch.ncp == ncp) {
error = EINVAL;
break;
}
* same vnode with the same name in the same directory),
* then there is nothing to do.
*/
- if (fromnd.nl_ncp == tond.nl_ncp)
+ if (fromnd.nl_nch.ncp == tond.nl_nch.ncp)
error = -1;
out:
if (!error) {
* locks prior to returning so we need to clear the pointers
* to bypass cleanup code later on.
*/
- error = VOP_NRENAME(fromnd.nl_ncp, tond.nl_ncp, tond.nl_cred);
+ error = VOP_NRENAME(&fromnd.nl_nch, &tond.nl_nch, tond.nl_cred);
} else {
if (error == -1)
error = 0;
error = EXDEV;
out:
if (!error) {
- error = VOP_NLINK(nd.nl_ncp, xp, nd.nl_cred);
+ error = VOP_NLINK(&nd.nl_nch, xp, nd.nl_cred);
}
/* fall through */
if (vap->va_mode == (mode_t)VNOVAL)
vap->va_mode = 0;
- error = VOP_NSYMLINK(nd.nl_ncp, &vp, nd.nl_cred, vap, pathcp);
+ error = VOP_NSYMLINK(&nd.nl_nch, &vp, nd.nl_cred, vap, pathcp);
if (error == 0) {
bzero((caddr_t)fhp, sizeof(nfh));
fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
*/
if (vap->va_mode == (mode_t)VNOVAL)
vap->va_mode = 0;
- error = VOP_NMKDIR(nd.nl_ncp, &vp, nd.nl_cred, vap);
+ error = VOP_NMKDIR(&nd.nl_nch, &vp, nd.nl_cred, vap);
if (error == 0) {
bzero((caddr_t)fhp, sizeof(nfh));
if (!error) {
vput(vp);
vp = NULL;
- error = VOP_NRMDIR(nd.nl_ncp, nd.nl_cred);
+ error = VOP_NRMDIR(&nd.nl_nch, nd.nl_cred);
}
nlookup_done(&nd);
*
* @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
* $FreeBSD: /repoman/r/ncvs/src/sys/nfsclient/nfs_subs.c,v 1.128 2004/04/14 23:23:55 peadar Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_subs.c,v 1.42 2006/09/03 18:52:30 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_subs.c,v 1.43 2006/10/27 04:56:34 dillon Exp $
*/
/*
* dirp may be set whether an error is returned or not, and must be
* released by the caller.
*
- * On return nd->nl_ncp usually points to the target ncp, which may represent
+ * On return nd->nl_nch usually points to the target ncp, which may represent
* a negative hit.
*
* NOTE: the caller must call nlookup_done(nd) unconditionally on return
struct mbuf *md;
char *fromcp, *tocp, *cp;
char *namebuf;
- struct namecache *ncp;
+ struct nchandle nch;
struct vnode *dp;
int error, rdonly;
* one. If this fails the directory has probably been removed while
* the target was chdir'd into it and any further lookup will fail.
*/
- if ((ncp = cache_fromdvp(dp, cred, 1)) == NULL) {
- error = EINVAL;
+ if ((error = cache_fromdvp(dp, cred, 1, &nch)) != 0)
goto out;
- }
- nlookup_init_raw(nd, namebuf, UIO_SYSSPACE, flags, cred, ncp);
- cache_drop(ncp);
+ nlookup_init_raw(nd, namebuf, UIO_SYSSPACE, flags, cred, &nch);
+ cache_drop(&nch);
/*
* Ok, do the lookup.
/*
* If no error occured return the requested dvpp and vpp. If
- * NLC_CREATE was specified nd->nl_ncp may represent a negative
+ * NLC_CREATE was specified nd->nl_nch may represent a negative
* cache hit in which case we do not attempt to obtain the vp.
*/
if (error == 0) {
- ncp = nd->nl_ncp;
if (dvpp) {
- if (ncp->nc_parent &&
- ncp->nc_parent->nc_mount == ncp->nc_mount) {
- error = cache_vget(ncp->nc_parent, nd->nl_cred,
- LK_EXCLUSIVE, dvpp);
+ if (nch.ncp->nc_parent) {
+ nch = nd->nl_nch;
+ nch.ncp = nch.ncp->nc_parent;
+ error = cache_vget(&nch, nd->nl_cred,
+ LK_EXCLUSIVE, dvpp);
} else {
error = ENXIO;
}
}
- if (vpp && ncp->nc_vp) {
- error = cache_vget(ncp, nd->nl_cred, LK_EXCLUSIVE, vpp);
+ if (vpp && nd->nl_nch.ncp->nc_vp) {
+ error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, vpp);
}
if (error) {
if (dvpp && *dvpp) {
*
* @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
* $FreeBSD: src/sys/nfs/nfs_syscalls.c,v 1.58.2.1 2000/11/26 02:30:06 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_syscalls.c,v 1.26 2006/09/05 00:55:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_syscalls.c,v 1.27 2006/10/27 04:56:34 dillon Exp $
*/
#include <sys/param.h>
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp);
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
nlookup_done(&nd);
if (error)
return (error);
*
* @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
* $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.66 2006/09/05 00:55:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.67 2006/10/27 04:56:34 dillon Exp $
*/
int32_t t1, t2;
cred = ap->a_cred;
- ncp = ap->a_ncp;
+ ncp = ap->a_nch->ncp;
KKASSERT(ncp->nc_parent && ncp->nc_parent->nc_vp);
dvp = ncp->nc_parent->nc_vp;
nticks = nfsneg_cache_timeout * hz;
else
nticks = 1;
- cache_setvp(ncp, NULL);
- cache_settimeout(ncp, nticks);
+ cache_setvp(ap->a_nch, NULL);
+ cache_settimeout(ap->a_nch, nticks);
}
nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
m_freem(mrep);
} else {
nfsm_loadattr(nvp, NULL);
}
- cache_setvp(ncp, nvp);
+ cache_setvp(ap->a_nch, nvp);
m_freem(mrep);
nfsmout:
vput(dvp);
u_quad_t fileno;
int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
int attrflag, fhsize;
- struct namecache *ncp;
- struct namecache *dncp;
+ struct nchandle nch;
+ struct nchandle dnch;
struct nlcomponent nlc;
#ifndef nolint
* ncp may be unnamed. Note that other unrelated operations may
* cause the ncp to be named at any time.
*/
- dncp = cache_fromdvp(vp, NULL, 0);
+ cache_fromdvp(vp, NULL, 0, &dnch);
bzero(&nlc, sizeof(nlc));
newvp = NULLVP;
md = mdsav2;
dp->nfs_type =
IFTODT(VTTOIF(np->n_vattr.va_type));
- if (dncp) {
+ if (dnch.ncp) {
printf("NFS/READDIRPLUS, ENTER %*.*s\n",
nlc.nlc_namelen, nlc.nlc_namelen,
nlc.nlc_nameptr);
- ncp = cache_nlookup(dncp, &nlc);
- cache_setunresolved(ncp);
- cache_setvp(ncp, newvp);
- cache_put(ncp);
+ nch = cache_nlookup(&dnch, &nlc);
+ cache_setunresolved(&nch);
+ cache_setvp(&nch, newvp);
+ cache_put(&nch);
} else {
printf("NFS/READDIRPLUS, UNABLE TO ENTER"
" %*.*s\n",
vput(newvp);
newvp = NULLVP;
}
- if (dncp)
- cache_drop(dncp);
+ if (dnch.ncp)
+ cache_drop(&dnch);
return (error);
}
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/ntfs/ntfs_vfsops.c,v 1.20.2.5 2001/12/25 01:44:45 dillon Exp $
- * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.42 2006/09/10 01:26:41 dillon Exp $
+ * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.43 2006/10/27 04:56:34 dillon Exp $
*/
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
nlookup_done(&nd);
if (error)
goto error_1;
*
* @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92
* $FreeBSD: src/sys/miscfs/nullfs/null_vfsops.c,v 1.35.2.3 2001/07/26 20:37:11 iedowse Exp $
- * $DragonFly: src/sys/vfs/nullfs/null_vfsops.c,v 1.28 2006/10/10 17:16:48 dillon Exp $
+ * $DragonFly: src/sys/vfs/nullfs/null_vfsops.c,v 1.29 2006/10/27 04:56:34 dillon Exp $
*/
/*
*/
rootvp = NULL;
error = nlookup_init(&nd, args.target, UIO_USERSPACE, NLC_FOLLOW);
- if (error == 0)
- error = nlookup(&nd);
- if (error == 0) {
- error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE,
- &rootvp);
- }
+ if (error)
+ goto fail1;
+ error = nlookup(&nd);
+ if (error)
+ goto fail2;
+ error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &rootvp);
+ if (error)
+ goto fail2;
xmp = (struct null_mount *) kmalloc(sizeof(struct null_mount),
M_NULLFSMNT, M_WAITOK); /* XXX */
/*
* Save reference to underlying FS
- */
- /*
+ *
* As lite stacking enters the scene, the old way of doing this
- * -- via the vnode -- is not good enough anymore...
+ * -- via the vnode -- is not good enough anymore. Use the
+ * underlying filesystem's namecache handle as our mount point
+ * root, adjusting the mount to point to us.
+ *
+ * NCF_ISMOUNTPT is normally set on the mount point, but we also
+ * want to set it on the base directory being mounted to prevent
+ * that directory from being destroyed out from under the nullfs
+ * mount.
*/
- xmp->nullm_vfs = nd.nl_ncp->nc_mount;
+ xmp->nullm_vfs = nd.nl_nch.mount;
+ mp->mnt_ncmountpt = nd.nl_nch;
+ cache_changemount(&mp->mnt_ncmountpt, mp);
+ mp->mnt_ncmountpt.ncp->nc_flag |= NCF_ISMOUNTPT;
+ cache_unlock(&mp->mnt_ncmountpt);
+ cache_zero(&nd.nl_nch);
nlookup_done(&nd);
vfs_add_vnodeops(mp, &null_vnode_vops, &mp->mnt_vn_norm_ops);
- vn_unlock(rootvp);
+ vn_unlock(rootvp); /* leave reference intact */
/*
* Keep a held reference to the root vnode.
(void)nullfs_statfs(mp, &mp->mnt_stat, cred);
NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntfromname);
+
+ /*
+ * So unmount won't complain about namecache refs still existing
+ */
+ mp->mnt_kern_flag |= MNTK_NCALIASED;
return (0);
+fail2:
+ nlookup_done(&nd);
+fail1:
+ return (error);
}
/*
* Ancestors:
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
* $FreeBSD: src/sys/miscfs/nullfs/null_vnops.c,v 1.38.2.6 2002/07/31 00:32:28 semenu Exp $
- * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.27 2006/07/18 22:22:15 dillon Exp $
+ * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.28 2006/10/27 04:56:34 dillon Exp $
* ...and...
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
*
static int
null_nresolve(struct vop_nresolve_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_nresolve_ap(ap);
}
static int
null_ncreate(struct vop_ncreate_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_ncreate_ap(ap);
}
static int
null_nmkdir(struct vop_nmkdir_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_nmkdir_ap(ap);
}
static int
null_nmknod(struct vop_nmknod_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_nmknod_ap(ap);
}
static int
null_nlink(struct vop_nlink_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_nlink_ap(ap);
}
static int
null_nsymlink(struct vop_nsymlink_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_nsymlink_ap(ap);
}
static int
null_nwhiteout(struct vop_nwhiteout_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_nwhiteout_ap(ap);
}
static int
null_nremove(struct vop_nremove_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_nremove_ap(ap);
}
static int
null_nrmdir(struct vop_nrmdir_args *ap)
{
- ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops;
+ ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops;
return vop_nrmdir_ap(ap);
}
{
struct mount *lmp;
- lmp = MOUNTTONULLMOUNT(ap->a_fncp->nc_mount)->nullm_vfs;
- if (lmp != MOUNTTONULLMOUNT(ap->a_tncp->nc_mount)->nullm_vfs)
+ lmp = MOUNTTONULLMOUNT(ap->a_fnch->mount)->nullm_vfs;
+ if (lmp != MOUNTTONULLMOUNT(ap->a_tnch->mount)->nullm_vfs)
return (EINVAL);
ap->a_head.a_ops = lmp->mnt_vn_norm_ops;
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/fs/udf/udf_vfsops.c,v 1.16 2003/11/05 06:56:08 scottl Exp $
- * $DragonFly: src/sys/vfs/udf/udf_vfsops.c,v 1.23 2006/09/10 01:26:41 dillon Exp $
+ * $DragonFly: src/sys/vfs/udf/udf_vfsops.c,v 1.24 2006/10/27 04:56:34 dillon Exp $
*/
/* udf_vfsops.c */
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
nlookup_done(&nd);
if (error)
return (error);
*
* @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
* $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.117.2.10 2002/06/23 22:34:52 iedowse Exp $
- * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.50 2006/09/10 01:26:41 dillon Exp $
+ * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.51 2006/10/27 04:56:34 dillon Exp $
*/
#include "opt_quota.h"
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &devvp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
nlookup_done(&nd);
if (error)
goto error_1;
*
* @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
* $FreeBSD: src/sys/miscfs/union/union_vfsops.c,v 1.39.2.2 2001/10/25 19:18:53 dillon Exp $
- * $DragonFly: src/sys/vfs/union/union_vfsops.c,v 1.27 2006/09/19 16:06:17 dillon Exp $
+ * $DragonFly: src/sys/vfs/union/union_vfsops.c,v 1.28 2006/10/27 04:56:34 dillon Exp $
*/
/*
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &upperrootvp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &upperrootvp);
nlookup_done(&nd);
if (error)
goto bad;
*
* @(#)vm_swap.c 8.5 (Berkeley) 2/17/94
* $FreeBSD: src/sys/vm/vm_swap.c,v 1.96.2.2 2001/10/14 18:46:47 iedowse Exp $
- * $DragonFly: src/sys/vm/vm_swap.c,v 1.30 2006/09/10 01:26:41 dillon Exp $
+ * $DragonFly: src/sys/vm/vm_swap.c,v 1.31 2006/10/27 04:56:34 dillon Exp $
*/
#include "opt_swap.h"
if (error == 0)
error = nlookup(&nd);
if (error == 0)
- error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp);
+ error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error)
return (error);
* @(#) Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved.
* @(#)fstat.c 8.3 (Berkeley) 5/2/95
* $FreeBSD: src/usr.bin/fstat/fstat.c,v 1.21.2.7 2001/11/21 10:49:37 dwmalone Exp $
- * $DragonFly: src/usr.bin/fstat/fstat.c,v 1.19 2006/09/11 20:24:57 dillon Exp $
+ * $DragonFly: src/usr.bin/fstat/fstat.c,v 1.20 2006/10/27 04:56:27 dillon Exp $
*/
#define _KERNEL_STRUCTURES
void dofiles(struct kinfo_proc *kp);
void dommap(struct kinfo_proc *kp);
-void vtrans(struct vnode *vp, struct namecache *ncp, int i, int flag);
+void vtrans(struct vnode *vp, struct nchandle *ncr, int i, int flag);
int ufs_filestat(struct vnode *vp, struct filestat *fsp);
int nfs_filestat(struct vnode *vp, struct filestat *fsp);
-char *getmnton(struct mount *m, struct namecache_list *ncplist, struct namecache *ncp);
+char *getmnton(struct mount *m, struct namecache_list *ncplist, struct nchandle *ncr);
void pipetrans(struct pipe *pi, int i, int flag);
void socktrans(struct socket *sock, int i);
void getinetproto(int number);
* root directory vnode, if one
*/
if (filed.fd_rdir)
- vtrans(filed.fd_rdir, filed.fd_nrdir, RDIR, FREAD);
+ vtrans(filed.fd_rdir, &filed.fd_nrdir, RDIR, FREAD);
/*
* current working directory vnode
*/
- vtrans(filed.fd_cdir, filed.fd_ncdir, CDIR, FREAD);
+ vtrans(filed.fd_cdir, &filed.fd_ncdir, CDIR, FREAD);
/*
* ktrace vnode, if one
*/
continue;
}
if (file.f_type == DTYPE_VNODE) {
- vtrans((struct vnode *)file.f_data, file.f_ncp, i,
+ vtrans((struct vnode *)file.f_data, &file.f_nchandle, i,
file.f_flag);
} else if (file.f_type == DTYPE_SOCKET) {
if (checkfile == 0)
#ifdef DTYPE_FIFO
else if (file.f_type == DTYPE_FIFO) {
if (checkfile == 0)
- vtrans((struct vnode *)file.f_data, file.f_ncp,
+ vtrans((struct vnode *)file.f_data, &file.f_nchandle,
i, file.f_flag);
}
#endif
}
void
-vtrans(struct vnode *vp, struct namecache *ncp, int i, int flag)
+vtrans(struct vnode *vp, struct nchandle *ncr, int i, int flag)
{
struct vnode vn;
struct filestat fst;
if (nflg)
(void)printf(" %3d,%-9d ", major(fst.fsid), minor(fst.fsid));
else
- (void)printf(" %-*s", wflg_mnt, getmnton(vn.v_mount, &vn.v_namecache, ncp));
+ (void)printf(" %-*s", wflg_mnt, getmnton(vn.v_mount, &vn.v_namecache, ncr));
if (nflg)
(void)sprintf(mode, "%o", fst.mode);
else
char *
-getmnton(struct mount *m, struct namecache_list *ncplist, struct namecache *ncp)
+getmnton(struct mount *m, struct namecache_list *ncplist, struct nchandle *ncr)
{
static struct mount mount_l;
static struct mtab {
char mntonname[MNAMELEN];
} *mhead = NULL;
struct mtab *mt;
+ struct namecache *ncp;
struct namecache ncp_copy;
static char path[1024];
int i;
/*
* If no ncp is passed try to find one via ncplist.
*/
- if (ncp == NULL) {
+ if (ncr == NULL || ncr->ncp == NULL) {
ncp = ncplist->tqh_first;
+ } else {
+ ncp = ncr->ncp;
}
/*
warnx("can't read ncp at %p", ncp);
return (NULL);
}
- if (ncp_copy.nc_flag & NCF_MOUNTPT) {
- ncp = ncp_copy.nc_parent;
- continue;
- }
if (i <= ncp_copy.nc_nlen)
break;
i -= ncp_copy.nc_nlen;