Merge branch 'devel' into next

Conflicts:

	fs/nfs/file.c

Fix up the conflict with Jon Corbet's bkl-removal tree
This commit is contained in:
Trond Myklebust
2008-07-15 18:34:16 -04:00
35 changed files with 1851 additions and 1166 deletions

View File

@@ -63,22 +63,11 @@ static const struct rpc_credops gss_nullops;
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
#define NFS_NGROUPS 16
#define GSS_CRED_SLACK 1024 /* XXX: unused */
#define GSS_CRED_SLACK 1024
/* length of a krb5 verifier (48), plus data added before arguments when
* using integrity (two 4-byte integers): */
#define GSS_VERF_SLACK 100
/* XXX this define must match the gssd define
* as it is passed to gssd to signal the use of
* machine creds should be part of the shared rpc interface */
#define CA_RUN_AS_MACHINE 0x00000200
/* dump the buffer in `emacs-hexl' style */
#define isprint(c) ((c > 0x1f) && (c < 0x7f))
struct gss_auth {
struct kref kref;
struct rpc_auth rpc_auth;
@@ -146,7 +135,7 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
q = (const void *)((const char *)p + len);
if (unlikely(q > end || q < p))
return ERR_PTR(-EFAULT);
dest->data = kmemdup(p, len, GFP_KERNEL);
dest->data = kmemdup(p, len, GFP_NOFS);
if (unlikely(dest->data == NULL))
return ERR_PTR(-ENOMEM);
dest->len = len;
@@ -171,7 +160,7 @@ gss_alloc_context(void)
{
struct gss_cl_ctx *ctx;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
ctx = kzalloc(sizeof(*ctx), GFP_NOFS);
if (ctx != NULL) {
ctx->gc_proc = RPC_GSS_PROC_DATA;
ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
@@ -272,7 +261,7 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
return NULL;
}
/* Try to add a upcall to the pipefs queue.
/* Try to add an upcall to the pipefs queue.
* If an upcall owned by our uid already exists, then we return a reference
* to that upcall instead of adding the new upcall.
*/
@@ -341,7 +330,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
{
struct gss_upcall_msg *gss_msg;
gss_msg = kzalloc(sizeof(*gss_msg), GFP_KERNEL);
gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
if (gss_msg != NULL) {
INIT_LIST_HEAD(&gss_msg->list);
rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
@@ -493,7 +482,6 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
{
const void *p, *end;
void *buf;
struct rpc_clnt *clnt;
struct gss_upcall_msg *gss_msg;
struct inode *inode = filp->f_path.dentry->d_inode;
struct gss_cl_ctx *ctx;
@@ -503,11 +491,10 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
if (mlen > MSG_BUF_MAXSIZE)
goto out;
err = -ENOMEM;
buf = kmalloc(mlen, GFP_KERNEL);
buf = kmalloc(mlen, GFP_NOFS);
if (!buf)
goto out;
clnt = RPC_I(inode)->private;
err = -EFAULT;
if (copy_from_user(buf, src, mlen))
goto err;
@@ -806,7 +793,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
dprintk("RPC: gss_create_cred for uid %d, flavor %d\n",
acred->uid, auth->au_flavor);
if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS)))
goto out_err;
rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops);

View File

@@ -70,7 +70,7 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
q = (const void *)((const char *)p + len);
if (unlikely(q > end || q < p))
return ERR_PTR(-EFAULT);
res->data = kmemdup(p, len, GFP_KERNEL);
res->data = kmemdup(p, len, GFP_NOFS);
if (unlikely(res->data == NULL))
return ERR_PTR(-ENOMEM);
res->len = len;
@@ -131,7 +131,7 @@ gss_import_sec_context_kerberos(const void *p,
struct krb5_ctx *ctx;
int tmp;
if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL)))
if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS)))
goto out_err;
p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));

View File

@@ -76,7 +76,7 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
q = (const void *)((const char *)p + len);
if (unlikely(q > end || q < p))
return ERR_PTR(-EFAULT);
res->data = kmemdup(p, len, GFP_KERNEL);
res->data = kmemdup(p, len, GFP_NOFS);
if (unlikely(res->data == NULL))
return ERR_PTR(-ENOMEM);
return q;
@@ -90,7 +90,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len,
struct spkm3_ctx *ctx;
int version;
if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL)))
if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS)))
goto out_err;
p = simple_get_bytes(p, end, &version, sizeof(version));

View File

@@ -90,7 +90,7 @@ asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits)
int
decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen)
{
if (!(out->data = kzalloc(explen,GFP_KERNEL)))
if (!(out->data = kzalloc(explen,GFP_NOFS)))
return 0;
out->len = explen;
memcpy(out->data, in, enclen);

View File

@@ -66,7 +66,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
acred->uid, acred->gid);
if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
if (!(cred = kmalloc(sizeof(*cred), GFP_NOFS)))
return ERR_PTR(-ENOMEM);
rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);

View File

@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kallsyms.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
@@ -58,7 +59,6 @@ static void call_start(struct rpc_task *task);
static void call_reserve(struct rpc_task *task);
static void call_reserveresult(struct rpc_task *task);
static void call_allocate(struct rpc_task *task);
static void call_encode(struct rpc_task *task);
static void call_decode(struct rpc_task *task);
static void call_bind(struct rpc_task *task);
static void call_bind_status(struct rpc_task *task);
@@ -70,9 +70,9 @@ static void call_refreshresult(struct rpc_task *task);
static void call_timeout(struct rpc_task *task);
static void call_connect(struct rpc_task *task);
static void call_connect_status(struct rpc_task *task);
static __be32 * call_header(struct rpc_task *task);
static __be32 * call_verify(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 void rpc_register_client(struct rpc_clnt *clnt)
@@ -324,6 +324,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
clnt->cl_autobind = 1;
if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
clnt->cl_discrtry = 1;
if (!(args->flags & RPC_CLNT_CREATE_QUIET))
clnt->cl_chatty = 1;
return clnt;
}
@@ -690,6 +692,21 @@ rpc_restart_call(struct rpc_task *task)
}
EXPORT_SYMBOL_GPL(rpc_restart_call);
#ifdef RPC_DEBUG
static const char *rpc_proc_name(const struct rpc_task *task)
{
const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
if (proc) {
if (proc->p_name)
return proc->p_name;
else
return "NULL";
} else
return "no proc";
}
#endif
/*
* 0. Initial state
*
@@ -701,9 +718,9 @@ call_start(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
dprintk("RPC: %5u call_start %s%d proc %d (%s)\n", task->tk_pid,
dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid,
clnt->cl_protname, clnt->cl_vers,
task->tk_msg.rpc_proc->p_proc,
rpc_proc_name(task),
(RPC_IS_ASYNC(task) ? "async" : "sync"));
/* Increment call count */
@@ -861,7 +878,7 @@ rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
* 3. Encode arguments of an RPC call
*/
static void
call_encode(struct rpc_task *task)
rpc_xdr_encode(struct rpc_task *task)
{
struct rpc_rqst *req = task->tk_rqstp;
kxdrproc_t encode;
@@ -876,23 +893,19 @@ call_encode(struct rpc_task *task)
(char *)req->rq_buffer + req->rq_callsize,
req->rq_rcvsize);
/* Encode header and provided arguments */
encode = task->tk_msg.rpc_proc->p_encode;
if (!(p = call_header(task))) {
printk(KERN_INFO "RPC: call_header failed, exit EIO\n");
p = rpc_encode_header(task);
if (p == NULL) {
printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n");
rpc_exit(task, -EIO);
return;
}
encode = task->tk_msg.rpc_proc->p_encode;
if (encode == NULL)
return;
task->tk_status = rpcauth_wrap_req(task, encode, req, p,
task->tk_msg.rpc_argp);
if (task->tk_status == -ENOMEM) {
/* XXX: Is this sane? */
rpc_delay(task, 3*HZ);
task->tk_status = -EAGAIN;
}
}
/*
@@ -929,11 +942,9 @@ call_bind_status(struct rpc_task *task)
}
switch (task->tk_status) {
case -EAGAIN:
dprintk("RPC: %5u rpcbind waiting for another request "
"to finish\n", task->tk_pid);
/* avoid busy-waiting here -- could be a network outage. */
rpc_delay(task, 5*HZ);
case -ENOMEM:
dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid);
rpc_delay(task, HZ >> 2);
goto retry_timeout;
case -EACCES:
dprintk("RPC: %5u remote rpcbind: RPC program/version "
@@ -1046,10 +1057,16 @@ call_transmit(struct rpc_task *task)
/* Encode here so that rpcsec_gss can use correct sequence number. */
if (rpc_task_need_encode(task)) {
BUG_ON(task->tk_rqstp->rq_bytes_sent != 0);
call_encode(task);
rpc_xdr_encode(task);
/* Did the encode result in an error condition? */
if (task->tk_status != 0)
if (task->tk_status != 0) {
/* Was the error nonfatal? */
if (task->tk_status == -EAGAIN)
rpc_delay(task, HZ >> 4);
else
rpc_exit(task, task->tk_status);
return;
}
}
xprt_transmit(task);
if (task->tk_status < 0)
@@ -1132,7 +1149,8 @@ call_status(struct rpc_task *task)
rpc_exit(task, status);
break;
default:
printk("%s: RPC call returned error %d\n",
if (clnt->cl_chatty)
printk("%s: RPC call returned error %d\n",
clnt->cl_protname, -status);
rpc_exit(task, status);
}
@@ -1157,7 +1175,8 @@ call_timeout(struct rpc_task *task)
task->tk_timeouts++;
if (RPC_IS_SOFT(task)) {
printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
if (clnt->cl_chatty)
printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
clnt->cl_protname, clnt->cl_server);
rpc_exit(task, -EIO);
return;
@@ -1165,7 +1184,8 @@ call_timeout(struct rpc_task *task)
if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) {
task->tk_flags |= RPC_CALL_MAJORSEEN;
printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
if (clnt->cl_chatty)
printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
clnt->cl_protname, clnt->cl_server);
}
rpc_force_rebind(clnt);
@@ -1196,8 +1216,9 @@ call_decode(struct rpc_task *task)
task->tk_pid, task->tk_status);
if (task->tk_flags & RPC_CALL_MAJORSEEN) {
printk(KERN_NOTICE "%s: server %s OK\n",
clnt->cl_protname, clnt->cl_server);
if (clnt->cl_chatty)
printk(KERN_NOTICE "%s: server %s OK\n",
clnt->cl_protname, clnt->cl_server);
task->tk_flags &= ~RPC_CALL_MAJORSEEN;
}
@@ -1224,8 +1245,7 @@ call_decode(struct rpc_task *task)
goto out_retry;
}
/* Verify the RPC header */
p = call_verify(task);
p = rpc_verify_header(task);
if (IS_ERR(p)) {
if (p == ERR_PTR(-EAGAIN))
goto out_retry;
@@ -1243,7 +1263,7 @@ call_decode(struct rpc_task *task)
return;
out_retry:
task->tk_status = 0;
/* Note: call_verify() may have freed the RPC slot */
/* Note: rpc_verify_header() may have freed the RPC slot */
if (task->tk_rqstp == req) {
req->rq_received = req->rq_rcv_buf.len = 0;
if (task->tk_client->cl_discrtry)
@@ -1290,11 +1310,8 @@ call_refreshresult(struct rpc_task *task)
return;
}
/*
* Call header serialization
*/
static __be32 *
call_header(struct rpc_task *task)
rpc_encode_header(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
struct rpc_rqst *req = task->tk_rqstp;
@@ -1314,11 +1331,8 @@ call_header(struct rpc_task *task)
return p;
}
/*
* Reply header verification
*/
static __be32 *
call_verify(struct rpc_task *task)
rpc_verify_header(struct rpc_task *task)
{
struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
@@ -1392,7 +1406,7 @@ call_verify(struct rpc_task *task)
task->tk_action = call_bind;
goto out_retry;
case RPC_AUTH_TOOWEAK:
printk(KERN_NOTICE "call_verify: server %s requires stronger "
printk(KERN_NOTICE "RPC: server %s requires stronger "
"authentication.\n", task->tk_client->cl_server);
break;
default:
@@ -1431,10 +1445,10 @@ call_verify(struct rpc_task *task)
error = -EPROTONOSUPPORT;
goto out_err;
case RPC_PROC_UNAVAIL:
dprintk("RPC: %5u %s: proc %p unsupported by program %u, "
dprintk("RPC: %5u %s: proc %s unsupported by program %u, "
"version %u on server %s\n",
task->tk_pid, __func__,
task->tk_msg.rpc_proc,
rpc_proc_name(task),
task->tk_client->cl_prog,
task->tk_client->cl_vers,
task->tk_client->cl_server);
@@ -1517,44 +1531,53 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int
EXPORT_SYMBOL_GPL(rpc_call_null);
#ifdef RPC_DEBUG
static void rpc_show_header(void)
{
printk(KERN_INFO "-pid- flgs status -client- --rqstp- "
"-timeout ---ops--\n");
}
static void rpc_show_task(const struct rpc_clnt *clnt,
const struct rpc_task *task)
{
const char *rpc_waitq = "none";
char *p, action[KSYM_SYMBOL_LEN];
if (RPC_IS_QUEUED(task))
rpc_waitq = rpc_qname(task->tk_waitqueue);
/* map tk_action pointer to a function name; then trim off
* the "+0x0 [sunrpc]" */
sprint_symbol(action, (unsigned long)task->tk_action);
p = strchr(action, '+');
if (p)
*p = '\0';
printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%s q:%s\n",
task->tk_pid, task->tk_flags, task->tk_status,
clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops,
clnt->cl_protname, clnt->cl_vers, rpc_proc_name(task),
action, rpc_waitq);
}
void rpc_show_tasks(void)
{
struct rpc_clnt *clnt;
struct rpc_task *t;
struct rpc_task *task;
int header = 0;
spin_lock(&rpc_client_lock);
if (list_empty(&all_clients))
goto out;
printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
"-rpcwait -action- ---ops--\n");
list_for_each_entry(clnt, &all_clients, cl_clients) {
if (list_empty(&clnt->cl_tasks))
continue;
spin_lock(&clnt->cl_lock);
list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
const char *rpc_waitq = "none";
int proc;
if (t->tk_msg.rpc_proc)
proc = t->tk_msg.rpc_proc->p_proc;
else
proc = -1;
if (RPC_IS_QUEUED(t))
rpc_waitq = rpc_qname(t->tk_waitqueue);
printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
t->tk_pid, proc,
t->tk_flags, t->tk_status,
t->tk_client,
(t->tk_client ? t->tk_client->cl_prog : 0),
t->tk_rqstp, t->tk_timeout,
rpc_waitq,
t->tk_action, t->tk_ops);
list_for_each_entry(task, &clnt->cl_tasks, tk_task) {
if (!header) {
rpc_show_header();
header++;
}
rpc_show_task(clnt, task);
}
spin_unlock(&clnt->cl_lock);
}
out:
spin_unlock(&rpc_client_lock);
}
#endif

View File

@@ -32,6 +32,10 @@
#define RPCBIND_PROGRAM (100000u)
#define RPCBIND_PORT (111u)
#define RPCBVERS_2 (2u)
#define RPCBVERS_3 (3u)
#define RPCBVERS_4 (4u)
enum {
RPCBPROC_NULL,
RPCBPROC_SET,
@@ -64,6 +68,7 @@ enum {
#define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING)
static void rpcb_getport_done(struct rpc_task *, void *);
static void rpcb_map_release(void *data);
static struct rpc_program rpcb_program;
struct rpcbind_args {
@@ -76,27 +81,22 @@ struct rpcbind_args {
const char * r_netid;
const char * r_addr;
const char * r_owner;
int r_status;
};
static struct rpc_procinfo rpcb_procedures2[];
static struct rpc_procinfo rpcb_procedures3[];
static struct rpc_procinfo rpcb_procedures4[];
struct rpcb_info {
int rpc_vers;
u32 rpc_vers;
struct rpc_procinfo * rpc_proc;
};
static struct rpcb_info rpcb_next_version[];
static struct rpcb_info rpcb_next_version6[];
static void rpcb_map_release(void *data)
{
struct rpcbind_args *map = data;
xprt_put(map->r_xprt);
kfree(map);
}
static const struct rpc_call_ops rpcb_getport_ops = {
.rpc_call_done = rpcb_getport_done,
.rpc_release = rpcb_map_release,
@@ -108,9 +108,46 @@ static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
rpc_wake_up_status(&xprt->binding, status);
}
static void rpcb_map_release(void *data)
{
struct rpcbind_args *map = data;
rpcb_wake_rpcbind_waiters(map->r_xprt, map->r_status);
xprt_put(map->r_xprt);
kfree(map);
}
static const struct sockaddr_in rpcb_inaddr_loopback = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
.sin_port = htons(RPCBIND_PORT),
};
static const struct sockaddr_in6 rpcb_in6addr_loopback = {
.sin6_family = AF_INET6,
.sin6_addr = IN6ADDR_LOOPBACK_INIT,
.sin6_port = htons(RPCBIND_PORT),
};
static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr,
size_t addrlen, u32 version)
{
struct rpc_create_args args = {
.protocol = XPRT_TRANSPORT_UDP,
.address = addr,
.addrsize = addrlen,
.servername = "localhost",
.program = &rpcb_program,
.version = version,
.authflavor = RPC_AUTH_UNIX,
.flags = RPC_CLNT_CREATE_NOPING,
};
return rpc_create(&args);
}
static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
size_t salen, int proto, u32 version,
int privileged)
size_t salen, int proto, u32 version)
{
struct rpc_create_args args = {
.protocol = proto,
@@ -120,7 +157,8 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
.program = &rpcb_program,
.version = version,
.authflavor = RPC_AUTH_UNIX,
.flags = RPC_CLNT_CREATE_NOPING,
.flags = (RPC_CLNT_CREATE_NOPING |
RPC_CLNT_CREATE_NONPRIVPORT),
};
switch (srvaddr->sa_family) {
@@ -134,29 +172,72 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
return NULL;
}
if (!privileged)
args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
return rpc_create(&args);
}
static int rpcb_register_call(struct sockaddr *addr, size_t addrlen,
u32 version, struct rpc_message *msg,
int *result)
{
struct rpc_clnt *rpcb_clnt;
int error = 0;
*result = 0;
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);
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, *result);
return error;
}
/**
* 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
* @prot: transport protocol to register
* @port: port value to register
* @okay: result code
* @okay: OUT: result code
*
* port == 0 means unregister, port != 0 means register.
* RPC services invoke this function to advertise their contact
* information via the system's rpcbind daemon. RPC services
* invoke this function once for each [program, version, transport]
* tuple they wish to advertise.
*
* This routine supports only rpcbind version 2.
* Callers may also unregister RPC services that are no longer
* available by setting the passed-in port to zero. This removes
* all registered transports for [program, version] from the local
* rpcbind database.
*
* Returns zero if the registration request was dispatched
* successfully and a reply was received. The rpcbind daemon's
* boolean result code is stored in *okay.
*
* Returns an errno value and sets *result to zero if there was
* some problem that prevented the rpcbind request from being
* dispatched, or if the rpcbind daemon did not respond within
* the timeout.
*
* This function uses rpcbind protocol version 2 to contact the
* local rpcbind daemon.
*
* Registration works over both AF_INET and AF_INET6, and services
* registered via this function are advertised as available for any
* address. If the local rpcbind daemon is listening on AF_INET6,
* services registered via this function will be advertised on
* IN6ADDR_ANY (ie available for all AF_INET and AF_INET6
* addresses).
*/
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,
@@ -164,32 +245,159 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
.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);
msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET];
if (port)
msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
error = rpc_call_sync(rpcb_clnt, &msg, 0);
return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback,
sizeof(rpcb_inaddr_loopback),
RPCBVERS_2, &msg, okay);
}
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);
/*
* Fill in AF_INET family-specific arguments to register
*/
static int rpcb_register_netid4(struct sockaddr_in *address_to_register,
struct rpc_message *msg)
{
struct rpcbind_args *map = msg->rpc_argp;
unsigned short port = ntohs(address_to_register->sin_port);
char buf[32];
return error;
/* Construct AF_INET universal address */
snprintf(buf, sizeof(buf),
NIPQUAD_FMT".%u.%u",
NIPQUAD(address_to_register->sin_addr.s_addr),
port >> 8, port & 0xff);
map->r_addr = buf;
dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with "
"local rpcbind\n", (port ? "" : "un"),
map->r_prog, map->r_vers,
map->r_addr, map->r_netid);
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
if (port)
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback,
sizeof(rpcb_inaddr_loopback),
RPCBVERS_4, msg, msg->rpc_resp);
}
/*
* Fill in AF_INET6 family-specific arguments to register
*/
static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register,
struct rpc_message *msg)
{
struct rpcbind_args *map = msg->rpc_argp;
unsigned short port = ntohs(address_to_register->sin6_port);
char buf[64];
/* Construct AF_INET6 universal address */
snprintf(buf, sizeof(buf),
NIP6_FMT".%u.%u",
NIP6(address_to_register->sin6_addr),
port >> 8, port & 0xff);
map->r_addr = buf;
dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with "
"local rpcbind\n", (port ? "" : "un"),
map->r_prog, map->r_vers,
map->r_addr, map->r_netid);
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
if (port)
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
return rpcb_register_call((struct sockaddr *)&rpcb_in6addr_loopback,
sizeof(rpcb_in6addr_loopback),
RPCBVERS_4, msg, msg->rpc_resp);
}
/**
* rpcb_v4_register - set or unset a port registration with the local rpcbind
* @program: RPC program number of service to (un)register
* @version: RPC version number of service to (un)register
* @address: address family, IP address, and port to (un)register
* @netid: netid of transport protocol to (un)register
* @result: result code from rpcbind RPC call
*
* RPC services invoke this function to advertise their contact
* information via the system's rpcbind daemon. RPC services
* invoke this function once for each [program, version, address,
* netid] tuple they wish to advertise.
*
* Callers may also unregister RPC services that are no longer
* available by setting the port number in the passed-in address
* to zero. Callers pass a netid of "" to unregister all
* transport netids associated with [program, version, address].
*
* Returns zero if the registration request was dispatched
* successfully and a reply was received. The rpcbind daemon's
* result code is stored in *result.
*
* Returns an errno value and sets *result to zero if there was
* some problem that prevented the rpcbind request from being
* dispatched, or if the rpcbind daemon did not respond within
* the timeout.
*
* This function uses rpcbind protocol version 4 to contact the
* local rpcbind daemon. The local rpcbind daemon must support
* version 4 of the rpcbind protocol in order for these functions
* to register a service successfully.
*
* Supported netids include "udp" and "tcp" for UDP and TCP over
* IPv4, and "udp6" and "tcp6" for UDP and TCP over IPv6,
* respectively.
*
* The contents of @address determine the address family and the
* port to be registered. The usual practice is to pass INADDR_ANY
* as the raw address, but specifying a non-zero address is also
* supported by this API if the caller wishes to advertise an RPC
* service on a specific network interface.
*
* Note that passing in INADDR_ANY does not create the same service
* registration as IN6ADDR_ANY. The former advertises an RPC
* service on any IPv4 address, but not on IPv6. The latter
* advertises the service on all IPv4 and IPv6 addresses.
*/
int rpcb_v4_register(const u32 program, const u32 version,
const struct sockaddr *address, const char *netid,
int *result)
{
struct rpcbind_args map = {
.r_prog = program,
.r_vers = version,
.r_netid = netid,
.r_owner = RPCB_OWNER_STRING,
};
struct rpc_message msg = {
.rpc_argp = &map,
.rpc_resp = result,
};
*result = 0;
switch (address->sa_family) {
case AF_INET:
return rpcb_register_netid4((struct sockaddr_in *)address,
&msg);
case AF_INET6:
return rpcb_register_netid6((struct sockaddr_in6 *)address,
&msg);
}
return -EAFNOSUPPORT;
}
/**
@@ -227,7 +435,7 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
__func__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
sizeof(*sin), prot, 2, 0);
sizeof(*sin), prot, RPCBVERS_2);
if (IS_ERR(rpcb_clnt))
return PTR_ERR(rpcb_clnt);
@@ -289,17 +497,16 @@ void rpcb_getport_async(struct rpc_task *task)
/* Autobind on cloned rpc clients is discouraged */
BUG_ON(clnt->cl_parent != clnt);
/* Put self on the wait queue to ensure we get notified if
* some other task is already attempting to bind the port */
rpc_sleep_on(&xprt->binding, task, NULL);
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, __func__);
goto bailout_nowake;
return;
}
/* 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);
/* Someone else may have bound if we slept */
if (xprt_bound(xprt)) {
status = 0;
@@ -338,7 +545,7 @@ void rpcb_getport_async(struct rpc_task *task)
task->tk_pid, __func__, bind_version);
rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot,
bind_version, 0);
bind_version);
if (IS_ERR(rpcb_clnt)) {
status = PTR_ERR(rpcb_clnt);
dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
@@ -361,15 +568,15 @@ void rpcb_getport_async(struct rpc_task *task)
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 */
map->r_status = -EIO;
child = rpcb_call_async(rpcb_clnt, map, proc);
rpc_release_client(rpcb_clnt);
if (IS_ERR(child)) {
status = -EIO;
/* rpcb_map_release() has freed the arguments */
dprintk("RPC: %5u %s: rpc_run_task failed\n",
task->tk_pid, __func__);
goto bailout_nofree;
return;
}
rpc_put_task(child);
@@ -378,7 +585,6 @@ void rpcb_getport_async(struct rpc_task *task)
bailout_nofree:
rpcb_wake_rpcbind_waiters(xprt, status);
bailout_nowake:
task->tk_status = status;
}
EXPORT_SYMBOL_GPL(rpcb_getport_async);
@@ -417,9 +623,13 @@ static void rpcb_getport_done(struct rpc_task *child, void *data)
dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
child->tk_pid, status, map->r_port);
rpcb_wake_rpcbind_waiters(xprt, status);
map->r_status = status;
}
/*
* XDR functions for rpcbind
*/
static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p,
struct rpcbind_args *rpcb)
{
@@ -438,7 +648,7 @@ 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",
dprintk("RPC: rpcb_decode_getport result %u\n",
*portp);
return 0;
}
@@ -447,8 +657,8 @@ 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);
dprintk("RPC: rpcb_decode_set: call %s\n",
(*boolp ? "succeeded" : "failed"));
return 0;
}
@@ -571,52 +781,60 @@ out_err:
static struct rpc_procinfo rpcb_procedures2[] = {
PROC(SET, mapping, set),
PROC(UNSET, mapping, set),
PROC(GETADDR, mapping, getport),
PROC(GETPORT, mapping, getport),
};
static struct rpc_procinfo rpcb_procedures3[] = {
PROC(SET, mapping, set),
PROC(UNSET, mapping, set),
PROC(SET, getaddr, set),
PROC(UNSET, getaddr, set),
PROC(GETADDR, getaddr, getaddr),
};
static struct rpc_procinfo rpcb_procedures4[] = {
PROC(SET, mapping, set),
PROC(UNSET, mapping, set),
PROC(SET, getaddr, set),
PROC(UNSET, getaddr, set),
PROC(GETADDR, getaddr, getaddr),
PROC(GETVERSADDR, getaddr, getaddr),
};
static struct rpcb_info rpcb_next_version[] = {
#ifdef CONFIG_SUNRPC_BIND34
{ 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] },
{ 3, &rpcb_procedures3[RPCBPROC_GETADDR] },
#endif
{ 2, &rpcb_procedures2[RPCBPROC_GETPORT] },
{ 0, NULL },
{
.rpc_vers = RPCBVERS_2,
.rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT],
},
{
.rpc_proc = NULL,
},
};
static struct rpcb_info rpcb_next_version6[] = {
#ifdef CONFIG_SUNRPC_BIND34
{ 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] },
{ 3, &rpcb_procedures3[RPCBPROC_GETADDR] },
#endif
{ 0, NULL },
{
.rpc_vers = RPCBVERS_4,
.rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR],
},
{
.rpc_vers = RPCBVERS_3,
.rpc_proc = &rpcb_procedures3[RPCBPROC_GETADDR],
},
{
.rpc_proc = NULL,
},
};
static struct rpc_version rpcb_version2 = {
.number = 2,
.number = RPCBVERS_2,
.nrprocs = RPCB_HIGHPROC_2,
.procs = rpcb_procedures2
};
static struct rpc_version rpcb_version3 = {
.number = 3,
.number = RPCBVERS_3,
.nrprocs = RPCB_HIGHPROC_3,
.procs = rpcb_procedures3
};
static struct rpc_version rpcb_version4 = {
.number = 4,
.number = RPCBVERS_4,
.nrprocs = RPCB_HIGHPROC_4,
.procs = rpcb_procedures4
};

