mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 00:52:01 +00:00
Merge branch 'hotfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'hotfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: SUNRPC: Fix an rpcbind breakage for the case of IPv6 lookups SUNRPC: Fix a double-free in rpcbind NFS: Fix readdir cache invalidation
This commit is contained in:
commit
f57e91682d
@ -204,7 +204,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
|
|||||||
* Note: assumes we have exclusive access to this mapping either
|
* Note: assumes we have exclusive access to this mapping either
|
||||||
* through inode->i_mutex or some other mechanism.
|
* through inode->i_mutex or some other mechanism.
|
||||||
*/
|
*/
|
||||||
if (page->index == 0 && invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1) < 0) {
|
if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
|
||||||
/* Should never happen */
|
/* Should never happen */
|
||||||
nfs_zap_mapping(inode, inode->i_mapping);
|
nfs_zap_mapping(inode, inode->i_mapping);
|
||||||
}
|
}
|
||||||
|
@ -243,10 +243,10 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rpcb_getport_sync);
|
EXPORT_SYMBOL_GPL(rpcb_getport_sync);
|
||||||
|
|
||||||
static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, int version)
|
static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
|
||||||
{
|
{
|
||||||
struct rpc_message msg = {
|
struct rpc_message msg = {
|
||||||
.rpc_proc = rpcb_next_version[version].rpc_proc,
|
.rpc_proc = proc,
|
||||||
.rpc_argp = map,
|
.rpc_argp = map,
|
||||||
.rpc_resp = &map->r_port,
|
.rpc_resp = &map->r_port,
|
||||||
};
|
};
|
||||||
@ -271,6 +271,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
|
|||||||
void rpcb_getport_async(struct rpc_task *task)
|
void rpcb_getport_async(struct rpc_task *task)
|
||||||
{
|
{
|
||||||
struct rpc_clnt *clnt = task->tk_client;
|
struct rpc_clnt *clnt = task->tk_client;
|
||||||
|
struct rpc_procinfo *proc;
|
||||||
u32 bind_version;
|
u32 bind_version;
|
||||||
struct rpc_xprt *xprt = task->tk_xprt;
|
struct rpc_xprt *xprt = task->tk_xprt;
|
||||||
struct rpc_clnt *rpcb_clnt;
|
struct rpc_clnt *rpcb_clnt;
|
||||||
@ -280,7 +281,6 @@ void rpcb_getport_async(struct rpc_task *task)
|
|||||||
struct sockaddr *sap = (struct sockaddr *)&addr;
|
struct sockaddr *sap = (struct sockaddr *)&addr;
|
||||||
size_t salen;
|
size_t salen;
|
||||||
int status;
|
int status;
|
||||||
struct rpcb_info *info;
|
|
||||||
|
|
||||||
dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
|
dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
|
||||||
task->tk_pid, __func__,
|
task->tk_pid, __func__,
|
||||||
@ -313,10 +313,12 @@ void rpcb_getport_async(struct rpc_task *task)
|
|||||||
/* Don't ever use rpcbind v2 for AF_INET6 requests */
|
/* Don't ever use rpcbind v2 for AF_INET6 requests */
|
||||||
switch (sap->sa_family) {
|
switch (sap->sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
info = rpcb_next_version;
|
proc = rpcb_next_version[xprt->bind_index].rpc_proc;
|
||||||
|
bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
info = rpcb_next_version6;
|
proc = rpcb_next_version6[xprt->bind_index].rpc_proc;
|
||||||
|
bind_version = rpcb_next_version6[xprt->bind_index].rpc_vers;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
status = -EAFNOSUPPORT;
|
status = -EAFNOSUPPORT;
|
||||||
@ -324,14 +326,13 @@ void rpcb_getport_async(struct rpc_task *task)
|
|||||||
task->tk_pid, __func__);
|
task->tk_pid, __func__);
|
||||||
goto bailout_nofree;
|
goto bailout_nofree;
|
||||||
}
|
}
|
||||||
if (info[xprt->bind_index].rpc_proc == NULL) {
|
if (proc == NULL) {
|
||||||
xprt->bind_index = 0;
|
xprt->bind_index = 0;
|
||||||
status = -EPFNOSUPPORT;
|
status = -EPFNOSUPPORT;
|
||||||
dprintk("RPC: %5u %s: no more getport versions available\n",
|
dprintk("RPC: %5u %s: no more getport versions available\n",
|
||||||
task->tk_pid, __func__);
|
task->tk_pid, __func__);
|
||||||
goto bailout_nofree;
|
goto bailout_nofree;
|
||||||
}
|
}
|
||||||
bind_version = info[xprt->bind_index].rpc_vers;
|
|
||||||
|
|
||||||
dprintk("RPC: %5u %s: trying rpcbind version %u\n",
|
dprintk("RPC: %5u %s: trying rpcbind version %u\n",
|
||||||
task->tk_pid, __func__, bind_version);
|
task->tk_pid, __func__, bind_version);
|
||||||
@ -361,22 +362,20 @@ void rpcb_getport_async(struct rpc_task *task)
|
|||||||
map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR);
|
map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR);
|
||||||
map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */
|
map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */
|
||||||
|
|
||||||
child = rpcb_call_async(rpcb_clnt, map, xprt->bind_index);
|
child = rpcb_call_async(rpcb_clnt, map, proc);
|
||||||
rpc_release_client(rpcb_clnt);
|
rpc_release_client(rpcb_clnt);
|
||||||
if (IS_ERR(child)) {
|
if (IS_ERR(child)) {
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
|
/* rpcb_map_release() has freed the arguments */
|
||||||
dprintk("RPC: %5u %s: rpc_run_task failed\n",
|
dprintk("RPC: %5u %s: rpc_run_task failed\n",
|
||||||
task->tk_pid, __func__);
|
task->tk_pid, __func__);
|
||||||
goto bailout;
|
goto bailout_nofree;
|
||||||
}
|
}
|
||||||
rpc_put_task(child);
|
rpc_put_task(child);
|
||||||
|
|
||||||
task->tk_xprt->stat.bind_count++;
|
task->tk_xprt->stat.bind_count++;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bailout:
|
|
||||||
kfree(map);
|
|
||||||
xprt_put(xprt);
|
|
||||||
bailout_nofree:
|
bailout_nofree:
|
||||||
rpcb_wake_rpcbind_waiters(xprt, status);
|
rpcb_wake_rpcbind_waiters(xprt, status);
|
||||||
bailout_nowake:
|
bailout_nowake:
|
||||||
|
Loading…
Reference in New Issue
Block a user