+ /*
+ * If there's a exclusive lock currently applied
+ * to the file, then we've gotta wait for the
+ * lock with everyone else.
+ */
+again:
+ while (vp->v_flag & VEXLOCK) {
+ /*
+ * If we're holding an exclusive
+ * lock, then release it.
+ */
+ if (fp->f_flag & FEXLOCK) {
+ vn_unlock(fp, FEXLOCK);
+ continue;
+ }
+ if (cmd & LOCK_NB)
+ return (EWOULDBLOCK);
+ vp->v_flag |= VLWAIT;
+ sleep((caddr_t)&vp->v_exlockc, priority);
+ }
+ if ((cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) {
+ /*
+ * Must wait for any shared locks to finish
+ * before we try to apply a exclusive lock.
+ *
+ * If we're holding a shared
+ * lock, then release it.
+ */
+ if (fp->f_flag & FSHLOCK) {
+ vn_unlock(fp, FSHLOCK);
+ goto again;
+ }
+ if (cmd & LOCK_NB)
+ return (EWOULDBLOCK);
+ vp->v_flag |= VLWAIT;
+ sleep((caddr_t)&vp->v_shlockc, PLOCK);
+ goto again;
+ }
+ if (fp->f_flag & FEXLOCK)
+ panic("vn_lock");
+ if (cmd & LOCK_EX) {
+ cmd &= ~LOCK_SH;
+ vp->v_exlockc++;
+ vp->v_flag |= VEXLOCK;
+ fp->f_flag |= FEXLOCK;
+ }
+ if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {
+ vp->v_shlockc++;
+ vp->v_flag |= VSHLOCK;
+ fp->f_flag |= FSHLOCK;
+ }
+ return (0);
+}
+
+/*
+ * Unlock a file.
+ */
+vn_unlock(fp, kind)
+ register struct file *fp;
+ int kind;
+{
+ register struct vnode *vp = (struct vnode *)fp->f_data;
+ int flags;
+
+ kind &= fp->f_flag;
+ if (vp == NULL || kind == 0)
+ return;
+ flags = vp->v_flag;
+ if (kind & FSHLOCK) {
+ if ((flags & VSHLOCK) == 0)
+ panic("vn_unlock: SHLOCK");
+ if (--vp->v_shlockc == 0) {
+ vp->v_flag &= ~VSHLOCK;
+ if (flags & VLWAIT)
+ wakeup((caddr_t)&vp->v_shlockc);
+ }
+ fp->f_flag &= ~FSHLOCK;
+ }
+ if (kind & FEXLOCK) {
+ if ((flags & VEXLOCK) == 0)
+ panic("vn_unlock: EXLOCK");
+ if (--vp->v_exlockc == 0) {
+ vp->v_flag &= ~(VEXLOCK|VLWAIT);
+ if (flags & VLWAIT)
+ wakeup((caddr_t)&vp->v_exlockc);
+ }
+ fp->f_flag &= ~FEXLOCK;
+ }
+}
+
+/*
+ * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
+ * - look up fsid in mount list (if not found ret error)
+ * - get vp by calling VFS_FHTOVP() macro
+ * - if lockflag lock it with VOP_LOCK()
+ */
+vn_fhtovp(fhp, lockflag, vpp)
+ fhandle_t *fhp;
+ int lockflag;
+ struct vnode **vpp;
+{
+ register struct mount *mp;
+
+ if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
+ return (ESTALE);
+ if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
+ return (ESTALE);
+ if (!lockflag)
+ VOP_UNLOCK(*vpp);
+ return (0);
+}
+
+/*
+ * Noop
+ */
+vfs_noop()
+{
+
+ return (ENXIO);
+}
+
+/*
+ * Null op
+ */
+vfs_nullop()
+{
+
+ return (0);