📄 klm_lockmgr.c
字号:
} case KLM_TEST: switch (error) { case klm_granted: ld->l_type = F_UNLCK; /* mark lock available */ error = 0; goto ereturn; case klm_denied: ld->l_type = (reply.klm_testrply_u.holder.exclusive) ? F_WRLCK : F_RDLCK; ld->l_start = reply.klm_testrply_u.holder.l_offset; ld->l_len = reply.klm_testrply_u.holder.l_len; ld->l_pid = reply.klm_testrply_u.holder.svid; error = 0; goto ereturn; case klm_denied_nolocks: goto nolocks_wait; /* back off; loop forever */ case EINTR: /* may want to take a longjmp here */ goto requestloop; /* loop forever */ } }/*NOTREACHED*/nolocks_wait: timeout(wakeup, (caddr_t)&lm_sa, (klm_backoff_timeout * hz)); (void) sleep((caddr_t)&lm_sa, PZERO|PCATCH); untimeout(wakeup, (caddr_t)&lm_sa); goto requestloop; /* now try again */cancel: if(klm_debug) printf("klm_lockctl: request canceled for pid:%d\n", args.alock.pid); /* * If we get here, a signal interrupted a rqst that must be cancelled. * Change the procedure number to KLM_CANCEL and reissue the exact same * request. Use the results to decide what return value to give. */ xdrproc = KLM_CANCEL; error = talk_to_lockmgr(xdrproc,xdrargs, &args, xdrreply, &reply, cred); switch (error) { case klm_granted: error = 0; /* lock granted */ goto ereturn; case klm_denied: /* may want to take a longjmp here */ error = EINTR; goto ereturn; case EINTR: goto cancel; /* ignore signals til cancel succeeds */ case klm_denied_nolocks: error = ENOLCK; /* no resources available?! */ goto ereturn; case ENOLCK: goto ereturn; }/*NOTREACHED*/ereturn: if(klm_debug) printf("klm_lockctl: returning: err: %d\n", error); return(error);}/* * Send the given request to the local lock-manager. * If timeout or error, go back to the portmapper to check the port number. * This routine loops forever until one of the following occurs: * 1) A legitimate (not 'klm_working') reply is returned (returns 'stat'). * * 2) A signal occurs (returns EINTR). In this case, at least one try * has been made to do the RPC; this protects against jamming the * CPU if a KLM_CANCEL request has yet to go out. * * 3) A drastic error occurs (e.g., the local lock-manager has never * been activated OR cannot create a client-handle) (returns ENOLCK). */statictalk_to_lockmgr(xdrproc, xdrargs, args, xdrreply, reply, cred) u_long xdrproc; xdrproc_t xdrargs; klm_lockargs *args; xdrproc_t xdrreply; klm_testrply *reply; struct ucred *cred;{ register CLIENT *client; struct timeval tmo; register int error; register int retries; /* set up a client handle to talk to the local lock manager */ client = clntkudp_create(&lm_sa, (u_long)KLM_PROG, (u_long)KLM_VERS, klm_first_retry, cred); if (client == (CLIENT *) NULL) { return(ENOLCK); } tmo.tv_sec = klm_first_timeout; tmo.tv_usec = 0; /* init and manage xid on behalf of lockd/kernel communication */ smp_lock(&lk_rpcxid, LK_RETRY); if (!lm_xid) lm_xid = time.tv_sec; client->cl_xid = lm_xid++; smp_unlock(&lk_rpcxid); /* * If cached port number, go right to CLNT_CALL(). * This works because timeouts go back to the portmapper to * refresh the port number. */ if (lm_sa.sin_port != 0) { retries = klm_timeout_retry; goto retryloop; /* skip first portmapper query */ } for (;;) {remaploop: if (klm_debug) { printf ("remap: pid:%d proc:%d %d %d\n", args->alock.pid, (int) xdrproc, time.tv_sec, lm_xid); } /* go get the port number from the portmapper... * if return 1, signal was received before portmapper answered; * if return -1, the lock-manager is not registered * else, got a port number */ switch(getport_loop(&lm_sa, (u_long)KLM_PROG, (u_long)KLM_VERS, (u_long)KLM_PROTO)) { case 1: error = EINTR; /* signal interrupted things */ goto out; case -1: error = ENOLCK; goto out; } /* * If a signal occurred, pop back out to the higher * level to decide what action to take. If we just * got a port number from the portmapper, the next * call into this subroutine will jump to retryloop. */ if (ISSIG(u.u_procp,0)) { error = EINTR; goto out; } /* reset the lock-manager client handle */ (void) clntkudp_init(client, &lm_sa, klm_remap_retry, cred); tmo.tv_sec = klm_normal_timeout; retries = klm_timeout_retry;retryloop: if (klm_debug) { printf ("retry: pid:%d proc:%d %d %d %d\n", args->alock.pid, (int) xdrproc, time.tv_sec, lm_xid, retries); } /* retry the request until completion, timeout, or error */ for (;;) { smp_lock(&lk_rpcxid, LK_RETRY); client->cl_xid = lm_xid++; smp_unlock(&lk_rpcxid); error = (int) CLNT_CALL(client, xdrproc, xdrargs, (caddr_t)args, xdrreply, (caddr_t)reply, tmo); if (klm_debug)printf("retry: rec'd: pid:%d proce:%d [off:%d,len:%d] err:%d rs:%d %d %d\n", args->alock.pid, (int) xdrproc, args->alock.l_offset, args->alock.l_len, error, (int) reply->stat, time.tv_sec, lm_xid); switch (error) { case RPC_SUCCESS: error = (int) reply->stat; if (error == (int) klm_working) { if (ISSIG(u.u_procp,0)) { error = EINTR; goto out; } /* lock-mgr is up...can wait longer */ (void) clntkudp_init(client, &lm_sa, klm_working_retry, cred); tmo.tv_sec = klm_working_timeout; retries = klm_timeout_retry; klm_succ_work++; continue; /* retry */ } klm_succ_out++; goto out; /* got a legitimate answer */ case RPC_TIMEDOUT: if(klm_debug) printf("retry: RPC_TIMEDOUT:pid:%d retries:%d\n", args->alock.pid, retries); klm_to++; if (--retries > 0) continue; else goto remaploop; /* ask for port# again */ default: klm_other++; if (klm_debug) printf("lock-manager: RPC error:%d sleeping:%d\n", error, (klm_normal_timeout*hz)); /* on RPC error, wait a bit and try again */ timeout(wakeup, (caddr_t)&lm_sa, (klm_normal_timeout * hz)); error = sleep((caddr_t)&lm_sa,PZERO|PCATCH); untimeout(wakeup, (caddr_t)&lm_sa); if (error) { error = EINTR; goto out; } goto remaploop; /* ask for port# again */ } /*switch*/ } /*for*/ /* loop until timeout, error, or completion */ } /*for*/ /* loop until signal or completion */out: AUTH_DESTROY(client->cl_auth); /* drop the authenticator */ CLNT_DESTROY(client); /* drop the client handle */ return(error);}/* * Pass Record-locking requests to the local Lock-Manager daemon. * * Note: this routine is called from ufs_rlock () as a result of an * attempt to lock a local file AND * WHEN nfs is configured AND the daemon based * region locking functionality * is enabled (kernel_locking = 0) */intklm_drlock(gp, ld, cmd, cred) struct gnode *gp; struct flock *ld; int cmd; struct ucred *cred;{ lockhandle_t lh; fhandle_t fh; if(u.u_error = makefh(&fh, gp)) return; lh.lh_id = fh; lh.lh_gp = gp; lh.lh_servername = hostname; return (klm_lockctl(&lh, ld, cmd, cred)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -