aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-08-05 12:06:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-15 01:59:08 -0400
commit870bfc6b47ecf64845dbf8e5d7a09877998e1b69 (patch)
tree8dbee6080950eaf16772d2fb1ac9b38f127b1178 /fs/lockd
parent31a9bd79d76026a8c8cff63c6887483e2e766ee4 (diff)
LOCKD: Don't call utsname()->nodename from nlmclnt_setlockargs
commit 9a1b6bf818e74bb7aabaecb59492b739f2f4d742 upstream. Firstly, nlmclnt_setlockargs can be called from a reclaimer thread, in which case we're in entirely the wrong namespace. Secondly, commit 8aac62706adaaf0fab02c4327761561c8bda9448 (move exit_task_namespaces() outside of exit_notify()) now means that exit_task_work() is called after exit_task_namespaces(), which triggers an Oops when we're freeing up the locks. Fix this by ensuring that we initialise the nlm_host's rpc_client at mount time, so that the cl_nodename field is initialised to the value of utsname()->nodename that the net namespace uses. Then replace the lockd callers of utsname()->nodename. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: Toralf Förster <toralf.foerster@gmx.de> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Nix <nix@esperi.org.uk> Cc: Jeff Layton <jlayton@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/clntlock.c13
-rw-r--r--fs/lockd/clntproc.c5
2 files changed, 12 insertions, 6 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 01bfe7662751..41e491b8e5d7 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -64,12 +64,17 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
64 nlm_init->protocol, nlm_version, 64 nlm_init->protocol, nlm_version,
65 nlm_init->hostname, nlm_init->noresvport, 65 nlm_init->hostname, nlm_init->noresvport,
66 nlm_init->net); 66 nlm_init->net);
67 if (host == NULL) { 67 if (host == NULL)
68 lockd_down(nlm_init->net); 68 goto out_nohost;
69 return ERR_PTR(-ENOLCK); 69 if (host->h_rpcclnt == NULL && nlm_bind_host(host) == NULL)
70 } 70 goto out_nobind;
71 71
72 return host; 72 return host;
73out_nobind:
74 nlmclnt_release_host(host);
75out_nohost:
76 lockd_down(nlm_init->net);
77 return ERR_PTR(-ENOLCK);
73} 78}
74EXPORT_SYMBOL_GPL(nlmclnt_init); 79EXPORT_SYMBOL_GPL(nlmclnt_init);
75 80
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 9760ecb9b60f..acd394716349 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -125,14 +125,15 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
125{ 125{
126 struct nlm_args *argp = &req->a_args; 126 struct nlm_args *argp = &req->a_args;
127 struct nlm_lock *lock = &argp->lock; 127 struct nlm_lock *lock = &argp->lock;
128 char *nodename = req->a_host->h_rpcclnt->cl_nodename;
128 129
129 nlmclnt_next_cookie(&argp->cookie); 130 nlmclnt_next_cookie(&argp->cookie);
130 memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh)); 131 memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh));
131 lock->caller = utsname()->nodename; 132 lock->caller = nodename;
132 lock->oh.data = req->a_owner; 133 lock->oh.data = req->a_owner;
133 lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s", 134 lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
134 (unsigned int)fl->fl_u.nfs_fl.owner->pid, 135 (unsigned int)fl->fl_u.nfs_fl.owner->pid,
135 utsname()->nodename); 136 nodename);
136 lock->svid = fl->fl_u.nfs_fl.owner->pid; 137 lock->svid = fl->fl_u.nfs_fl.owner->pid;
137 lock->fl.fl_start = fl->fl_start; 138 lock->fl.fl_start = fl->fl_start;
138 lock->fl.fl_end = fl->fl_end; 139 lock->fl.fl_end = fl->fl_end;