diff options
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r-- | fs/sysfs/dir.c | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index d23e66dfba74..671868914b5b 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -406,22 +406,19 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | |||
406 | /** | 406 | /** |
407 | * sysfs_addrm_start - prepare for sysfs_dirent add/remove | 407 | * sysfs_addrm_start - prepare for sysfs_dirent add/remove |
408 | * @acxt: pointer to sysfs_addrm_cxt to be used | 408 | * @acxt: pointer to sysfs_addrm_cxt to be used |
409 | * @parent_sd: parent sysfs_dirent | ||
410 | * | 409 | * |
411 | * This function is called when the caller is about to add or | 410 | * This function is called when the caller is about to add or remove |
412 | * remove sysfs_dirent under @parent_sd. This function acquires | 411 | * sysfs_dirent. This function acquires sysfs_mutex. @acxt is used |
413 | * sysfs_mutex. @acxt is used to keep and pass context to | 412 | * to keep and pass context to other addrm functions. |
414 | * other addrm functions. | ||
415 | * | 413 | * |
416 | * LOCKING: | 414 | * LOCKING: |
417 | * Kernel thread context (may sleep). sysfs_mutex is locked on | 415 | * Kernel thread context (may sleep). sysfs_mutex is locked on |
418 | * return. | 416 | * return. |
419 | */ | 417 | */ |
420 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | 418 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt) |
421 | struct sysfs_dirent *parent_sd) | 419 | __acquires(sysfs_mutex) |
422 | { | 420 | { |
423 | memset(acxt, 0, sizeof(*acxt)); | 421 | memset(acxt, 0, sizeof(*acxt)); |
424 | acxt->parent_sd = parent_sd; | ||
425 | 422 | ||
426 | mutex_lock(&sysfs_mutex); | 423 | mutex_lock(&sysfs_mutex); |
427 | } | 424 | } |
@@ -430,10 +427,11 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | |||
430 | * __sysfs_add_one - add sysfs_dirent to parent without warning | 427 | * __sysfs_add_one - add sysfs_dirent to parent without warning |
431 | * @acxt: addrm context to use | 428 | * @acxt: addrm context to use |
432 | * @sd: sysfs_dirent to be added | 429 | * @sd: sysfs_dirent to be added |
430 | * @parent_sd: the parent sysfs_dirent to add @sd to | ||
433 | * | 431 | * |
434 | * Get @acxt->parent_sd and set sd->s_parent to it and increment | 432 | * Get @parent_sd and set @sd->s_parent to it and increment nlink of |
435 | * nlink of parent inode if @sd is a directory and link into the | 433 | * the parent inode if @sd is a directory and link into the children |
436 | * children list of the parent. | 434 | * list of the parent. |
437 | * | 435 | * |
438 | * This function should be called between calls to | 436 | * This function should be called between calls to |
439 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be | 437 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be |
@@ -446,20 +444,21 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | |||
446 | * 0 on success, -EEXIST if entry with the given name already | 444 | * 0 on success, -EEXIST if entry with the given name already |
447 | * exists. | 445 | * exists. |
448 | */ | 446 | */ |
449 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | 447 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, |
448 | struct sysfs_dirent *parent_sd) | ||
450 | { | 449 | { |
451 | struct sysfs_inode_attrs *ps_iattr; | 450 | struct sysfs_inode_attrs *ps_iattr; |
452 | int ret; | 451 | int ret; |
453 | 452 | ||
454 | sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); | 453 | sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); |
455 | sd->s_parent = sysfs_get(acxt->parent_sd); | 454 | sd->s_parent = sysfs_get(parent_sd); |
456 | 455 | ||
457 | ret = sysfs_link_sibling(sd); | 456 | ret = sysfs_link_sibling(sd); |
458 | if (ret) | 457 | if (ret) |
459 | return ret; | 458 | return ret; |
460 | 459 | ||
461 | /* Update timestamps on the parent */ | 460 | /* Update timestamps on the parent */ |
462 | ps_iattr = acxt->parent_sd->s_iattr; | 461 | ps_iattr = parent_sd->s_iattr; |
463 | if (ps_iattr) { | 462 | if (ps_iattr) { |
464 | struct iattr *ps_iattrs = &ps_iattr->ia_iattr; | 463 | struct iattr *ps_iattrs = &ps_iattr->ia_iattr; |
465 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; | 464 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; |
@@ -493,10 +492,11 @@ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) | |||
493 | * sysfs_add_one - add sysfs_dirent to parent | 492 | * sysfs_add_one - add sysfs_dirent to parent |
494 | * @acxt: addrm context to use | 493 | * @acxt: addrm context to use |
495 | * @sd: sysfs_dirent to be added | 494 | * @sd: sysfs_dirent to be added |
495 | * @parent_sd: the parent sysfs_dirent to add @sd to | ||
496 | * | 496 | * |
497 | * Get @acxt->parent_sd and set sd->s_parent to it and increment | 497 | * Get @parent_sd and set @sd->s_parent to it and increment nlink of |
498 | * nlink of parent inode if @sd is a directory and link into the | 498 | * the parent inode if @sd is a directory and link into the children |
499 | * children list of the parent. | 499 | * list of the parent. |
500 | * | 500 | * |
501 | * This function should be called between calls to | 501 | * This function should be called between calls to |
502 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be | 502 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be |
@@ -509,17 +509,18 @@ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) | |||
509 | * 0 on success, -EEXIST if entry with the given name already | 509 | * 0 on success, -EEXIST if entry with the given name already |
510 | * exists. | 510 | * exists. |
511 | */ | 511 | */ |
512 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | 512 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, |
513 | struct sysfs_dirent *parent_sd) | ||
513 | { | 514 | { |
514 | int ret; | 515 | int ret; |
515 | 516 | ||
516 | ret = __sysfs_add_one(acxt, sd); | 517 | ret = __sysfs_add_one(acxt, sd, parent_sd); |
517 | if (ret == -EEXIST) { | 518 | if (ret == -EEXIST) { |
518 | char *path = kzalloc(PATH_MAX, GFP_KERNEL); | 519 | char *path = kzalloc(PATH_MAX, GFP_KERNEL); |
519 | WARN(1, KERN_WARNING | 520 | WARN(1, KERN_WARNING |
520 | "sysfs: cannot create duplicate filename '%s'\n", | 521 | "sysfs: cannot create duplicate filename '%s'\n", |
521 | (path == NULL) ? sd->s_name | 522 | (path == NULL) ? sd->s_name |
522 | : (sysfs_pathname(acxt->parent_sd, path), | 523 | : (sysfs_pathname(parent_sd, path), |
523 | strlcat(path, "/", PATH_MAX), | 524 | strlcat(path, "/", PATH_MAX), |
524 | strlcat(path, sd->s_name, PATH_MAX), | 525 | strlcat(path, sd->s_name, PATH_MAX), |
525 | path)); | 526 | path)); |
@@ -553,7 +554,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
553 | sysfs_unlink_sibling(sd); | 554 | sysfs_unlink_sibling(sd); |
554 | 555 | ||
555 | /* Update timestamps on the parent */ | 556 | /* Update timestamps on the parent */ |
556 | ps_iattr = acxt->parent_sd->s_iattr; | 557 | ps_iattr = sd->s_parent->s_iattr; |
557 | if (ps_iattr) { | 558 | if (ps_iattr) { |
558 | struct iattr *ps_iattrs = &ps_iattr->ia_iattr; | 559 | struct iattr *ps_iattrs = &ps_iattr->ia_iattr; |
559 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; | 560 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; |
@@ -576,6 +577,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
576 | * sysfs_mutex is released. | 577 | * sysfs_mutex is released. |
577 | */ | 578 | */ |
578 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) | 579 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) |
580 | __releases(sysfs_mutex) | ||
579 | { | 581 | { |
580 | /* release resources acquired by sysfs_addrm_start() */ | 582 | /* release resources acquired by sysfs_addrm_start() */ |
581 | mutex_unlock(&sysfs_mutex); | 583 | mutex_unlock(&sysfs_mutex); |
@@ -678,8 +680,8 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, | |||
678 | sd->s_dir.kobj = kobj; | 680 | sd->s_dir.kobj = kobj; |
679 | 681 | ||
680 | /* link in */ | 682 | /* link in */ |
681 | sysfs_addrm_start(&acxt, parent_sd); | 683 | sysfs_addrm_start(&acxt); |
682 | rc = sysfs_add_one(&acxt, sd); | 684 | rc = sysfs_add_one(&acxt, sd, parent_sd); |
683 | sysfs_addrm_finish(&acxt); | 685 | sysfs_addrm_finish(&acxt); |
684 | 686 | ||
685 | if (rc == 0) | 687 | if (rc == 0) |
@@ -772,7 +774,7 @@ static void remove_dir(struct sysfs_dirent *sd) | |||
772 | { | 774 | { |
773 | struct sysfs_addrm_cxt acxt; | 775 | struct sysfs_addrm_cxt acxt; |
774 | 776 | ||
775 | sysfs_addrm_start(&acxt, sd->s_parent); | 777 | sysfs_addrm_start(&acxt); |
776 | sysfs_remove_one(&acxt, sd); | 778 | sysfs_remove_one(&acxt, sd); |
777 | sysfs_addrm_finish(&acxt); | 779 | sysfs_addrm_finish(&acxt); |
778 | } | 780 | } |
@@ -792,7 +794,7 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) | |||
792 | return; | 794 | return; |
793 | 795 | ||
794 | pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); | 796 | pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); |
795 | sysfs_addrm_start(&acxt, dir_sd); | 797 | sysfs_addrm_start(&acxt); |
796 | pos = rb_first(&dir_sd->s_dir.children); | 798 | pos = rb_first(&dir_sd->s_dir.children); |
797 | while (pos) { | 799 | while (pos) { |
798 | struct sysfs_dirent *sd = to_sysfs_dirent(pos); | 800 | struct sysfs_dirent *sd = to_sysfs_dirent(pos); |