diff options
author | Eric W. Biederman <ebiederm@maxwell.aristanetworks.com> | 2009-11-20 19:08:55 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 14:24:54 -0500 |
commit | a16bbc3430ed94b543222f4c8ef68025f8493e93 (patch) | |
tree | e866babd9a5ab024bcd68a9f935c4b373b1e8ac7 /fs/sysfs/dir.c | |
parent | 06fc0d66f7ed3a3b08e8fcf8c325ecf0b8f93fea (diff) |
sysfs: Gut sysfs_addrm_start and sysfs_addrm_finish
With lazy inode updates and dentry operations bringing everything
into sync on demand there is no longer any need to immediately
update the vfs or grab i_mutex to protect those updates as we
make changes to sysfs.
Acked-by: Serge Hallyn <serue@us.ibm.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r-- | fs/sysfs/dir.c | 91 |
1 files changed, 4 insertions, 87 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); |