aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r--fs/sysfs/dir.c250
1 files changed, 186 insertions, 64 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 9fc8558fd86c..edb30621b82f 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -30,7 +30,7 @@ static DEFINE_IDA(sysfs_ino_ida);
30 * Locking: 30 * Locking:
31 * mutex_lock(sysfs_mutex) 31 * mutex_lock(sysfs_mutex)
32 */ 32 */
33static void sysfs_link_sibling(struct sysfs_dirent *sd) 33void sysfs_link_sibling(struct sysfs_dirent *sd)
34{ 34{
35 struct sysfs_dirent *parent_sd = sd->s_parent; 35 struct sysfs_dirent *parent_sd = sd->s_parent;
36 36
@@ -49,7 +49,7 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd)
49 * Locking: 49 * Locking:
50 * mutex_lock(sysfs_mutex) 50 * mutex_lock(sysfs_mutex)
51 */ 51 */
52static void sysfs_unlink_sibling(struct sysfs_dirent *sd) 52void sysfs_unlink_sibling(struct sysfs_dirent *sd)
53{ 53{
54 struct sysfs_dirent **pos; 54 struct sysfs_dirent **pos;
55 55
@@ -165,7 +165,7 @@ void sysfs_put_active_two(struct sysfs_dirent *sd)
165 * 165 *
166 * Deny new active references and drain existing ones. 166 * Deny new active references and drain existing ones.
167 */ 167 */
168void sysfs_deactivate(struct sysfs_dirent *sd) 168static void sysfs_deactivate(struct sysfs_dirent *sd)
169{ 169{
170 DECLARE_COMPLETION_ONSTACK(wait); 170 DECLARE_COMPLETION_ONSTACK(wait);
171 int v; 171 int v;
@@ -318,27 +318,164 @@ static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry)
318 d_rehash(dentry); 318 d_rehash(dentry);
319} 319}
320 320
321static int sysfs_ilookup_test(struct inode *inode, void *arg)
322{
323 struct sysfs_dirent *sd = arg;
324 return inode->i_ino == sd->s_ino;
325}
326
321/** 327/**
322 * sysfs_attach_dirent - attach sysfs_dirent to its parent and dentry 328 * sysfs_addrm_start - prepare for sysfs_dirent add/remove
323 * @sd: sysfs_dirent to attach 329 * @acxt: pointer to sysfs_addrm_cxt to be used
324 * @parent_sd: parent to attach to (optional) 330 * @parent_sd: parent sysfs_dirent
325 * @dentry: dentry to be associated to @sd (optional)
326 * 331 *
327 * Attach @sd to @parent_sd and/or @dentry. Both are optional. 332 * This function is called when the caller is about to add or
333 * remove sysfs_dirent under @parent_sd. This function acquires
334 * sysfs_mutex, grabs inode for @parent_sd if available and lock
335 * i_mutex of it. @acxt is used to keep and pass context to
336 * other addrm functions.
328 * 337 *
329 * LOCKING: 338 * LOCKING:
330 * mutex_lock(sysfs_mutex) 339 * Kernel thread context (may sleep). sysfs_mutex is locked on
340 * return. i_mutex of parent inode is locked on return if
341 * available.
331 */ 342 */
332void sysfs_attach_dirent(struct sysfs_dirent *sd, 343void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
333 struct sysfs_dirent *parent_sd, struct dentry *dentry) 344 struct sysfs_dirent *parent_sd)
334{ 345{
335 if (dentry) 346 struct inode *inode;
336 sysfs_attach_dentry(sd, dentry);
337 347
338 if (parent_sd) { 348 memset(acxt, 0, sizeof(*acxt));
339 sd->s_parent = sysfs_get(parent_sd); 349 acxt->parent_sd = parent_sd;
340 sysfs_link_sibling(sd); 350
351 /* Lookup parent inode. inode initialization and I_NEW
352 * clearing are protected by sysfs_mutex. By grabbing it and
353 * looking up with _nowait variant, inode state can be
354 * determined reliably.
355 */
356 mutex_lock(&sysfs_mutex);
357
358 inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
359 parent_sd);
360
361 if (inode && !(inode->i_state & I_NEW)) {
362 /* parent inode available */
363 acxt->parent_inode = inode;
364
365 /* sysfs_mutex is below i_mutex in lock hierarchy.
366 * First, trylock i_mutex. If fails, unlock
367 * sysfs_mutex and lock them in order.
368 */
369 if (!mutex_trylock(&inode->i_mutex)) {
370 mutex_unlock(&sysfs_mutex);
371 mutex_lock(&inode->i_mutex);
372 mutex_lock(&sysfs_mutex);
373 }
374 } else
375 iput(inode);
376}
377
378/**
379 * sysfs_add_one - add sysfs_dirent to parent
380 * @acxt: addrm context to use
381 * @sd: sysfs_dirent to be added
382 *
383 * Get @acxt->parent_sd and set sd->s_parent to it and increment
384 * nlink of parent inode if @sd is a directory. @sd is NOT
385 * linked into the children list of the parent. The caller
386 * should invoke sysfs_link_sibling() after this function
387 * completes if @sd needs to be on the children list.
388 *
389 * This function should be called between calls to
390 * sysfs_addrm_start() and sysfs_addrm_finish() and should be
391 * passed the same @acxt as passed to sysfs_addrm_start().
392 *
393 * LOCKING:
394 * Determined by sysfs_addrm_start().
395 */
396void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
397{
398 sd->s_parent = sysfs_get(acxt->parent_sd);
399
400 if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
401 inc_nlink(acxt->parent_inode);
402
403 acxt->cnt++;
404}
405
406/**
407 * sysfs_remove_one - remove sysfs_dirent from parent
408 * @acxt: addrm context to use
409 * @sd: sysfs_dirent to be added
410 *
411 * Mark @sd removed and drop nlink of parent inode if @sd is a
412 * directory. @sd is NOT unlinked from the children list of the
413 * parent. The caller is repsonsible for removing @sd from the
414 * children list before calling this function.
415 *
416 * This function should be called between calls to
417 * sysfs_addrm_start() and sysfs_addrm_finish() and should be
418 * passed the same @acxt as passed to sysfs_addrm_start().
419 *
420 * LOCKING:
421 * Determined by sysfs_addrm_start().
422 */
423void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
424{
425 BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED));
426
427 sd->s_flags |= SYSFS_FLAG_REMOVED;
428 sd->s_sibling = acxt->removed;
429 acxt->removed = sd;
430
431 if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
432 drop_nlink(acxt->parent_inode);
433
434 acxt->cnt++;
435}
436
437/**
438 * sysfs_addrm_finish - finish up sysfs_dirent add/remove
439 * @acxt: addrm context to finish up
440 *
441 * Finish up sysfs_dirent add/remove. Resources acquired by
442 * sysfs_addrm_start() are released and removed sysfs_dirents are
443 * cleaned up. Timestamps on the parent inode are updated.
444 *
445 * LOCKING:
446 * All mutexes acquired by sysfs_addrm_start() are released.
447 *
448 * RETURNS:
449 * Number of added/removed sysfs_dirents since sysfs_addrm_start().
450 */
451int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
452{
453 /* release resources acquired by sysfs_addrm_start() */
454 mutex_unlock(&sysfs_mutex);
455 if (acxt->parent_inode) {
456 struct inode *inode = acxt->parent_inode;
457
458 /* if added/removed, update timestamps on the parent */
459 if (acxt->cnt)
460 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
461
462 mutex_unlock(&inode->i_mutex);
463 iput(inode);
464 }
465
466 /* kill removed sysfs_dirents */
467 while (acxt->removed) {
468 struct sysfs_dirent *sd = acxt->removed;
469
470 acxt->removed = sd->s_sibling;
471 sd->s_sibling = NULL;
472
473 sysfs_drop_dentry(sd);
474 sysfs_deactivate(sd);
475 sysfs_put(sd);
341 } 476 }
477
478 return acxt->cnt;
342} 479}
343 480
344/** 481/**
@@ -396,19 +533,20 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
396 const char *name, struct sysfs_dirent **p_sd) 533 const char *name, struct sysfs_dirent **p_sd)
397{ 534{
398 struct dentry *parent = parent_sd->s_dentry; 535 struct dentry *parent = parent_sd->s_dentry;
536 struct sysfs_addrm_cxt acxt;
399 int error; 537 int error;
400 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 538 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
401 struct dentry *dentry; 539 struct dentry *dentry;
402 struct inode *inode; 540 struct inode *inode;
403 struct sysfs_dirent *sd; 541 struct sysfs_dirent *sd;
404 542
405 mutex_lock(&parent->d_inode->i_mutex); 543 sysfs_addrm_start(&acxt, parent_sd);
406 544
407 /* allocate */ 545 /* allocate */
408 dentry = lookup_one_len(name, parent, strlen(name)); 546 dentry = lookup_one_len(name, parent, strlen(name));
409 if (IS_ERR(dentry)) { 547 if (IS_ERR(dentry)) {
410 error = PTR_ERR(dentry); 548 error = PTR_ERR(dentry);
411 goto out_unlock; 549 goto out_finish;
412 } 550 }
413 551
414 error = -EEXIST; 552 error = -EEXIST;
@@ -433,23 +571,18 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
433 } 571 }
434 572
435 /* link in */ 573 /* link in */
436 mutex_lock(&sysfs_mutex);
437
438 error = -EEXIST; 574 error = -EEXIST;
439 if (sysfs_find_dirent(parent_sd, name)) { 575 if (sysfs_find_dirent(parent_sd, name))
440 mutex_unlock(&sysfs_mutex);
441 goto out_iput; 576 goto out_iput;
442 }
443 577
578 sysfs_add_one(&acxt, sd);
579 sysfs_link_sibling(sd);
444 sysfs_instantiate(dentry, inode); 580 sysfs_instantiate(dentry, inode);
445 inc_nlink(parent->d_inode); 581 sysfs_attach_dentry(sd, dentry);
446 sysfs_attach_dirent(sd, parent_sd, dentry);
447
448 mutex_unlock(&sysfs_mutex);
449 582
450 *p_sd = sd; 583 *p_sd = sd;
451 error = 0; 584 error = 0;
452 goto out_unlock; /* pin directory dentry in core */ 585 goto out_finish; /* pin directory dentry in core */
453 586
454 out_iput: 587 out_iput:
455 iput(inode); 588 iput(inode);
@@ -459,8 +592,8 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
459 d_drop(dentry); 592 d_drop(dentry);
460 out_dput: 593 out_dput:
461 dput(dentry); 594 dput(dentry);
462 out_unlock: 595 out_finish:
463 mutex_unlock(&parent->d_inode->i_mutex); 596 sysfs_addrm_finish(&acxt);
464 return error; 597 return error;
465} 598}
466 599
@@ -561,16 +694,12 @@ const struct inode_operations sysfs_dir_inode_operations = {
561 694
562static void remove_dir(struct sysfs_dirent *sd) 695static void remove_dir(struct sysfs_dirent *sd)
563{ 696{
564 mutex_lock(&sysfs_mutex); 697 struct sysfs_addrm_cxt acxt;
565 sysfs_unlink_sibling(sd);
566 sd->s_flags |= SYSFS_FLAG_REMOVED;
567 mutex_unlock(&sysfs_mutex);
568 698
569 pr_debug(" o %s removing done\n", sd->s_name); 699 sysfs_addrm_start(&acxt, sd->s_parent);
570 700 sysfs_unlink_sibling(sd);
571 sysfs_drop_dentry(sd); 701 sysfs_remove_one(&acxt, sd);
572 sysfs_deactivate(sd); 702 sysfs_addrm_finish(&acxt);
573 sysfs_put(sd);
574} 703}
575 704
576void sysfs_remove_subdir(struct sysfs_dirent *sd) 705void sysfs_remove_subdir(struct sysfs_dirent *sd)
@@ -581,38 +710,26 @@ void sysfs_remove_subdir(struct sysfs_dirent *sd)
581 710
582static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) 711static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
583{ 712{
584 struct sysfs_dirent *removed = NULL; 713 struct sysfs_addrm_cxt acxt;
585 struct sysfs_dirent **pos; 714 struct sysfs_dirent **pos;
586 715
587 if (!dir_sd) 716 if (!dir_sd)
588 return; 717 return;
589 718
590 pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); 719 pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
591 mutex_lock(&sysfs_mutex); 720 sysfs_addrm_start(&acxt, dir_sd);
592 pos = &dir_sd->s_children; 721 pos = &dir_sd->s_children;
593 while (*pos) { 722 while (*pos) {
594 struct sysfs_dirent *sd = *pos; 723 struct sysfs_dirent *sd = *pos;
595 724
596 if (sysfs_type(sd) && (sysfs_type(sd) & SYSFS_NOT_PINNED)) { 725 if (sysfs_type(sd) && (sysfs_type(sd) & SYSFS_NOT_PINNED)) {
597 sd->s_flags |= SYSFS_FLAG_REMOVED;
598 *pos = sd->s_sibling; 726 *pos = sd->s_sibling;
599 sd->s_sibling = removed; 727 sd->s_sibling = NULL;
600 removed = sd; 728 sysfs_remove_one(&acxt, sd);
601 } else 729 } else
602 pos = &(*pos)->s_sibling; 730 pos = &(*pos)->s_sibling;
603 } 731 }
604 mutex_unlock(&sysfs_mutex); 732 sysfs_addrm_finish(&acxt);
605
606 while (removed) {
607 struct sysfs_dirent *sd = removed;
608
609 removed = sd->s_sibling;
610 sd->s_sibling = NULL;
611
612 sysfs_drop_dentry(sd);
613 sysfs_deactivate(sd);
614 sysfs_put(sd);
615 }
616 733
617 remove_dir(dir_sd); 734 remove_dir(dir_sd);
618} 735}
@@ -772,7 +889,8 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
772 sd = sysfs_new_dirent("_DIR_", 0, 0); 889 sd = sysfs_new_dirent("_DIR_", 0, 0);
773 if (sd) { 890 if (sd) {
774 mutex_lock(&sysfs_mutex); 891 mutex_lock(&sysfs_mutex);
775 sysfs_attach_dirent(sd, parent_sd, NULL); 892 sd->s_parent = sysfs_get(parent_sd);
893 sysfs_link_sibling(sd);
776 mutex_unlock(&sysfs_mutex); 894 mutex_unlock(&sysfs_mutex);
777 } 895 }
778 896
@@ -957,6 +1075,7 @@ struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj)
957 struct sysfs_dirent *parent_sd = parent->d_fsdata; 1075 struct sysfs_dirent *parent_sd = parent->d_fsdata;
958 struct dentry *shadow; 1076 struct dentry *shadow;
959 struct sysfs_dirent *sd; 1077 struct sysfs_dirent *sd;
1078 struct sysfs_addrm_cxt acxt;
960 1079
961 sd = ERR_PTR(-EINVAL); 1080 sd = ERR_PTR(-EINVAL);
962 if (!sysfs_is_shadowed_inode(inode)) 1081 if (!sysfs_is_shadowed_inode(inode))
@@ -970,15 +1089,18 @@ struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj)
970 if (!sd) 1089 if (!sd)
971 goto nomem; 1090 goto nomem;
972 sd->s_elem.dir.kobj = kobj; 1091 sd->s_elem.dir.kobj = kobj;
973 /* point to parent_sd but don't attach to it */
974 sd->s_parent = sysfs_get(parent_sd);
975 mutex_lock(&sysfs_mutex);
976 sysfs_attach_dirent(sd, NULL, shadow);
977 mutex_unlock(&sysfs_mutex);
978 1092
1093 sysfs_addrm_start(&acxt, parent_sd);
1094
1095 /* add but don't link into children list */
1096 sysfs_add_one(&acxt, sd);
1097
1098 /* attach and instantiate dentry */
1099 sysfs_attach_dentry(sd, shadow);
979 d_instantiate(shadow, igrab(inode)); 1100 d_instantiate(shadow, igrab(inode));
980 inc_nlink(inode); 1101 inc_nlink(inode); /* tj: synchronization? */
981 inc_nlink(parent->d_inode); 1102
1103 sysfs_addrm_finish(&acxt);
982 1104
983 dget(shadow); /* Extra count - pin the dentry in core */ 1105 dget(shadow); /* Extra count - pin the dentry in core */
984 1106