- /*
- * 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;
- if (error = tsleep((caddr_t)&vp->v_exlockc, priority,
- lockstr, 0))
- return (error);
- }
- if (error = 0 && (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;
- if (error = tsleep((caddr_t)&vp->v_shlockc, PLOCK | PCATCH,
- lockstr, 0) == 0)
- return (error);
- }
- 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);