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.c112
1 files changed, 88 insertions, 24 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 590717861c7a..b2b83067ccc8 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -380,9 +380,15 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
380{ 380{
381 struct sysfs_inode_attrs *ps_iattr; 381 struct sysfs_inode_attrs *ps_iattr;
382 382
383 if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) 383 if (sysfs_find_dirent(acxt->parent_sd, sd->s_ns, sd->s_name))
384 return -EEXIST; 384 return -EEXIST;
385 385
386 if (sysfs_ns_type(acxt->parent_sd) && !sd->s_ns) {
387 WARN(1, KERN_WARNING "sysfs: ns required in '%s' for '%s'\n",
388 acxt->parent_sd->s_name, sd->s_name);
389 return -EINVAL;
390 }
391
386 sd->s_parent = sysfs_get(acxt->parent_sd); 392 sd->s_parent = sysfs_get(acxt->parent_sd);
387 393
388 sysfs_link_sibling(sd); 394 sysfs_link_sibling(sd);
@@ -533,13 +539,17 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
533 * Pointer to sysfs_dirent if found, NULL if not. 539 * Pointer to sysfs_dirent if found, NULL if not.
534 */ 540 */
535struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, 541struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
542 const void *ns,
536 const unsigned char *name) 543 const unsigned char *name)
537{ 544{
538 struct sysfs_dirent *sd; 545 struct sysfs_dirent *sd;
539 546
540 for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) 547 for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) {
548 if (sd->s_ns != ns)
549 continue;
541 if (!strcmp(sd->s_name, name)) 550 if (!strcmp(sd->s_name, name))
542 return sd; 551 return sd;
552 }
543 return NULL; 553 return NULL;
544} 554}
545 555
@@ -558,12 +568,13 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
558 * Pointer to sysfs_dirent if found, NULL if not. 568 * Pointer to sysfs_dirent if found, NULL if not.
559 */ 569 */
560struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, 570struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
571 const void *ns,
561 const unsigned char *name) 572 const unsigned char *name)
562{ 573{
563 struct sysfs_dirent *sd; 574 struct sysfs_dirent *sd;
564 575
565 mutex_lock(&sysfs_mutex); 576 mutex_lock(&sysfs_mutex);
566 sd = sysfs_find_dirent(parent_sd, name); 577 sd = sysfs_find_dirent(parent_sd, ns, name);
567 sysfs_get(sd); 578 sysfs_get(sd);
568 mutex_unlock(&sysfs_mutex); 579 mutex_unlock(&sysfs_mutex);
569 580
@@ -572,7 +583,8 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
572EXPORT_SYMBOL_GPL(sysfs_get_dirent); 583EXPORT_SYMBOL_GPL(sysfs_get_dirent);
573 584
574static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, 585static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
575 const char *name, struct sysfs_dirent **p_sd) 586 enum kobj_ns_type type, const void *ns, const char *name,
587 struct sysfs_dirent **p_sd)
576{ 588{
577 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 589 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
578 struct sysfs_addrm_cxt acxt; 590 struct sysfs_addrm_cxt acxt;
@@ -583,6 +595,9 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
583 sd = sysfs_new_dirent(name, mode, SYSFS_DIR); 595 sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
584 if (!sd) 596 if (!sd)
585 return -ENOMEM; 597 return -ENOMEM;
598
599 sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT);
600 sd->s_ns = ns;
586 sd->s_dir.kobj = kobj; 601 sd->s_dir.kobj = kobj;
587 602
588 /* link in */ 603 /* link in */
@@ -601,7 +616,25 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
601int sysfs_create_subdir(struct kobject *kobj, const char *name, 616int sysfs_create_subdir(struct kobject *kobj, const char *name,
602 struct sysfs_dirent **p_sd) 617 struct sysfs_dirent **p_sd)
603{ 618{
604 return create_dir(kobj, kobj->sd, name, p_sd); 619 return create_dir(kobj, kobj->sd,
620 KOBJ_NS_TYPE_NONE, NULL, name, p_sd);
621}
622
623static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj)
624{
625 const struct kobj_ns_type_operations *ops;
626 enum kobj_ns_type type;
627
628 ops = kobj_child_ns_ops(kobj);
629 if (!ops)
630 return KOBJ_NS_TYPE_NONE;
631
632 type = ops->type;
633 BUG_ON(type <= KOBJ_NS_TYPE_NONE);
634 BUG_ON(type >= KOBJ_NS_TYPES);
635 BUG_ON(!kobj_ns_type_registered(type));
636
637 return type;
605} 638}
606 639
607/** 640/**
@@ -610,7 +643,9 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
610 */ 643 */
611int sysfs_create_dir(struct kobject * kobj) 644int sysfs_create_dir(struct kobject * kobj)
612{ 645{
646 enum kobj_ns_type type;
613 struct sysfs_dirent *parent_sd, *sd; 647 struct sysfs_dirent *parent_sd, *sd;
648 const void *ns = NULL;
614 int error = 0; 649 int error = 0;
615 650
616 BUG_ON(!kobj); 651 BUG_ON(!kobj);
@@ -620,7 +655,11 @@ int sysfs_create_dir(struct kobject * kobj)
620 else 655 else
621 parent_sd = &sysfs_root; 656 parent_sd = &sysfs_root;
622 657
623 error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); 658 if (sysfs_ns_type(parent_sd))
659 ns = kobj->ktype->namespace(kobj);
660 type = sysfs_read_ns_type(kobj);
661
662 error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd);
624 if (!error) 663 if (!error)
625 kobj->sd = sd; 664 kobj->sd = sd;
626 return error; 665 return error;
@@ -630,13 +669,19 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
630 struct nameidata *nd) 669 struct nameidata *nd)
631{ 670{
632 struct dentry *ret = NULL; 671 struct dentry *ret = NULL;
633 struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; 672 struct dentry *parent = dentry->d_parent;
673 struct sysfs_dirent *parent_sd = parent->d_fsdata;
634 struct sysfs_dirent *sd; 674 struct sysfs_dirent *sd;
635 struct inode *inode; 675 struct inode *inode;
676 enum kobj_ns_type type;
677 const void *ns;
636 678
637 mutex_lock(&sysfs_mutex); 679 mutex_lock(&sysfs_mutex);
638 680
639 sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); 681 type = sysfs_ns_type(parent_sd);
682 ns = sysfs_info(dir->i_sb)->ns[type];
683
684 sd = sysfs_find_dirent(parent_sd, ns, dentry->d_name.name);
640 685
641 /* no such entry */ 686 /* no such entry */
642 if (!sd) { 687 if (!sd) {
@@ -735,7 +780,8 @@ void sysfs_remove_dir(struct kobject * kobj)
735} 780}
736 781
737int sysfs_rename(struct sysfs_dirent *sd, 782int sysfs_rename(struct sysfs_dirent *sd,
738 struct sysfs_dirent *new_parent_sd, const char *new_name) 783 struct sysfs_dirent *new_parent_sd, const void *new_ns,
784 const char *new_name)
739{ 785{
740 const char *dup_name = NULL; 786 const char *dup_name = NULL;
741 int error; 787 int error;
@@ -743,12 +789,12 @@ int sysfs_rename(struct sysfs_dirent *sd,
743 mutex_lock(&sysfs_mutex); 789 mutex_lock(&sysfs_mutex);
744 790
745 error = 0; 791 error = 0;
746 if ((sd->s_parent == new_parent_sd) && 792 if ((sd->s_parent == new_parent_sd) && (sd->s_ns == new_ns) &&
747 (strcmp(sd->s_name, new_name) == 0)) 793 (strcmp(sd->s_name, new_name) == 0))
748 goto out; /* nothing to rename */ 794 goto out; /* nothing to rename */
749 795
750 error = -EEXIST; 796 error = -EEXIST;
751 if (sysfs_find_dirent(new_parent_sd, new_name)) 797 if (sysfs_find_dirent(new_parent_sd, new_ns, new_name))
752 goto out; 798 goto out;
753 799
754 /* rename sysfs_dirent */ 800 /* rename sysfs_dirent */
@@ -770,6 +816,7 @@ int sysfs_rename(struct sysfs_dirent *sd,
770 sd->s_parent = new_parent_sd; 816 sd->s_parent = new_parent_sd;
771 sysfs_link_sibling(sd); 817 sysfs_link_sibling(sd);
772 } 818 }
819 sd->s_ns = new_ns;
773 820
774 error = 0; 821 error = 0;
775 out: 822 out:
@@ -780,19 +827,28 @@ int sysfs_rename(struct sysfs_dirent *sd,
780 827
781int sysfs_rename_dir(struct kobject *kobj, const char *new_name) 828int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
782{ 829{
783 return sysfs_rename(kobj->sd, kobj->sd->s_parent, new_name); 830 struct sysfs_dirent *parent_sd = kobj->sd->s_parent;
831 const void *new_ns = NULL;
832
833 if (sysfs_ns_type(parent_sd))
834 new_ns = kobj->ktype->namespace(kobj);
835
836 return sysfs_rename(kobj->sd, parent_sd, new_ns, new_name);
784} 837}
785 838
786int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) 839int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
787{ 840{
788 struct sysfs_dirent *sd = kobj->sd; 841 struct sysfs_dirent *sd = kobj->sd;
789 struct sysfs_dirent *new_parent_sd; 842 struct sysfs_dirent *new_parent_sd;
843 const void *new_ns = NULL;
790 844
791 BUG_ON(!sd->s_parent); 845 BUG_ON(!sd->s_parent);
846 if (sysfs_ns_type(sd->s_parent))
847 new_ns = kobj->ktype->namespace(kobj);
792 new_parent_sd = new_parent_kobj && new_parent_kobj->sd ? 848 new_parent_sd = new_parent_kobj && new_parent_kobj->sd ?
793 new_parent_kobj->sd : &sysfs_root; 849 new_parent_kobj->sd : &sysfs_root;
794 850
795 return sysfs_rename(sd, new_parent_sd, sd->s_name); 851 return sysfs_rename(sd, new_parent_sd, new_ns, sd->s_name);
796} 852}
797 853
798/* Relationship between s_mode and the DT_xxx types */ 854/* Relationship between s_mode and the DT_xxx types */
@@ -807,32 +863,35 @@ static int sysfs_dir_release(struct inode *inode, struct file *filp)
807 return 0; 863 return 0;
808} 864}
809 865
810static struct sysfs_dirent *sysfs_dir_pos(struct sysfs_dirent *parent_sd, 866static struct sysfs_dirent *sysfs_dir_pos(const void *ns,
811 ino_t ino, struct sysfs_dirent *pos) 867 struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos)
812{ 868{
813 if (pos) { 869 if (pos) {
814 int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && 870 int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) &&
815 pos->s_parent == parent_sd && 871 pos->s_parent == parent_sd &&
816 ino == pos->s_ino; 872 ino == pos->s_ino;
817 sysfs_put(pos); 873 sysfs_put(pos);
818 if (valid) 874 if (!valid)
819 return pos; 875 pos = NULL;
820 } 876 }
821 pos = NULL; 877 if (!pos && (ino > 1) && (ino < INT_MAX)) {
822 if ((ino > 1) && (ino < INT_MAX)) {
823 pos = parent_sd->s_dir.children; 878 pos = parent_sd->s_dir.children;
824 while (pos && (ino > pos->s_ino)) 879 while (pos && (ino > pos->s_ino))
825 pos = pos->s_sibling; 880 pos = pos->s_sibling;
826 } 881 }
882 while (pos && pos->s_ns != ns)
883 pos = pos->s_sibling;
827 return pos; 884 return pos;
828} 885}
829 886
830static struct sysfs_dirent *sysfs_dir_next_pos(struct sysfs_dirent *parent_sd, 887static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns,
831 ino_t ino, struct sysfs_dirent *pos) 888 struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos)
832{ 889{
833 pos = sysfs_dir_pos(parent_sd, ino, pos); 890 pos = sysfs_dir_pos(ns, parent_sd, ino, pos);
834 if (pos) 891 if (pos)
835 pos = pos->s_sibling; 892 pos = pos->s_sibling;
893 while (pos && pos->s_ns != ns)
894 pos = pos->s_sibling;
836 return pos; 895 return pos;
837} 896}
838 897
@@ -841,8 +900,13 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
841 struct dentry *dentry = filp->f_path.dentry; 900 struct dentry *dentry = filp->f_path.dentry;
842 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 901 struct sysfs_dirent * parent_sd = dentry->d_fsdata;
843 struct sysfs_dirent *pos = filp->private_data; 902 struct sysfs_dirent *pos = filp->private_data;
903 enum kobj_ns_type type;
904 const void *ns;
844 ino_t ino; 905 ino_t ino;
845 906
907 type = sysfs_ns_type(parent_sd);
908 ns = sysfs_info(dentry->d_sb)->ns[type];
909
846 if (filp->f_pos == 0) { 910 if (filp->f_pos == 0) {
847 ino = parent_sd->s_ino; 911 ino = parent_sd->s_ino;
848 if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) 912 if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0)
@@ -857,9 +921,9 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
857 filp->f_pos++; 921 filp->f_pos++;
858 } 922 }
859 mutex_lock(&sysfs_mutex); 923 mutex_lock(&sysfs_mutex);
860 for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos); 924 for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
861 pos; 925 pos;
862 pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) { 926 pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) {
863 const char * name; 927 const char * name;
864 unsigned int type; 928 unsigned int type;
865 int len, ret; 929 int len, ret;