Esempio n. 1
0
static int
nnpfs_dnlc_lookup_int(struct vnode *dvp,
		    nnpfs_componentname *cnp,
		    struct vnode **res)
{
    int error;
    u_long saved_flags;

    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup(%lx, \"%s\")\n",
		      (unsigned long)dvp, cnp->cn_nameptr));
    
    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup: v_id = %lu\n", (u_long)dvp->v_id));
    
    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup: calling cache_lookup:"
		      "dvp = %lx, cnp = (%s, %ld), flags = %lx\n",
		      (unsigned long)dvp,
		      cnp->cn_nameptr, cnp->cn_namelen,
		      cnp->cn_flags));

    saved_flags = cnp->cn_flags;
    cnp->cn_flags |= MAKEENTRY | LOCKPARENT | ISLASTCN;

    error = cache_lookup(dvp, res, cnp);

    cnp->cn_flags = saved_flags;

    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup: cache_lookup returned. "
		      "error = %d, *res = %lx\n", error,
		      (unsigned long)*res));
    return error;
}
Esempio n. 2
0
void
free_nnpfs_node(struct nnpfs_node *node)
{
    struct nnpfs *nnpfsp = NNPFS_FROM_XNODE(node);

    NNPFSDEB(XDEBNODE, ("free_nnpfs_node(%lx) (%d,%d,%d,%d)\n",
		      (unsigned long)node,
		      node->handle.a,
		      node->handle.b,
		      node->handle.c,
		      node->handle.d));

    /* XXX Really need to put back dirty data first. */

    if (DATA_FROM_XNODE(node)) {
	vrele(DATA_FROM_XNODE(node));
	DATA_FROM_XNODE(node) = NULL;
    }
    nnpfsp->nnodes--;
    XNODE_TO_VNODE(node)->v_data = NULL;
    if (node->rd_cred) {
	crfree (node->rd_cred);
	node->rd_cred = NULL;
    }
    if (node->wr_cred) {
	crfree (node->wr_cred);
	node->wr_cred = NULL;
    }

    nnpfs_free(node, sizeof(*node), M_NNPFS_NODE);

    NNPFSDEB(XDEBNODE, ("free_nnpfs_node done\n"));
}
int
xfs_vptofh(struct vnode * vp,
	   struct fid * fhp)
{
#ifdef ARLA_KNFS
    struct xfs_node *xn;
    NNPFSDEB(XDEBVFOPS, ("xfs_vptofh\n"));

    if (MAXFIDSZ < 16)
	return EOPNOTSUPP;

    xn = VNODE_TO_XNODE(vp);

    if (xn == NULL)
	return EINVAL;

    fhp->fid_len = 16;
    memcpy(fhp->fid_data, &xn->handle,  16);

