aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@maxwell.aristanetworks.com>2009-11-20 19:08:55 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:24:54 -0500
commita16bbc3430ed94b543222f4c8ef68025f8493e93 (patch)
treee866babd9a5ab024bcd68a9f935c4b373b1e8ac7 /fs/sysfs
parent06fc0d66f7ed3a3b08e8fcf8c325ecf0b8f93fea (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')
-rw-r--r--fs/sysfs/dir.c91
-rw-r--r--fs/sysfs/sysfs.h2
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
389static 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 */
411void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, 403void 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 */
597static 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 */
629void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) 557void 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 */
90struct sysfs_addrm_cxt { 90struct 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/*