diff options
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r-- | fs/sysfs/dir.c | 119 |
1 files changed, 59 insertions, 60 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 4762a9aa0b27..31b6cf30636d 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -368,9 +368,10 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | |||
368 | return sd; | 368 | return sd; |
369 | } | 369 | } |
370 | 370 | ||
371 | static int create_dir(struct kobject *kobj, struct dentry *parent, | 371 | static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, |
372 | const char *name, struct dentry **p_dentry) | 372 | const char *name, struct sysfs_dirent **p_sd) |
373 | { | 373 | { |
374 | struct dentry *parent = parent_sd->s_dentry; | ||
374 | int error; | 375 | int error; |
375 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; | 376 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; |
376 | struct dentry *dentry; | 377 | struct dentry *dentry; |
@@ -409,14 +410,14 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, | |||
409 | 410 | ||
410 | /* link in */ | 411 | /* link in */ |
411 | error = -EEXIST; | 412 | error = -EEXIST; |
412 | if (sysfs_find_dirent(parent->d_fsdata, name)) | 413 | if (sysfs_find_dirent(parent_sd, name)) |
413 | goto out_iput; | 414 | goto out_iput; |
414 | 415 | ||
415 | sysfs_instantiate(dentry, inode); | 416 | sysfs_instantiate(dentry, inode); |
416 | inc_nlink(parent->d_inode); | 417 | inc_nlink(parent->d_inode); |
417 | sysfs_attach_dirent(sd, parent->d_fsdata, dentry); | 418 | sysfs_attach_dirent(sd, parent_sd, dentry); |
418 | 419 | ||
419 | *p_dentry = dentry; | 420 | *p_sd = sd; |
420 | error = 0; | 421 | error = 0; |
421 | goto out_unlock; /* pin directory dentry in core */ | 422 | goto out_unlock; /* pin directory dentry in core */ |
422 | 423 | ||
@@ -433,38 +434,37 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, | |||
433 | return error; | 434 | return error; |
434 | } | 435 | } |
435 | 436 | ||
436 | 437 | int sysfs_create_subdir(struct kobject *kobj, const char *name, | |
437 | int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d) | 438 | struct sysfs_dirent **p_sd) |
438 | { | 439 | { |
439 | return create_dir(k,k->dentry,n,d); | 440 | return create_dir(kobj, kobj->sd, name, p_sd); |
440 | } | 441 | } |
441 | 442 | ||
442 | /** | 443 | /** |
443 | * sysfs_create_dir - create a directory for an object. | 444 | * sysfs_create_dir - create a directory for an object. |
444 | * @kobj: object we're creating directory for. | 445 | * @kobj: object we're creating directory for. |
445 | * @shadow_parent: parent parent object. | 446 | * @shadow_parent: parent object. |
446 | */ | 447 | */ |
447 | 448 | int sysfs_create_dir(struct kobject *kobj, | |
448 | int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent) | 449 | struct sysfs_dirent *shadow_parent_sd) |
449 | { | 450 | { |
450 | struct dentry * dentry = NULL; | 451 | struct sysfs_dirent *parent_sd, *sd; |
451 | struct dentry * parent; | ||
452 | int error = 0; | 452 | int error = 0; |
453 | 453 | ||
454 | BUG_ON(!kobj); | 454 | BUG_ON(!kobj); |
455 | 455 | ||
456 | if (shadow_parent) | 456 | if (shadow_parent_sd) |
457 | parent = shadow_parent; | 457 | parent_sd = shadow_parent_sd; |
458 | else if (kobj->parent) | 458 | else if (kobj->parent) |
459 | parent = kobj->parent->dentry; | 459 | parent_sd = kobj->parent->sd; |
460 | else if (sysfs_mount && sysfs_mount->mnt_sb) | 460 | else if (sysfs_mount && sysfs_mount->mnt_sb) |
461 | parent = sysfs_mount->mnt_sb->s_root; | 461 | parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; |
462 | else | 462 | else |
463 | return -EFAULT; | 463 | return -EFAULT; |
464 | 464 | ||
465 | error = create_dir(kobj,parent,kobject_name(kobj),&dentry); | 465 | error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); |
466 | if (!error) | 466 | if (!error) |
467 | kobj->dentry = dentry; | 467 | kobj->sd = sd; |
468 | return error; | 468 | return error; |
469 | } | 469 | } |
470 | 470 | ||
@@ -525,18 +525,16 @@ const struct inode_operations sysfs_dir_inode_operations = { | |||
525 | .setattr = sysfs_setattr, | 525 | .setattr = sysfs_setattr, |
526 | }; | 526 | }; |
527 | 527 | ||
528 | static void remove_dir(struct dentry * d) | 528 | static void remove_dir(struct sysfs_dirent *sd) |
529 | { | 529 | { |
530 | struct dentry *parent = d->d_parent; | 530 | struct dentry *parent = sd->s_parent->s_dentry; |
531 | struct sysfs_dirent *sd = d->d_fsdata; | ||
532 | 531 | ||
533 | mutex_lock(&parent->d_inode->i_mutex); | 532 | mutex_lock(&parent->d_inode->i_mutex); |
534 | 533 | ||
535 | sysfs_unlink_sibling(sd); | 534 | sysfs_unlink_sibling(sd); |
536 | sd->s_flags |= SYSFS_FLAG_REMOVED; | 535 | sd->s_flags |= SYSFS_FLAG_REMOVED; |
537 | 536 | ||
538 | pr_debug(" o %s removing done (%d)\n",d->d_name.name, | 537 | pr_debug(" o %s removing done\n", sd->s_name); |
539 | atomic_read(&d->d_count)); | ||
540 | 538 | ||
541 | mutex_unlock(&parent->d_inode->i_mutex); | 539 | mutex_unlock(&parent->d_inode->i_mutex); |
542 | 540 | ||
@@ -545,25 +543,26 @@ static void remove_dir(struct dentry * d) | |||
545 | sysfs_put(sd); | 543 | sysfs_put(sd); |
546 | } | 544 | } |
547 | 545 | ||
548 | void sysfs_remove_subdir(struct dentry * d) | 546 | void sysfs_remove_subdir(struct sysfs_dirent *sd) |
549 | { | 547 | { |
550 | remove_dir(d); | 548 | remove_dir(sd); |
551 | } | 549 | } |
552 | 550 | ||
553 | 551 | ||
554 | static void __sysfs_remove_dir(struct dentry *dentry) | 552 | static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) |
555 | { | 553 | { |
556 | struct sysfs_dirent *removed = NULL; | 554 | struct sysfs_dirent *removed = NULL; |
557 | struct sysfs_dirent *parent_sd; | ||
558 | struct sysfs_dirent **pos; | 555 | struct sysfs_dirent **pos; |
556 | struct dentry *dir; | ||
559 | 557 | ||
560 | if (!dentry) | 558 | if (!dir_sd) |
561 | return; | 559 | return; |
562 | 560 | ||
563 | pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); | 561 | dir = dir_sd->s_dentry; |
564 | mutex_lock(&dentry->d_inode->i_mutex); | 562 | |
565 | parent_sd = dentry->d_fsdata; | 563 | pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); |
566 | pos = &parent_sd->s_children; | 564 | mutex_lock(&dir->d_inode->i_mutex); |
565 | pos = &dir_sd->s_children; | ||
567 | while (*pos) { | 566 | while (*pos) { |
568 | struct sysfs_dirent *sd = *pos; | 567 | struct sysfs_dirent *sd = *pos; |
569 | 568 | ||
@@ -575,7 +574,7 @@ static void __sysfs_remove_dir(struct dentry *dentry) | |||
575 | } else | 574 | } else |
576 | pos = &(*pos)->s_sibling; | 575 | pos = &(*pos)->s_sibling; |
577 | } | 576 | } |
578 | mutex_unlock(&dentry->d_inode->i_mutex); | 577 | mutex_unlock(&dir->d_inode->i_mutex); |
579 | 578 | ||
580 | while (removed) { | 579 | while (removed) { |
581 | struct sysfs_dirent *sd = removed; | 580 | struct sysfs_dirent *sd = removed; |
@@ -588,7 +587,7 @@ static void __sysfs_remove_dir(struct dentry *dentry) | |||
588 | sysfs_put(sd); | 587 | sysfs_put(sd); |
589 | } | 588 | } |
590 | 589 | ||
591 | remove_dir(dentry); | 590 | remove_dir(dir_sd); |
592 | } | 591 | } |
593 | 592 | ||
594 | /** | 593 | /** |
@@ -602,25 +601,25 @@ static void __sysfs_remove_dir(struct dentry *dentry) | |||
602 | 601 | ||
603 | void sysfs_remove_dir(struct kobject * kobj) | 602 | void sysfs_remove_dir(struct kobject * kobj) |
604 | { | 603 | { |
605 | struct dentry *d = kobj->dentry; | 604 | struct sysfs_dirent *sd = kobj->sd; |
606 | 605 | ||
607 | spin_lock(&kobj_sysfs_assoc_lock); | 606 | spin_lock(&kobj_sysfs_assoc_lock); |
608 | kobj->dentry = NULL; | 607 | kobj->sd = NULL; |
609 | spin_unlock(&kobj_sysfs_assoc_lock); | 608 | spin_unlock(&kobj_sysfs_assoc_lock); |
610 | 609 | ||
611 | __sysfs_remove_dir(d); | 610 | __sysfs_remove_dir(sd); |
612 | } | 611 | } |
613 | 612 | ||
614 | int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, | 613 | int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, |
615 | const char *new_name) | 614 | const char *new_name) |
616 | { | 615 | { |
617 | struct sysfs_dirent *sd = kobj->dentry->d_fsdata; | 616 | struct sysfs_dirent *sd = kobj->sd; |
618 | struct sysfs_dirent *parent_sd = new_parent->d_fsdata; | 617 | struct dentry *new_parent = new_parent_sd->s_dentry; |
619 | struct dentry *new_dentry; | 618 | struct dentry *new_dentry; |
620 | char *dup_name; | 619 | char *dup_name; |
621 | int error; | 620 | int error; |
622 | 621 | ||
623 | if (!new_parent) | 622 | if (!new_parent_sd) |
624 | return -EFAULT; | 623 | return -EFAULT; |
625 | 624 | ||
626 | down_write(&sysfs_rename_sem); | 625 | down_write(&sysfs_rename_sem); |
@@ -637,9 +636,9 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, | |||
637 | * shadows of the same directory | 636 | * shadows of the same directory |
638 | */ | 637 | */ |
639 | error = -EINVAL; | 638 | error = -EINVAL; |
640 | if (kobj->dentry->d_parent->d_inode != new_parent->d_inode || | 639 | if (sd->s_parent->s_dentry->d_inode != new_parent->d_inode || |
641 | new_dentry->d_parent->d_inode != new_parent->d_inode || | 640 | new_dentry->d_parent->d_inode != new_parent->d_inode || |
642 | new_dentry == kobj->dentry) | 641 | new_dentry == sd->s_dentry) |
643 | goto out_dput; | 642 | goto out_dput; |
644 | 643 | ||
645 | error = -EEXIST; | 644 | error = -EEXIST; |
@@ -661,12 +660,12 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, | |||
661 | 660 | ||
662 | /* move under the new parent */ | 661 | /* move under the new parent */ |
663 | d_add(new_dentry, NULL); | 662 | d_add(new_dentry, NULL); |
664 | d_move(kobj->dentry, new_dentry); | 663 | d_move(sd->s_dentry, new_dentry); |
665 | 664 | ||
666 | sysfs_unlink_sibling(sd); | 665 | sysfs_unlink_sibling(sd); |
667 | sysfs_get(parent_sd); | 666 | sysfs_get(new_parent_sd); |
668 | sysfs_put(sd->s_parent); | 667 | sysfs_put(sd->s_parent); |
669 | sd->s_parent = parent_sd; | 668 | sd->s_parent = new_parent_sd; |
670 | sysfs_link_sibling(sd); | 669 | sysfs_link_sibling(sd); |
671 | 670 | ||
672 | error = 0; | 671 | error = 0; |
@@ -691,9 +690,9 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) | |||
691 | int error; | 690 | int error; |
692 | 691 | ||
693 | old_parent_dentry = kobj->parent ? | 692 | old_parent_dentry = kobj->parent ? |
694 | kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; | 693 | kobj->parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root; |
695 | new_parent_dentry = new_parent ? | 694 | new_parent_dentry = new_parent ? |
696 | new_parent->dentry : sysfs_mount->mnt_sb->s_root; | 695 | new_parent->sd->s_dentry : sysfs_mount->mnt_sb->s_root; |
697 | 696 | ||
698 | if (old_parent_dentry->d_inode == new_parent_dentry->d_inode) | 697 | if (old_parent_dentry->d_inode == new_parent_dentry->d_inode) |
699 | return 0; /* nothing to move */ | 698 | return 0; /* nothing to move */ |
@@ -705,7 +704,7 @@ again: | |||
705 | } | 704 | } |
706 | 705 | ||
707 | new_parent_sd = new_parent_dentry->d_fsdata; | 706 | new_parent_sd = new_parent_dentry->d_fsdata; |
708 | sd = kobj->dentry->d_fsdata; | 707 | sd = kobj->sd; |
709 | 708 | ||
710 | new_dentry = lookup_one_len(kobj->name, new_parent_dentry, | 709 | new_dentry = lookup_one_len(kobj->name, new_parent_dentry, |
711 | strlen(kobj->name)); | 710 | strlen(kobj->name)); |
@@ -715,7 +714,7 @@ again: | |||
715 | } else | 714 | } else |
716 | error = 0; | 715 | error = 0; |
717 | d_add(new_dentry, NULL); | 716 | d_add(new_dentry, NULL); |
718 | d_move(kobj->dentry, new_dentry); | 717 | d_move(sd->s_dentry, new_dentry); |
719 | dput(new_dentry); | 718 | dput(new_dentry); |
720 | 719 | ||
721 | /* Remove from old parent's list and insert into new parent's list. */ | 720 | /* Remove from old parent's list and insert into new parent's list. */ |
@@ -885,7 +884,7 @@ int sysfs_make_shadowed_dir(struct kobject *kobj, | |||
885 | struct inode *inode; | 884 | struct inode *inode; |
886 | struct inode_operations *i_op; | 885 | struct inode_operations *i_op; |
887 | 886 | ||
888 | inode = kobj->dentry->d_inode; | 887 | inode = kobj->sd->s_dentry->d_inode; |
889 | if (inode->i_op != &sysfs_dir_inode_operations) | 888 | if (inode->i_op != &sysfs_dir_inode_operations) |
890 | return -EINVAL; | 889 | return -EINVAL; |
891 | 890 | ||
@@ -912,16 +911,16 @@ int sysfs_make_shadowed_dir(struct kobject *kobj, | |||
912 | * directory. | 911 | * directory. |
913 | */ | 912 | */ |
914 | 913 | ||
915 | struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) | 914 | struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) |
916 | { | 915 | { |
917 | struct dentry *dir = kobj->dentry; | 916 | struct dentry *dir = kobj->sd->s_dentry; |
918 | struct inode *inode = dir->d_inode; | 917 | struct inode *inode = dir->d_inode; |
919 | struct dentry *parent = dir->d_parent; | 918 | struct dentry *parent = dir->d_parent; |
920 | struct sysfs_dirent *parent_sd = parent->d_fsdata; | 919 | struct sysfs_dirent *parent_sd = parent->d_fsdata; |
921 | struct dentry *shadow; | 920 | struct dentry *shadow; |
922 | struct sysfs_dirent *sd; | 921 | struct sysfs_dirent *sd; |
923 | 922 | ||
924 | shadow = ERR_PTR(-EINVAL); | 923 | sd = ERR_PTR(-EINVAL); |
925 | if (!sysfs_is_shadowed_inode(inode)) | 924 | if (!sysfs_is_shadowed_inode(inode)) |
926 | goto out; | 925 | goto out; |
927 | 926 | ||
@@ -944,25 +943,25 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) | |||
944 | dget(shadow); /* Extra count - pin the dentry in core */ | 943 | dget(shadow); /* Extra count - pin the dentry in core */ |
945 | 944 | ||
946 | out: | 945 | out: |
947 | return shadow; | 946 | return sd; |
948 | nomem: | 947 | nomem: |
949 | dput(shadow); | 948 | dput(shadow); |
950 | shadow = ERR_PTR(-ENOMEM); | 949 | sd = ERR_PTR(-ENOMEM); |
951 | goto out; | 950 | goto out; |
952 | } | 951 | } |
953 | 952 | ||
954 | /** | 953 | /** |
955 | * sysfs_remove_shadow_dir - remove an object's directory. | 954 | * sysfs_remove_shadow_dir - remove an object's directory. |
956 | * @shadow: dentry of shadow directory | 955 | * @shadow_sd: sysfs_dirent of shadow directory |
957 | * | 956 | * |
958 | * The only thing special about this is that we remove any files in | 957 | * The only thing special about this is that we remove any files in |
959 | * the directory before we remove the directory, and we've inlined | 958 | * the directory before we remove the directory, and we've inlined |
960 | * what used to be sysfs_rmdir() below, instead of calling separately. | 959 | * what used to be sysfs_rmdir() below, instead of calling separately. |
961 | */ | 960 | */ |
962 | 961 | ||
963 | void sysfs_remove_shadow_dir(struct dentry *shadow) | 962 | void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd) |
964 | { | 963 | { |
965 | __sysfs_remove_dir(shadow); | 964 | __sysfs_remove_dir(shadow_sd); |
966 | } | 965 | } |
967 | 966 | ||
968 | const struct file_operations sysfs_dir_operations = { | 967 | const struct file_operations sysfs_dir_operations = { |