static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, size_t salen, int proto, u32 version, int privileged) { struct rpc_create_args args = { .protocol = proto, .address = srvaddr, .addrsize = salen, .servername = hostname, .program = &rpcb_program, .version = version, .authflavor = RPC_AUTH_UNIX, .flags = RPC_CLNT_CREATE_NOPING, }; switch (srvaddr->sa_family) { case AF_INET: ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); break; case AF_INET6: ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT); break; default: return NULL; } if (!privileged) args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; return rpc_create(&args); }
flux_rpc_t *flux_rpc_raw (flux_t *h, const char *topic, const void *data, int len, uint32_t nodeid, int flags) { flux_rpc_t *rpc; int rx_expected = 1; if ((flags & FLUX_RPC_NORESPONSE)) rx_expected = 0; if (!(rpc = rpc_create (h, rx_expected))) goto error; #if HAVE_CALIPER cali_begin_string_byname ("flux.message.rpc", "single"); cali_begin_int_byname ("flux.message.response_expected", !(flags & FLUX_RPC_NORESPONSE)); #endif if (rpc_request_send_raw (rpc, topic, nodeid, data, len) < 0) goto error; #if HAVE_CALIPER cali_end_byname ("flux.message.response_expected"); cali_end_byname ("flux.message.rpc"); #endif return rpc; error: flux_rpc_destroy (rpc); return NULL; }
static flux_rpc_t *flux_vrpcf (flux_t *h, const char *topic, uint32_t nodeid, int flags, const char *fmt, va_list ap) { flux_rpc_t *rpc; int rx_expected = 1; if ((flags & FLUX_RPC_NORESPONSE)) rx_expected = 0; if (!(rpc = rpc_create (h, rx_expected))) goto error; #if HAVE_CALIPER cali_begin_string_byname ("flux.message.rpc", "single"); cali_begin_int_byname ("flux.message.rpc.nodeid", nodeid); cali_begin_int_byname ("flux.message.response_expected", !(flags & FLUX_RPC_NORESPONSE)); #endif if (rpc_request_vsendf (rpc, topic, nodeid, fmt, ap) < 0) goto error; #if HAVE_CALIPER cali_end_byname ("flux.message.response_expected"); cali_end_byname ("flux.message.rpc.nodeid"); cali_end_byname ("flux.message.rpc"); #endif return rpc; error: flux_rpc_destroy (rpc); return NULL; }
static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt) { static const struct sockaddr_un gssp_localaddr = { .sun_family = AF_LOCAL, .sun_path = GSSPROXY_SOCK_PATHNAME, }; struct rpc_create_args args = { .net = net, .protocol = XPRT_TRANSPORT_LOCAL, .address = (struct sockaddr *)&gssp_localaddr, .addrsize = sizeof(gssp_localaddr), .servername = "localhost", .program = &gssp_program, .version = GSSPROXY_VERS_1, .authflavor = RPC_AUTH_NULL, /* * Note we want connection to be done in the caller's * filesystem namespace. We therefore turn off the idle * timeout, which would result in reconnections being * done without the correct namespace: */ .flags = RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_NO_IDLE_TIMEOUT }; struct rpc_clnt *clnt; int result = 0; clnt = rpc_create(&args); if (IS_ERR(clnt)) { dprintk("RPC: failed to create AF_LOCAL gssproxy " "client (errno %ld).\n", PTR_ERR(clnt)); result = -PTR_ERR(clnt); *_clnt = NULL; goto out; } dprintk("RPC: created new gssp local client (gssp_local_clnt: " "%p)\n", clnt); *_clnt = clnt; out: return result; } void init_gssp_clnt(struct sunrpc_net *sn) { mutex_init(&sn->gssp_lock); sn->gssp_clnt = NULL; init_waitqueue_head(&sn->gssp_wq); }
flux_rpc_t *flux_rpc (flux_t h, const char *topic, const char *json_str, uint32_t nodeid, int flags) { flux_rpc_t *rpc = rpc_create (h, flags, 1); if (rpc_request_send (rpc, 0, topic, json_str, nodeid) < 0) goto error; if (!rpc->oneway) rpc->nodemap[0] = nodeid; return rpc; error: flux_rpc_destroy (rpc); return NULL; }
flux_rpc_t *flux_rpc_multi (flux_t h, const char *topic, const char *json_str, const char *nodeset, int flags) { nodeset_t *ns = NULL; nodeset_iterator_t *itr = NULL; flux_rpc_t *rpc = NULL; int i; uint32_t count; if (!topic || !nodeset) { errno = EINVAL; goto error; } if (!strcmp (nodeset, "all")) { if (flux_get_size (h, &count) < 0) goto error; ns = nodeset_create_range (0, count - 1); } else { if ((ns = nodeset_create_string (nodeset))) count = nodeset_count (ns); } if (!ns) { errno = EINVAL; goto error; } if (!(rpc = rpc_create (h, flags, count))) goto error; if (!(itr = nodeset_iterator_create (ns))) goto error; for (i = 0; i < count; i++) { uint32_t nodeid = nodeset_next (itr); assert (nodeid != NODESET_EOF); if (rpc_request_send (rpc, i, topic, json_str, nodeid) < 0) goto error; if (!rpc->oneway) rpc->nodemap[i] = nodeid; } nodeset_iterator_destroy (itr); return rpc; error: if (rpc) flux_rpc_destroy (rpc); if (itr) nodeset_iterator_destroy (itr); if (ns) nodeset_destroy (ns); return NULL; }
struct p2p *p2p_init(const char *rpc_srv, const char *stun_srv) { char ip[64]; struct skt_addr tmpaddr; static stun_addr _mapped; struct p2p *p2p = CALLOC(1, struct p2p); if (!p2p) { loge("malloc failed: %d\n", errno); return NULL; } p2p->rpc = rpc_create(rpc_srv, _rpc_port); if (!p2p->rpc) { loge("rpc_create failed\n"); return NULL; } RPC_REGISTER_MSG_MAP(BASIC_RPC_API_RESP); rpc_set_cb(p2p->rpc, on_rpc_read, on_rpc_write, on_rpc_error, p2p); skt_getaddr_by_fd(p2p->rpc->fd, &tmpaddr); skt_addr_ntop(_local_ip, tmpaddr.ip); //_local_port = tmpaddr.port; //logi("_local_port = %d\n", _local_port); stun_init(stun_srv); p2p->nat.type = stun_nat_type(); p2p->nat.uuid = p2p->rpc->send_pkt.header.uuid_src; p2p->nat.local.ip = skt_addr_pton(_local_ip); _local_port = random_port(); p2p->nat.local.port = _local_port; p2p->nat.fd = stun_socket(_local_ip, _local_port, &_mapped); _mapped.addr = ntohl(_mapped.addr); skt_addr_ntop(ip, _mapped.addr); p2p->nat.reflect.ip = _mapped.addr; p2p->nat.reflect.port = _mapped.port; logi("get nat info from local\n"); logi("nat.type = %d\n", p2p->nat.type); logi("nat.local_addr %s:%d\n", _local_ip, p2p->nat.local.port); logi("nat.reflect_addr %s:%d\n", ip, p2p->nat.reflect.port); p2p->rpc_state = P2P_RPC_INIT; _p2p = p2p; return p2p; }
static int do_probe_callback(void *data) { struct nfs4_client *clp = data; struct sockaddr_in addr; struct nfs4_callback *cb = &clp->cl_callback; struct rpc_timeout timeparms = { .to_initval = (NFSD_LEASE_TIME/4) * HZ, .to_retries = 5, .to_maxval = (NFSD_LEASE_TIME/2) * HZ, .to_exponential = 1, }; struct rpc_program * program = &cb->cb_program; struct rpc_create_args args = { .protocol = IPPROTO_TCP, .address = (struct sockaddr *)&addr, .addrsize = sizeof(addr), .timeout = &timeparms, .program = program, .version = nfs_cb_version[1]->number, .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ .flags = (RPC_CLNT_CREATE_NOPING), }; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], .rpc_argp = clp, }; struct rpc_clnt *client; int status; /* Initialize address */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(cb->cb_port); addr.sin_addr.s_addr = htonl(cb->cb_addr); /* Initialize rpc_program */ program->name = "nfs4_cb"; program->number = cb->cb_prog; program->nrvers = ARRAY_SIZE(nfs_cb_version); program->version = nfs_cb_version; program->stats = &cb->cb_stat; /* Initialize rpc_stat */ memset(program->stats, 0, sizeof(cb->cb_stat)); program->stats->program = program; /* Create RPC client */ client = rpc_create(&args); if (IS_ERR(client)) { dprintk("NFSD: couldn't create callback client\n"); status = PTR_ERR(client); goto out_err; } status = rpc_call_sync(client, &msg, RPC_TASK_SOFT); if (status) goto out_release_client; cb->cb_client = client; atomic_set(&cb->cb_set, 1); put_nfs4_client(clp); return 0; out_release_client: rpc_shutdown_client(client); out_err: put_nfs4_client(clp); dprintk("NFSD: warning: no callback path to client %.*s\n", (int)clp->cl_name.len, clp->cl_name.data); return status; } /* * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... */ void nfsd4_probe_callback(struct nfs4_client *clp) { struct task_struct *t; BUG_ON(atomic_read(&clp->cl_callback.cb_set)); /* the task holds a reference to the nfs4_client struct */ atomic_inc(&clp->cl_count); t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe"); if (IS_ERR(t)) atomic_dec(&clp->cl_count); return; } /* * called with dp->dl_count inc'ed. * nfs4_lock_state() may or may not have been called. */ void nfsd4_cb_recall(struct nfs4_delegation *dp) { struct nfs4_client *clp = dp->dl_client; struct rpc_clnt *clnt = clp->cl_callback.cb_client; struct nfs4_cb_recall *cbr = &dp->dl_recall; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL], .rpc_argp = cbr, }; int retries = 1; int status = 0; cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */ cbr->cbr_dp = dp; status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); while (retries--) { switch (status) { case -EIO: /* Network partition? */ atomic_set(&clp->cl_callback.cb_set, 0); case -EBADHANDLE: case -NFS4ERR_BAD_STATEID: /* Race: client probably got cb_recall * before open reply granting delegation */ break; default: goto out_put_cred; } ssleep(2); status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); } out_put_cred: /* * Success or failure, now we're either waiting for lease expiration * or deleg_return. */ put_nfs4_client(clp); nfs4_put_delegation(dp); return; }
int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn) { struct rpc_timeout timeparms = { .to_initval = max_cb_time(), .to_retries = 0, }; struct rpc_create_args args = { .net = &init_net, .address = (struct sockaddr *) &conn->cb_addr, .addrsize = conn->cb_addrlen, .timeout = &timeparms, .program = &cb_program, .version = 0, .authflavor = clp->cl_flavor, .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), }; struct rpc_clnt *client; if (clp->cl_minorversion == 0) { if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) return -EINVAL; args.client_name = clp->cl_principal; args.prognumber = conn->cb_prog, args.protocol = XPRT_TRANSPORT_TCP; clp->cl_cb_ident = conn->cb_ident; } else { args.bc_xprt = conn->cb_xprt; args.prognumber = clp->cl_cb_session->se_cb_prog; args.protocol = XPRT_TRANSPORT_BC_TCP; } /* Create RPC client */ client = rpc_create(&args); if (IS_ERR(client)) { dprintk("NFSD: couldn't create callback client: %ld\n", PTR_ERR(client)); return PTR_ERR(client); } clp->cl_cb_client = client; return 0; } static void warn_no_callback_path(struct nfs4_client *clp, int reason) { dprintk("NFSD: warning: no callback path to client %.*s: error %d\n", (int)clp->cl_name.len, clp->cl_name.data, reason); } static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) { struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); if (task->tk_status) warn_no_callback_path(clp, task->tk_status); else atomic_set(&clp->cl_cb_set, 1); } static const struct rpc_call_ops nfsd4_cb_probe_ops = { /* XXX: release method to ensure we set the cb channel down if * necessary on early failure? */ .rpc_call_done = nfsd4_cb_probe_done, }; static struct rpc_cred *callback_cred; int set_callback_cred(void) { if (callback_cred) return 0; callback_cred = rpc_lookup_machine_cred(); if (!callback_cred) return -ENOMEM; return 0; } static struct workqueue_struct *callback_wq; static void do_probe_callback(struct nfs4_client *clp) { struct nfsd4_callback *cb = &clp->cl_cb_null; cb->cb_op = NULL; cb->cb_clp = clp; cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL]; cb->cb_msg.rpc_argp = NULL; cb->cb_msg.rpc_resp = NULL; cb->cb_msg.rpc_cred = callback_cred; cb->cb_ops = &nfsd4_cb_probe_ops; queue_work(callback_wq, &cb->cb_work); } /* * Poke the callback thread to process any updates to the callback * parameters, and send a null probe. */ void nfsd4_probe_callback(struct nfs4_client *clp) { set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); do_probe_callback(clp); }
int setup_callback_client(struct nfs4_client *clp) { struct nfs4_cb_conn *cb = &clp->cl_cb_conn; struct rpc_timeout timeparms = { .to_initval = max_cb_time(), .to_retries = 0, }; struct rpc_create_args args = { .protocol = XPRT_TRANSPORT_TCP, .address = (struct sockaddr *) &cb->cb_addr, .addrsize = cb->cb_addrlen, .timeout = &timeparms, .program = &cb_program, .prognumber = cb->cb_prog, .version = nfs_cb_version[1]->number, .authflavor = clp->cl_flavor, .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), .client_name = clp->cl_principal, }; struct rpc_clnt *client; if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) return -EINVAL; if (cb->cb_minorversion) { args.bc_xprt = clp->cl_cb_xprt; args.protocol = XPRT_TRANSPORT_BC_TCP; } /* Create RPC client */ client = rpc_create(&args); if (IS_ERR(client)) { dprintk("NFSD: couldn't create callback client: %ld\n", PTR_ERR(client)); return PTR_ERR(client); } cb->cb_client = client; return 0; } static void warn_no_callback_path(struct nfs4_client *clp, int reason) { dprintk("NFSD: warning: no callback path to client %.*s: error %d\n", (int)clp->cl_name.len, clp->cl_name.data, reason); } static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) { struct nfs4_client *clp = calldata; if (task->tk_status) warn_no_callback_path(clp, task->tk_status); else atomic_set(&clp->cl_cb_conn.cb_set, 1); put_nfs4_client(clp); } static const struct rpc_call_ops nfsd4_cb_probe_ops = { .rpc_call_done = nfsd4_cb_probe_done, }; static struct rpc_cred *callback_cred; int set_callback_cred(void) { callback_cred = rpc_lookup_machine_cred(); if (!callback_cred) return -ENOMEM; return 0; }
int setup_callback_client(struct nfs4_client *clp) { struct nfs4_cb_conn *cb = &clp->cl_cb_conn; struct rpc_timeout timeparms = { .to_initval = max_cb_time(), .to_retries = 0, }; struct rpc_create_args args = { .protocol = XPRT_TRANSPORT_TCP, .address = (struct sockaddr *) &cb->cb_addr, .addrsize = cb->cb_addrlen, .timeout = &timeparms, .program = &cb_program, .prognumber = cb->cb_prog, .version = nfs_cb_version[1]->number, .authflavor = clp->cl_flavor, .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), .client_name = clp->cl_principal, }; struct rpc_clnt *client; if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) return -EINVAL; if (cb->cb_minorversion) { args.bc_xprt = clp->cl_cb_xprt; args.protocol = XPRT_TRANSPORT_BC_TCP; } /* Create RPC client */ client = rpc_create(&args); if (IS_ERR(client)) { dprintk("NFSD: couldn't create callback client: %ld\n", PTR_ERR(client)); return PTR_ERR(client); } cb->cb_client = client; return 0; } static void warn_no_callback_path(struct nfs4_client *clp, int reason) { dprintk("NFSD: warning: no callback path to client %.*s: error %d\n", (int)clp->cl_name.len, clp->cl_name.data, reason); } static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) { struct nfs4_client *clp = calldata; if (task->tk_status) warn_no_callback_path(clp, task->tk_status); else atomic_set(&clp->cl_cb_conn.cb_set, 1); put_nfs4_client(clp); } static const struct rpc_call_ops nfsd4_cb_probe_ops = { .rpc_call_done = nfsd4_cb_probe_done, }; static struct rpc_cred *callback_cred; int set_callback_cred(void) { if (callback_cred) return 0; callback_cred = rpc_lookup_machine_cred(); if (!callback_cred) return -ENOMEM; return 0; } void do_probe_callback(struct nfs4_client *clp) { struct nfs4_cb_conn *cb = &clp->cl_cb_conn; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], .rpc_argp = clp, .rpc_cred = callback_cred }; int status; status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN, &nfsd4_cb_probe_ops, (void *)clp); if (status) { warn_no_callback_path(clp, status); put_nfs4_client(clp); } } /* * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... */ void nfsd4_probe_callback(struct nfs4_client *clp) { int status; BUG_ON(atomic_read(&clp->cl_cb_conn.cb_set)); status = setup_callback_client(clp); if (status) { warn_no_callback_path(clp, status); return; } /* the task holds a reference to the nfs4_client struct */ atomic_inc(&clp->cl_count); do_probe_callback(clp); }
flux_rpc_t *flux_rpc_multi (flux_t *h, const char *topic, const char *json_str, const char *nodeset, int flags) { nodeset_t *ns = NULL; nodeset_iterator_t *itr = NULL; flux_rpc_t *rpc = NULL; int i; uint32_t count; int rx_expected; if (!topic || !nodeset) { errno = EINVAL; goto error; } if (!strcmp (nodeset, "all")) { if (flux_get_size (h, &count) < 0) goto error; ns = nodeset_create_range (0, count - 1); } else { if ((ns = nodeset_create_string (nodeset))) count = nodeset_count (ns); } if (!ns) { errno = EINVAL; goto error; } rx_expected = count; if ((flags & FLUX_RPC_NORESPONSE)) rx_expected = 0; if (!(rpc = rpc_create (h, rx_expected))) goto error; if (!(itr = nodeset_iterator_create (ns))) goto error; #if HAVE_CALIPER cali_begin_string_byname ("flux.message.rpc", "multi"); cali_begin_int_byname ("flux.message.response_expected", !(flags & FLUX_RPC_NORESPONSE)); #endif for (i = 0; i < count; i++) { uint32_t nodeid = nodeset_next (itr); assert (nodeid != NODESET_EOF); #if HAVE_CALIPER cali_begin_int_byname ("flux.message.rpc.nodeid", nodeid); #endif if (rpc_request_send (rpc, topic, nodeid, json_str) < 0) goto error; #if HAVE_CALIPER cali_end_byname ("flux.message.rpc.nodeid"); #endif } #if HAVE_CALIPER cali_end_byname ("flux.message.response_expected"); cali_end_byname ("flux.message.rpc"); #endif nodeset_iterator_destroy (itr); return rpc; error: if (rpc) flux_rpc_destroy (rpc); if (itr) nodeset_iterator_destroy (itr); if (ns) nodeset_destroy (ns); return NULL; }
int setup_callback_client(struct nfs4_client *clp) { struct sockaddr_in addr; struct nfs4_cb_conn *cb = &clp->cl_cb_conn; struct rpc_timeout timeparms = { .to_initval = max_cb_time(), .to_retries = 0, }; struct rpc_create_args args = { .protocol = IPPROTO_TCP, .address = (struct sockaddr *)&addr, .addrsize = sizeof(addr), .timeout = &timeparms, .program = &cb_program, .prognumber = cb->cb_prog, .version = nfs_cb_version[1]->number, .authflavor = clp->cl_flavor, .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), .client_name = clp->cl_principal, }; struct rpc_clnt *client; if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) return -EINVAL; /* Initialize address */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(cb->cb_port); addr.sin_addr.s_addr = htonl(cb->cb_addr); /* Create RPC client */ client = rpc_create(&args); if (IS_ERR(client)) { dprintk("NFSD: couldn't create callback client: %ld\n", PTR_ERR(client)); return PTR_ERR(client); } cb->cb_client = client; return 0; } static void warn_no_callback_path(struct nfs4_client *clp, int reason) { dprintk("NFSD: warning: no callback path to client %.*s: error %d\n", (int)clp->cl_name.len, clp->cl_name.data, reason); } static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) { struct nfs4_client *clp = calldata; if (task->tk_status) warn_no_callback_path(clp, task->tk_status); else atomic_set(&clp->cl_cb_conn.cb_set, 1); put_nfs4_client(clp); } static const struct rpc_call_ops nfsd4_cb_probe_ops = { .rpc_call_done = nfsd4_cb_probe_done, }; static struct rpc_cred *lookup_cb_cred(struct nfs4_cb_conn *cb) { struct auth_cred acred = { .machine_cred = 1 }; /* * Note in the gss case this doesn't actually have to wait for a * gss upcall (or any calls to the client); this just creates a * non-uptodate cred which the rpc state machine will fill in with * a refresh_upcall later. */ return rpcauth_lookup_credcache(cb->cb_client->cl_auth, &acred, RPCAUTH_LOOKUP_NEW); } void do_probe_callback(struct nfs4_client *clp) { struct nfs4_cb_conn *cb = &clp->cl_cb_conn; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], .rpc_argp = clp, }; struct rpc_cred *cred; int status; cred = lookup_cb_cred(cb); if (IS_ERR(cred)) { status = PTR_ERR(cred); goto out; } cb->cb_cred = cred; msg.rpc_cred = cb->cb_cred; status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT, &nfsd4_cb_probe_ops, (void *)clp); out: if (status) { warn_no_callback_path(clp, status); put_nfs4_client(clp); } } /* * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... */ void nfsd4_probe_callback(struct nfs4_client *clp) { int status; BUG_ON(atomic_read(&clp->cl_cb_conn.cb_set)); status = setup_callback_client(clp); if (status) { warn_no_callback_path(clp, status); return; } /* the task holds a reference to the nfs4_client struct */ atomic_inc(&clp->cl_count); do_probe_callback(clp); } static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) { struct nfs4_delegation *dp = calldata; struct nfs4_client *clp = dp->dl_client; switch (task->tk_status) { case -EIO: /* Network partition? */ atomic_set(&clp->cl_cb_conn.cb_set, 0); warn_no_callback_path(clp, task->tk_status); case -EBADHANDLE: case -NFS4ERR_BAD_STATEID: /* Race: client probably got cb_recall * before open reply granting delegation */ break; default: /* success, or error we can't handle */ return; } if (dp->dl_retries--) { rpc_delay(task, 2*HZ); task->tk_status = 0; rpc_restart_call(task); } else { atomic_set(&clp->cl_cb_conn.cb_set, 0); warn_no_callback_path(clp, task->tk_status); } } static void nfsd4_cb_recall_release(void *calldata) { struct nfs4_delegation *dp = calldata; struct nfs4_client *clp = dp->dl_client; nfs4_put_delegation(dp); put_nfs4_client(clp); } static const struct rpc_call_ops nfsd4_cb_recall_ops = { .rpc_call_done = nfsd4_cb_recall_done, .rpc_release = nfsd4_cb_recall_release, }; /* * called with dp->dl_count inc'ed. */ void nfsd4_cb_recall(struct nfs4_delegation *dp) { struct nfs4_client *clp = dp->dl_client; struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL], .rpc_argp = dp, .rpc_cred = clp->cl_cb_conn.cb_cred }; int status; dp->dl_retries = 1; status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp); if (status) { put_nfs4_client(clp); nfs4_put_delegation(dp); } }
static int vsnfs_create_rpcclient(struct vsnfs_server *server) { struct rpc_clnt *clnt = NULL; struct vsnfs_fh *resp = NULL; struct vsnfs_getrootargs argp = { .path = server->mnt_path, .len = strlen(server->mnt_path), }; int ret = VSNFS_OK; struct rpc_create_args args = { .protocol = IPPROTO_TCP, .address = (struct sockaddr *)&server->cl_addr, .addrsize = server->cl_addrlen, .servername = server->ip_addr, .program = &vsnfs_program, .version = server->cl_rpc_ops->version, .authflavor = RPC_AUTH_NULL, .flags = RPC_CLNT_CREATE_NOPING, /* check the flags options */ }; printk(KERN_ERR "inside vsnfs_Create_rpcClient\n"); printk(KERN_ERR "calling rpc_create\n"); clnt = rpc_create(&args); if (IS_ERR(clnt)) { printk(KERN_ERR "%s: cannot create RPC client = %ld\n", __func__, PTR_ERR(clnt)); ret = PTR_ERR(clnt); goto out_rpcclient; } printk(KERN_ERR "RPC client created\n"); server->cl_rpcclient = clnt; /* TO DO: getting root handle should be moved outside of this function */ resp = kmalloc(sizeof(struct vsnfs_fh), GFP_KERNEL); if (!resp) { ret = -ENOMEM; goto out_rpcclient; } ret = server->cl_rpc_ops->getroot(server, &argp, resp); if (ret == 0) { vsnfs_trace(KERN_DEFAULT, "success :-) inode : %s type: %d\n", resp->data, resp->type); } else { vsnfs_trace(KERN_DEFAULT, "failure :-( %d\n", ret); ret = -VSNFSERR_REMOTE; goto out_rpcclient; } memcpy(&server->root_fh, resp, sizeof(struct vsnfs_fh)); vsnfs_trace(KERN_DEFAULT, "success :-) inode : %s\n", server->root_fh.data); out_rpcclient: kfree(resp); return ret; } /* 2. Filesystem registration and superblock operations */ static int vsnfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); static void vsnfs_kill_sb(struct super_block *); /** * vsnfs_umount_begin: - Used to unmount the filesystem */ static void vsnfs_umount_begin(struct super_block *sb) { struct vsnfs_server *server = VSNFS_SB(sb); struct rpc_clnt *rpc; if ((rpc = server->cl_rpcclient) != NULL) rpc_killall_tasks(rpc); } int vsnfs_write_inode(struct inode *inode, int sync) { printk("Inside wrrite inode\n"); return -EOPNOTSUPP; } void vsnfs_clear_inode(struct inode *inode) { printk("Inside clear inode\n"); }
/* * Create NSM client for the local host */ static struct rpc_clnt * nsm_create(void) { struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK), .sin_port = 0, }; struct rpc_create_args args = { .protocol = IPPROTO_UDP, .address = (struct sockaddr *)&sin, .addrsize = sizeof(sin), .servername = "localhost", .program = &nsm_program, .version = SM_VERSION, .authflavor = RPC_AUTH_NULL, .flags = (RPC_CLNT_CREATE_ONESHOT), }; return rpc_create(&args); } /* * XDR functions for NSM. */ static __be32 * xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) { char buffer[20], *name; /* * Use the dotted-quad IP address of the remote host as * identifier. Linux statd always looks up the canonical * hostname first for whatever remote hostname it receives, * so this works alright. */ if (nsm_use_hostnames) { name = argp->mon_name; } else { sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr)); name = buffer; } if (!(p = xdr_encode_string(p, name)) || !(p = xdr_encode_string(p, utsname()->nodename))) return ERR_PTR(-EIO); *p++ = htonl(argp->prog); *p++ = htonl(argp->vers); *p++ = htonl(argp->proc); return p; } static int xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) { p = xdr_encode_common(rqstp, p, argp); if (IS_ERR(p)) return PTR_ERR(p); /* Surprise - there may even be room for an IPv6 address now */ *p++ = argp->addr; *p++ = 0; *p++ = 0; *p++ = 0; rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); return 0; }