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; }
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; }