aboutsummaryrefslogtreecommitdiffstats
path: root/fs/kernfs/dir.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-01-10 08:57:24 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-10 16:48:08 -0500
commit99177a34110889a8f2c36420c34e3bcc9bfd8a70 (patch)
tree53aa8ccc23e3bd92192a8d0518aa4f5f84a634d9 /fs/kernfs/dir.c
parentf601f9a2bf7dc1f7ee18feece4c4e2fc6845d6c4 (diff)
kernfs: remove kernfs_addrm_cxt
kernfs_addrm_cxt and the accompanying kernfs_addrm_start/finish() were added because there were operations which should be performed outside kernfs_mutex after adding and removing kernfs_nodes. The necessary operations were recorded in kernfs_addrm_cxt and performed by kernfs_addrm_finish(); however, after the recent changes which relocated deactivation and unmapping so that they're performed directly during removal, the only operation kernfs_addrm_finish() performs is kernfs_put(), which can be moved inside the removal path too. This patch moves the kernfs_put() of the base ref to __kernfs_remove() and remove kernfs_addrm_cxt and kernfs_addrm_start/finish(). * kernfs_add_one() is updated to grab and release the parent's active ref and kernfs_mutex itself. kernfs_get/put_active() and kernfs_addrm_start/finish() invocations around it are removed from all users. * __kernfs_remove() puts an unlinked node directly instead of chaining it to kernfs_addrm_cxt. Its callers are updated to grab and release kernfs_mutex instead of calling kernfs_addrm_start/finish() around it. v2: Updated to fit the v2 restructuring of removal path. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/kernfs/dir.c')
-rw-r--r--fs/kernfs/dir.c114
1 files changed, 26 insertions, 88 deletions
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index f878e4f2efe7..770d687ee9f3 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -399,28 +399,7 @@ struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name,
399} 399}
400 400
401/** 401/**
402 * kernfs_addrm_start - prepare for kernfs_node add/remove
403 * @acxt: pointer to kernfs_addrm_cxt to be used
404 *
405 * This function is called when the caller is about to add or remove
406 * kernfs_node. This function acquires kernfs_mutex. @acxt is used
407 * to keep and pass context to other addrm functions.
408 *
409 * LOCKING:
410 * Kernel thread context (may sleep). kernfs_mutex is locked on
411 * return.
412 */
413void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt)
414 __acquires(kernfs_mutex)
415{
416 memset(acxt, 0, sizeof(*acxt));
417
418 mutex_lock(&kernfs_mutex);
419}
420
421/**
422 * kernfs_add_one - add kernfs_node to parent without warning 402 * kernfs_add_one - add kernfs_node to parent without warning
423 * @acxt: addrm context to use
424 * @kn: kernfs_node to be added 403 * @kn: kernfs_node to be added
425 * @parent: the parent kernfs_node to add @kn to 404 * @parent: the parent kernfs_node to add @kn to
426 * 405 *
@@ -428,34 +407,29 @@ void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt)
428 * parent inode if @kn is a directory and link into the children list 407 * parent inode if @kn is a directory and link into the children list
429 * of the parent. 408 * of the parent.
430 * 409 *
431 * This function should be called between calls to
432 * kernfs_addrm_start() and kernfs_addrm_finish() and should be passed
433 * the same @acxt as passed to kernfs_addrm_start().
434 *
435 * LOCKING:
436 * Determined by kernfs_addrm_start().
437 *
438 * RETURNS: 410 * RETURNS:
439 * 0 on success, -EEXIST if entry with the given name already 411 * 0 on success, -EEXIST if entry with the given name already
440 * exists. 412 * exists.
441 */ 413 */
442int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, 414int kernfs_add_one(struct kernfs_node *kn, struct kernfs_node *parent)
443 struct kernfs_node *parent)
444{ 415{
445 bool has_ns = kernfs_ns_enabled(parent);
446 struct kernfs_iattrs *ps_iattr; 416 struct kernfs_iattrs *ps_iattr;
417 bool has_ns;
447 int ret; 418 int ret;
448 419
449 WARN_ON_ONCE(atomic_read(&parent->active) < 0); 420 if (!kernfs_get_active(parent))
421 return -ENOENT;
450 422
451 if (has_ns != (bool)kn->ns) { 423 mutex_lock(&kernfs_mutex);
452 WARN(1, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", 424
453 has_ns ? "required" : "invalid", parent->name, kn->name); 425 ret = -EINVAL;
454 return -EINVAL; 426 has_ns = kernfs_ns_enabled(parent);
455 } 427 if (WARN(has_ns != (bool)kn->ns, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n",
428 has_ns ? "required" : "invalid", parent->name, kn->name))
429 goto out_unlock;
456 430
457 if (kernfs_type(parent) != KERNFS_DIR) 431 if (kernfs_type(parent) != KERNFS_DIR)
458 return -EINVAL; 432 goto out_unlock;
459 433
460 kn->hash = kernfs_name_hash(kn->name, kn->ns); 434 kn->hash = kernfs_name_hash(kn->name, kn->ns);
461 kn->parent = parent; 435 kn->parent = parent;
@@ -463,7 +437,7 @@ int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn,
463 437
464 ret = kernfs_link_sibling(kn); 438 ret = kernfs_link_sibling(kn);
465 if (ret) 439 if (ret)
466 return ret; 440 goto out_unlock;
467 441
468 /* Update timestamps on the parent */ 442 /* Update timestamps on the parent */
469 ps_iattr = parent->iattr; 443 ps_iattr = parent->iattr;
@@ -474,34 +448,11 @@ int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn,
474 448
475 /* Mark the entry added into directory tree */ 449 /* Mark the entry added into directory tree */
476 atomic_sub(KN_DEACTIVATED_BIAS, &kn->active); 450 atomic_sub(KN_DEACTIVATED_BIAS, &kn->active);
477 return 0; 451 ret = 0;
478} 452out_unlock:
479
480/**
481 * kernfs_addrm_finish - finish up kernfs_node add/remove
482 * @acxt: addrm context to finish up
483 *
484 * Finish up kernfs_node add/remove. Resources acquired by
485 * kernfs_addrm_start() are released and removed kernfs_nodes are
486 * cleaned up.
487 *
488 * LOCKING:
489 * kernfs_mutex is released.
490 */
491void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt)
492 __releases(kernfs_mutex)
493{
494 /* release resources acquired by kernfs_addrm_start() */
495 mutex_unlock(&kernfs_mutex); 453 mutex_unlock(&kernfs_mutex);
496 454 kernfs_put_active(parent);
497 /* kill removed kernfs_nodes */ 455 return ret;
498 while (acxt->removed) {
499 struct kernfs_node *kn = acxt->removed;
500
501 acxt->removed = kn->u.removed_list;
502
503 kernfs_put(kn);
504 }
505} 456}
506 457
507/** 458/**
@@ -633,7 +584,6 @@ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
633 const char *name, umode_t mode, 584 const char *name, umode_t mode,
634 void *priv, const void *ns) 585 void *priv, const void *ns)
635{ 586{
636 struct kernfs_addrm_cxt acxt;
637 struct kernfs_node *kn; 587 struct kernfs_node *kn;
638 int rc; 588 int rc;
639 589
@@ -648,14 +598,7 @@ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
648 kn->priv = priv; 598 kn->priv = priv;
649 599
650 /* link in */ 600 /* link in */
651 rc = -ENOENT; 601 rc = kernfs_add_one(kn, parent);
652 if (kernfs_get_active(parent)) {
653 kernfs_addrm_start(&acxt);
654 rc = kernfs_add_one(&acxt, kn, parent);
655 kernfs_addrm_finish(&acxt);
656 kernfs_put_active(parent);
657 }
658
659 if (!rc) 602 if (!rc)
660 return kn; 603 return kn;
661 604
@@ -841,8 +784,7 @@ static void __kernfs_deactivate(struct kernfs_node *kn)
841 } 784 }
842} 785}
843 786
844static void __kernfs_remove(struct kernfs_addrm_cxt *acxt, 787static void __kernfs_remove(struct kernfs_node *kn)
845 struct kernfs_node *kn)
846{ 788{
847 struct kernfs_node *pos; 789 struct kernfs_node *pos;
848 790
@@ -890,8 +832,7 @@ static void __kernfs_remove(struct kernfs_addrm_cxt *acxt,
890 ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; 832 ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME;
891 } 833 }
892 834
893 pos->u.removed_list = acxt->removed; 835 kernfs_put(pos);
894 acxt->removed = pos;
895 } 836 }
896 837
897 kernfs_put(pos); 838 kernfs_put(pos);
@@ -906,11 +847,9 @@ static void __kernfs_remove(struct kernfs_addrm_cxt *acxt,
906 */ 847 */
907void kernfs_remove(struct kernfs_node *kn) 848void kernfs_remove(struct kernfs_node *kn)
908{ 849{
909 struct kernfs_addrm_cxt acxt; 850 mutex_lock(&kernfs_mutex);
910 851 __kernfs_remove(kn);
911 kernfs_addrm_start(&acxt); 852 mutex_unlock(&kernfs_mutex);
912 __kernfs_remove(&acxt, kn);
913 kernfs_addrm_finish(&acxt);
914} 853}
915 854
916/** 855/**
@@ -925,7 +864,6 @@ void kernfs_remove(struct kernfs_node *kn)
925int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, 864int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
926 const void *ns) 865 const void *ns)
927{ 866{
928 struct kernfs_addrm_cxt acxt;
929 struct kernfs_node *kn; 867 struct kernfs_node *kn;
930 868
931 if (!parent) { 869 if (!parent) {
@@ -934,13 +872,13 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
934 return -ENOENT; 872 return -ENOENT;
935 } 873 }
936 874
937 kernfs_addrm_start(&acxt); 875 mutex_lock(&kernfs_mutex);
938 876
939 kn = kernfs_find_ns(parent, name, ns); 877 kn = kernfs_find_ns(parent, name, ns);
940 if (kn) 878 if (kn)
941 __kernfs_remove(&acxt, kn); 879 __kernfs_remove(kn);
942 880
943 kernfs_addrm_finish(&acxt); 881 mutex_unlock(&kernfs_mutex);
944 882
945 if (kn) 883 if (kn)
946 return 0; 884 return 0;