    return 0;
#else
    NNPFSDEB(XDEBVFOPS, ("xfs_vptofh\n"));
    return EOPNOTSUPP;
#endif
}
Esempio n. 4
0
int
new_nnpfs_node(struct nnpfs *nnpfsp,
	     struct nnpfs_msg_node *node,
	     struct nnpfs_node **xpp,
	     d_thread_t *p)
{
    struct nnpfs_node *result;

    NNPFSDEB(XDEBNODE, ("new_nnpfs_node (%d,%d,%d,%d)\n",
		      node->handle.a,
		      node->handle.b,
		      node->handle.c,
		      node->handle.d));

retry:
    /* Does not allow duplicates */
    result = nnpfs_node_find(&nnpfsp->nodehead, &node->handle);
    if (result == 0) {
	int error;
	struct vnode *v;

	error = nnpfs_getnewvnode(nnpfsp, &v, &node->handle);
	if (error)
	    return error;

	result = VNODE_TO_XNODE(v);
	result->anonrights = node->anonrights;

	nnpfsp->nnodes++;
    } else {
	/* Node is already cached */
	if(nnpfs_do_vget(XNODE_TO_VNODE(result), 0, p))
	    goto retry;
    }

    /* Init other fields */
    nnpfs_attr2vattr(&node->attr, &result->attr, 1);
    result->vn->v_type = result->attr.va_type;
    result->tokens = node->tokens;
    bcopy(node->id, result->id, sizeof(result->id));
    bcopy(node->rights, result->rights, sizeof(result->rights));

#ifdef __APPLE__
    if (result->vn->v_type == VREG && (!UBCINFOEXISTS(result->vn)))
	ubc_info_init(result->vn);
#endif

    *xpp = result;
    NNPFSDEB(XDEBNODE, ("return: new_nnpfs_node\n"));
    return 0;
}
Esempio n. 5
0
int
nnpfs_pioctl_call(d_thread_t *proc,
		struct sys_pioctl_args *arg,
		register_t *return_value)
{
    int error;
    struct ViceIoctl vice_ioctl;
    char *pathptr;
    struct vnode *vp = NULL;

    NNPFSDEB(XDEBSYS, ("nnpfs_syscall(%d, %lx, %d, %lx, %d)\n", 
		     SCARG(arg, operation),
		     (unsigned long)SCARG(arg, a_pathP),
		     SCARG(arg, a_opcode),
		     (unsigned long)SCARG(arg, a_paramsP),
		     SCARG(arg, a_followSymlinks)));

    /* Copy in the data structure for us */

    error = copyin(SCARG(arg, a_paramsP),
		   &vice_ioctl,
		   sizeof(vice_ioctl));

    if (error)
	return error;

    pathptr = SCARG(arg, a_pathP);

    if (pathptr != NULL) {
	error = lookup_node (pathptr, SCARG(arg, a_followSymlinks), &vp,
			     proc);
	if(error)
	    return error;
    }
	
    switch (SCARG(arg, a_opcode)) {
    case VIOC_FHGET :
	return fhget_call (proc, &vice_ioctl, vp);
    case VIOC_FHOPEN :
	return fhopen_call (proc, &vice_ioctl, vp,
			    SCARG(arg, a_followSymlinks), return_value);
    case VIOC_NNPFSDEBUG :
	if (vp != NULL)
	    vrele (vp);
	return nnpfs_debug (proc, &vice_ioctl);
    default :
	NNPFSDEB(XDEBSYS, ("a_opcode = %x\n", SCARG(arg, a_opcode)));
	return remote_pioctl (proc, arg, &vice_ioctl, vp);
    }
}
Esempio n. 6
0
int
xfs_devopen(dev_t dev, int flag, int devtype, d_thread_t *proc)
{
	NNPFSDEB(XDEBDEV, ("xfsopen dev = %d.%d, flag = %d, devtype = %d\n", 
	    major(dev), minor(dev), flag, devtype));
	return xfs_devopen_common(dev);
}
int
xfs_start(struct mount * mp, int flags, d_thread_t * p)
{
    NNPFSDEB(XDEBVFOPS, ("xfs_start mp = %lx, flags = %d, proc = %lx\n", 
		       (unsigned long)mp, flags, (unsigned long)p));
    return 0;
}
Esempio n. 8
0
static int
fhget_call (d_thread_t *p,
	    struct ViceIoctl *vice_ioctl,
	    struct vnode *vp)
{
    int error;

    NNPFSDEB(XDEBSYS, ("fhget_call\n"));

    if (vp == NULL)
	return EBADF;

#if defined(__APPLE__) || defined(__osf__)
    error = EINVAL; /* XXX: Leaks vnodes if fhget/fhopen is used */
    goto out;
#endif

    error = nnpfs_suser (p);
    if (error)
	goto out;

#if (defined(HAVE_GETFH) && defined(HAVE_FHOPEN)) || defined(__osf__)
    error = getfh_compat (p, vice_ioctl, vp);
#else
    error = trad_fhget (p, vice_ioctl, vp);
#endif /* HAVE_GETFH && HAVE_FHOPEN */
out:
    vrele(vp);
    return error;
}
int
xfs_unmount(struct mount * mp, int mntflags, d_thread_t *p)
{
    NNPFSDEB(XDEBVFOPS, ("xfs_umount: mp = %lx, mntflags = %d, proc = %lx\n", 
		       (unsigned long)mp, mntflags, (unsigned long)p));
    return xfs_unmount_common(mp, mntflags);
}
Esempio n. 10
0
int
nnpfspioctl(syscall_d_thread_t *proc, void *varg, register_t *return_value)
#endif
{
#ifdef NNPFS_NOT_LKM
    struct sys_nnpfspioctl_args *arg = (struct sys_nnpfspioctl_args *) varg;
#else
    struct sys_pioctl_args *arg = (struct sys_pioctl_args *) varg;
#endif
    int error = EINVAL;

    switch (SCARG(arg, operation)) {
    case AFSCALL_PIOCTL:
	error = nnpfs_pioctl_call(syscall_thread_to_thread(proc),
				  varg, return_value);
	break;
    case AFSCALL_SETPAG:
#ifdef HAVE_FREEBSD_THREAD
	error = nnpfs_setpag_call(&nnpfs_thread_to_cred(proc));
#else
	error = nnpfs_setpag_call(&nnpfs_proc_to_cred(syscall_thread_to_thread(proc)));
#endif
	break;
    default:
	NNPFSDEB(XDEBSYS, ("Unimplemeted nnpfspioctl: %d\n",
			 SCARG(arg, operation)));
	error = EINVAL;
	break;
    }

    return error;
}
Esempio n. 11
0
void
nnpfs_dnlc_purge_mp(struct mount *mp)
{
    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_purge_mp()\n"));

    tbl_clear ();
    cache_purgevfs(mp);
}
Esempio n. 12
0
int
xfs_devclose(dev_t dev, int flag, int devtype, d_thread_t *p)
{
	NNPFSDEB(XDEBDEV, ("xfs_devclose dev = %d(%d), flag = 0x%x\n",
	   major(dev), minor(dev), flag));

	return xfs_devclose_common(dev, p);
}
Esempio n. 13
0
int
xfs_devioctl(dev_t dev,  u_long cmd,  caddr_t data, int flags,  d_thread_t *p)
{
	NNPFSDEB(XDEBDEV, ("xfs_devioctl dev = %d.%d, cmd = %lu, "
	    "data = %lx, flags = %x\n", major(dev), minor(dev), 
	    (unsigned long)cmd, (unsigned long)data, flags));
	return ENOTTY;
}
int
xfs_quotactl(struct mount *mp, int cmd, uid_t uid, caddr_t arg, d_thread_t *p)
{
    NNPFSDEB(XDEBVFOPS, ("xfs_quotactl: mp = %lx, cmd = %d, uid = %u, "
		       "arg = %lx, proc = %lx\n", 
		       (unsigned long)mp, cmd, uid,
		       (unsigned long)arg, (unsigned long)p));
    return EOPNOTSUPP;
}
Esempio n. 15
0
void
nnpfs_dnlc_purge (struct vnode *vp)
{
    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_purge\n"));

    if (tbl.dvp == vp || tbl.vp == vp)
	tbl_clear ();

    cache_purge(vp);
}
int
xfs_root(struct mount *mp, struct vnode **vpp)
{
    NNPFSDEB(XDEBVFOPS, ("xfs_root mp = %lx\n", (unsigned long)mp));
#ifdef HAVE_FREEBSD_THREAD
    return xfs_root_common(mp, vpp, xfs_curthread(), xfs_curthread()->td_proc->p_ucred);
#else
    return xfs_root_common(mp, vpp, xfs_curproc(), xfs_curproc()->p_ucred);
#endif
}
int
xfs_statfs(struct mount *mp, struct statfs *sbp, d_thread_t *p)
{
    NNPFSDEB(XDEBVFOPS, ("xfs_statfs: mp = %lx, sbp = %lx, proc = %lx\n", 
		       (unsigned long)mp,
		       (unsigned long)sbp,
		       (unsigned long)p));
    bcopy(&mp->mnt_stat, sbp, sizeof(*sbp));
    return 0;
}
Esempio n. 18
0
static int
lookup_node (const char *pathptr,
	     int follow_links_p,
	     struct vnode **res,
	     d_thread_t *proc)
{
    int error;
    char path[MAXPATHLEN];
#ifdef __osf__
    struct nameidata *ndp = &u.u_nd;
#else
    struct nameidata nd, *ndp = &nd;
#endif
    struct vnode *vp;
    size_t count;

    NNPFSDEB(XDEBSYS, ("nnpfs_syscall: looking up: %lx\n",
		     (unsigned long)pathptr));

    error = copyinstr((char *) pathptr, path, MAXPATHLEN, &count);

    NNPFSDEB(XDEBSYS, ("nnpfs_syscall: looking up: %s, error: %d\n", path, error));

    if (error)
	return error;

    NDINIT(ndp, LOOKUP,
	   follow_links_p ? FOLLOW : 0,
	   UIO_SYSSPACE, path, proc);

    error = namei(ndp);
	
    if (error != 0) {
	NNPFSDEB(XDEBSYS, ("nnpfs_syscall: error during namei: %d\n", error));
	return EINVAL;
    }

    vp = ndp->ni_vp;

    *res = vp;
    return 0;
}
int
xfs_sync(struct mount *mp, int waitfor, struct ucred *cred, d_thread_t *p)
{
    NNPFSDEB(XDEBVFOPS, ("xfs_sync: mp = %lx, waitfor = %d, "
		       "cred = %lx, proc = %lx\n",
		       (unsigned long)mp,
		       waitfor,
		       (unsigned long)cred,
		       (unsigned long)p));
    return 0;
}
int
xfs_vget(struct mount * mp,
#ifdef __APPLE__
	 void *ino,
#else
	 ino_t ino,
#endif
	 struct vnode ** vpp)
{
    NNPFSDEB(XDEBVFOPS, ("xfs_vget\n"));
    return EOPNOTSUPP;
}
Esempio n. 21
0
int
xfs_install_device(void)
{
	int i;

	for (i = 0; i < NNNPFS; i++) {
		NNPFSDEB(XDEBDEV, ("before initq(messageq and sleepq)\n"));
		xfs_initq(&xfs_channel[i].messageq);
		xfs_initq(&xfs_channel[i].sleepq);
		xfs_channel[i].status = 0;
	}
	return 0;
}
Esempio n. 22
0
int
nnpfs_dnlc_enter_name(struct vnode *dvp,
		    const char *name,
		    struct vnode *vp)
{
    struct componentname cn;

    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter_name(%lx, \"%s\", %lx)\n",
		      (unsigned long)dvp,
		      name,
		      (unsigned long)vp));

    nnpfs_cnp_init (&cn, name, NULL, NULL, LOOKUP);
    return nnpfs_dnlc_enter (dvp, &cn, vp);
}
Esempio n. 23
0
int
xfs_uninstall_device(void)
{
	int i;
	struct xfs_channel *chan;
	int ret = 0;
	
	for (i = 0; i < NNNPFS; i++) {
		chan = &xfs_channel[i];
		if (chan->status & CHANNEL_OPENED)
			xfs_devclose(makedev(0, i), 0, 0, NULL);
	}
	
	NNPFSDEB(XDEBLKM, ("xfs_uninstall_device error %d\n", ret));
	return ret;
}
Esempio n. 24
0
int
xfs_devpoll(dev_t dev, int events, d_thread_t * p)
{
	struct xfs_channel *chan = &xfs_channel[minor(dev)];
	
	NNPFSDEB(XDEBDEV, ("xfs_devpoll dev = %d(%d), events = 0x%x\n",
	    major(dev), minor(dev), events));

	if ((events & (POLLIN | POLLRDNORM)) == 0)
		return 0;			/* only supports read */
	
	if (!xfs_emptyq(&chan->messageq))
		return (events & (POLLIN | POLLRDNORM));
	
	selrecord (p, &chan->selinfo);

	return 0;
}
int
xfs_checkexp (struct mount *mp,
#ifdef __FreeBSD__
	      struct sockaddr *nam,
#else
	      struct mbuf *nam,
#endif
	      int *exflagsp,
	      struct ucred **credanonp)
{
    NNPFSDEB(XDEBVFOPS, ("xfs_checkexp\n"));

#if 0
    np = vfs_export_lookup(mp, &ump->um_export, nam);
    if (np == NULL)
	return EACCES;
#endif
    return 0;
}
Esempio n. 26
0
static int
trad_fhget (d_thread_t *p,
	    struct ViceIoctl *vice_ioctl,
	    struct vnode *vp)
{
    int error;
    struct mount *mnt;
    struct vattr vattr;
    size_t len;
    struct nnpfs_fhandle_t nnpfs_handle;
    struct nnpfs_fh_args fh_args;

#ifdef HAVE_FREEBSD_THREAD
    nnpfs_vop_getattr(vp, &vattr, nnpfs_thread_to_cred(p), p, error);
#else
    nnpfs_vop_getattr(vp, &vattr, nnpfs_proc_to_cred(p), p, error);
#endif
    if (error)
	return error;

