NFS client bugfixes for 3.11
- Stable patch for lockd to fix Oopses due to inappropriate calls to utsname()->nodename - Stable patches for sunrpc to fix Oopses on shutdown when using AF_LOCAL sockets with rpcbind - Fix memory leak and error checking issues in nfs4_proc_lookup_mountpoint - Fix a regression with the sync mount option failing to work for nfs4 mounts - Fix a writeback performance issue when doing cache invalidation - Remove an incorrect call to nfs_setsecurity in nfs_fhget -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.13 (GNU/Linux) iQIcBAABAgAGBQJSBRqqAAoJEGcL54qWCgDyejoP/RNfkebEex2ugAAfymMOUNjA qc8X/YO8KDQD5T0X8P9MFXzgSSMPT5YfemxfKDpkjJlYwij8O9D8r1BAfgmhhKFI bVp9J8pH5Y3jXgLFVsubEc9N9CXLI0yRzcOFfzapYmGJV/ZO4cBAi8HMowFtbREj l2uk9H8XQ1p8KqVWXhFKoXVL2b9q0CGj5z3+RkE/rD5uuZyusbTB6OhNFArPnwXk aCx373mlvpIAhU6DkueCiXaHH06Mff2Vlu6eBkGrdfBGC6l+x1nwevxYH750fqSU 8O94rQkw9++qnIIvBJF/g1NzqyDhychJcXtgGLdxYUdWH3c8tevJZxCEj7U/dIJQ ndEaZGFxSFfdnxrwJBWtB+xsEfe9K4no9JwlkyVi8oZ5j2NUv7cJpA5cdQ4IUf/1 uqTlIxtPHQhHWCUUKpGLlhLiZyvwOPtJvuBl/Pc9UYQbyNtSqjYBk9mamrrIC6FK mF6jXgWe9x+miBqWYrEdPNLGdx/hUhhqGweYPJa6jTcxif+2l2xGfscWYI89Io/e qy8YNcHUrRci+o+YfY4lLhk88WBZogzFOYc4jDaLCEL1TE5B2k/jHr9v39V5S7Ks 63bhmfCTxB82uMzFeUWbiPzWQzt030pXPYy/PUPaucy/+QaZC/0lZ3HJKRKI37JJ ygSD7ndCZJCG+PxLkk49 =W12x -----END PGP SIGNATURE----- Merge tag 'nfs-for-3.11-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs Pull NFS client bugfixes from Trond Myklebust: - Stable patch for lockd to fix Oopses due to inappropriate calls to utsname()->nodename - Stable patches for sunrpc to fix Oopses on shutdown when using AF_LOCAL sockets with rpcbind - Fix memory leak and error checking issues in nfs4_proc_lookup_mountpoint - Fix a regression with the sync mount option failing to work for nfs4 mounts - Fix a writeback performance issue when doing cache invalidation - Remove an incorrect call to nfs_setsecurity in nfs_fhget * tag 'nfs-for-3.11-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4: Fix up nfs4_proc_lookup_mountpoint NFS: Remove unnecessary call to nfs_setsecurity in nfs_fhget() NFSv4: Fix the sync mount option for nfs4 mounts NFS: Fix writeback performance issue on cache invalidation SUNRPC: If the rpcbind channel is disconnected, fail the call to unregister SUNRPC: Don't auto-disconnect from the local rpcbind socket LOCKD: Don't call utsname()->nodename from nlmclnt_setlockargs
This commit is contained in:
commit
b8ea0d06ff
9 changed files with 68 additions and 27 deletions
|
@ -64,12 +64,17 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
|
|||
nlm_init->protocol, nlm_version,
|
||||
nlm_init->hostname, nlm_init->noresvport,
|
||||
nlm_init->net);
|
||||
if (host == NULL) {
|
||||
lockd_down(nlm_init->net);
|
||||
return ERR_PTR(-ENOLCK);
|
||||
}
|
||||
if (host == NULL)
|
||||
goto out_nohost;
|
||||
if (host->h_rpcclnt == NULL && nlm_bind_host(host) == NULL)
|
||||
goto out_nobind;
|
||||
|
||||
return host;
|
||||
out_nobind:
|
||||
nlmclnt_release_host(host);
|
||||
out_nohost:
|
||||
lockd_down(nlm_init->net);
|
||||
return ERR_PTR(-ENOLCK);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nlmclnt_init);
|
||||
|
||||
|
|
|
@ -125,14 +125,15 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
|
|||
{
|
||||
struct nlm_args *argp = &req->a_args;
|
||||
struct nlm_lock *lock = &argp->lock;
|
||||
char *nodename = req->a_host->h_rpcclnt->cl_nodename;
|
||||
|
||||
nlmclnt_next_cookie(&argp->cookie);
|
||||
memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh));
|
||||
lock->caller = utsname()->nodename;
|
||||
lock->caller = nodename;
|
||||
lock->oh.data = req->a_owner;
|
||||
lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
|
||||
(unsigned int)fl->fl_u.nfs_fl.owner->pid,
|
||||
utsname()->nodename);
|
||||
nodename);
|
||||
lock->svid = fl->fl_u.nfs_fl.owner->pid;
|
||||
lock->fl.fl_start = fl->fl_start;
|
||||
lock->fl.fl_end = fl->fl_end;
|
||||
|
|
|
@ -463,7 +463,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
|
|||
unlock_new_inode(inode);
|
||||
} else
|
||||
nfs_refresh_inode(inode, fattr);
|
||||
nfs_setsecurity(inode, fattr, label);
|
||||
dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n",
|
||||
inode->i_sb->s_id,
|
||||
(long long)NFS_FILEID(inode),
|
||||
|
@ -963,9 +962,15 @@ EXPORT_SYMBOL_GPL(nfs_revalidate_inode);
|
|||
static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping)
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
int ret;
|
||||
|
||||
if (mapping->nrpages != 0) {
|
||||
int ret = invalidate_inode_pages2(mapping);
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
ret = nfs_sync_mapping(mapping);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = invalidate_inode_pages2(mapping);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -3071,15 +3071,13 @@ struct rpc_clnt *
|
|||
nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name,
|
||||
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
|
||||
{
|
||||
struct rpc_clnt *client = NFS_CLIENT(dir);
|
||||
int status;
|
||||
struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir));
|
||||
|
||||
status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL);
|
||||
if (status < 0) {
|
||||
rpc_shutdown_client(client);
|
||||
if (status < 0)
|
||||
return ERR_PTR(status);
|
||||
}
|
||||
return client;
|
||||
return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;
|
||||
}
|
||||
|
||||
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
|
||||
|
|
|
@ -2478,6 +2478,10 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server,
|
|||
if (server->flags & NFS_MOUNT_NOAC)
|
||||
sb_mntdata.mntflags |= MS_SYNCHRONOUS;
|
||||
|
||||
if (mount_info->cloned != NULL && mount_info->cloned->sb != NULL)
|
||||
if (mount_info->cloned->sb->s_flags & MS_SYNCHRONOUS)
|
||||
sb_mntdata.mntflags |= MS_SYNCHRONOUS;
|
||||
|
||||
/* Get a superblock - note that we may end up sharing one that already exists */
|
||||
s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata);
|
||||
if (IS_ERR(s)) {
|
||||
|
|
|
@ -121,6 +121,7 @@ struct rpc_task_setup {
|
|||
#define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */
|
||||
#define RPC_TASK_SENT 0x0800 /* message was sent */
|
||||
#define RPC_TASK_TIMEOUT 0x1000 /* fail with ETIMEDOUT on timeout */
|
||||
#define RPC_TASK_NOCONNECT 0x2000 /* return ENOTCONN if not connected */
|
||||
|
||||
#define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC)
|
||||
#define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER)
|
||||
|
|
|
@ -1660,6 +1660,10 @@ call_connect(struct rpc_task *task)
|
|||
task->tk_action = call_connect_status;
|
||||
if (task->tk_status < 0)
|
||||
return;
|
||||
if (task->tk_flags & RPC_TASK_NOCONNECT) {
|
||||
rpc_exit(task, -ENOTCONN);
|
||||
return;
|
||||
}
|
||||
xprt_connect(task);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ struct sunrpc_net {
|
|||
struct rpc_clnt *rpcb_local_clnt4;
|
||||
spinlock_t rpcb_clnt_lock;
|
||||
unsigned int rpcb_users;
|
||||
unsigned int rpcb_is_af_local : 1;
|
||||
|
||||
struct mutex gssp_lock;
|
||||
wait_queue_head_t gssp_wq;
|
||||
|
|
|
@ -204,13 +204,15 @@ void rpcb_put_local(struct net *net)
|
|||
}
|
||||
|
||||
static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt,
|
||||
struct rpc_clnt *clnt4)
|
||||
struct rpc_clnt *clnt4,
|
||||
bool is_af_local)
|
||||
{
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
|
||||
/* Protected by rpcb_create_local_mutex */
|
||||
sn->rpcb_local_clnt = clnt;
|
||||
sn->rpcb_local_clnt4 = clnt4;
|
||||
sn->rpcb_is_af_local = is_af_local ? 1 : 0;
|
||||
smp_wmb();
|
||||
sn->rpcb_users = 1;
|
||||
dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: "
|
||||
|
@ -238,6 +240,14 @@ static int rpcb_create_local_unix(struct net *net)
|
|||
.program = &rpcb_program,
|
||||
.version = RPCBVERS_2,
|
||||
.authflavor = RPC_AUTH_NULL,
|
||||
/*
|
||||
* We turn off the idle timeout to prevent the kernel
|
||||
* from automatically disconnecting the socket.
|
||||
* Otherwise, we'd have to cache the mount namespace
|
||||
* of the caller and somehow pass that to the socket
|
||||
* reconnect code.
|
||||
*/
|
||||
.flags = RPC_CLNT_CREATE_NO_IDLE_TIMEOUT,
|
||||
};
|
||||
struct rpc_clnt *clnt, *clnt4;
|
||||
int result = 0;
|
||||
|
@ -263,7 +273,7 @@ static int rpcb_create_local_unix(struct net *net)
|
|||
clnt4 = NULL;
|
||||
}
|
||||
|
||||
rpcb_set_local(net, clnt, clnt4);
|
||||
rpcb_set_local(net, clnt, clnt4, true);
|
||||
|
||||
out:
|
||||
return result;
|
||||
|
@ -315,7 +325,7 @@ static int rpcb_create_local_net(struct net *net)
|
|||
clnt4 = NULL;
|
||||
}
|
||||
|
||||
rpcb_set_local(net, clnt, clnt4);
|
||||
rpcb_set_local(net, clnt, clnt4, false);
|
||||
|
||||
out:
|
||||
return result;
|
||||
|
@ -376,13 +386,16 @@ static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname,
|
|||
return rpc_create(&args);
|
||||
}
|
||||
|
||||
static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg)
|
||||
static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, struct rpc_message *msg, bool is_set)
|
||||
{
|
||||
int result, error = 0;
|
||||
int flags = RPC_TASK_NOCONNECT;
|
||||
int error, result = 0;
|
||||
|
||||
if (is_set || !sn->rpcb_is_af_local)
|
||||
flags = RPC_TASK_SOFTCONN;
|
||||
msg->rpc_resp = &result;
|
||||
|
||||
error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN);
|
||||
error = rpc_call_sync(clnt, msg, flags);
|
||||
if (error < 0) {
|
||||
dprintk("RPC: failed to contact local rpcbind "
|
||||
"server (errno %d).\n", -error);
|
||||
|
@ -439,16 +452,19 @@ int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short
|
|||
.rpc_argp = &map,
|
||||
};
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
bool is_set = false;
|
||||
|
||||
dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
|
||||
"rpcbind\n", (port ? "" : "un"),
|
||||
prog, vers, prot, port);
|
||||
|
||||
msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET];
|
||||
if (port)
|
||||
if (port != 0) {
|
||||
msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
|
||||
is_set = true;
|
||||
}
|
||||
|
||||
return rpcb_register_call(sn->rpcb_local_clnt, &msg);
|
||||
return rpcb_register_call(sn, sn->rpcb_local_clnt, &msg, is_set);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -461,6 +477,7 @@ static int rpcb_register_inet4(struct sunrpc_net *sn,
|
|||
const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
|
||||
struct rpcbind_args *map = msg->rpc_argp;
|
||||
unsigned short port = ntohs(sin->sin_port);
|
||||
bool is_set = false;
|
||||
int result;
|
||||
|
||||
map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
|
||||
|
@ -471,10 +488,12 @@ static int rpcb_register_inet4(struct sunrpc_net *sn,
|
|||
map->r_addr, map->r_netid);
|
||||
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
|
||||
if (port)
|
||||
if (port != 0) {
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
|
||||
is_set = true;
|
||||
}
|
||||
|
||||
result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
|
||||
result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
|
||||
kfree(map->r_addr);
|
||||
return result;
|
||||
}
|
||||
|
@ -489,6 +508,7 @@ static int rpcb_register_inet6(struct sunrpc_net *sn,
|
|||
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
|
||||
struct rpcbind_args *map = msg->rpc_argp;
|
||||
unsigned short port = ntohs(sin6->sin6_port);
|
||||
bool is_set = false;
|
||||
int result;
|
||||
|
||||
map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
|
||||
|
@ -499,10 +519,12 @@ static int rpcb_register_inet6(struct sunrpc_net *sn,
|
|||
map->r_addr, map->r_netid);
|
||||
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
|
||||
if (port)
|
||||
if (port != 0) {
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
|
||||
is_set = true;
|
||||
}
|
||||
|
||||
result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
|
||||
result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
|
||||
kfree(map->r_addr);
|
||||
return result;
|
||||
}
|
||||
|
@ -519,7 +541,7 @@ static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn,
|
|||
map->r_addr = "";
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
|
||||
|
||||
return rpcb_register_call(sn->rpcb_local_clnt4, msg);
|
||||
return rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue