diff options
author | Tejun Heo <tj@kernel.org> | 2014-02-03 14:02:58 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-07 18:42:40 -0500 |
commit | 988cd7afb3f37598891ca70b4c6eb914c338c46a (patch) | |
tree | cea29f9fe0d8057441f3350235ec1666ff231d7a /fs/kernfs | |
parent | ccf02aaf8167bb8bfb3c17c01c843d309b872671 (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 kernfs_mutex itself.
sysfs_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: Rebased on top of "kernfs: associate a new kernfs_node with its
parent on creation" which dropped @parent from kernfs_add_one().
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/kernfs')
-rw-r--r-- | fs/kernfs/dir.c | 109 | ||||
-rw-r--r-- | fs/kernfs/file.c | 6 | ||||
-rw-r--r-- | fs/kernfs/kernfs-internal.h | 11 | ||||
-rw-r--r-- | fs/kernfs/symlink.c | 6 |
4 files changed, 28 insertions, 104 deletions
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 9603c06550a0..948551d222b4 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c | |||
@@ -396,69 +396,44 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, | |||
396 | } | 396 | } |
397 | 397 | ||
398 | /** | 398 | /** |
399 | * kernfs_addrm_start - prepare for kernfs_node add/remove | ||
400 | * @acxt: pointer to kernfs_addrm_cxt to be used | ||
401 | * | ||
402 | * This function is called when the caller is about to add or remove | ||
403 | * kernfs_node. This function acquires kernfs_mutex. @acxt is used | ||
404 | * to keep and pass context to other addrm functions. | ||
405 | * | ||
406 | * LOCKING: | ||
407 | * Kernel thread context (may sleep). kernfs_mutex is locked on | ||
408 | * return. | ||
409 | */ | ||
410 | void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt) | ||
411 | __acquires(kernfs_mutex) | ||
412 | { | ||
413 | memset(acxt, 0, sizeof(*acxt)); | ||
414 | |||
415 | mutex_lock(&kernfs_mutex); | ||
416 | } | ||
417 | |||
418 | /** | ||
419 | * kernfs_add_one - add kernfs_node to parent without warning | 399 | * kernfs_add_one - add kernfs_node to parent without warning |
420 | * @acxt: addrm context to use | ||
421 | * @kn: kernfs_node to be added | 400 | * @kn: kernfs_node to be added |
422 | * | 401 | * |
423 | * The caller must already have initialized @kn->parent. This | 402 | * The caller must already have initialized @kn->parent. This |
424 | * function increments nlink of the parent's inode if @kn is a | 403 | * function increments nlink of the parent's inode if @kn is a |
425 | * directory and link into the children list of the parent. | 404 | * directory and link into the children list of the parent. |
426 | * | 405 | * |
427 | * This function should be called between calls to | ||
428 | * kernfs_addrm_start() and kernfs_addrm_finish() and should be passed | ||
429 | * the same @acxt as passed to kernfs_addrm_start(). | ||
430 | * | ||
431 | * LOCKING: | ||
432 | * Determined by kernfs_addrm_start(). | ||
433 | * | ||
434 | * RETURNS: | 406 | * RETURNS: |
435 | * 0 on success, -EEXIST if entry with the given name already | 407 | * 0 on success, -EEXIST if entry with the given name already |
436 | * exists. | 408 | * exists. |
437 | */ | 409 | */ |
438 | int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn) | 410 | int kernfs_add_one(struct kernfs_node *kn) |
439 | { | 411 | { |
440 | struct kernfs_node *parent = kn->parent; | 412 | struct kernfs_node *parent = kn->parent; |
441 | bool has_ns = kernfs_ns_enabled(parent); | ||
442 | struct kernfs_iattrs *ps_iattr; | 413 | struct kernfs_iattrs *ps_iattr; |
414 | bool has_ns; | ||
443 | int ret; | 415 | int ret; |
444 | 416 | ||
445 | if (has_ns != (bool)kn->ns) { | 417 | mutex_lock(&kernfs_mutex); |
446 | WARN(1, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", | 418 | |
447 | has_ns ? "required" : "invalid", parent->name, kn->name); | 419 | ret = -EINVAL; |
448 | return -EINVAL; | 420 | has_ns = kernfs_ns_enabled(parent); |
449 | } | 421 | if (WARN(has_ns != (bool)kn->ns, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", |
422 | has_ns ? "required" : "invalid", parent->name, kn->name)) | ||
423 | goto out_unlock; | ||
450 | 424 | ||
451 | if (kernfs_type(parent) != KERNFS_DIR) | 425 | if (kernfs_type(parent) != KERNFS_DIR) |
452 | return -EINVAL; | 426 | goto out_unlock; |
453 | 427 | ||
428 | ret = -ENOENT; | ||
454 | if (parent->flags & KERNFS_REMOVED) | 429 | if (parent->flags & KERNFS_REMOVED) |
455 | return -ENOENT; | 430 | goto out_unlock; |
456 | 431 | ||
457 | kn->hash = kernfs_name_hash(kn->name, kn->ns); | 432 | kn->hash = kernfs_name_hash(kn->name, kn->ns); |
458 | 433 | ||
459 | ret = kernfs_link_sibling(kn); | 434 | ret = kernfs_link_sibling(kn); |
460 | if (ret) | 435 | if (ret) |
461 | return ret; | 436 | goto out_unlock; |
462 | 437 | ||
463 | /* Update timestamps on the parent */ | 438 | /* Update timestamps on the parent */ |
464 | ps_iattr = parent->iattr; | 439 | ps_iattr = parent->iattr; |
@@ -469,35 +444,10 @@ int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn) | |||
469 | 444 | ||
470 | /* Mark the entry added into directory tree */ | 445 | /* Mark the entry added into directory tree */ |
471 | kn->flags &= ~KERNFS_REMOVED; | 446 | kn->flags &= ~KERNFS_REMOVED; |
472 | 447 | ret = 0; | |
473 | return 0; | 448 | out_unlock: |
474 | } | ||
475 | |||
476 | /** | ||
477 | * kernfs_addrm_finish - finish up kernfs_node add/remove | ||
478 | * @acxt: addrm context to finish up | ||
479 | * | ||
480 | * Finish up kernfs_node add/remove. Resources acquired by | ||
481 | * kernfs_addrm_start() are released and removed kernfs_nodes are | ||
482 | * cleaned up. | ||
483 | * | ||
484 | * LOCKING: | ||
485 | * kernfs_mutex is released. | ||
486 | */ | ||
487 | void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt) | ||
488 | __releases(kernfs_mutex) | ||
489 | { | ||
490 | /* release resources acquired by kernfs_addrm_start() */ | ||
491 | mutex_unlock(&kernfs_mutex); | 449 | mutex_unlock(&kernfs_mutex); |
492 | 450 | return ret; | |
493 | /* kill removed kernfs_nodes */ | ||
494 | while (acxt->removed) { | ||
495 | struct kernfs_node *kn = acxt->removed; | ||
496 | |||
497 | acxt->removed = kn->u.removed_list; | ||
498 | |||
499 | kernfs_put(kn); | ||
500 | } | ||
501 | } | 451 | } |
502 | 452 | ||
503 | /** | 453 | /** |
@@ -630,7 +580,6 @@ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, | |||
630 | const char *name, umode_t mode, | 580 | const char *name, umode_t mode, |
631 | void *priv, const void *ns) | 581 | void *priv, const void *ns) |
632 | { | 582 | { |
633 | struct kernfs_addrm_cxt acxt; | ||
634 | struct kernfs_node *kn; | 583 | struct kernfs_node *kn; |
635 | int rc; | 584 | int rc; |
636 | 585 | ||
@@ -644,10 +593,7 @@ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, | |||
644 | kn->priv = priv; | 593 | kn->priv = priv; |
645 | 594 | ||
646 | /* link in */ | 595 | /* link in */ |
647 | kernfs_addrm_start(&acxt); | 596 | rc = kernfs_add_one(kn); |
648 | rc = kernfs_add_one(&acxt, kn); | ||
649 | kernfs_addrm_finish(&acxt); | ||
650 | |||
651 | if (!rc) | 597 | if (!rc) |
652 | return kn; | 598 | return kn; |
653 | 599 | ||
@@ -800,8 +746,7 @@ static struct kernfs_node *kernfs_next_descendant_post(struct kernfs_node *pos, | |||
800 | return pos->parent; | 746 | return pos->parent; |
801 | } | 747 | } |
802 | 748 | ||
803 | static void __kernfs_remove(struct kernfs_addrm_cxt *acxt, | 749 | static void __kernfs_remove(struct kernfs_node *kn) |
804 | struct kernfs_node *kn) | ||
805 | { | 750 | { |
806 | struct kernfs_node *pos; | 751 | struct kernfs_node *pos; |
807 | 752 | ||
@@ -845,8 +790,7 @@ static void __kernfs_remove(struct kernfs_addrm_cxt *acxt, | |||
845 | ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; | 790 | ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; |
846 | } | 791 | } |
847 | 792 | ||
848 | pos->u.removed_list = acxt->removed; | 793 | kernfs_put(pos); |
849 | acxt->removed = pos; | ||
850 | } | 794 | } |
851 | 795 | ||
852 | kernfs_put(pos); | 796 | kernfs_put(pos); |
@@ -861,11 +805,9 @@ static void __kernfs_remove(struct kernfs_addrm_cxt *acxt, | |||
861 | */ | 805 | */ |
862 | void kernfs_remove(struct kernfs_node *kn) | 806 | void kernfs_remove(struct kernfs_node *kn) |
863 | { | 807 | { |
864 | struct kernfs_addrm_cxt acxt; | 808 | mutex_lock(&kernfs_mutex); |
865 | 809 | __kernfs_remove(kn); | |
866 | kernfs_addrm_start(&acxt); | 810 | mutex_unlock(&kernfs_mutex); |
867 | __kernfs_remove(&acxt, kn); | ||
868 | kernfs_addrm_finish(&acxt); | ||
869 | } | 811 | } |
870 | 812 | ||
871 | /** | 813 | /** |
@@ -880,7 +822,6 @@ void kernfs_remove(struct kernfs_node *kn) | |||
880 | int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, | 822 | int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, |
881 | const void *ns) | 823 | const void *ns) |
882 | { | 824 | { |
883 | struct kernfs_addrm_cxt acxt; | ||
884 | struct kernfs_node *kn; | 825 | struct kernfs_node *kn; |
885 | 826 | ||
886 | if (!parent) { | 827 | if (!parent) { |
@@ -889,13 +830,13 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, | |||
889 | return -ENOENT; | 830 | return -ENOENT; |
890 | } | 831 | } |
891 | 832 | ||
892 | kernfs_addrm_start(&acxt); | 833 | mutex_lock(&kernfs_mutex); |
893 | 834 | ||
894 | kn = kernfs_find_ns(parent, name, ns); | 835 | kn = kernfs_find_ns(parent, name, ns); |
895 | if (kn) | 836 | if (kn) |
896 | __kernfs_remove(&acxt, kn); | 837 | __kernfs_remove(kn); |
897 | 838 | ||
898 | kernfs_addrm_finish(&acxt); | 839 | mutex_unlock(&kernfs_mutex); |
899 | 840 | ||
900 | if (kn) | 841 | if (kn) |
901 | return 0; | 842 | return 0; |
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index dbf397bfdff2..10a8c91c49d6 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c | |||
@@ -820,7 +820,6 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent, | |||
820 | bool name_is_static, | 820 | bool name_is_static, |
821 | struct lock_class_key *key) | 821 | struct lock_class_key *key) |
822 | { | 822 | { |
823 | struct kernfs_addrm_cxt acxt; | ||
824 | struct kernfs_node *kn; | 823 | struct kernfs_node *kn; |
825 | unsigned flags; | 824 | unsigned flags; |
826 | int rc; | 825 | int rc; |
@@ -855,10 +854,7 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent, | |||
855 | if (ops->mmap) | 854 | if (ops->mmap) |
856 | kn->flags |= KERNFS_HAS_MMAP; | 855 | kn->flags |= KERNFS_HAS_MMAP; |
857 | 856 | ||
858 | kernfs_addrm_start(&acxt); | 857 | rc = kernfs_add_one(kn); |
859 | rc = kernfs_add_one(&acxt, kn); | ||
860 | kernfs_addrm_finish(&acxt); | ||
861 | |||
862 | if (rc) { | 858 | if (rc) { |
863 | kernfs_put(kn); | 859 | kernfs_put(kn); |
864 | return ERR_PTR(rc); | 860 | return ERR_PTR(rc); |
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index eb536b76374a..46b58de794d6 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h | |||
@@ -45,13 +45,6 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) | |||
45 | } | 45 | } |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Context structure to be used while adding/removing nodes. | ||
49 | */ | ||
50 | struct kernfs_addrm_cxt { | ||
51 | struct kernfs_node *removed; | ||
52 | }; | ||
53 | |||
54 | /* | ||
55 | * mount.c | 48 | * mount.c |
56 | */ | 49 | */ |
57 | struct kernfs_super_info { | 50 | struct kernfs_super_info { |
@@ -100,9 +93,7 @@ extern const struct inode_operations kernfs_dir_iops; | |||
100 | 93 | ||
101 | struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); | 94 | struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); |
102 | void kernfs_put_active(struct kernfs_node *kn); | 95 | void kernfs_put_active(struct kernfs_node *kn); |
103 | void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt); | 96 | int kernfs_add_one(struct kernfs_node *kn); |
104 | int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn); | ||
105 | void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt); | ||
106 | struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, | 97 | struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, |
107 | const char *name, umode_t mode, | 98 | const char *name, umode_t mode, |
108 | unsigned flags); | 99 | unsigned flags); |
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 4d457055acb9..8a198898e39a 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c | |||
@@ -27,7 +27,6 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, | |||
27 | struct kernfs_node *target) | 27 | struct kernfs_node *target) |
28 | { | 28 | { |
29 | struct kernfs_node *kn; | 29 | struct kernfs_node *kn; |
30 | struct kernfs_addrm_cxt acxt; | ||
31 | int error; | 30 | int error; |
32 | 31 | ||
33 | kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK); | 32 | kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK); |
@@ -39,10 +38,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, | |||
39 | kn->symlink.target_kn = target; | 38 | kn->symlink.target_kn = target; |
40 | kernfs_get(target); /* ref owned by symlink */ | 39 | kernfs_get(target); /* ref owned by symlink */ |
41 | 40 | ||
42 | kernfs_addrm_start(&acxt); | 41 | error = kernfs_add_one(kn); |
43 | error = kernfs_add_one(&acxt, kn); | ||
44 | kernfs_addrm_finish(&acxt); | ||
45 | |||
46 | if (!error) | 42 | if (!error) |
47 | return kn; | 43 | return kn; |
48 | 44 | ||