    mnt = vp->v_mount;

    SCARG(&fh_args, fsid)   = mnt->mnt_stat.f_fsid;
    SCARG(&fh_args, fileid) = vattr.va_fileid;
    SCARG(&fh_args, gen)    = vattr.va_gen;
    
    nnpfs_handle.len = sizeof(fh_args);
    memcpy (nnpfs_handle.fhdata, &fh_args, sizeof(fh_args));
    len = sizeof(nnpfs_handle);

    if (vice_ioctl->out_size < len)
	return EINVAL;

    error = copyout (&nnpfs_handle, vice_ioctl->out, len);
    if (error) {
	NNPFSDEB(XDEBSYS, ("fhget_call: copyout failed: %d\n", error));
    }
    return error;
}
Esempio n. 27
0
static int
fhopen_call (d_thread_t *p,
	     struct ViceIoctl *vice_ioctl,
	     struct vnode *vp,
	     int flags,
	     register_t *retval)
{

    NNPFSDEB(XDEBSYS, ("fhopen_call: flags = %d\n", flags));

    if (vp != NULL) {
	vrele (vp);
	return EINVAL;
    }

#if defined(__APPLE__) || defined(__osf__)
    return EINVAL; /* XXX: Leaks vnodes if fhget/fhopen is used */
#endif

    return nnpfs_fhopen (p,
		       (struct nnpfs_fhandle_t *)vice_ioctl->in,
		       flags,
		       retval);
}
static int
common_fhtovp(struct mount * mp,
	   struct fid * fhp,
	   struct vnode ** vpp)
{
#ifdef ARLA_KNFS
    struct netcred *np = NULL;
    struct xfs_node *xn;
    struct vnode *vp;
    xfs_handle handle;
    int error;

