Merge branch 'nfs-for-2.6.37' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* 'nfs-for-2.6.37' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (67 commits)
  SUNRPC: Cleanup duplicate assignment in rpcauth_refreshcred
  nfs: fix unchecked value
  Ask for time_delta during fsinfo probe
  Revalidate caches on lock
  SUNRPC: After calling xprt_release(), we must restart from call_reserve
  NFSv4: Fix up the 'dircount' hint in encode_readdir
  NFSv4: Clean up nfs4_decode_dirent
  NFSv4: nfs4_decode_dirent must clear entry->fattr->valid
  NFSv4: Fix a regression in decode_getfattr
  NFSv4: Fix up decode_attr_filehandle() to handle the case of empty fh pointer
  NFS: Ensure we check all allocation return values in new readdir code
  NFS: Readdir plus in v4
  NFS: introduce generic decode_getattr function
  NFS: check xdr_decode for errors
  NFS: nfs_readdir_filler catch all errors
  NFS: readdir with vmapped pages
  NFS: remove page size checking code
  NFS: decode_dirent should use an xdr_stream
  SUNRPC: Add a helper function xdr_inline_peek
  NFS: remove readdir plus limit
  ...
This commit is contained in:
Linus Torvalds 2010-10-25 13:48:29 -07:00
commit 74eb94b218
41 changed files with 2235 additions and 1518 deletions

View file

@ -595,7 +595,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
int
rpcauth_refreshcred(struct rpc_task *task)
{
struct rpc_cred *cred = task->tk_rqstp->rq_cred;
struct rpc_cred *cred;
int err;
cred = task->tk_rqstp->rq_cred;

View file

@ -1675,7 +1675,7 @@ rpc_verify_header(struct rpc_task *task)
rpcauth_invalcred(task);
/* Ensure we obtain a new XID! */
xprt_release(task);
task->tk_action = call_refresh;
task->tk_action = call_reserve;
goto out_retry;
case RPC_AUTH_BADCRED:
case RPC_AUTH_BADVERF:

View file

@ -211,8 +211,9 @@ static int rpcb_create_local(void)
*/
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));
dprintk("RPC: failed to bind second program to "
"rpcbind v4 client (errno %ld).\n",
PTR_ERR(clnt4));
clnt4 = NULL;
}
@ -475,57 +476,6 @@ int rpcb_v4_register(const u32 program, const u32 version,
return -EAFNOSUPPORT;
}
/**
* rpcb_getport_sync - obtain the port for an RPC service on a given host
* @sin: address of remote peer
* @prog: RPC program number to bind
* @vers: RPC version number to bind
* @prot: transport protocol to use to make this request
*
* Return value is the requested advertised port number,
* or a negative errno value.
*
* Called from outside the RPC client in a synchronous task context.
* Uses default timeout parameters specified by underlying transport.
*
* XXX: Needs to support IPv6
*/
int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
{
struct rpcbind_args map = {
.r_prog = prog,
.r_vers = vers,
.r_prot = prot,
.r_port = 0,
};
struct rpc_message msg = {
.rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT],
.rpc_argp = &map,
.rpc_resp = &map,
};
struct rpc_clnt *rpcb_clnt;
int status;
dprintk("RPC: %s(%pI4, %u, %u, %d)\n",
__func__, &sin->sin_addr.s_addr, prog, vers, prot);
rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
sizeof(*sin), prot, RPCBVERS_2);
if (IS_ERR(rpcb_clnt))
return PTR_ERR(rpcb_clnt);
status = rpc_call_sync(rpcb_clnt, &msg, 0);
rpc_shutdown_client(rpcb_clnt);
if (status >= 0) {
if (map.r_port != 0)
return map.r_port;
status = -EACCES;
}
return status;
}
EXPORT_SYMBOL_GPL(rpcb_getport_sync);
static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
{
struct rpc_message msg = {

View file

@ -908,7 +908,7 @@ static int rpciod_start(void)
* Create the rpciod thread and wait for it to start.
*/
dprintk("RPC: creating workqueue rpciod\n");
wq = create_workqueue("rpciod");
wq = alloc_workqueue("rpciod", WQ_RESCUER, 0);
rpciod_workqueue = wq;
return rpciod_workqueue != NULL;
}

View file

@ -111,6 +111,23 @@ xdr_decode_string_inplace(__be32 *p, char **sp,
}
EXPORT_SYMBOL_GPL(xdr_decode_string_inplace);
/**
* xdr_terminate_string - '\0'-terminate a string residing in an xdr_buf
* @buf: XDR buffer where string resides
* @len: length of string, in bytes
*
*/
void
xdr_terminate_string(struct xdr_buf *buf, const u32 len)
{
char *kaddr;
kaddr = kmap_atomic(buf->pages[0], KM_USER0);
kaddr[buf->page_base + len] = '\0';
kunmap_atomic(kaddr, KM_USER0);
}
EXPORT_SYMBOL(xdr_terminate_string);
void
xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base,
unsigned int len)
@ -395,24 +412,29 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len)
{
struct kvec *tail;
size_t copy;
char *p;
unsigned int pglen = buf->page_len;
unsigned int tailbuf_len;
tail = buf->tail;
BUG_ON (len > pglen);
tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len;
/* Shift the tail first */
if (tail->iov_len != 0) {
p = (char *)tail->iov_base + len;
if (tail->iov_len > len) {
copy = tail->iov_len - len;
memmove(p, tail->iov_base, copy);
} else
buf->buflen -= len;
/* Copy from the inlined pages into the tail */
if (tailbuf_len != 0) {
unsigned int free_space = tailbuf_len - tail->iov_len;
if (len < free_space)
free_space = len;
tail->iov_len += free_space;
copy = len;
if (copy > tail->iov_len)
if (tail->iov_len > len) {
char *p = (char *)tail->iov_base + len;
memmove(p, tail->iov_base, tail->iov_len - len);
} else
copy = tail->iov_len;
/* Copy from the inlined pages into the tail */
_copy_from_pages((char *)tail->iov_base,
buf->pages, buf->page_base + pglen - len,
copy);
@ -550,6 +572,27 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
}
EXPORT_SYMBOL_GPL(xdr_init_decode);
/**
* xdr_inline_peek - Allow read-ahead in the XDR data stream
* @xdr: pointer to xdr_stream struct
* @nbytes: number of bytes of data to decode
*
* Check if the input buffer is long enough to enable us to decode
* 'nbytes' more bytes of data starting at the current position.
* If so return the current pointer without updating the current
* pointer position.
*/
__be32 * xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes)
{
__be32 *p = xdr->p;
__be32 *q = p + XDR_QUADLEN(nbytes);
if (unlikely(q > xdr->end || q < p))
return NULL;
return p;
}
EXPORT_SYMBOL_GPL(xdr_inline_peek);
/**
* xdr_inline_decode - Retrieve non-page XDR data to decode
* @xdr: pointer to xdr_stream struct