Merge branch 'devel' into linux-next
Este cometimento está contido em:
@@ -55,16 +55,8 @@ static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
|
||||
|
||||
/*
|
||||
* RFC 4291, Section 2.2.1
|
||||
*
|
||||
* To keep the result as short as possible, especially
|
||||
* since we don't shorthand, we don't want leading zeros
|
||||
* in each halfword, so avoid %pI6.
|
||||
*/
|
||||
return snprintf(buf, buflen, "%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
ntohs(addr->s6_addr16[0]), ntohs(addr->s6_addr16[1]),
|
||||
ntohs(addr->s6_addr16[2]), ntohs(addr->s6_addr16[3]),
|
||||
ntohs(addr->s6_addr16[4]), ntohs(addr->s6_addr16[5]),
|
||||
ntohs(addr->s6_addr16[6]), ntohs(addr->s6_addr16[7]));
|
||||
return snprintf(buf, buflen, "%pI6c", addr);
|
||||
}
|
||||
|
||||
static size_t rpc_ntop6(const struct sockaddr *sap,
|
||||
|
@@ -79,7 +79,7 @@ static void call_connect_status(struct rpc_task *task);
|
||||
|
||||
static __be32 *rpc_encode_header(struct rpc_task *task);
|
||||
static __be32 *rpc_verify_header(struct rpc_task *task);
|
||||
static int rpc_ping(struct rpc_clnt *clnt, int flags);
|
||||
static int rpc_ping(struct rpc_clnt *clnt);
|
||||
|
||||
static void rpc_register_client(struct rpc_clnt *clnt)
|
||||
{
|
||||
@@ -340,7 +340,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
|
||||
return clnt;
|
||||
|
||||
if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
|
||||
int err = rpc_ping(clnt, RPC_TASK_SOFT);
|
||||
int err = rpc_ping(clnt);
|
||||
if (err != 0) {
|
||||
rpc_shutdown_client(clnt);
|
||||
return ERR_PTR(err);
|
||||
@@ -528,7 +528,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
|
||||
clnt->cl_prog = program->number;
|
||||
clnt->cl_vers = version->number;
|
||||
clnt->cl_stats = program->stats;
|
||||
err = rpc_ping(clnt, RPC_TASK_SOFT);
|
||||
err = rpc_ping(clnt);
|
||||
if (err != 0) {
|
||||
rpc_shutdown_client(clnt);
|
||||
clnt = ERR_PTR(err);
|
||||
@@ -1060,7 +1060,7 @@ call_bind_status(struct rpc_task *task)
|
||||
goto retry_timeout;
|
||||
case -EPFNOSUPPORT:
|
||||
/* server doesn't support any rpcbind version we know of */
|
||||
dprintk("RPC: %5u remote rpcbind service unavailable\n",
|
||||
dprintk("RPC: %5u unrecognized remote rpcbind service\n",
|
||||
task->tk_pid);
|
||||
break;
|
||||
case -EPROTONOSUPPORT:
|
||||
@@ -1069,6 +1069,21 @@ call_bind_status(struct rpc_task *task)
|
||||
task->tk_status = 0;
|
||||
task->tk_action = call_bind;
|
||||
return;
|
||||
case -ECONNREFUSED: /* connection problems */
|
||||
case -ECONNRESET:
|
||||
case -ENOTCONN:
|
||||
case -EHOSTDOWN:
|
||||
case -EHOSTUNREACH:
|
||||
case -ENETUNREACH:
|
||||
case -EPIPE:
|
||||
dprintk("RPC: %5u remote rpcbind unreachable: %d\n",
|
||||
task->tk_pid, task->tk_status);
|
||||
if (!RPC_IS_SOFTCONN(task)) {
|
||||
rpc_delay(task, 5*HZ);
|
||||
goto retry_timeout;
|
||||
}
|
||||
status = task->tk_status;
|
||||
break;
|
||||
default:
|
||||
dprintk("RPC: %5u unrecognized rpcbind error (%d)\n",
|
||||
task->tk_pid, -task->tk_status);
|
||||
@@ -1180,11 +1195,25 @@ static void
|
||||
call_transmit_status(struct rpc_task *task)
|
||||
{
|
||||
task->tk_action = call_status;
|
||||
|
||||
/*
|
||||
* Common case: success. Force the compiler to put this
|
||||
* test first.
|
||||
*/
|
||||
if (task->tk_status == 0) {
|
||||
xprt_end_transmit(task);
|
||||
rpc_task_force_reencode(task);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (task->tk_status) {
|
||||
case -EAGAIN:
|
||||
break;
|
||||
default:
|
||||
dprint_status(task);
|
||||
xprt_end_transmit(task);
|
||||
rpc_task_force_reencode(task);
|
||||
break;
|
||||
/*
|
||||
* Special cases: if we've been waiting on the
|
||||
* socket's write_space() callback, or if the
|
||||
@@ -1192,11 +1221,16 @@ call_transmit_status(struct rpc_task *task)
|
||||
* then hold onto the transport lock.
|
||||
*/
|
||||
case -ECONNREFUSED:
|
||||
case -ECONNRESET:
|
||||
case -ENOTCONN:
|
||||
case -EHOSTDOWN:
|
||||
case -EHOSTUNREACH:
|
||||
case -ENETUNREACH:
|
||||
if (RPC_IS_SOFTCONN(task)) {
|
||||
xprt_end_transmit(task);
|
||||
rpc_exit(task, task->tk_status);
|
||||
break;
|
||||
}
|
||||
case -ECONNRESET:
|
||||
case -ENOTCONN:
|
||||
case -EPIPE:
|
||||
rpc_task_force_reencode(task);
|
||||
}
|
||||
@@ -1346,6 +1380,10 @@ call_timeout(struct rpc_task *task)
|
||||
dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
|
||||
task->tk_timeouts++;
|
||||
|
||||
if (RPC_IS_SOFTCONN(task)) {
|
||||
rpc_exit(task, -ETIMEDOUT);
|
||||
return;
|
||||
}
|
||||
if (RPC_IS_SOFT(task)) {
|
||||
if (clnt->cl_chatty)
|
||||
printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
|
||||
@@ -1675,14 +1713,14 @@ static struct rpc_procinfo rpcproc_null = {
|
||||
.p_decode = rpcproc_decode_null,
|
||||
};
|
||||
|
||||
static int rpc_ping(struct rpc_clnt *clnt, int flags)
|
||||
static int rpc_ping(struct rpc_clnt *clnt)
|
||||
{
|
||||
struct rpc_message msg = {
|
||||
.rpc_proc = &rpcproc_null,
|
||||
};
|
||||
int err;
|
||||
msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0);
|
||||
err = rpc_call_sync(clnt, &msg, flags);
|
||||
err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN);
|
||||
put_rpccred(msg.rpc_cred);
|
||||
return err;
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <linux/in6.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
@@ -110,6 +111,9 @@ static void rpcb_getport_done(struct rpc_task *, void *);
|
||||
static void rpcb_map_release(void *data);
|
||||
static struct rpc_program rpcb_program;
|
||||
|
||||
static struct rpc_clnt * rpcb_local_clnt;
|
||||
static struct rpc_clnt * rpcb_local_clnt4;
|
||||
|
||||
struct rpcbind_args {
|
||||
struct rpc_xprt * r_xprt;
|
||||
|
||||
@@ -163,21 +167,60 @@ static const struct sockaddr_in rpcb_inaddr_loopback = {
|
||||
.sin_port = htons(RPCBIND_PORT),
|
||||
};
|
||||
|
||||
static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr,
|
||||
size_t addrlen, u32 version)
|
||||
static DEFINE_MUTEX(rpcb_create_local_mutex);
|
||||
|
||||
/*
|
||||
* Returns zero on success, otherwise a negative errno value
|
||||
* is returned.
|
||||
*/
|
||||
static int rpcb_create_local(void)
|
||||
{
|
||||
struct rpc_create_args args = {
|
||||
.protocol = XPRT_TRANSPORT_UDP,
|
||||
.address = addr,
|
||||
.addrsize = addrlen,
|
||||
.protocol = XPRT_TRANSPORT_TCP,
|
||||
.address = (struct sockaddr *)&rpcb_inaddr_loopback,
|
||||
.addrsize = sizeof(rpcb_inaddr_loopback),
|
||||
.servername = "localhost",
|
||||
.program = &rpcb_program,
|
||||
.version = version,
|
||||
.version = RPCBVERS_2,
|
||||
.authflavor = RPC_AUTH_UNIX,
|
||||
.flags = RPC_CLNT_CREATE_NOPING,
|
||||
};
|
||||
struct rpc_clnt *clnt, *clnt4;
|
||||
int result = 0;
|
||||
|
||||
return rpc_create(&args);
|
||||
if (rpcb_local_clnt)
|
||||
return result;
|
||||
|
||||
mutex_lock(&rpcb_create_local_mutex);
|
||||
if (rpcb_local_clnt)
|
||||
goto out;
|
||||
|
||||
clnt = rpc_create(&args);
|
||||
if (IS_ERR(clnt)) {
|
||||
dprintk("RPC: failed to create local rpcbind "
|
||||
"client (errno %ld).\n", PTR_ERR(clnt));
|
||||
result = -PTR_ERR(clnt);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* This results in an RPC ping. On systems running portmapper,
|
||||
* the v4 ping will fail. Proceed anyway, but disallow rpcb
|
||||
* v4 upcalls.
|
||||
*/
|
||||
clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
|
||||
if (IS_ERR(clnt4)) {
|
||||
dprintk("RPC: failed to create local rpcbind v4 "
|
||||
"cleint (errno %ld).\n", PTR_ERR(clnt4));
|
||||
clnt4 = NULL;
|
||||
}
|
||||
|
||||
rpcb_local_clnt = clnt;
|
||||
rpcb_local_clnt4 = clnt4;
|
||||
|
||||
out:
|
||||
mutex_unlock(&rpcb_create_local_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
|
||||
@@ -209,22 +252,13 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
|
||||
return rpc_create(&args);
|
||||
}
|
||||
|
||||
static int rpcb_register_call(const u32 version, struct rpc_message *msg)
|
||||
static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg)
|
||||
{
|
||||
struct sockaddr *addr = (struct sockaddr *)&rpcb_inaddr_loopback;
|
||||
size_t addrlen = sizeof(rpcb_inaddr_loopback);
|
||||
struct rpc_clnt *rpcb_clnt;
|
||||
int result, error = 0;
|
||||
|
||||
msg->rpc_resp = &result;
|
||||
|
||||
rpcb_clnt = rpcb_create_local(addr, addrlen, version);
|
||||
if (!IS_ERR(rpcb_clnt)) {
|
||||
error = rpc_call_sync(rpcb_clnt, msg, 0);
|
||||
rpc_shutdown_client(rpcb_clnt);
|
||||
} else
|
||||
error = PTR_ERR(rpcb_clnt);
|
||||
|
||||
error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN);
|
||||
if (error < 0) {
|
||||
dprintk("RPC: failed to contact local rpcbind "
|
||||
"server (errno %d).\n", -error);
|
||||
@@ -279,6 +313,11 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
|
||||
struct rpc_message msg = {
|
||||
.rpc_argp = &map,
|
||||
};
|
||||
int error;
|
||||
|
||||
error = rpcb_create_local();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
|
||||
"rpcbind\n", (port ? "" : "un"),
|
||||
@@ -288,7 +327,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
|
||||
if (port)
|
||||
msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
|
||||
|
||||
return rpcb_register_call(RPCBVERS_2, &msg);
|
||||
return rpcb_register_call(rpcb_local_clnt, &msg);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -313,7 +352,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap,
|
||||
if (port)
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
|
||||
|
||||
result = rpcb_register_call(RPCBVERS_4, msg);
|
||||
result = rpcb_register_call(rpcb_local_clnt4, msg);
|
||||
kfree(map->r_addr);
|
||||
return result;
|
||||
}
|
||||
@@ -340,7 +379,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap,
|
||||
if (port)
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
|
||||
|
||||
result = rpcb_register_call(RPCBVERS_4, msg);
|
||||
result = rpcb_register_call(rpcb_local_clnt4, msg);
|
||||
kfree(map->r_addr);
|
||||
return result;
|
||||
}
|
||||
@@ -356,7 +395,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg)
|
||||
map->r_addr = "";
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
|
||||
|
||||
return rpcb_register_call(RPCBVERS_4, msg);
|
||||
return rpcb_register_call(rpcb_local_clnt4, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,6 +453,13 @@ int rpcb_v4_register(const u32 program, const u32 version,
|
||||
struct rpc_message msg = {
|
||||
.rpc_argp = &map,
|
||||
};
|
||||
int error;
|
||||
|
||||
error = rpcb_create_local();
|
||||
if (error)
|
||||
return error;
|
||||
if (rpcb_local_clnt4 == NULL)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
if (address == NULL)
|
||||
return rpcb_unregister_all_protofamilies(&msg);
|
||||
@@ -491,7 +537,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
|
||||
.rpc_message = &msg,
|
||||
.callback_ops = &rpcb_getport_ops,
|
||||
.callback_data = map,
|
||||
.flags = RPC_TASK_ASYNC,
|
||||
.flags = RPC_TASK_ASYNC | RPC_TASK_SOFTCONN,
|
||||
};
|
||||
|
||||
return rpc_run_task(&task_setup_data);
|
||||
@@ -1027,3 +1073,15 @@ static struct rpc_program rpcb_program = {
|
||||
.version = rpcb_version,
|
||||
.stats = &rpcb_stats,
|
||||
};
|
||||
|
||||
/**
|
||||
* cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
|
||||
*
|
||||
*/
|
||||
void cleanup_rpcb_clnt(void)
|
||||
{
|
||||
if (rpcb_local_clnt4)
|
||||
rpc_shutdown_client(rpcb_local_clnt4);
|
||||
if (rpcb_local_clnt)
|
||||
rpc_shutdown_client(rpcb_local_clnt);
|
||||
}
|
||||
|
@@ -24,6 +24,8 @@
|
||||
|
||||
extern struct cache_detail ip_map_cache, unix_gid_cache;
|
||||
|
||||
extern void cleanup_rpcb_clnt(void);
|
||||
|
||||
static int __init
|
||||
init_sunrpc(void)
|
||||
{
|
||||
@@ -53,6 +55,7 @@ out:
|
||||
static void __exit
|
||||
cleanup_sunrpc(void)
|
||||
{
|
||||
cleanup_rpcb_clnt();
|
||||
rpcauth_remove_module();
|
||||
cleanup_socket_xprt();
|
||||
svc_cleanup_xprt_sock();
|
||||
|
@@ -2033,7 +2033,7 @@ static void xs_connect(struct rpc_task *task)
|
||||
if (xprt_test_and_set_connecting(xprt))
|
||||
return;
|
||||
|
||||
if (transport->sock != NULL) {
|
||||
if (transport->sock != NULL && !RPC_IS_SOFTCONN(task)) {
|
||||
dprintk("RPC: xs_connect delayed xprt %p for %lu "
|
||||
"seconds\n",
|
||||
xprt, xprt->reestablish_timeout / HZ);
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador