Commit 58acfd93 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://nfsclient.bkbits.net/linux-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 3a33f489 8d945ef7
...@@ -106,7 +106,7 @@ nfs_idmap_new(struct nfs_server *server) ...@@ -106,7 +106,7 @@ nfs_idmap_new(struct nfs_server *server)
"%s/idmap", idmap->idmap_server->client->cl_pathname); "%s/idmap", idmap->idmap_server->client->cl_pathname);
idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path, idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path,
idmap->idmap_server, &idmap_upcall_ops); idmap->idmap_server, &idmap_upcall_ops, 0);
if (IS_ERR(idmap->idmap_dentry)) if (IS_ERR(idmap->idmap_dentry))
goto err_free; goto err_free;
......
...@@ -65,7 +65,7 @@ nfs4_get_client(void) ...@@ -65,7 +65,7 @@ nfs4_get_client(void)
struct nfs4_client *clp; struct nfs4_client *clp;
if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL))) if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL)))
memset(clp, 0, sizeof(nfs4_verifier)); memset(clp, 0, sizeof(*clp));
return clp; return clp;
} }
......
...@@ -127,6 +127,7 @@ u32 * rpcauth_checkverf(struct rpc_task *, u32 *); ...@@ -127,6 +127,7 @@ u32 * rpcauth_checkverf(struct rpc_task *, u32 *);
int rpcauth_refreshcred(struct rpc_task *); int rpcauth_refreshcred(struct rpc_task *);
void rpcauth_invalcred(struct rpc_task *); void rpcauth_invalcred(struct rpc_task *);
int rpcauth_uptodatecred(struct rpc_task *); int rpcauth_uptodatecred(struct rpc_task *);
int rpcauth_deadcred(struct rpc_task *);
void rpcauth_init_credcache(struct rpc_auth *); void rpcauth_init_credcache(struct rpc_auth *);
void rpcauth_free_credcache(struct rpc_auth *); void rpcauth_free_credcache(struct rpc_auth *);
......
...@@ -39,12 +39,12 @@ u32 gss_import_sec_context( ...@@ -39,12 +39,12 @@ u32 gss_import_sec_context(
u32 gss_get_mic( u32 gss_get_mic(
struct gss_ctx *ctx_id, struct gss_ctx *ctx_id,
u32 qop, u32 qop,
struct xdr_netobj *message_buffer, struct xdr_netobj *message,
struct xdr_netobj *message_token); struct xdr_netobj *mic_token);
u32 gss_verify_mic( u32 gss_verify_mic(
struct gss_ctx *ctx_id, struct gss_ctx *ctx_id,
struct xdr_netobj *signbuf, struct xdr_netobj *message,
struct xdr_netobj *checksum, struct xdr_netobj *mic_token,
u32 *qstate); u32 *qstate);
u32 gss_delete_sec_context( u32 gss_delete_sec_context(
struct gss_ctx **ctx_id); struct gss_ctx **ctx_id);
...@@ -95,12 +95,12 @@ struct gss_api_ops { ...@@ -95,12 +95,12 @@ struct gss_api_ops {
u32 (*gss_get_mic)( u32 (*gss_get_mic)(
struct gss_ctx *ctx_id, struct gss_ctx *ctx_id,
u32 qop, u32 qop,
struct xdr_netobj *message_buffer, struct xdr_netobj *message,
struct xdr_netobj *message_token); struct xdr_netobj *mic_token);
u32 (*gss_verify_mic)( u32 (*gss_verify_mic)(
struct gss_ctx *ctx_id, struct gss_ctx *ctx_id,
struct xdr_netobj *signbuf, struct xdr_netobj *message,
struct xdr_netobj *checksum, struct xdr_netobj *mic_token,
u32 *qstate); u32 *qstate);
void (*gss_delete_sec_context)( void (*gss_delete_sec_context)(
void *internal_ctx_id); void *internal_ctx_id);
......
...@@ -24,6 +24,8 @@ struct rpc_inode { ...@@ -24,6 +24,8 @@ struct rpc_inode {
int pipelen; int pipelen;
int nreaders; int nreaders;
wait_queue_head_t waitq; wait_queue_head_t waitq;
#define RPC_PIPE_WAIT_FOR_OPEN 1
int flags;
struct rpc_pipe_ops *ops; struct rpc_pipe_ops *ops;
}; };
...@@ -38,10 +40,11 @@ extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); ...@@ -38,10 +40,11 @@ extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *);
extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *); extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
extern int rpc_rmdir(char *); extern int rpc_rmdir(char *);
extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *); extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
extern int rpc_unlink(char *); extern int rpc_unlink(char *);
void __rpc_purge_current_upcall(struct file *); void __rpc_purge_current_upcall(struct file *);
void __rpc_purge_one_upcall(struct file *filp, struct rpc_pipe_msg *target);
#endif #endif
#endif #endif
...@@ -369,3 +369,9 @@ rpcauth_uptodatecred(struct rpc_task *task) ...@@ -369,3 +369,9 @@ rpcauth_uptodatecred(struct rpc_task *task)
(task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE); (task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
} }
int
rpcauth_deadcred(struct rpc_task *task)
{
return !(task->tk_msg.rpc_cred) ||
(task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_DEAD);
}
...@@ -156,7 +156,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) ...@@ -156,7 +156,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
} }
static struct gss_cl_ctx * static struct gss_cl_ctx *
gss_cred_get_ctx(struct rpc_cred *cred) gss_cred_get_uptodate_ctx(struct rpc_cred *cred)
{ {
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
struct gss_cl_ctx *ctx = NULL; struct gss_cl_ctx *ctx = NULL;
...@@ -206,9 +206,22 @@ dup_netobj(struct xdr_netobj *source, struct xdr_netobj *dest) ...@@ -206,9 +206,22 @@ dup_netobj(struct xdr_netobj *source, struct xdr_netobj *dest)
return 0; return 0;
} }
static struct gss_cl_ctx *
gss_cred_get_ctx(struct rpc_cred *cred)
{
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
struct gss_cl_ctx *ctx = NULL;
read_lock(&gss_ctx_lock);
if (gss_cred->gc_ctx)
ctx = gss_get_ctx(gss_cred->gc_ctx);
read_unlock(&gss_ctx_lock);
return ctx;
}
static int static int
gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf, gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
struct gss_cl_ctx **gc, uid_t *uid) struct gss_cl_ctx **gc, uid_t *uid, int *gss_err)
{ {
char *end = buf->data + buf->len; char *end = buf->data + buf->len;
char *p = buf->data; char *p = buf->data;
...@@ -231,8 +244,17 @@ gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf, ...@@ -231,8 +244,17 @@ gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
/* FIXME: discarded timeout for now */ /* FIXME: discarded timeout for now */
if (simple_get_bytes(&p, end, &timeout, sizeof(timeout))) if (simple_get_bytes(&p, end, &timeout, sizeof(timeout)))
goto err_free_ctx; goto err_free_ctx;
*gss_err = 0;
if (simple_get_bytes(&p, end, &ctx->gc_win, sizeof(ctx->gc_win))) if (simple_get_bytes(&p, end, &ctx->gc_win, sizeof(ctx->gc_win)))
goto err_free_ctx; goto err_free_ctx;
/* gssd signals an error by passing ctx->gc_win = 0: */
if (!ctx->gc_win) {
/* in which case the next int is an error code: */
if (simple_get_bytes(&p, end, gss_err, sizeof(*gss_err)))
goto err_free_ctx;
err = 0;
goto err_free_ctx;
}
if (simple_get_netobj(&p, end, &tmp_buf)) if (simple_get_netobj(&p, end, &tmp_buf))
goto err_free_ctx; goto err_free_ctx;
if (dup_netobj(&tmp_buf, &ctx->gc_wire_ctx)) { if (dup_netobj(&tmp_buf, &ctx->gc_wire_ctx)) {
...@@ -261,6 +283,7 @@ gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf, ...@@ -261,6 +283,7 @@ gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
struct gss_upcall_msg { struct gss_upcall_msg {
struct rpc_pipe_msg msg; struct rpc_pipe_msg msg;
struct list_head list; struct list_head list;
struct gss_auth *auth;
struct rpc_wait_queue waitq; struct rpc_wait_queue waitq;
uid_t uid; uid_t uid;
atomic_t count; atomic_t count;
...@@ -296,8 +319,6 @@ gss_release_callback(struct rpc_task *task) ...@@ -296,8 +319,6 @@ gss_release_callback(struct rpc_task *task)
gss_msg = gss_find_upcall(gss_auth, task->tk_msg.rpc_cred->cr_uid); gss_msg = gss_find_upcall(gss_auth, task->tk_msg.rpc_cred->cr_uid);
if (gss_msg) { if (gss_msg) {
rpc_wake_up(&gss_msg->waitq); rpc_wake_up(&gss_msg->waitq);
list_del(&gss_msg->list);
gss_release_msg(gss_msg);
} }
spin_unlock(&gss_auth->lock); spin_unlock(&gss_auth->lock);
} }
...@@ -328,19 +349,24 @@ gss_upcall(struct rpc_clnt *clnt, struct rpc_task *task, uid_t uid) ...@@ -328,19 +349,24 @@ gss_upcall(struct rpc_clnt *clnt, struct rpc_task *task, uid_t uid)
memset(gss_new, 0, sizeof(*gss_new)); memset(gss_new, 0, sizeof(*gss_new));
INIT_LIST_HEAD(&gss_new->list); INIT_LIST_HEAD(&gss_new->list);
INIT_RPC_WAITQ(&gss_new->waitq, "RPCSEC_GSS upcall waitq"); INIT_RPC_WAITQ(&gss_new->waitq, "RPCSEC_GSS upcall waitq");
atomic_set(&gss_new->count, 2); atomic_set(&gss_new->count, 1);
msg = &gss_new->msg; msg = &gss_new->msg;
msg->data = &gss_new->uid; msg->data = &gss_new->uid;
msg->len = sizeof(gss_new->uid); msg->len = sizeof(gss_new->uid);
gss_new->uid = uid; gss_new->uid = uid;
gss_new->auth = gss_auth;
list_add(&gss_new->list, &gss_auth->upcalls); list_add(&gss_new->list, &gss_auth->upcalls);
gss_new = NULL; gss_new = NULL;
task->tk_timeout = 5 * HZ;
rpc_sleep_on(&gss_msg->waitq, task, gss_release_callback, NULL); rpc_sleep_on(&gss_msg->waitq, task, gss_release_callback, NULL);
spin_unlock(&gss_auth->lock); spin_unlock(&gss_auth->lock);
res = rpc_queue_upcall(dentry->d_inode, msg); res = rpc_queue_upcall(dentry->d_inode, msg);
spin_lock(&gss_auth->lock); spin_lock(&gss_auth->lock);
if (res) if (res) {
rpc_wake_up(&gss_msg->waitq);
list_del(&gss_msg->list);
gss_release_msg(gss_msg); gss_release_msg(gss_msg);
}
return res; return res;
out_sleep: out_sleep:
rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL); rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
...@@ -354,13 +380,12 @@ gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, ...@@ -354,13 +380,12 @@ gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
char *dst, size_t buflen) char *dst, size_t buflen)
{ {
char *data = (char *)msg->data + msg->copied; char *data = (char *)msg->data + msg->copied;
ssize_t mlen = msg->len - msg->copied; ssize_t mlen = msg->len;
ssize_t left; ssize_t left;
if (mlen > buflen) if (mlen > buflen)
mlen = buflen; mlen = buflen;
left = copy_to_user(dst, data, mlen); left = copy_to_user(dst, data, mlen);
msg->copied += mlen - left;
return mlen - left; return mlen - left;
} }
...@@ -381,9 +406,10 @@ gss_pipe_downcall(struct file *filp, const char *src, size_t mlen) ...@@ -381,9 +406,10 @@ gss_pipe_downcall(struct file *filp, const char *src, size_t mlen)
struct auth_cred acred = { 0 }; struct auth_cred acred = { 0 };
struct rpc_cred *cred; struct rpc_cred *cred;
struct gss_upcall_msg *gss_msg; struct gss_upcall_msg *gss_msg;
struct gss_cl_ctx *ctx; struct gss_cl_ctx *ctx = NULL;
ssize_t left; ssize_t left;
int err; int err;
int gss_err;
if (mlen > sizeof(buf)) if (mlen > sizeof(buf))
return -ENOSPC; return -ENOSPC;
...@@ -395,23 +421,30 @@ gss_pipe_downcall(struct file *filp, const char *src, size_t mlen) ...@@ -395,23 +421,30 @@ gss_pipe_downcall(struct file *filp, const char *src, size_t mlen)
auth = clnt->cl_auth; auth = clnt->cl_auth;
gss_auth = container_of(auth, struct gss_auth, rpc_auth); gss_auth = container_of(auth, struct gss_auth, rpc_auth);
mech = gss_auth->mech; mech = gss_auth->mech;
err = gss_parse_init_downcall(mech, &obj, &ctx, &acred.uid); err = gss_parse_init_downcall(mech, &obj, &ctx, &acred.uid, &gss_err);
if (err) if (err)
goto err; goto err;
cred = rpcauth_lookup_credcache(auth, &acred, 0); cred = rpcauth_lookup_credcache(auth, &acred, 0);
if (!cred) if (!cred)
goto err_release_ctx; goto err;
gss_cred_set_ctx(cred, ctx); if (gss_err)
cred->cr_flags |= RPCAUTH_CRED_DEAD;
else
gss_cred_set_ctx(cred, ctx);
spin_lock(&gss_auth->lock); spin_lock(&gss_auth->lock);
gss_msg = gss_find_upcall(gss_auth, acred.uid); gss_msg = gss_find_upcall(gss_auth, acred.uid);
if (gss_msg) if (gss_msg) {
list_del(&gss_msg->list);
__rpc_purge_one_upcall(filp, &gss_msg->msg);
rpc_wake_up(&gss_msg->waitq); rpc_wake_up(&gss_msg->waitq);
gss_release_msg(gss_msg);
}
spin_unlock(&gss_auth->lock); spin_unlock(&gss_auth->lock);
rpc_release_client(clnt); rpc_release_client(clnt);
return mlen; return mlen;
err_release_ctx:
gss_destroy_ctx(ctx);
err: err:
if (ctx)
gss_destroy_ctx(ctx);
rpc_release_client(clnt); rpc_release_client(clnt);
dprintk("RPC: gss_pipe_downcall returning %d\n", err); dprintk("RPC: gss_pipe_downcall returning %d\n", err);
return err; return err;
...@@ -421,9 +454,13 @@ void ...@@ -421,9 +454,13 @@ void
gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
{ {
struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg);
struct gss_auth *gss_auth = gss_msg->auth;
spin_lock(&gss_auth->lock);
list_del(&gss_msg->list);
rpc_wake_up(&gss_msg->waitq); rpc_wake_up(&gss_msg->waitq);
gss_release_msg(gss_msg); gss_release_msg(gss_msg);
spin_unlock(&gss_auth->lock);
} }
/* /*
...@@ -459,7 +496,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) ...@@ -459,7 +496,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s", snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
clnt->cl_pathname, clnt->cl_pathname,
gss_auth->mech->gm_ops->name); gss_auth->mech->gm_ops->name);
gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops); gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
if (IS_ERR(gss_auth->dentry)) if (IS_ERR(gss_auth->dentry))
goto err_free; goto err_free;
...@@ -637,7 +674,7 @@ gss_refresh(struct rpc_task *task) ...@@ -637,7 +674,7 @@ gss_refresh(struct rpc_task *task)
task->tk_timeout = xprt->timeout.to_current; task->tk_timeout = xprt->timeout.to_current;
spin_lock(&gss_auth->lock); spin_lock(&gss_auth->lock);
if (gss_cred_get_ctx(cred)) if (gss_cred_get_uptodate_ctx(cred))
goto out; goto out;
err = gss_upcall(clnt, task, cred->cr_uid); err = gss_upcall(clnt, task, cred->cr_uid);
out: out:
...@@ -648,8 +685,8 @@ gss_refresh(struct rpc_task *task) ...@@ -648,8 +685,8 @@ gss_refresh(struct rpc_task *task)
static u32 * static u32 *
gss_validate(struct rpc_task *task, u32 *p) gss_validate(struct rpc_task *task, u32 *p)
{ {
struct gss_cred *cred = (struct gss_cred *)task->tk_msg.rpc_cred; struct rpc_cred *cred = task->tk_msg.rpc_cred;
struct gss_cl_ctx *ctx = cred->gc_ctx; struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
u32 seq, qop_state; u32 seq, qop_state;
struct xdr_netobj bufin; struct xdr_netobj bufin;
struct xdr_netobj bufout; struct xdr_netobj bufout;
......
...@@ -190,33 +190,33 @@ gss_import_sec_context(struct xdr_netobj *input_token, ...@@ -190,33 +190,33 @@ gss_import_sec_context(struct xdr_netobj *input_token,
->gss_import_sec_context(input_token, *ctx_id); ->gss_import_sec_context(input_token, *ctx_id);
} }
/* gss_verify_mic: hash messages_buffer and return gss verify token. */ /* gss_get_mic: compute a mic over message and return mic_token. */
u32 u32
gss_get_mic(struct gss_ctx *context_handle, gss_get_mic(struct gss_ctx *context_handle,
u32 qop, u32 qop,
struct xdr_netobj *message_buffer, struct xdr_netobj *message,
struct xdr_netobj *message_token) struct xdr_netobj *mic_token)
{ {
return context_handle->mech_type->gm_ops return context_handle->mech_type->gm_ops
->gss_get_mic(context_handle, ->gss_get_mic(context_handle,
qop, qop,
message_buffer, message,
message_token); mic_token);
} }
/* gss_verify_mic: hash messages_buffer and return gss verify token. */ /* gss_verify_mic: check whether the provided mic_token verifies message. */
u32 u32
gss_verify_mic(struct gss_ctx *context_handle, gss_verify_mic(struct gss_ctx *context_handle,
struct xdr_netobj *signbuf, struct xdr_netobj *message,
struct xdr_netobj *checksum, struct xdr_netobj *mic_token,
u32 *qstate) u32 *qstate)
{ {
return context_handle->mech_type->gm_ops return context_handle->mech_type->gm_ops
->gss_verify_mic(context_handle, ->gss_verify_mic(context_handle,
signbuf, message,
checksum, mic_token,
qstate); qstate);
} }
......
...@@ -850,17 +850,16 @@ call_refreshresult(struct rpc_task *task) ...@@ -850,17 +850,16 @@ call_refreshresult(struct rpc_task *task)
task->tk_status = 0; task->tk_status = 0;
task->tk_action = call_reserve; task->tk_action = call_reserve;
if (status >= 0) if (status >= 0 && rpcauth_uptodatecred(task))
return;
if (rpcauth_deadcred(task)) {
rpc_exit(task, -EACCES);
return; return;
switch (status) {
case -EPIPE:
rpc_delay(task, 3*HZ);
case -ETIMEDOUT:
task->tk_action = call_refresh;
break;
default:
rpc_exit(task, -EACCES);
} }
task->tk_action = call_refresh;
if (status != -ETIMEDOUT)
rpc_delay(task, 3*HZ);
return;
} }
/* /*
...@@ -909,6 +908,8 @@ call_verify(struct rpc_task *task) ...@@ -909,6 +908,8 @@ call_verify(struct rpc_task *task)
switch ((n = ntohl(*p++))) { switch ((n = ntohl(*p++))) {
case RPC_AUTH_REJECTEDCRED: case RPC_AUTH_REJECTEDCRED:
case RPC_AUTH_REJECTEDVERF: case RPC_AUTH_REJECTEDVERF:
case RPCSEC_GSS_CREDPROBLEM:
case RPCSEC_GSS_CTXPROBLEM:
if (!task->tk_cred_retry) if (!task->tk_cred_retry)
break; break;
task->tk_cred_retry--; task->tk_cred_retry--;
......
...@@ -75,6 +75,28 @@ __rpc_purge_current_upcall(struct file *filp) ...@@ -75,6 +75,28 @@ __rpc_purge_current_upcall(struct file *filp)
msg->errno = 0; msg->errno = 0;
} }
void
__rpc_purge_one_upcall(struct file *filp, struct rpc_pipe_msg *target)
{
struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
struct rpc_pipe_msg *msg;
msg = filp->private_data;
if (msg == target) {
filp->private_data = NULL;
goto found;
}
list_for_each_entry(msg, &rpci->pipe, list) {
if (msg == target) {
list_del(&msg->list);
goto found;
}
}
BUG();
found:
return;
}
int int
rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
{ {
...@@ -82,7 +104,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) ...@@ -82,7 +104,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
int res = 0; int res = 0;
down(&inode->i_sem); down(&inode->i_sem);
if (rpci->nreaders) { if (rpci->nreaders || (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN)) {
list_add_tail(&msg->list, &rpci->pipe); list_add_tail(&msg->list, &rpci->pipe);
rpci->pipelen += msg->len; rpci->pipelen += msg->len;
} else } else
...@@ -149,7 +171,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) ...@@ -149,7 +171,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
down(&inode->i_sem); down(&inode->i_sem);
if (filp->f_mode & FMODE_READ) if (filp->f_mode & FMODE_READ)
rpci->nreaders --; rpci->nreaders --;
if (!rpci->nreaders) if (!rpci->nreaders && !(rpci->flags & RPC_PIPE_WAIT_FOR_OPEN))
__rpc_purge_upcall(inode, -EPIPE); __rpc_purge_upcall(inode, -EPIPE);
up(&inode->i_sem); up(&inode->i_sem);
return 0; return 0;
...@@ -273,6 +295,8 @@ rpc_show_info(struct seq_file *m, void *v) ...@@ -273,6 +295,8 @@ rpc_show_info(struct seq_file *m, void *v)
clnt->cl_prog, clnt->cl_vers); clnt->cl_prog, clnt->cl_vers);
seq_printf(m, "address: %u.%u.%u.%u\n", seq_printf(m, "address: %u.%u.%u.%u\n",
NIPQUAD(clnt->cl_xprt->addr.sin_addr.s_addr)); NIPQUAD(clnt->cl_xprt->addr.sin_addr.s_addr));
seq_printf(m, "protocol: %s\n",
clnt->cl_xprt->prot == IPPROTO_UDP ? "udp" : "tcp");
return 0; return 0;
} }
...@@ -644,7 +668,7 @@ rpc_rmdir(char *path) ...@@ -644,7 +668,7 @@ rpc_rmdir(char *path)
} }
struct dentry * struct dentry *
rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops) rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
{ {
struct nameidata nd; struct nameidata nd;
struct dentry *dentry; struct dentry *dentry;
...@@ -663,6 +687,7 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops) ...@@ -663,6 +687,7 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops)
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
rpci = RPC_I(inode); rpci = RPC_I(inode);
rpci->private = private; rpci->private = private;
rpci->flags = flags;
rpci->ops = ops; rpci->ops = ops;
inode_dir_notify(dir, DN_CREATE); inode_dir_notify(dir, DN_CREATE);
out: out:
......
...@@ -57,6 +57,7 @@ EXPORT_SYMBOL(rpc_wake_up); ...@@ -57,6 +57,7 @@ EXPORT_SYMBOL(rpc_wake_up);
EXPORT_SYMBOL(rpc_queue_upcall); EXPORT_SYMBOL(rpc_queue_upcall);
EXPORT_SYMBOL(rpc_mkpipe); EXPORT_SYMBOL(rpc_mkpipe);
EXPORT_SYMBOL(__rpc_purge_current_upcall); EXPORT_SYMBOL(__rpc_purge_current_upcall);
EXPORT_SYMBOL(__rpc_purge_one_upcall);
/* Client transport */ /* Client transport */
EXPORT_SYMBOL(xprt_create_proto); EXPORT_SYMBOL(xprt_create_proto);
......
...@@ -678,7 +678,8 @@ udp_data_ready(struct sock *sk, int len) ...@@ -678,7 +678,8 @@ udp_data_ready(struct sock *sk, int len)
struct rpc_xprt *xprt; struct rpc_xprt *xprt;
struct rpc_rqst *rovr; struct rpc_rqst *rovr;
struct sk_buff *skb; struct sk_buff *skb;
int err, repsize, copied; int err, repsize, copied;
u32 xid;
read_lock(&sk->sk_callback_lock); read_lock(&sk->sk_callback_lock);
dprintk("RPC: udp_data_ready...\n"); dprintk("RPC: udp_data_ready...\n");
...@@ -701,16 +702,18 @@ udp_data_ready(struct sock *sk, int len) ...@@ -701,16 +702,18 @@ udp_data_ready(struct sock *sk, int len)
goto dropit; goto dropit;
} }
/* Copy the XID from the skb... */
if (skb_copy_bits(skb, sizeof(struct udphdr), &xid, sizeof(xid)) < 0)
goto dropit;
/* Look up and lock the request corresponding to the given XID */ /* Look up and lock the request corresponding to the given XID */
spin_lock(&xprt->sock_lock); spin_lock(&xprt->sock_lock);
rovr = xprt_lookup_rqst(xprt, *(u32 *) (skb->h.raw + sizeof(struct udphdr))); rovr = xprt_lookup_rqst(xprt, xid);
if (!rovr) if (!rovr)
goto out_unlock; goto out_unlock;
task = rovr->rq_task; task = rovr->rq_task;
dprintk("RPC: %4d received reply\n", task->tk_pid); dprintk("RPC: %4d received reply\n", task->tk_pid);
xprt_pktdump("packet data:",
(u32 *) (skb->h.raw+sizeof(struct udphdr)), repsize);
if ((copied = rovr->rq_rlen) > repsize) if ((copied = rovr->rq_rlen) > repsize)
copied = repsize; copied = repsize;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment