/* * Adds a socket to the list for servicing by nfscbds. */ int nfscbd_addsock(struct file *fp) { int siz; struct socket *so; int error; SVCXPRT *xprt; so = fp->f_data; siz = sb_max_adj; error = soreserve(so, siz, siz); if (error) return (error); /* * Steal the socket from userland so that it doesn't close * unexpectedly. */ if (so->so_type == SOCK_DGRAM) xprt = svc_dg_create(nfscbd_pool, so, 0, 0); else xprt = svc_vc_create(nfscbd_pool, so, 0, 0); if (xprt) { fp->f_ops = &badfileops; fp->f_data = NULL; svc_reg(xprt, NFS_CALLBCKPROG, NFSV4_CBVERS, nfscb_program, NULL); SVC_RELEASE(xprt); } return (0); }
/* * Adds a socket to the list for servicing by nfsds. */ int nfsrvd_addsock(struct file *fp) { int siz; struct socket *so; int error = 0; SVCXPRT *xprt; static u_int64_t sockref = 0; so = fp->f_data; siz = sb_max_adj; error = soreserve(so, siz, siz); if (error) goto out; /* * Steal the socket from userland so that it doesn't close * unexpectedly. */ if (so->so_type == SOCK_DGRAM) xprt = svc_dg_create(nfsrvd_pool, so, 0, 0); else xprt = svc_vc_create(nfsrvd_pool, so, 0, 0); if (xprt) { fp->f_ops = &badfileops; fp->f_data = NULL; xprt->xp_sockref = ++sockref; if (nfs_minvers == NFS_VER2) svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, NULL); if (nfs_minvers <= NFS_VER3 && nfs_maxvers >= NFS_VER3) svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, NULL); if (nfs_maxvers >= NFS_VER4) svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, NULL); if (so->so_type == SOCK_STREAM) svc_loss_reg(xprt, nfssvc_loss); SVC_RELEASE(xprt); } out: NFSEXITCODE(error); return (error); }
static void clnt_reconnect_destroy(CLIENT *cl) { struct rc_data *rc = (struct rc_data *)cl->cl_private; SVCXPRT *xprt; if (rc->rc_client) CLNT_DESTROY(rc->rc_client); if (rc->rc_backchannel) { xprt = (SVCXPRT *)rc->rc_backchannel; xprt_unregister(xprt); SVC_RELEASE(xprt); } crfree(rc->rc_ucred); mtx_destroy(&rc->rc_lock); mem_free(rc, sizeof(*rc)); mem_free(cl, sizeof (CLIENT)); }
static void svc_dg_destroy_task(struct work_pool_entry *wpe) { struct rpc_dplx_rec *rec = opr_containerof(wpe, struct rpc_dplx_rec, ioq.ioq_wpe); uint16_t xp_flags; __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s() %p fd %d xp_refs %" PRIu32, __func__, rec, rec->xprt.xp_fd, rec->xprt.xp_refs); if (rec->xprt.xp_refs) { /* instead of nanosleep */ work_pool_submit(&svc_work_pool, &(rec->ioq.ioq_wpe)); return; } xp_flags = atomic_postclear_uint16_t_bits(&rec->xprt.xp_flags, SVC_XPRT_FLAG_CLOSE); if ((xp_flags & SVC_XPRT_FLAG_CLOSE) && rec->xprt.xp_fd != RPC_ANYFD) { (void)close(rec->xprt.xp_fd); rec->xprt.xp_fd = RPC_ANYFD; } if (rec->xprt.xp_ops->xp_free_user_data) rec->xprt.xp_ops->xp_free_user_data(&rec->xprt); if (rec->xprt.xp_tp) mem_free(rec->xprt.xp_tp, 0); if (rec->xprt.xp_netid) mem_free(rec->xprt.xp_netid, 0); if (rec->xprt.xp_parent) SVC_RELEASE(rec->xprt.xp_parent, SVC_RELEASE_FLAG_NONE); svc_dg_xprt_free(DG_DR(rec)); }
/*ARGSUSED*/ static bool_t svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, struct sockaddr **addrp, struct mbuf **mp) { struct socket *so = NULL; struct sockaddr *sa = NULL; int error; SVCXPRT *new_xprt; /* * The socket upcall calls xprt_active() which will eventually * cause the server to call us here. We attempt to accept a * connection from the socket and turn it into a new * transport. If the accept fails, we have drained all pending * connections so we call xprt_inactive(). */ sx_xlock(&xprt->xp_lock); error = svc_vc_accept(xprt->xp_socket, &so); if (error == EWOULDBLOCK) { /* * We must re-test for new connections after taking * the lock to protect us in the case where a new * connection arrives after our call to accept fails * with EWOULDBLOCK. The pool lock protects us from * racing the upcall after our TAILQ_EMPTY() call * returns false. */ ACCEPT_LOCK(); mtx_lock(&xprt->xp_pool->sp_lock); if (TAILQ_EMPTY(&xprt->xp_socket->so_comp)) xprt_inactive_locked(xprt); mtx_unlock(&xprt->xp_pool->sp_lock); ACCEPT_UNLOCK(); sx_xunlock(&xprt->xp_lock); return (FALSE); } if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); if (xprt->xp_upcallset) { xprt->xp_upcallset = 0; soupcall_clear(xprt->xp_socket, SO_RCV); } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); xprt_inactive(xprt); sx_xunlock(&xprt->xp_lock); return (FALSE); } sx_xunlock(&xprt->xp_lock); sa = 0; error = soaccept(so, &sa); if (error) { /* * XXX not sure if I need to call sofree or soclose here. */ if (sa) free(sa, M_SONAME); return (FALSE); } /* * svc_vc_create_conn will call xprt_register - we don't need * to do anything with the new connection except derefence it. */ new_xprt = svc_vc_create_conn(xprt->xp_pool, so, sa); if (!new_xprt) { soclose(so); } else { SVC_RELEASE(new_xprt); } free(sa, M_SONAME); return (FALSE); /* there is never an rpc msg to be processed */ }