diff options
author | dfr <dfr@FreeBSD.org> | 2008-06-26 10:21:54 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2008-06-26 10:21:54 +0000 |
commit | 41cea6d5ca71b8cf057f9face8055b218b30e18e (patch) | |
tree | 994a214037913bc4e44eaee5070c65aeadf53485 /sys/rpc/svc_vc.c | |
parent | ca3c788812715a263f83dcec4bdabaf6c10eb922 (diff) | |
download | FreeBSD-src-41cea6d5ca71b8cf057f9face8055b218b30e18e.zip FreeBSD-src-41cea6d5ca71b8cf057f9face8055b218b30e18e.tar.gz |
Re-implement the client side of rpc.lockd in the kernel. This implementation
provides the correct semantics for flock(2) style locks which are used by the
lockf(1) command line tool and the pidfile(3) library. It also implements
recovery from server restarts and ensures that dirty cache blocks are written
to the server before obtaining locks (allowing multiple clients to use file
locking to safely share data).
Sponsored by: Isilon Systems
PR: 94256
MFC after: 2 weeks
Diffstat (limited to 'sys/rpc/svc_vc.c')
-rw-r--r-- | sys/rpc/svc_vc.c | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index 54edfd0..47530da 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -132,6 +132,15 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, struct sockaddr* sa; int error; + if (so->so_state & SS_ISCONNECTED) { + error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa); + if (error) + return (NULL); + xprt = svc_vc_create_conn(pool, so, sa); + free(sa, M_SONAME); + return (xprt); + } + xprt = mem_alloc(sizeof(SVCXPRT)); mtx_init(&xprt->xp_lock, "xprt->xp_lock", NULL, MTX_DEF); xprt->xp_pool = pool; @@ -180,8 +189,32 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr) SVCXPRT *xprt = NULL; struct cf_conn *cd = NULL; struct sockaddr* sa = NULL; + struct sockopt opt; + int one = 1; int error; + bzero(&opt, sizeof(struct sockopt)); + opt.sopt_dir = SOPT_SET; + opt.sopt_level = SOL_SOCKET; + opt.sopt_name = SO_KEEPALIVE; + opt.sopt_val = &one; + opt.sopt_valsize = sizeof(one); + error = sosetopt(so, &opt); + if (error) + return (NULL); + + if (so->so_proto->pr_protocol == IPPROTO_TCP) { + bzero(&opt, sizeof(struct sockopt)); + opt.sopt_dir = SOPT_SET; + opt.sopt_level = IPPROTO_TCP; + opt.sopt_name = TCP_NODELAY; + opt.sopt_val = &one; + opt.sopt_valsize = sizeof(one); + error = sosetopt(so, &opt); + if (error) + return (NULL); + } + cd = mem_alloc(sizeof(*cd)); cd->strm_stat = XPRT_IDLE; @@ -306,8 +339,6 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg) { struct socket *so = NULL; struct sockaddr *sa = NULL; - struct sockopt opt; - int one = 1; int error; /* @@ -351,16 +382,6 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg) sa = 0; error = soaccept(so, &sa); - if (!error) { - bzero(&opt, sizeof(struct sockopt)); - opt.sopt_dir = SOPT_SET; - opt.sopt_level = IPPROTO_TCP; - opt.sopt_name = TCP_NODELAY; - opt.sopt_val = &one; - opt.sopt_valsize = sizeof(one); - error = sosetopt(so, &opt); - } - if (error) { /* * XXX not sure if I need to call sofree or soclose here. @@ -374,7 +395,9 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg) * svc_vc_create_conn will call xprt_register - we don't need * to do anything with the new connection. */ - svc_vc_create_conn(xprt->xp_pool, so, sa); + if (!svc_vc_create_conn(xprt->xp_pool, so, sa)) + soclose(so); + free(sa, M_SONAME); return (FALSE); /* there is never an rpc msg to be processed */ |