FreeBSD/sys/nfs/nfs_lock.c
/*
 * nfs_advlock --
 *      NFS advisory byte-level locks.
 *
 * The vnode shall be (shared) locked on the entry, it is
 * unconditionally unlocked after.
 */
nfs_advlock
NFS advisory byte-level locks.

The vnode shall be (shared) locked on the entry, it is
unconditionally unlocked after.
nfs_advlock NFS advisory byte - level locks . The vnode shall be ( shared ) locked on the entry it is unconditionally unlocked after .
int
nfs_dolock(struct vop_advlock_args *ap)
{
	LOCKD_MSG msg;
	struct thread *td;
	struct vnode *vp;
	int error;
	struct flock *fl;
	struct proc *p;
	struct nfsmount *nmp;
	td = curthread;
	p = td->td_proc;
	vp = ap->a_vp;
	fl = ap->a_fl;
	nmp = VFSTONFS(vp->v_mount);
	ASSERT_VOP_LOCKED(vp, "nfs_dolock");
	nmp->nm_getinfo(vp, msg.lm_fh, &msg.lm_fh_len, &msg.lm_addr,
	    &msg.lm_nfsv3, NULL, NULL);
	VOP_UNLOCK(vp, 0);
	if (fl->l_whence != SEEK_END) {
		if ((fl->l_whence != SEEK_CUR && fl->l_whence != SEEK_SET) ||
		    fl->l_start < 0 ||
		    (fl->l_len < 0 &&
		     (fl->l_start == 0 || fl->l_start + fl->l_len < 0)))
			return (EINVAL);
		if (fl->l_len > 0 &&
			 (fl->l_len - 1 > OFF_MAX - fl->l_start))
			return (EOVERFLOW);
	}
	msg.lm_version = LOCKD_MSG_VERSION;
	msg.lm_msg_ident.pid = p->p_pid;
	mtx_lock(&Giant);
	if (p->p_nlminfo == NULL) {
		p->p_nlminfo = malloc(sizeof(struct nlminfo),
		    M_NLMINFO, M_WAITOK | M_ZERO);
		p->p_nlminfo->pid_start = p->p_stats->p_start;
		timevaladd(&p->p_nlminfo->pid_start, &boottime);
	}
	msg.lm_msg_ident.pid_start = p->p_nlminfo->pid_start;
	msg.lm_msg_ident.msg_seq = ++(p->p_nlminfo->msg_seq);
	msg.lm_fl = *fl;
	msg.lm_wait = ap->a_flags & F_WAIT;
	msg.lm_getlk = ap->a_op == F_GETLK;
	cru2x(td->td_ucred, &msg.lm_cred);
	for (;;) {
		error = nfslock_send(&msg);
		if (error)
			goto out;
		if (fl->l_type == F_UNLCK)
			goto out;
		error = tsleep(p->p_nlminfo, PUSER, "lockd", 20*hz);
		if (error != 0) {
			if (error == EWOULDBLOCK) {
				continue;
			}
			break;
		}
		if (msg.lm_getlk && p->p_nlminfo->retcode == 0) {
			if (p->p_nlminfo->set_getlk_pid) {
				fl->l_sysid = 0; 
				fl->l_pid = p->p_nlminfo->getlk_pid;
			} else {
				fl->l_type = F_UNLCK;
			}
		}
		error = p->p_nlminfo->retcode;
		break;
	}
 out:
	mtx_unlock(&Giant);
	return (error);
}
int nfs_dolock ( struct vop_advlock_args * ap ) { LOCKD_MSG msg ; struct thread * td ; struct vnode * vp ; int error ; struct flock * fl ; struct proc * p ; struct nfsmount * nmp ; td = curthread ; p = td -> td_proc ; vp = ap -> a_vp ; fl = ap -> a_fl ; nmp = VFSTONFS ( vp -> v_mount ) ; ASSERT_VOP_LOCKED ( vp , " " ) ; nmp -> nm_getinfo ( vp , msg . lm_fh , & msg . lm_fh_len , & msg . lm_addr , & msg . lm_nfsv3 , NULL , NULL ) ; VOP_UNLOCK ( vp , 0 ) ; if ( fl -> l_whence != SEEK_END ) { if ( ( fl -> l_whence != SEEK_CUR && fl -> l_whence != SEEK_SET ) || fl -> l_start < 0 || ( fl -> l_len < 0 && ( fl -> l_start == 0 || fl -> l_start + fl -> l_len < 0 ) ) ) return ( EINVAL ) ; if ( fl -> l_len > 0 && ( fl -> l_len - 1 > OFF_MAX - fl -> l_start ) ) return ( EOVERFLOW ) ; } msg . lm_version = LOCKD_MSG_VERSION ; msg . lm_msg_ident . pid = p -> p_pid ; mtx_lock ( & Giant ) ; if ( p -> p_nlminfo == NULL ) { p -> p_nlminfo = malloc ( sizeof ( struct nlminfo ) , M_NLMINFO , M_WAITOK | M_ZERO ) ; p -> p_nlminfo -> pid_start = p -> p_stats -> p_start ; timevaladd ( & p -> p_nlminfo -> pid_start , & boottime ) ; } msg . lm_msg_ident . pid_start = p -> p_nlminfo -> pid_start ; msg . lm_msg_ident . msg_seq = ++ ( p -> p_nlminfo -> msg_seq ) ; msg . lm_fl = * fl ; msg . lm_wait = ap -> a_flags & F_WAIT ; msg . lm_getlk = ap -> a_op == F_GETLK ; cru2x ( td -> td_ucred , & msg . lm_cred ) ; for ( ; ; ) { error = nfslock_send ( & msg ) ; if ( error ) goto out ; if ( fl -> l_type == F_UNLCK ) goto out ; error = tsleep ( p -> p_nlminfo , PUSER , " " , 20 * hz ) ; if ( error != 0 ) { if ( error == EWOULDBLOCK ) { continue ; } break ; } if ( msg . lm_getlk && p -> p_nlminfo -> retcode == 0 ) { if ( p -> p_nlminfo -> set_getlk_pid ) { fl -> l_sysid = 0 ; fl -> l_pid = p -> p_nlminfo -> getlk_pid ; } else { fl -> l_type = F_UNLCK ; } } error = p -> p_nlminfo -> retcode ; break ; } out : mtx_unlock ( & Giant ) ; return ( error ) ; }
nfs_advlock
      NFS advisory byte-level locks.
nfs_advlock NFS advisory byte - level locks .
/*
	 * the NLM protocol doesn't allow the server to return an error
	 * on ranges, so we do it.
	 */ /*
	 * Fill in the information structure.
	 */ /*
	 * if there is no nfsowner table yet, allocate one.
	 */ /* Unlocks succeed immediately.  */ /*
		 * Retry after 20 seconds if we haven't gotten a response yet.
		 * This number was picked out of thin air... but is longer
		 * then even a reasonably loaded system should take (at least
		 * on a local network).  XXX Probably should use a back-off
		 * scheme.
		 *
		 * XXX: No PCATCH here since we currently have no useful
		 * way to signal to the userland rpc.lockd that the request
		 * has been aborted.  Once the rpc.lockd implementation
		 * can handle aborts, and we report them properly,
		 * PCATCH can be put back.  In the mean time, if we did
		 * permit aborting, the lock attempt would "get lost"
		 * and the lock would get stuck in the locked state.
		 */ /*
				 * We timed out, so we rewrite the request
				 * to the fifo.
				 */ /* XXX */