    NNPFSDEB(XDEBVFOPS, ("xfs_fhtovp\n"));

    if (fhp->fid_len != 16) {
	printf("xfs_fhtovp: *PANIC* got a invalid length of a fid\n");
	return EINVAL;
    }

    memcpy(&handle, fhp->fid_data, sizeof(handle));
    NNPFSDEB(XDEBVFOPS, ("xfs_fhtovp: fid: %d.%d.%d.%d\n", 
		       handle.a, handle.d, handle.c, handle.d));

    NNPFSDEB(XDEBVFOPS, ("xfs_fhtovp: xfs_vnode_find\n"));
    xn = xfs_node_find(&xfs[0].nodehead, &handle);

    if (xn == NULL) {
	struct xfs_message_getattr msg;

        error = xfs_getnewvnode(xfs[0].mp, &vp, &handle);
        if (error)
            return error;
	
	xfs_do_vget(vp, 0, curproc);

    } else {
	/* XXX access ? */
	vp = XNODE_TO_VNODE(xn);

	/* XXX wrong ? (we tell arla below) */
        if (vp->v_usecount <= 0) 
	    xfs_do_vget(vp, 0, curproc);
	else
	    VREF(vp);
	error = 0;
    }

    *vpp = vp;

    if (error == 0) {
	NNPFSDEB(XDEBVFOPS, ("xfs_fhtovp done\n"));

	/* 
	 * XXX tell arla about this node is hold by nfsd.
	 * There need to be code in xfs_write too.
	 */
    } else
	NNPFSDEB(XDEBVFOPS, ("xfs_fhtovp failed (%d)\n", error));