View File

@@ -626,19 +626,15 @@ static void __rpc_execute(struct rpc_task *task)
/*
* Execute any pending callback.
*/
if (RPC_DO_CALLBACK(task)) {
/* Define a callback save pointer */
if (task->tk_callback) {
void (*save_callback)(struct rpc_task *);
/*
* If a callback exists, save it, reset it,
* call it.
* The save is needed to stop from resetting
* another callback set within the callback handler
* - Dave
* We set tk_callback to NULL before calling it,
* in case it sets the tk_callback field itself:
*/
save_callback=task->tk_callback;
task->tk_callback=NULL;
save_callback = task->tk_callback;
task->tk_callback = NULL;
save_callback(task);
}

View File

@@ -690,7 +690,7 @@ static void xprt_connect_status(struct rpc_task *task)
{
struct rpc_xprt *xprt = task->tk_xprt;
if (task->tk_status >= 0) {
if (task->tk_status == 0) {
xprt->stat.connect_count++;
xprt->stat.connect_time += (long)jiffies - xprt->stat.connect_start;
dprintk("RPC: %5u xprt_connect_status: connection established\n",
@@ -699,12 +699,6 @@ static void xprt_connect_status(struct rpc_task *task)
}
switch (task->tk_status) {
case -ECONNREFUSED:
case -ECONNRESET:
dprintk("RPC: %5u xprt_connect_status: server %s refused "
"connection\n", task->tk_pid,
task->tk_client->cl_server);
break;
case -ENOTCONN:
dprintk("RPC: %5u xprt_connect_status: connection broken\n",
task->tk_pid);
@@ -878,6 +872,7 @@ void xprt_transmit(struct rpc_task *task)
return;
req->rq_connect_cookie = xprt->connect_cookie;
req->rq_xtime = jiffies;
status = xprt->ops->send_request(task);
if (status == 0) {
dprintk("RPC: %5u xmit complete\n", task->tk_pid);

View File

@@ -579,7 +579,6 @@ static int xs_udp_send_request(struct rpc_task *task)
req->rq_svec->iov_base,
req->rq_svec->iov_len);
req->rq_xtime = jiffies;
status = xs_sendpages(transport->sock,
xs_addr(xprt),
xprt->addrlen, xdr,
@@ -671,7 +670,6 @@ static int xs_tcp_send_request(struct rpc_task *task)
* to cope with writespace callbacks arriving _after_ we have
* called sendmsg(). */
while (1) {
req->rq_xtime = jiffies;
status = xs_sendpages(transport->sock,
NULL, 0, xdr, req->rq_bytes_sent);