aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-11-26 08:16:25 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-11-28 10:13:53 -0500
commit3a0733692f6665a28c50ebadb6d9db2b183bcb91 (patch)
tree07173065b1a1cff301c2f77b1f970b7ad2ccd8bd /fs
parentf252bc6806a9428f2e3a429e4cdffbd012de9839 (diff)
nfsd: recovery - make rec_file per net
Opening and closing of this file is done in client tracking init and exit operations. Client tracking is done in network namespace context already. So let's make this file opened and closed per network context - this will simlify it's management. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/netns.h2
-rw-r--r--fs/nfsd/nfs4recover.c70
2 files changed, 37 insertions, 35 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 08d5fa1ce82a..130563210c68 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -84,6 +84,8 @@ struct nfsd_net {
84 84
85 /* client_lock protects the client lru list and session hash table */ 85 /* client_lock protects the client lru list and session hash table */
86 spinlock_t client_lock; 86 spinlock_t client_lock;
87
88 struct file *rec_file;
87}; 89};
88 90
89extern int nfsd_net_id; 91extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 651d5134e74c..3e76d281bba8 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -62,7 +62,6 @@ struct nfsd4_client_tracking_ops {
62}; 62};
63 63
64/* Globals */ 64/* Globals */
65static struct file *rec_file;
66static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 65static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
67static struct nfsd4_client_tracking_ops *client_tracking_ops; 66static struct nfsd4_client_tracking_ops *client_tracking_ops;
68static bool in_grace; 67static bool in_grace;
@@ -182,7 +181,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
182 181
183 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 182 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
184 return; 183 return;
185 if (!rec_file) 184 if (!nn->rec_file)
186 return; 185 return;
187 186
188 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 187 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
@@ -193,11 +192,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
193 if (status < 0) 192 if (status < 0)
194 return; 193 return;
195 194
196 status = mnt_want_write_file(rec_file); 195 status = mnt_want_write_file(nn->rec_file);
197 if (status) 196 if (status)
198 return; 197 return;
199 198
200 dir = rec_file->f_path.dentry; 199 dir = nn->rec_file->f_path.dentry;
201 /* lock the parent */ 200 /* lock the parent */
202 mutex_lock(&dir->d_inode->i_mutex); 201 mutex_lock(&dir->d_inode->i_mutex);
203 202
@@ -227,14 +226,14 @@ out_unlock:
227 if (crp) 226 if (crp)
228 crp->cr_clp = clp; 227 crp->cr_clp = clp;
229 } 228 }
230 vfs_fsync(rec_file, 0); 229 vfs_fsync(nn->rec_file, 0);
231 } else { 230 } else {
232 printk(KERN_ERR "NFSD: failed to write recovery record" 231 printk(KERN_ERR "NFSD: failed to write recovery record"
233 " (err %d); please check that %s exists" 232 " (err %d); please check that %s exists"
234 " and is writeable", status, 233 " and is writeable", status,
235 user_recovery_dirname); 234 user_recovery_dirname);
236 } 235 }
237 mnt_drop_write_file(rec_file); 236 mnt_drop_write_file(nn->rec_file);
238 nfs4_reset_creds(original_cred); 237 nfs4_reset_creds(original_cred);
239} 238}
240 239
@@ -267,7 +266,7 @@ static int
267nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) 266nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
268{ 267{
269 const struct cred *original_cred; 268 const struct cred *original_cred;
270 struct dentry *dir = rec_file->f_path.dentry; 269 struct dentry *dir = nn->rec_file->f_path.dentry;
271 LIST_HEAD(names); 270 LIST_HEAD(names);
272 int status; 271 int status;
273 272
@@ -275,13 +274,13 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
275 if (status < 0) 274 if (status < 0)
276 return status; 275 return status;
277 276
278 status = vfs_llseek(rec_file, 0, SEEK_SET); 277 status = vfs_llseek(nn->rec_file, 0, SEEK_SET);
279 if (status < 0) { 278 if (status < 0) {
280 nfs4_reset_creds(original_cred); 279 nfs4_reset_creds(original_cred);
281 return status; 280 return status;
282 } 281 }
283 282
284 status = vfs_readdir(rec_file, nfsd4_build_namelist, &names); 283 status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names);
285 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 284 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
286 while (!list_empty(&names)) { 285 while (!list_empty(&names)) {
287 struct name_list *entry; 286 struct name_list *entry;
@@ -305,14 +304,14 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
305} 304}
306 305
307static int 306static int
308nfsd4_unlink_clid_dir(char *name, int namlen) 307nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
309{ 308{
310 struct dentry *dir, *dentry; 309 struct dentry *dir, *dentry;
311 int status; 310 int status;
312 311
313 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 312 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
314 313
315 dir = rec_file->f_path.dentry; 314 dir = nn->rec_file->f_path.dentry;
316 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 315 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
317 dentry = lookup_one_len(name, dir, namlen); 316 dentry = lookup_one_len(name, dir, namlen);
318 if (IS_ERR(dentry)) { 317 if (IS_ERR(dentry)) {
@@ -339,14 +338,14 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
339 int status; 338 int status;
340 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 339 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
341 340
342 if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 341 if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
343 return; 342 return;
344 343
345 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 344 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
346 if (status) 345 if (status)
347 return legacy_recdir_name_error(status); 346 return legacy_recdir_name_error(status);
348 347
349 status = mnt_want_write_file(rec_file); 348 status = mnt_want_write_file(nn->rec_file);
350 if (status) 349 if (status)
351 goto out; 350 goto out;
352 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 351 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -355,10 +354,10 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
355 if (status < 0) 354 if (status < 0)
356 goto out_drop_write; 355 goto out_drop_write;
357 356
358 status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1); 357 status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn);
359 nfs4_reset_creds(original_cred); 358 nfs4_reset_creds(original_cred);
360 if (status == 0) { 359 if (status == 0) {
361 vfs_fsync(rec_file, 0); 360 vfs_fsync(nn->rec_file, 0);
362 if (in_grace) { 361 if (in_grace) {
363 /* remove reclaim record */ 362 /* remove reclaim record */
364 crp = nfsd4_find_reclaim_client(dname, nn); 363 crp = nfsd4_find_reclaim_client(dname, nn);
@@ -367,7 +366,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
367 } 366 }
368 } 367 }
369out_drop_write: 368out_drop_write:
370 mnt_drop_write_file(rec_file); 369 mnt_drop_write_file(nn->rec_file);
371out: 370out:
372 if (status) 371 if (status)
373 printk("NFSD: Failed to remove expired client state directory" 372 printk("NFSD: Failed to remove expired client state directory"
@@ -396,20 +395,20 @@ nfsd4_recdir_purge_old(struct nfsd_net *nn, time_t boot_time)
396 int status; 395 int status;
397 396
398 in_grace = false; 397 in_grace = false;
399 if (!rec_file) 398 if (!nn->rec_file)
400 return; 399 return;
401 status = mnt_want_write_file(rec_file); 400 status = mnt_want_write_file(nn->rec_file);
402 if (status) 401 if (status)
403 goto out; 402 goto out;
404 status = nfsd4_list_rec_dir(purge_old, nn); 403 status = nfsd4_list_rec_dir(purge_old, nn);
405 if (status == 0) 404 if (status == 0)
406 vfs_fsync(rec_file, 0); 405 vfs_fsync(nn->rec_file, 0);
407 mnt_drop_write_file(rec_file); 406 mnt_drop_write_file(nn->rec_file);
408out: 407out:
409 nfs4_release_reclaim(nn); 408 nfs4_release_reclaim(nn);
410 if (status) 409 if (status)
411 printk("nfsd4: failed to purge old clients from recovery" 410 printk("nfsd4: failed to purge old clients from recovery"
412 " directory %s\n", rec_file->f_path.dentry->d_name.name); 411 " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
413} 412}
414 413
415static int 414static int
@@ -430,13 +429,13 @@ nfsd4_recdir_load(struct net *net) {
430 int status; 429 int status;
431 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 430 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
432 431
433 if (!rec_file) 432 if (!nn->rec_file)
434 return 0; 433 return 0;
435 434
436 status = nfsd4_list_rec_dir(load_recdir, nn); 435 status = nfsd4_list_rec_dir(load_recdir, nn);
437 if (status) 436 if (status)
438 printk("nfsd4: failed loading clients from recovery" 437 printk("nfsd4: failed loading clients from recovery"
439 " directory %s\n", rec_file->f_path.dentry->d_name.name); 438 " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
440 return status; 439 return status;
441} 440}
442 441
@@ -445,15 +444,16 @@ nfsd4_recdir_load(struct net *net) {
445 */ 444 */
446 445
447static int 446static int
448nfsd4_init_recdir(void) 447nfsd4_init_recdir(struct net *net)
449{ 448{
449 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
450 const struct cred *original_cred; 450 const struct cred *original_cred;
451 int status; 451 int status;
452 452
453 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 453 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
454 user_recovery_dirname); 454 user_recovery_dirname);
455 455
456 BUG_ON(rec_file); 456 BUG_ON(nn->rec_file);
457 457
458 status = nfs4_save_creds(&original_cred); 458 status = nfs4_save_creds(&original_cred);
459 if (status < 0) { 459 if (status < 0) {
@@ -463,12 +463,12 @@ nfsd4_init_recdir(void)
463 return status; 463 return status;
464 } 464 }
465 465
466 rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 466 nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
467 if (IS_ERR(rec_file)) { 467 if (IS_ERR(nn->rec_file)) {
468 printk("NFSD: unable to find recovery directory %s\n", 468 printk("NFSD: unable to find recovery directory %s\n",
469 user_recovery_dirname); 469 user_recovery_dirname);
470 status = PTR_ERR(rec_file); 470 status = PTR_ERR(nn->rec_file);
471 rec_file = NULL; 471 nn->rec_file = NULL;
472 } 472 }
473 473
474 nfs4_reset_creds(original_cred); 474 nfs4_reset_creds(original_cred);
@@ -509,7 +509,7 @@ nfsd4_load_reboot_recovery_data(struct net *net)
509{ 509{
510 int status; 510 int status;
511 511
512 status = nfsd4_init_recdir(); 512 status = nfsd4_init_recdir(net);
513 if (!status) 513 if (!status)
514 status = nfsd4_recdir_load(net); 514 status = nfsd4_recdir_load(net);
515 if (status) 515 if (status)
@@ -544,12 +544,12 @@ err:
544} 544}
545 545
546static void 546static void
547nfsd4_shutdown_recdir(void) 547nfsd4_shutdown_recdir(struct nfsd_net *nn)
548{ 548{
549 if (!rec_file) 549 if (!nn->rec_file)
550 return; 550 return;
551 fput(rec_file); 551 fput(nn->rec_file);
552 rec_file = NULL; 552 nn->rec_file = NULL;
553} 553}
554 554
555static void 555static void
@@ -558,7 +558,7 @@ nfsd4_legacy_tracking_exit(struct net *net)
558 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 558 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
559 559
560 nfs4_release_reclaim(nn); 560 nfs4_release_reclaim(nn);
561 nfsd4_shutdown_recdir(); 561 nfsd4_shutdown_recdir(nn);
562 nfs4_legacy_state_shutdown(net); 562 nfs4_legacy_state_shutdown(net);
563} 563}
564 564