    return error;
#else /* !ARLA_KNFS */
    return EOPNOTSUPP;
#endif /* !ARLA_KNFS */
}
int
xfs_fhopen (d_thread_t *proc,
	    struct xfs_fhandle_t *fhp,
	    int user_flags,
	    register_t *retval)
{
    int error;
    struct vnode *vp;
#ifdef HAVE_FREEBSD_THREAD
    struct ucred *cred = proc->td_proc->p_ucred;
#else
    struct ucred *cred = proc->p_ucred;
#endif
    int flags = FFLAGS(user_flags);
    int index;
    struct file *fp;
    int mode;
    struct xfs_fhandle_t fh;

    NNPFSDEB(XDEBVFOPS, ("xfs_fhopen: flags = %d\n", user_flags));

    error = copyin (fhp, &fh, sizeof(fh));
    if (error)
	return error;

    error = xfs_fhlookup (proc, &fh, &vp);
    NNPFSDEB(XDEBVFOPS, ("xfs_fhlookup returned %d\n", error));
    if (error)
	return error;

    switch (vp->v_type) {
    case VDIR :
    case VREG :
	break;
    case VLNK :
	error = EMLINK;
	goto out;
    default :
	error = EOPNOTSUPP;
	goto out;
    }

    mode = 0;
    if (flags & FWRITE) {
	switch (vp->v_type) {
	case VREG :
	    break;
	case VDIR :
	    error = EISDIR;
	    goto out;
	default :
	    error = EOPNOTSUPP;
	    goto out;
	}

	error = vn_writechk (vp);
	if (error)
	    goto out;

	mode |= VWRITE;
    }
    if (flags & FREAD)
	mode |= VREAD;

    if (mode) {
	error = VOP_ACCESS(vp, mode, cred, proc);
	if (error)
	    goto out;
    }

    error = VOP_OPEN(vp, flags, cred, proc);
    if (error)
	goto out;

    error = falloc(proc, &fp, &index);
    if (error)
	goto out;

    if (flags & FWRITE)
        vp->v_writecount++;

#if defined(__FreeBSD_version) && __FreeBSD_version >= 300000
    if (vp->v_type == VREG) {
#ifdef HAVE_FREEBSD_THREAD
	error = xfs_vfs_object_create(vp, proc, proc->td_proc->p_ucred);
#else
	error = xfs_vfs_object_create(vp, proc, proc->p_ucred);
#endif
	if (error)
	    goto out;
    }
#endif

    fp->f_flag = flags & FMASK;
    fp->f_type = DTYPE_VNODE;
    fp->f_ops  = &vnops;
    fp->f_data = (caddr_t)vp;
    xfs_vfs_unlock(vp, proc);
    *retval = index;
#ifdef FILE_UNUSE
    FILE_UNUSE(fp, proc);
#endif
#ifdef __APPLE__
    *fdflags(proc, index) &= ~UF_RESERVED;
#endif
    return 0;
out:
    NNPFSDEB(XDEBVFOPS, ("xfs_fhopen: error = %d\n", error));
    vput(vp);
    return error;
}
int
xfs_fhlookup (d_thread_t *proc,
	      struct xfs_fhandle_t *fhp,
	      struct vnode **vpp)
{
    int error;
    struct mount *mp;
#if !(defined(HAVE_GETFH) && defined(HAVE_FHOPEN))
    struct ucred *cred = proc->p_ucred;
    struct vattr vattr;
    fsid_t fsid;
    struct xfs_fh_args *fh_args = (struct xfs_fh_args *)fhp->fhdata;

    NNPFSDEB(XDEBVFOPS, ("xfs_fhlookup (xfs)\n"));

    error = xfs_suser (proc);
    if (error)
	return EPERM;

    if (fhp->len < sizeof(struct xfs_fh_args))
	return EINVAL;
    
    fsid = SCARG(fh_args, fsid);

    mp = xfs_vfs_getvfs (&fsid);
    if (mp == NULL)
	return ENXIO;

#ifdef __APPLE__
    {
	uint32_t ino = SCARG(fh_args, fileid);
	error = VFS_VGET(mp, &ino, vpp);
    }
#else
    error = VFS_VGET(mp, SCARG(fh_args, fileid), vpp);
#endif

    if (error)
	return error;

    if (*vpp == NULL)
	return ENOENT;

    error = VOP_GETATTR(*vpp, &vattr, cred, proc);
    if (error) {
	vput(*vpp);
	return error;
    }

    if (vattr.va_gen != SCARG(fh_args, gen)) {
	vput(*vpp);
	return ENOENT;
    }
#else /* HAVE_GETFH && HAVE_FHOPEN */
    {
	fhandle_t *fh = (fhandle_t *) fhp;

	NNPFSDEB(XDEBVFOPS, ("xfs_fhlookup (native)\n"));

	mp = xfs_vfs_getvfs (&fh->fh_fsid);
	if (mp == NULL)
	    return ESTALE;

	if ((error = VFS_FHTOVP(mp, &fh->fh_fid, vpp)) != 0) {
	    *vpp = NULL;
	    return error;
	}
    }
#endif  /* HAVE_GETFH && HAVE_FHOPEN */

#ifdef HAVE_KERNEL_VFS_OBJECT_CREATE
    if ((*vpp)->v_type == VREG && (*vpp)->v_object == NULL)
#ifdef HAVE_FREEBSD_THREAD
	xfs_vfs_object_create (*vpp, proc, proc->td_proc->p_ucred);
#else
	xfs_vfs_object_create (*vpp, proc, proc->p_ucred);
#endif
#elif __APPLE__
    if ((*vpp)->v_type == VREG && (!UBCINFOEXISTS(*vpp))) {
        ubc_info_init(*vpp);
    }
    ubc_hold(*vpp);
#endif
    return 0;
}