mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branch 'nfs-for-2.6.33'
This commit is contained in:
commit
52c9948b1f
30 changed files with 1078 additions and 469 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -123,16 +123,19 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred)
|
|||
clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
rpcauth_unhash_cred(struct rpc_cred *cred)
|
||||
{
|
||||
spinlock_t *cache_lock;
|
||||
int ret;
|
||||
|
||||
cache_lock = &cred->cr_auth->au_credcache->lock;
|
||||
spin_lock(cache_lock);
|
||||
if (atomic_read(&cred->cr_count) == 0)
|
||||
ret = atomic_read(&cred->cr_count) == 0;
|
||||
if (ret)
|
||||
rpcauth_unhash_cred_locked(cred);
|
||||
spin_unlock(cache_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -446,31 +449,35 @@ void
|
|||
put_rpccred(struct rpc_cred *cred)
|
||||
{
|
||||
/* Fast path for unhashed credentials */
|
||||
if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
|
||||
goto need_lock;
|
||||
|
||||
if (!atomic_dec_and_test(&cred->cr_count))
|
||||
if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
|
||||
if (atomic_dec_and_test(&cred->cr_count))
|
||||
cred->cr_ops->crdestroy(cred);
|
||||
return;
|
||||
goto out_destroy;
|
||||
need_lock:
|
||||
}
|
||||
|
||||
if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
|
||||
return;
|
||||
if (!list_empty(&cred->cr_lru)) {
|
||||
number_cred_unused--;
|
||||
list_del_init(&cred->cr_lru);
|
||||
}
|
||||
if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
|
||||
rpcauth_unhash_cred(cred);
|
||||
if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
|
||||
cred->cr_expire = jiffies;
|
||||
list_add_tail(&cred->cr_lru, &cred_unused);
|
||||
number_cred_unused++;
|
||||
spin_unlock(&rpc_credcache_lock);
|
||||
return;
|
||||
if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) {
|
||||
cred->cr_expire = jiffies;
|
||||
list_add_tail(&cred->cr_lru, &cred_unused);
|
||||
number_cred_unused++;
|
||||
goto out_nodestroy;
|
||||
}
|
||||
if (!rpcauth_unhash_cred(cred)) {
|
||||
/* We were hashed and someone looked us up... */
|
||||
goto out_nodestroy;
|
||||
}
|
||||
}
|
||||
spin_unlock(&rpc_credcache_lock);
|
||||
out_destroy:
|
||||
cred->cr_ops->crdestroy(cred);
|
||||
return;
|
||||
out_nodestroy:
|
||||
spin_unlock(&rpc_credcache_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(put_rpccred);
|
||||
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
|
|||
* to that upcall instead of adding the new upcall.
|
||||
*/
|
||||
static inline struct gss_upcall_msg *
|
||||
gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
|
||||
gss_add_msg(struct gss_upcall_msg *gss_msg)
|
||||
{
|
||||
struct rpc_inode *rpci = gss_msg->inode;
|
||||
struct inode *inode = &rpci->vfs_inode;
|
||||
|
|
@ -445,7 +445,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
|
|||
gss_new = gss_alloc_msg(gss_auth, uid, clnt, gss_cred->gc_machine_cred);
|
||||
if (IS_ERR(gss_new))
|
||||
return gss_new;
|
||||
gss_msg = gss_add_msg(gss_auth, gss_new);
|
||||
gss_msg = gss_add_msg(gss_new);
|
||||
if (gss_msg == gss_new) {
|
||||
struct inode *inode = &gss_new->inode->vfs_inode;
|
||||
int res = rpc_queue_upcall(inode, &gss_new->msg);
|
||||
|
|
@ -485,7 +485,7 @@ gss_refresh_upcall(struct rpc_task *task)
|
|||
dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
|
||||
cred->cr_uid);
|
||||
gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
|
||||
if (IS_ERR(gss_msg) == -EAGAIN) {
|
||||
if (PTR_ERR(gss_msg) == -EAGAIN) {
|
||||
/* XXX: warning on the first, under the assumption we
|
||||
* shouldn't normally hit this case on a refresh. */
|
||||
warn_gssd();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -700,6 +700,10 @@ void xprt_connect(struct rpc_task *task)
|
|||
}
|
||||
if (!xprt_lock_write(xprt, task))
|
||||
return;
|
||||
|
||||
if (test_and_clear_bit(XPRT_CLOSE_WAIT, &xprt->state))
|
||||
xprt->ops->close(xprt);
|
||||
|
||||
if (xprt_connected(xprt))
|
||||
xprt_release_write(xprt, task);
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -2019,7 +2019,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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue