Beispiel #1
0
static int
nnpfs_dnlc_lock(struct vnode *dvp,
	      nnpfs_componentname *cnp,
	      struct vnode **res)
{
    int error = 0;

    /*
     * Try to handle the (complex) BSD locking protocol.
     */

    if (*res == dvp) {		/* "." */
	vref(dvp);
    } else if (cnp->cn_flags & ISDOTDOT) { /* ".." */
	u_long vpid = dvp->v_id;

#ifdef HAVE_FREEBSD_THREAD
	nnpfs_vfs_unlock(dvp, nnpfs_cnp_to_thread(cnp));
	error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_thread(cnp));
	nnpfs_vfs_writelock(dvp, nnpfs_cnp_to_thread(cnp));
#else
	nnpfs_vfs_unlock(dvp, nnpfs_cnp_to_proc(cnp));
	error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_proc(cnp));
	nnpfs_vfs_writelock(dvp, nnpfs_cnp_to_proc(cnp));
#endif

	if (error == 0 && dvp->v_id != vpid) {
	    vput(*res);
	    return 0;
	}
    } else {
#ifdef HAVE_FREEBSD_THREAD
	error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_thread(cnp));
#else
	error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_proc(cnp));
#endif
    }

    if (error == 0)
	return -1;
    else
	return 0;
}
int
nnpfs_fhopen (d_thread_t *proc,
	    struct nnpfs_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 nnpfs_fhandle_t fh;

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

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

    error = nnpfs_fhlookup (proc, &fh, &vp);
    NNPFSDEB(XDEBVFOPS, ("nnpfs_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 = nnpfs_vfs_object_create(vp, proc, proc->td_proc->p_ucred);
#else
	error = nnpfs_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;
    nnpfs_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, ("nnpfs_fhopen: error = %d\n", error));
    vput(vp);
    return error;
}
Beispiel #3
0
int
nnpfs_dnlc_enter(struct vnode *dvp,
	       nnpfs_componentname *cnp,
	       struct vnode *vp)
{
    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter_cnp(%lx, %lx, %lx)\n",
		      (unsigned long)dvp,
		      (unsigned long)cnp,
		      (unsigned long)vp));
    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter: v_id = %lu\n", (u_long)dvp->v_id));

    NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter: calling cache_enter:"
		      "dvp = %lx, vp = %lx, cnp = (%s, %ld), "
		      "nameiop = %lu, flags = %lx\n",
		      (unsigned long)dvp,
		      (unsigned long)vp,
		      cnp->cn_nameptr, cnp->cn_namelen,
		      cnp->cn_nameiop, cnp->cn_flags));

#ifdef NCHNAMLEN
    if (cnp->cn_namelen <= NCHNAMLEN)
#endif
    {
	/*
	 * This is to make sure there's no negative entry already in the dnlc
	 */
	u_long save_nameiop;
	u_long save_flags;
	struct vnode *dummy;

	save_nameiop    = cnp->cn_nameiop;
	save_flags      = cnp->cn_flags;
	cnp->cn_nameiop = CREATE;
	cnp->cn_flags  &= ~MAKEENTRY;

/*
 * The version number here is not entirely correct, but it's conservative.
 * The real change is sys/kern/vfs_cache:1.20
 */

#if __NetBSD_Version__ >= 104120000 || OpenBSD > 200211
	if (cache_lookup(dvp, &dummy, cnp) != -1) {
	    nnpfs_vfs_unlock(dummy, nnpfs_cnp_to_proc(cnp));
	    printf ("NNPFS PANIC WARNING! nnpfs_dnlc_enter: %s already in cache\n",
		    cnp->cn_nameptr);
	}
#else
	if (cache_lookup(dvp, &dummy, cnp) != 0) {
	    printf ("NNPFS PANIC WARNING! nnpfs_dnlc_enter: %s already in cache\n",
		    cnp->cn_nameptr);
	}
#endif


	cnp->cn_nameiop = save_nameiop;
	cnp->cn_flags   = save_flags;
	cache_enter(dvp, vp, cnp);
    }

    if (vp != NULL)
	tbl_enter (cnp->cn_namelen, cnp->cn_nameptr, dvp, vp);

    return 0;
}