Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Lockd: pass network namespace to creation and destruction routines

v2: dereference of most probably already released nlm_host removed in
nlmclnt_done() and reclaimer().

These routines are called from locks reclaimer() kernel thread. This thread
works in "init_net" network context and currently relays on persence on lockd
thread and it's per-net resources. Thus lockd_up() and lockd_down() can't relay
on current network context. So let's pass corrent one into them.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Stanislav Kinsbursky and committed by
J. Bruce Fields
e3f70ead f890edbb

+16 -14
+8 -5
fs/lockd/clntlock.c
··· 56 56 u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; 57 57 int status; 58 58 59 - status = lockd_up(); 59 + status = lockd_up(nlm_init->net); 60 60 if (status < 0) 61 61 return ERR_PTR(status); 62 62 ··· 65 65 nlm_init->hostname, nlm_init->noresvport, 66 66 nlm_init->net); 67 67 if (host == NULL) { 68 - lockd_down(); 68 + lockd_down(nlm_init->net); 69 69 return ERR_PTR(-ENOLCK); 70 70 } 71 71 ··· 80 80 */ 81 81 void nlmclnt_done(struct nlm_host *host) 82 82 { 83 + struct net *net = host->net; 84 + 83 85 nlmclnt_release_host(host); 84 - lockd_down(); 86 + lockd_down(net); 85 87 } 86 88 EXPORT_SYMBOL_GPL(nlmclnt_done); 87 89 ··· 222 220 struct nlm_wait *block; 223 221 struct file_lock *fl, *next; 224 222 u32 nsmstate; 223 + struct net *net = host->net; 225 224 226 225 allow_signal(SIGKILL); 227 226 228 227 down_write(&host->h_rwsem); 229 - lockd_up(); /* note: this cannot fail as lockd is already running */ 228 + lockd_up(net); /* note: this cannot fail as lockd is already running */ 230 229 231 230 dprintk("lockd: reclaiming locks for host %s\n", host->h_name); 232 231 ··· 278 275 279 276 /* Release host handle after use */ 280 277 nlmclnt_release_host(host); 281 - lockd_down(); 278 + lockd_down(net); 282 279 return 0; 283 280 }
+3 -4
fs/lockd/svc.c
··· 295 295 /* 296 296 * Bring up the lockd process if it's not already up. 297 297 */ 298 - int lockd_up(void) 298 + int lockd_up(struct net *net) 299 299 { 300 300 struct svc_serv *serv; 301 301 int error = 0; 302 - struct net *net = current->nsproxy->net_ns; 303 302 304 303 mutex_lock(&nlmsvc_mutex); 305 304 /* ··· 377 378 * Decrement the user count and bring down lockd if we're the last. 378 379 */ 379 380 void 380 - lockd_down(void) 381 + lockd_down(struct net *net) 381 382 { 382 383 mutex_lock(&nlmsvc_mutex); 383 384 if (nlmsvc_users) { 384 385 if (--nlmsvc_users) { 385 - lockd_down_net(current->nsproxy->net_ns); 386 + lockd_down_net(net); 386 387 goto out; 387 388 } 388 389 } else {
+3 -3
fs/nfsd/nfssvc.c
··· 220 220 ret = nfsd_init_socks(port); 221 221 if (ret) 222 222 goto out_racache; 223 - ret = lockd_up(); 223 + ret = lockd_up(&init_net); 224 224 if (ret) 225 225 goto out_racache; 226 226 ret = nfs4_state_start(); ··· 229 229 nfsd_up = true; 230 230 return 0; 231 231 out_lockd: 232 - lockd_down(); 232 + lockd_down(&init_net); 233 233 out_racache: 234 234 nfsd_racache_shutdown(); 235 235 return ret; ··· 246 246 if (!nfsd_up) 247 247 return; 248 248 nfs4_state_shutdown(); 249 - lockd_down(); 249 + lockd_down(&init_net); 250 250 nfsd_racache_shutdown(); 251 251 nfsd_up = false; 252 252 }
+2 -2
include/linux/lockd/bind.h
··· 54 54 55 55 extern int nlmclnt_proc(struct nlm_host *host, int cmd, 56 56 struct file_lock *fl); 57 - extern int lockd_up(void); 58 - extern void lockd_down(void); 57 + extern int lockd_up(struct net *net); 58 + extern void lockd_down(struct net *net); 59 59 60 60 #endif /* LINUX_LOCKD_BIND_H */