/** * xprt_reserve_xprt - serialize write access to transports * @task: task that is requesting access to the transport * * This prevents mixing the payload of separate requests, and prevents * transport connects from colliding with writes. No congestion control * is provided. */ int xprt_reserve_xprt(struct rpc_task *task) { struct rpc_xprt *xprt = task->tk_xprt; struct rpc_rqst *req = task->tk_rqstp; if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) { if (task == xprt->snd_task) return 1; if (task == NULL) return 0; goto out_sleep; } xprt->snd_task = task; if (req) { req->rq_bytes_sent = 0; req->rq_ntrans++; } return 1; out_sleep: dprintk("RPC: %5u failed to lock transport %p\n", task->tk_pid, xprt); task->tk_timeout = 0; task->tk_status = -EAGAIN; if (req && req->rq_ntrans) rpc_sleep_on(&xprt->resend, task, NULL, NULL); else rpc_sleep_on(&xprt->sending, task, NULL, NULL); return 0; }
/* * Serialize write access to sockets, in order to prevent different * requests from interfering with each other. * Also prevents TCP socket connects from colliding with writes. */ static int __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) { struct rpc_rqst *req = task->tk_rqstp; if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate)) { if (task == xprt->snd_task) return 1; if (task == NULL) return 0; goto out_sleep; } if (xprt->nocong || __xprt_get_cong(xprt, task)) { xprt->snd_task = task; if (req) { req->rq_bytes_sent = 0; req->rq_ntrans++; } return 1; } smp_mb__before_clear_bit(); clear_bit(XPRT_LOCKED, &xprt->sockstate); smp_mb__after_clear_bit(); out_sleep: dprintk("RPC: %4d failed to lock socket %p\n", task->tk_pid, xprt); task->tk_timeout = 0; task->tk_status = -EAGAIN; if (req && req->rq_ntrans) rpc_sleep_on(&xprt->resend, task, NULL, NULL); else rpc_sleep_on(&xprt->sending, task, NULL, NULL); return 0; }
/* * Serialize write access to sockets, in order to prevent different * requests from interfering with each other. * Also prevents TCP socket connects from colliding with writes. */ static int __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) { struct rpc_rqst *req = task->tk_rqstp; if (!xprt->snd_task) { if (xprt->nocong || __xprt_get_cong(xprt, task)) { xprt->snd_task = task; if (req) { req->rq_bytes_sent = 0; req->rq_ntrans++; } } } if (xprt->snd_task != task) { dprintk("RPC: %4d TCP write queue full\n", task->tk_pid); task->tk_timeout = 0; task->tk_status = -EAGAIN; if (req && req->rq_ntrans) rpc_sleep_on(&xprt->resend, task, NULL, NULL); else rpc_sleep_on(&xprt->sending, task, NULL, NULL); } return xprt->snd_task == task; }
/* Send an RPC call on the passive end of a transport * connection. */ static int xprt_rdma_bc_send_request(struct rpc_task *task) { struct rpc_rqst *rqst = task->tk_rqstp; struct svc_xprt *sxprt = rqst->rq_xprt->bc_xprt; struct svcxprt_rdma *rdma; int ret; dprintk("svcrdma: sending bc call with xid: %08x\n", be32_to_cpu(rqst->rq_xid)); if (!mutex_trylock(&sxprt->xpt_mutex)) { rpc_sleep_on(&sxprt->xpt_bc_pending, task, NULL); if (!mutex_trylock(&sxprt->xpt_mutex)) return -EAGAIN; rpc_wake_up_queued_task(&sxprt->xpt_bc_pending, task); } ret = -ENOTCONN; rdma = container_of(sxprt, struct svcxprt_rdma, sc_xprt); if (!test_bit(XPT_DEAD, &sxprt->xpt_flags)) ret = rpcrdma_bc_send_request(rdma, rqst); mutex_unlock(&sxprt->xpt_mutex); if (ret < 0) return ret; return 0; }
/* * There's currently a single callback channel slot. * If the slot is available, then mark it busy. Otherwise, set the * thread for sleeping on the callback RPC wait queue. */ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp, struct rpc_task *task) { struct nfs4_rpc_args *args = task->tk_msg.rpc_argp; u32 *ptr = (u32 *)clp->cl_sessionid.data; int status = 0; dprintk("%s: %u:%u:%u:%u\n", __func__, ptr[0], ptr[1], ptr[2], ptr[3]); if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); dprintk("%s slot is busy\n", __func__); status = -EAGAIN; goto out; } /* * We'll need the clp during XDR encoding and decoding, * and the sequence during decoding to verify the reply */ args->args_seq.cbs_clp = clp; task->tk_msg.rpc_resp = &args->args_seq; out: dprintk("%s status=%d\n", __func__, status); return status; }
/* * Serialize write access to sockets, in order to prevent different * requests from interfering with each other. * Also prevents TCP socket reconnections from colliding with writes. */ static int __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) { if (!xprt->snd_task) { if (xprt->nocong || __xprt_get_cong(xprt, task)) xprt->snd_task = task; } if (xprt->snd_task != task) { dprintk("RPC: %4d TCP write queue full\n", task->tk_pid); task->tk_timeout = 0; task->tk_status = -EAGAIN; if (task->tk_rqstp && task->tk_rqstp->rq_nresend) rpc_sleep_on(&xprt->resend, task, NULL, NULL); else rpc_sleep_on(&xprt->sending, task, NULL, NULL); } return xprt->snd_task == task; }
void rpc_run_child(struct rpc_task *task, struct rpc_task *child, rpc_action func) { unsigned long oldflags; save_flags(oldflags); cli(); rpc_make_runnable(child); restore_flags(oldflags); /* N.B. Is it possible for the child to have already finished? */ rpc_sleep_on(&childq, task, func, NULL); }
/** * xprt_rdma_alloc_slot - allocate an rpc_rqst * @xprt: controlling RPC transport * @task: RPC task requesting a fresh rpc_rqst * * tk_status values: * %0 if task->tk_rqstp points to a fresh rpc_rqst * %-EAGAIN if no rpc_rqst is available; queued on backlog */ static void xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) { struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); struct rpcrdma_req *req; req = rpcrdma_buffer_get(&r_xprt->rx_buf); if (!req) goto out_sleep; task->tk_rqstp = &req->rl_slot; task->tk_status = 0; return; out_sleep: rpc_sleep_on(&xprt->backlog, task, NULL); task->tk_status = -EAGAIN; }
/* * There's currently a single callback channel slot. * If the slot is available, then mark it busy. Otherwise, set the * thread for sleeping on the callback RPC wait queue. */ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp, struct rpc_task *task) { u32 *ptr = (u32 *)clp->cl_cb_session->se_sessionid.data; int status = 0; dprintk("%s: %u:%u:%u:%u\n", __func__, ptr[0], ptr[1], ptr[2], ptr[3]); if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); dprintk("%s slot is busy\n", __func__); status = -EAGAIN; goto out; } out: dprintk("%s status=%d\n", __func__, status); return status; }
static void nfs_flushd(struct rpc_task *task) { struct nfs_server *server; struct nfs_reqlist *cache; LIST_HEAD(head); dprintk("NFS: %4d flushd starting\n", task->tk_pid); server = (struct nfs_server *) task->tk_calldata; cache = server->rw_requests; for(;;) { spin_lock(&nfs_wreq_lock); if (nfs_scan_lru_dirty_timeout(server, &head)) { spin_unlock(&nfs_wreq_lock); nfs_flush_list(&head, server->wpages, FLUSH_AGING); continue; } if (nfs_scan_lru_read_timeout(server, &head)) { spin_unlock(&nfs_wreq_lock); nfs_pagein_list(&head, server->rpages); continue; } #ifdef CONFIG_NFS_V3 if (nfs_scan_lru_commit_timeout(server, &head)) { spin_unlock(&nfs_wreq_lock); nfs_commit_list(&head, FLUSH_AGING); continue; } #endif spin_unlock(&nfs_wreq_lock); break; } dprintk("NFS: %4d flushd back to sleep\n", task->tk_pid); if (task->tk_action) { task->tk_timeout = NFS_FLUSHD_TIMEOUT; cache->runat = jiffies + task->tk_timeout; rpc_sleep_on(&flushd_queue, task, NULL, NULL); } }
/** * rpcb_register - set or unset a port registration with the local rpcbind svc * @prog: RPC program number to bind * @vers: RPC version number to bind * @prot: transport protocol to use to make this request * @port: port value to register * @okay: result code * * port == 0 means unregister, port != 0 means register. * * This routine supports only rpcbind version 2. */ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) { struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK), }; struct rpcbind_args map = { .r_prog = prog, .r_vers = vers, .r_prot = prot, .r_port = port, }; struct rpc_message msg = { .rpc_proc = &rpcb_procedures2[port ? RPCBPROC_SET : RPCBPROC_UNSET], .rpc_argp = &map, .rpc_resp = okay, }; struct rpc_clnt *rpcb_clnt; int error = 0; dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " "rpcbind\n", (port ? "" : "un"), prog, vers, prot, port); rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, sizeof(sin), XPRT_TRANSPORT_UDP, 2, 1); if (IS_ERR(rpcb_clnt)) return PTR_ERR(rpcb_clnt); error = rpc_call_sync(rpcb_clnt, &msg, 0); rpc_shutdown_client(rpcb_clnt); if (error < 0) printk(KERN_WARNING "RPC: failed to contact local rpcbind " "server (errno %d).\n", -error); dprintk("RPC: registration status %d/%d\n", error, *okay); return error; } /** * rpcb_getport_sync - obtain the port for an RPC service on a given host * @sin: address of remote peer * @prog: RPC program number to bind * @vers: RPC version number to bind * @prot: transport protocol to use to make this request * * Return value is the requested advertised port number, * or a negative errno value. * * Called from outside the RPC client in a synchronous task context. * Uses default timeout parameters specified by underlying transport. * * XXX: Needs to support IPv6 */ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot) { struct rpcbind_args map = { .r_prog = prog, .r_vers = vers, .r_prot = prot, .r_port = 0, }; struct rpc_message msg = { .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], .rpc_argp = &map, .rpc_resp = &map.r_port, }; struct rpc_clnt *rpcb_clnt; int status; dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n", __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin, sizeof(*sin), prot, 2, 0); if (IS_ERR(rpcb_clnt)) return PTR_ERR(rpcb_clnt); status = rpc_call_sync(rpcb_clnt, &msg, 0); rpc_shutdown_client(rpcb_clnt); if (status >= 0) { if (map.r_port != 0) return map.r_port; status = -EACCES; } return status; } EXPORT_SYMBOL_GPL(rpcb_getport_sync); static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, int version) { struct rpc_message msg = { .rpc_proc = rpcb_next_version[version].rpc_proc, .rpc_argp = map, .rpc_resp = &map->r_port, }; struct rpc_task_setup task_setup_data = { .rpc_client = rpcb_clnt, .rpc_message = &msg, .callback_ops = &rpcb_getport_ops, .callback_data = map, .flags = RPC_TASK_ASYNC, }; return rpc_run_task(&task_setup_data); } /** * rpcb_getport_async - obtain the port for a given RPC service on a given host * @task: task that is waiting for portmapper request * * This one can be called for an ongoing RPC request, and can be used in * an async (rpciod) context. */ void rpcb_getport_async(struct rpc_task *task) { struct rpc_clnt *clnt = task->tk_client; u32 bind_version; struct rpc_xprt *xprt = task->tk_xprt; struct rpc_clnt *rpcb_clnt; static struct rpcbind_args *map; struct rpc_task *child; struct sockaddr_storage addr; struct sockaddr *sap = (struct sockaddr *)&addr; size_t salen; int status; struct rpcb_info *info; dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", task->tk_pid, __FUNCTION__, clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); /* Autobind on cloned rpc clients is discouraged */ BUG_ON(clnt->cl_parent != clnt); if (xprt_test_and_set_binding(xprt)) { status = -EAGAIN; /* tell caller to check again */ dprintk("RPC: %5u %s: waiting for another binder\n", task->tk_pid, __FUNCTION__); goto bailout_nowake; } /* Put self on queue before sending rpcbind request, in case * rpcb_getport_done completes before we return from rpc_run_task */ rpc_sleep_on(&xprt->binding, task, NULL, NULL); /* Someone else may have bound if we slept */ if (xprt_bound(xprt)) { status = 0; dprintk("RPC: %5u %s: already bound\n", task->tk_pid, __FUNCTION__); goto bailout_nofree; } salen = rpc_peeraddr(clnt, sap, sizeof(addr)); /* Don't ever use rpcbind v2 for AF_INET6 requests */ switch (sap->sa_family) { case AF_INET: info = rpcb_next_version; break; case AF_INET6: info = rpcb_next_version6; break; default: status = -EAFNOSUPPORT; dprintk("RPC: %5u %s: bad address family\n", task->tk_pid, __FUNCTION__); goto bailout_nofree; } if (info[xprt->bind_index].rpc_proc == NULL) { xprt->bind_index = 0; status = -EPFNOSUPPORT; dprintk("RPC: %5u %s: no more getport versions available\n", task->tk_pid, __FUNCTION__); goto bailout_nofree; } bind_version = info[xprt->bind_index].rpc_vers; dprintk("RPC: %5u %s: trying rpcbind version %u\n", task->tk_pid, __FUNCTION__, bind_version); rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot, bind_version, 0); if (IS_ERR(rpcb_clnt)) { status = PTR_ERR(rpcb_clnt); dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); goto bailout_nofree; } map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); if (!map) { status = -ENOMEM; dprintk("RPC: %5u %s: no memory available\n", task->tk_pid, __FUNCTION__); goto bailout_nofree; } map->r_prog = clnt->cl_prog; map->r_vers = clnt->cl_vers; map->r_prot = xprt->prot; map->r_port = 0; map->r_xprt = xprt_get(xprt); map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR); map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ child = rpcb_call_async(rpcb_clnt, map, xprt->bind_index); rpc_release_client(rpcb_clnt); if (IS_ERR(child)) { status = -EIO; dprintk("RPC: %5u %s: rpc_run_task failed\n", task->tk_pid, __FUNCTION__); goto bailout; } rpc_put_task(child); task->tk_xprt->stat.bind_count++; return; bailout: kfree(map); xprt_put(xprt); bailout_nofree: rpcb_wake_rpcbind_waiters(xprt, status); bailout_nowake: task->tk_status = status; } EXPORT_SYMBOL_GPL(rpcb_getport_async); /* * Rpcbind child task calls this callback via tk_exit. */ static void rpcb_getport_done(struct rpc_task *child, void *data) { struct rpcbind_args *map = data; struct rpc_xprt *xprt = map->r_xprt; int status = child->tk_status; /* Garbage reply: retry with a lesser rpcbind version */ if (status == -EIO) status = -EPROTONOSUPPORT; /* rpcbind server doesn't support this rpcbind protocol version */ if (status == -EPROTONOSUPPORT) xprt->bind_index++; if (status < 0) { /* rpcbind server not available on remote host? */ xprt->ops->set_port(xprt, 0); } else if (map->r_port == 0) { /* Requested RPC service wasn't registered on remote host */ xprt->ops->set_port(xprt, 0); status = -EACCES; } else { /* Succeeded */ xprt->ops->set_port(xprt, map->r_port); xprt_set_bound(xprt); status = 0; } dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n", child->tk_pid, status, map->r_port); rpcb_wake_rpcbind_waiters(xprt, status); } static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p, struct rpcbind_args *rpcb) { dprintk("RPC: rpcb_encode_mapping(%u, %u, %d, %u)\n", rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); *p++ = htonl(rpcb->r_prog); *p++ = htonl(rpcb->r_vers); *p++ = htonl(rpcb->r_prot); *p++ = htonl(rpcb->r_port); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p, unsigned short *portp) { *portp = (unsigned short) ntohl(*p++); dprintk("RPC: rpcb_decode_getport result %u\n", *portp); return 0; } static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, unsigned int *boolp) { *boolp = (unsigned int) ntohl(*p++); dprintk("RPC: rpcb_decode_set result %u\n", *boolp); return 0; } static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p, struct rpcbind_args *rpcb) { dprintk("RPC: rpcb_encode_getaddr(%u, %u, %s)\n", rpcb->r_prog, rpcb->r_vers, rpcb->r_addr); *p++ = htonl(rpcb->r_prog); *p++ = htonl(rpcb->r_vers); p = xdr_encode_string(p, rpcb->r_netid); p = xdr_encode_string(p, rpcb->r_addr); p = xdr_encode_string(p, rpcb->r_owner); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Obtain the port for a given RPC service on a given host. This one can * be called for an ongoing RPC request. */ void rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt) { struct rpc_portmap *map = clnt->cl_pmap; struct sockaddr_in *sap = &clnt->cl_xprt->addr; struct rpc_message msg = { .rpc_proc = &pmap_procedures[PMAP_GETPORT], .rpc_argp = map, .rpc_resp = &clnt->cl_port, .rpc_cred = NULL }; struct rpc_clnt *pmap_clnt; struct rpc_task *child; dprintk("RPC: %4d rpc_getport(%s, %d, %d, %d)\n", task->tk_pid, clnt->cl_server, map->pm_prog, map->pm_vers, map->pm_prot); /* Autobind on cloned rpc clients is discouraged */ BUG_ON(clnt->cl_parent != clnt); spin_lock(&pmap_lock); if (map->pm_binding) { rpc_sleep_on(&map->pm_bindwait, task, NULL, NULL); spin_unlock(&pmap_lock); return; } map->pm_binding = 1; spin_unlock(&pmap_lock); pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot, 0); if (IS_ERR(pmap_clnt)) { task->tk_status = PTR_ERR(pmap_clnt); goto bailout; } task->tk_status = 0; /* * Note: rpc_new_child will release client after a failure. */ if (!(child = rpc_new_child(pmap_clnt, task))) goto bailout; /* Setup the call info struct */ rpc_call_setup(child, &msg, 0); /* ... and run the child task */ rpc_run_child(task, child, pmap_getport_done); return; bailout: spin_lock(&pmap_lock); map->pm_binding = 0; rpc_wake_up(&map->pm_bindwait); spin_unlock(&pmap_lock); rpc_exit(task, -EIO); } #ifdef CONFIG_ROOT_NFS int rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot) { struct rpc_portmap map = { .pm_prog = prog, .pm_vers = vers, .pm_prot = prot, .pm_port = 0 }; struct rpc_clnt *pmap_clnt; char hostname[32]; int status; dprintk("RPC: rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n", NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr)); pmap_clnt = pmap_create(hostname, sin, prot, 0); if (IS_ERR(pmap_clnt)) return PTR_ERR(pmap_clnt); /* Setup the call info struct */ status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0); if (status >= 0) { if (map.pm_port != 0) return map.pm_port; status = -EACCES; } return status; } #endif static void pmap_getport_done(struct rpc_task *task) { struct rpc_clnt *clnt = task->tk_client; struct rpc_xprt *xprt = task->tk_xprt; struct rpc_portmap *map = clnt->cl_pmap; dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n", task->tk_pid, task->tk_status, clnt->cl_port); xprt->ops->set_port(xprt, 0); if (task->tk_status < 0) { /* Make the calling task exit with an error */ task->tk_action = rpc_exit_task; } else if (clnt->cl_port == 0) { /* Program not registered */ rpc_exit(task, -EACCES); } else { xprt->ops->set_port(xprt, clnt->cl_port); clnt->cl_port = htons(clnt->cl_port); } spin_lock(&pmap_lock); map->pm_binding = 0; rpc_wake_up(&map->pm_bindwait); spin_unlock(&pmap_lock); } /* * Set or unset a port registration with the local portmapper. * port == 0 means unregister, port != 0 means register. */ int rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) { struct sockaddr_in sin; struct rpc_portmap map; struct rpc_clnt *pmap_clnt; int error = 0; dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n", prog, vers, prot, port); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1); if (IS_ERR(pmap_clnt)) { error = PTR_ERR(pmap_clnt); dprintk("RPC: couldn't create pmap client. Error = %d\n", error); return error; } map.pm_prog = prog; map.pm_vers = vers; map.pm_prot = prot; map.pm_port = port; error = rpc_call(pmap_clnt, port? PMAP_SET : PMAP_UNSET, &map, okay, 0); if (error < 0) { printk(KERN_WARNING "RPC: failed to contact portmap (errno %d).\n", error); } dprintk("RPC: registration status %d/%d\n", error, *okay); /* Client deleted automatically because cl_oneshot == 1 */ return error; } static struct rpc_clnt * pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged) { struct rpc_xprt *xprt; struct rpc_clnt *clnt; /* printk("pmap: create xprt\n"); */ xprt = xprt_create_proto(proto, srvaddr, NULL); if (IS_ERR(xprt)) return (struct rpc_clnt *)xprt; xprt->ops->set_port(xprt, RPC_PMAP_PORT); if (!privileged) xprt->resvport = 0; /* printk("pmap: create clnt\n"); */ clnt = rpc_new_client(xprt, hostname, &pmap_program, RPC_PMAP_VERSION, RPC_AUTH_UNIX); if (!IS_ERR(clnt)) { clnt->cl_softrtry = 1; clnt->cl_oneshot = 1; } return clnt; } /* * XDR encode/decode functions for PMAP */ static int xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpc_portmap *map) { dprintk("RPC: xdr_encode_mapping(%d, %d, %d, %d)\n", map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port); *p++ = htonl(map->pm_prog); *p++ = htonl(map->pm_vers); *p++ = htonl(map->pm_prot); *p++ = htonl(map->pm_port); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } static int xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp) { *portp = (unsigned short) ntohl(*p++); return 0; }
void rpc_delay(struct rpc_task *task, unsigned long delay) { task->tk_timeout = delay; rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); }