diff options
| -rw-r--r-- | fs/sysfs/dir.c | 91 | ||||
| -rw-r--r-- | fs/sysfs/sysfs.h | 2 |
2 files changed, 4 insertions, 89 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e319379d36db..f3af45e47eaa 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -386,12 +386,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | |||
| 386 | return NULL; | 386 | return NULL; |
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | static int sysfs_ilookup_test(struct inode *inode, void *arg) | ||
| 390 | { | ||
| 391 | struct sysfs_dirent *sd = arg; | ||
| 392 | return inode->i_ino == sd->s_ino; | ||
| 393 | } | ||
| 394 | |||
| 395 | /** | 389 | /** |
| 396 | * sysfs_addrm_start - prepare for sysfs_dirent add/remove | 390 | * sysfs_addrm_start - prepare for sysfs_dirent add/remove |
| 397 | * @acxt: pointer to sysfs_addrm_cxt to be used | 391 | * @acxt: pointer to sysfs_addrm_cxt to be used |
| @@ -399,47 +393,20 @@ static int sysfs_ilookup_test(struct inode *inode, void *arg) | |||
| 399 | * | 393 | * |
| 400 | * This function is called when the caller is about to add or | 394 | * This function is called when the caller is about to add or |
| 401 | * remove sysfs_dirent under @parent_sd. This function acquires | 395 | * remove sysfs_dirent under @parent_sd. This function acquires |
| 402 | * sysfs_mutex, grabs inode for @parent_sd if available and lock | 396 | * sysfs_mutex. @acxt is used to keep and pass context to |
| 403 | * i_mutex of it. @acxt is used to keep and pass context to | ||
| 404 | * other addrm functions. | 397 | * other addrm functions. |
| 405 | * | 398 | * |
| 406 | * LOCKING: | 399 | * LOCKING: |
| 407 | * Kernel thread context (may sleep). sysfs_mutex is locked on | 400 | * Kernel thread context (may sleep). sysfs_mutex is locked on |
| 408 | * return. i_mutex of parent inode is locked on return if | 401 | * return. |
| 409 | * available. | ||
| 410 | */ | 402 | */ |
| 411 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | 403 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, |
| 412 | struct sysfs_dirent *parent_sd) | 404 | struct sysfs_dirent *parent_sd) |
| 413 | { | 405 | { |
| 414 | struct inode *inode; | ||
| 415 | |||
| 416 | memset(acxt, 0, sizeof(*acxt)); | 406 | memset(acxt, 0, sizeof(*acxt)); |
| 417 | acxt->parent_sd = parent_sd; | 407 | acxt->parent_sd = parent_sd; |
| 418 | 408 | ||
| 419 | /* Lookup parent inode. inode initialization is protected by | ||
| 420 | * sysfs_mutex, so inode existence can be determined by | ||
| 421 | * looking up inode while holding sysfs_mutex. | ||
| 422 | */ | ||
| 423 | mutex_lock(&sysfs_mutex); | 409 | mutex_lock(&sysfs_mutex); |
| 424 | |||
| 425 | inode = ilookup5(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test, | ||
| 426 | parent_sd); | ||
| 427 | if (inode) { | ||
| 428 | WARN_ON(inode->i_state & I_NEW); | ||
| 429 | |||
| 430 | /* parent inode available */ | ||
| 431 | acxt->parent_inode = inode; | ||
| 432 | |||
| 433 | /* sysfs_mutex is below i_mutex in lock hierarchy. | ||
| 434 | * First, trylock i_mutex. If fails, unlock | ||
| 435 | * sysfs_mutex and lock them in order. | ||
| 436 | */ | ||
| 437 | if (!mutex_trylock(&inode->i_mutex)) { | ||
| 438 | mutex_unlock(&sysfs_mutex); | ||
| 439 | mutex_lock(&inode->i_mutex); | ||
| 440 | mutex_lock(&sysfs_mutex); | ||
| 441 | } | ||
| 442 | } | ||
| 443 | } | 410 | } |
| 444 | 411 | ||
| 445 | /** | 412 | /** |
| @@ -471,11 +438,6 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
| 471 | 438 | ||
| 472 | sd->s_parent = sysfs_get(acxt->parent_sd); | 439 | sd->s_parent = sysfs_get(acxt->parent_sd); |
| 473 | 440 | ||
| 474 | if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) | ||
| 475 | inc_nlink(acxt->parent_inode); | ||
| 476 | |||
| 477 | acxt->cnt++; | ||
| 478 | |||
| 479 | sysfs_link_sibling(sd); | 441 | sysfs_link_sibling(sd); |
| 480 | 442 | ||
| 481 | /* Update timestamps on the parent */ | 443 | /* Update timestamps on the parent */ |
| @@ -579,40 +541,6 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
| 579 | sd->s_flags |= SYSFS_FLAG_REMOVED; | 541 | sd->s_flags |= SYSFS_FLAG_REMOVED; |
| 580 | sd->s_sibling = acxt->removed; | 542 | sd->s_sibling = acxt->removed; |
| 581 | acxt->removed = sd; | 543 | acxt->removed = sd; |
| 582 | |||
| 583 | if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) | ||
| 584 | drop_nlink(acxt->parent_inode); | ||
| 585 | |||
| 586 | acxt->cnt++; | ||
| 587 | } | ||
| 588 | |||
| 589 | /** | ||
| 590 | * sysfs_dec_nlink - Decrement link count for the specified sysfs_dirent | ||
| 591 | * @sd: target sysfs_dirent | ||
| 592 | * | ||
| 593 | * Decrement nlink for @sd. @sd must have been unlinked from its | ||
| 594 | * parent on entry to this function such that it can't be looked | ||
| 595 | * up anymore. | ||
| 596 | */ | ||
| 597 | static void sysfs_dec_nlink(struct sysfs_dirent *sd) | ||
| 598 | { | ||
| 599 | struct inode *inode; | ||
| 600 | |||
| 601 | inode = ilookup(sysfs_sb, sd->s_ino); | ||
| 602 | if (!inode) | ||
| 603 | return; | ||
| 604 | |||
| 605 | /* adjust nlink and update timestamp */ | ||
| 606 | mutex_lock(&inode->i_mutex); | ||
| 607 | |||
| 608 | inode->i_ctime = CURRENT_TIME; | ||
| 609 | drop_nlink(inode); | ||
| 610 | if (sysfs_type(sd) == SYSFS_DIR) | ||
| 611 | drop_nlink(inode); | ||
| 612 | |||
| 613 | mutex_unlock(&inode->i_mutex); | ||
| 614 | |||
| 615 | iput(inode); | ||
| 616 | } | 544 | } |
| 617 | 545 | ||
| 618 | /** | 546 | /** |
| @@ -621,25 +549,15 @@ static void sysfs_dec_nlink(struct sysfs_dirent *sd) | |||
| 621 | * | 549 | * |
| 622 | * Finish up sysfs_dirent add/remove. Resources acquired by | 550 | * Finish up sysfs_dirent add/remove. Resources acquired by |
| 623 | * sysfs_addrm_start() are released and removed sysfs_dirents are | 551 | * sysfs_addrm_start() are released and removed sysfs_dirents are |
| 624 | * cleaned up. Timestamps on the parent inode are updated. | 552 | * cleaned up. |
| 625 | * | 553 | * |
| 626 | * LOCKING: | 554 | * LOCKING: |
| 627 | * All mutexes acquired by sysfs_addrm_start() are released. | 555 | * sysfs_mutex is released. |
| 628 | */ | 556 | */ |
| 629 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) | 557 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) |
| 630 | { | 558 | { |
| 631 | /* release resources acquired by sysfs_addrm_start() */ | 559 | /* release resources acquired by sysfs_addrm_start() */ |
| 632 | mutex_unlock(&sysfs_mutex); | 560 | mutex_unlock(&sysfs_mutex); |
| 633 | if (acxt->parent_inode) { | ||
| 634 | struct inode *inode = acxt->parent_inode; | ||
| 635 | |||
| 636 | /* if added/removed, update timestamps on the parent */ | ||
| 637 | if (acxt->cnt) | ||
| 638 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | ||
| 639 | |||
| 640 | mutex_unlock(&inode->i_mutex); | ||
| 641 | iput(inode); | ||
| 642 | } | ||
| 643 | 561 | ||
| 644 | /* kill removed sysfs_dirents */ | 562 | /* kill removed sysfs_dirents */ |
| 645 | while (acxt->removed) { | 563 | while (acxt->removed) { |
| @@ -648,7 +566,6 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) | |||
| 648 | acxt->removed = sd->s_sibling; | 566 | acxt->removed = sd->s_sibling; |
| 649 | sd->s_sibling = NULL; | 567 | sd->s_sibling = NULL; |
| 650 | 568 | ||
| 651 | sysfs_dec_nlink(sd); | ||
| 652 | sysfs_deactivate(sd); | 569 | sysfs_deactivate(sd); |
| 653 | unmap_bin_file(sd); | 570 | unmap_bin_file(sd); |
| 654 | sysfs_put(sd); | 571 | sysfs_put(sd); |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 12ccc07459d8..90b35012abb2 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
| @@ -89,9 +89,7 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | |||
| 89 | */ | 89 | */ |
| 90 | struct sysfs_addrm_cxt { | 90 | struct sysfs_addrm_cxt { |
| 91 | struct sysfs_dirent *parent_sd; | 91 | struct sysfs_dirent *parent_sd; |
| 92 | struct inode *parent_inode; | ||
| 93 | struct sysfs_dirent *removed; | 92 | struct sysfs_dirent *removed; |
| 94 | int cnt; | ||
| 95 | }; | 93 | }; |
| 96 | 94 | ||
| 97 | /* | 95 | /* |
