diff options
Diffstat (limited to 'fs/sysfs')
| -rw-r--r-- | fs/sysfs/bin.c | 26 | ||||
| -rw-r--r-- | fs/sysfs/dir.c | 114 | ||||
| -rw-r--r-- | fs/sysfs/file.c | 17 | ||||
| -rw-r--r-- | fs/sysfs/group.c | 6 | ||||
| -rw-r--r-- | fs/sysfs/inode.c | 6 | ||||
| -rw-r--r-- | fs/sysfs/mount.c | 95 | ||||
| -rw-r--r-- | fs/sysfs/symlink.c | 35 | ||||
| -rw-r--r-- | fs/sysfs/sysfs.h | 34 |
8 files changed, 273 insertions, 60 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index e9d293593e52..4e321f7353fa 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
| @@ -46,9 +46,9 @@ struct bin_buffer { | |||
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | static int | 48 | static int |
| 49 | fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) | 49 | fill_read(struct file *file, char *buffer, loff_t off, size_t count) |
| 50 | { | 50 | { |
| 51 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 51 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 52 | struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; | 52 | struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; |
| 53 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 53 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
| 54 | int rc; | 54 | int rc; |
| @@ -59,7 +59,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) | |||
| 59 | 59 | ||
| 60 | rc = -EIO; | 60 | rc = -EIO; |
| 61 | if (attr->read) | 61 | if (attr->read) |
| 62 | rc = attr->read(kobj, attr, buffer, off, count); | 62 | rc = attr->read(file, kobj, attr, buffer, off, count); |
| 63 | 63 | ||
| 64 | sysfs_put_active(attr_sd); | 64 | sysfs_put_active(attr_sd); |
| 65 | 65 | ||
| @@ -70,8 +70,7 @@ static ssize_t | |||
| 70 | read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) | 70 | read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) |
| 71 | { | 71 | { |
| 72 | struct bin_buffer *bb = file->private_data; | 72 | struct bin_buffer *bb = file->private_data; |
| 73 | struct dentry *dentry = file->f_path.dentry; | 73 | int size = file->f_path.dentry->d_inode->i_size; |
| 74 | int size = dentry->d_inode->i_size; | ||
| 75 | loff_t offs = *off; | 74 | loff_t offs = *off; |
| 76 | int count = min_t(size_t, bytes, PAGE_SIZE); | 75 | int count = min_t(size_t, bytes, PAGE_SIZE); |
| 77 | char *temp; | 76 | char *temp; |
| @@ -92,7 +91,7 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) | |||
| 92 | 91 | ||
| 93 | mutex_lock(&bb->mutex); | 92 | mutex_lock(&bb->mutex); |
| 94 | 93 | ||
| 95 | count = fill_read(dentry, bb->buffer, offs, count); | 94 | count = fill_read(file, bb->buffer, offs, count); |
| 96 | if (count < 0) { | 95 | if (count < 0) { |
| 97 | mutex_unlock(&bb->mutex); | 96 | mutex_unlock(&bb->mutex); |
| 98 | goto out_free; | 97 | goto out_free; |
| @@ -117,9 +116,9 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) | |||
| 117 | } | 116 | } |
| 118 | 117 | ||
| 119 | static int | 118 | static int |
| 120 | flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) | 119 | flush_write(struct file *file, char *buffer, loff_t offset, size_t count) |
| 121 | { | 120 | { |
| 122 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 121 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 123 | struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; | 122 | struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; |
| 124 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 123 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
| 125 | int rc; | 124 | int rc; |
| @@ -130,7 +129,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) | |||
| 130 | 129 | ||
| 131 | rc = -EIO; | 130 | rc = -EIO; |
| 132 | if (attr->write) | 131 | if (attr->write) |
| 133 | rc = attr->write(kobj, attr, buffer, offset, count); | 132 | rc = attr->write(file, kobj, attr, buffer, offset, count); |
| 134 | 133 | ||
| 135 | sysfs_put_active(attr_sd); | 134 | sysfs_put_active(attr_sd); |
| 136 | 135 | ||
| @@ -141,8 +140,7 @@ static ssize_t write(struct file *file, const char __user *userbuf, | |||
| 141 | size_t bytes, loff_t *off) | 140 | size_t bytes, loff_t *off) |
| 142 | { | 141 | { |
| 143 | struct bin_buffer *bb = file->private_data; | 142 | struct bin_buffer *bb = file->private_data; |
| 144 | struct dentry *dentry = file->f_path.dentry; | 143 | int size = file->f_path.dentry->d_inode->i_size; |
| 145 | int size = dentry->d_inode->i_size; | ||
| 146 | loff_t offs = *off; | 144 | loff_t offs = *off; |
| 147 | int count = min_t(size_t, bytes, PAGE_SIZE); | 145 | int count = min_t(size_t, bytes, PAGE_SIZE); |
| 148 | char *temp; | 146 | char *temp; |
| @@ -165,7 +163,7 @@ static ssize_t write(struct file *file, const char __user *userbuf, | |||
| 165 | 163 | ||
| 166 | memcpy(bb->buffer, temp, count); | 164 | memcpy(bb->buffer, temp, count); |
| 167 | 165 | ||
| 168 | count = flush_write(dentry, bb->buffer, offs, count); | 166 | count = flush_write(file, bb->buffer, offs, count); |
| 169 | mutex_unlock(&bb->mutex); | 167 | mutex_unlock(&bb->mutex); |
| 170 | 168 | ||
| 171 | if (count > 0) | 169 | if (count > 0) |
| @@ -363,7 +361,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma) | |||
| 363 | if (!attr->mmap) | 361 | if (!attr->mmap) |
| 364 | goto out_put; | 362 | goto out_put; |
| 365 | 363 | ||
| 366 | rc = attr->mmap(kobj, attr, vma); | 364 | rc = attr->mmap(file, kobj, attr, vma); |
| 367 | if (rc) | 365 | if (rc) |
| 368 | goto out_put; | 366 | goto out_put; |
| 369 | 367 | ||
| @@ -501,7 +499,7 @@ int sysfs_create_bin_file(struct kobject *kobj, | |||
| 501 | void sysfs_remove_bin_file(struct kobject *kobj, | 499 | void sysfs_remove_bin_file(struct kobject *kobj, |
| 502 | const struct bin_attribute *attr) | 500 | const struct bin_attribute *attr) |
| 503 | { | 501 | { |
| 504 | sysfs_hash_and_remove(kobj->sd, attr->attr.name); | 502 | sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name); |
| 505 | } | 503 | } |
| 506 | 504 | ||
| 507 | EXPORT_SYMBOL_GPL(sysfs_create_bin_file); | 505 | EXPORT_SYMBOL_GPL(sysfs_create_bin_file); |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 590717861c7a..7e54bac8c4b0 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -380,7 +380,7 @@ 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 | sd->s_parent = sysfs_get(acxt->parent_sd); | 386 | sd->s_parent = sysfs_get(acxt->parent_sd); |
| @@ -533,13 +533,17 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) | |||
| 533 | * Pointer to sysfs_dirent if found, NULL if not. | 533 | * Pointer to sysfs_dirent if found, NULL if not. |
| 534 | */ | 534 | */ |
| 535 | struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | 535 | struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, |
| 536 | const void *ns, | ||
| 536 | const unsigned char *name) | 537 | const unsigned char *name) |
| 537 | { | 538 | { |
| 538 | struct sysfs_dirent *sd; | 539 | struct sysfs_dirent *sd; |
| 539 | 540 | ||
| 540 | for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) | 541 | for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { |
| 542 | if (ns && sd->s_ns && (sd->s_ns != ns)) | ||
| 543 | continue; | ||
| 541 | if (!strcmp(sd->s_name, name)) | 544 | if (!strcmp(sd->s_name, name)) |
| 542 | return sd; | 545 | return sd; |
| 546 | } | ||
| 543 | return NULL; | 547 | return NULL; |
| 544 | } | 548 | } |
| 545 | 549 | ||
| @@ -558,12 +562,13 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | |||
| 558 | * Pointer to sysfs_dirent if found, NULL if not. | 562 | * Pointer to sysfs_dirent if found, NULL if not. |
| 559 | */ | 563 | */ |
| 560 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | 564 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, |
| 565 | const void *ns, | ||
| 561 | const unsigned char *name) | 566 | const unsigned char *name) |
| 562 | { | 567 | { |
| 563 | struct sysfs_dirent *sd; | 568 | struct sysfs_dirent *sd; |
| 564 | 569 | ||
| 565 | mutex_lock(&sysfs_mutex); | 570 | mutex_lock(&sysfs_mutex); |
| 566 | sd = sysfs_find_dirent(parent_sd, name); | 571 | sd = sysfs_find_dirent(parent_sd, ns, name); |
| 567 | sysfs_get(sd); | 572 | sysfs_get(sd); |
| 568 | mutex_unlock(&sysfs_mutex); | 573 | mutex_unlock(&sysfs_mutex); |
| 569 | 574 | ||
| @@ -572,7 +577,8 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | |||
| 572 | EXPORT_SYMBOL_GPL(sysfs_get_dirent); | 577 | EXPORT_SYMBOL_GPL(sysfs_get_dirent); |
| 573 | 578 | ||
| 574 | static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, | 579 | static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, |
| 575 | const char *name, struct sysfs_dirent **p_sd) | 580 | enum kobj_ns_type type, const void *ns, const char *name, |
| 581 | struct sysfs_dirent **p_sd) | ||
| 576 | { | 582 | { |
| 577 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; | 583 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; |
| 578 | struct sysfs_addrm_cxt acxt; | 584 | struct sysfs_addrm_cxt acxt; |
| @@ -583,6 +589,9 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, | |||
| 583 | sd = sysfs_new_dirent(name, mode, SYSFS_DIR); | 589 | sd = sysfs_new_dirent(name, mode, SYSFS_DIR); |
| 584 | if (!sd) | 590 | if (!sd) |
| 585 | return -ENOMEM; | 591 | return -ENOMEM; |
| 592 | |||
| 593 | sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT); | ||
| 594 | sd->s_ns = ns; | ||
| 586 | sd->s_dir.kobj = kobj; | 595 | sd->s_dir.kobj = kobj; |
| 587 | 596 | ||
| 588 | /* link in */ | 597 | /* link in */ |
| @@ -601,7 +610,33 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, | |||
| 601 | int sysfs_create_subdir(struct kobject *kobj, const char *name, | 610 | int sysfs_create_subdir(struct kobject *kobj, const char *name, |
| 602 | struct sysfs_dirent **p_sd) | 611 | struct sysfs_dirent **p_sd) |
| 603 | { | 612 | { |
| 604 | return create_dir(kobj, kobj->sd, name, p_sd); | 613 | return create_dir(kobj, kobj->sd, |
| 614 | KOBJ_NS_TYPE_NONE, NULL, name, p_sd); | ||
| 615 | } | ||
| 616 | |||
| 617 | /** | ||
| 618 | * sysfs_read_ns_type: return associated ns_type | ||
| 619 | * @kobj: the kobject being queried | ||
| 620 | * | ||
| 621 | * Each kobject can be tagged with exactly one namespace type | ||
| 622 | * (i.e. network or user). Return the ns_type associated with | ||
| 623 | * this object if any | ||
| 624 | */ | ||
| 625 | static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj) | ||
| 626 | { | ||
| 627 | const struct kobj_ns_type_operations *ops; | ||
| 628 | enum kobj_ns_type type; | ||
| 629 | |||
| 630 | ops = kobj_child_ns_ops(kobj); | ||
| 631 | if (!ops) | ||
| 632 | return KOBJ_NS_TYPE_NONE; | ||
| 633 | |||
| 634 | type = ops->type; | ||
| 635 | BUG_ON(type <= KOBJ_NS_TYPE_NONE); | ||
| 636 | BUG_ON(type >= KOBJ_NS_TYPES); | ||
| 637 | BUG_ON(!kobj_ns_type_registered(type)); | ||
| 638 | |||
| 639 | return type; | ||
| 605 | } | 640 | } |
| 606 | 641 | ||
| 607 | /** | 642 | /** |
| @@ -610,7 +645,9 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name, | |||
| 610 | */ | 645 | */ |
| 611 | int sysfs_create_dir(struct kobject * kobj) | 646 | int sysfs_create_dir(struct kobject * kobj) |
| 612 | { | 647 | { |
| 648 | enum kobj_ns_type type; | ||
| 613 | struct sysfs_dirent *parent_sd, *sd; | 649 | struct sysfs_dirent *parent_sd, *sd; |
| 650 | const void *ns = NULL; | ||
| 614 | int error = 0; | 651 | int error = 0; |
| 615 | 652 | ||
| 616 | BUG_ON(!kobj); | 653 | BUG_ON(!kobj); |
| @@ -620,7 +657,11 @@ int sysfs_create_dir(struct kobject * kobj) | |||
| 620 | else | 657 | else |
| 621 | parent_sd = &sysfs_root; | 658 | parent_sd = &sysfs_root; |
| 622 | 659 | ||
| 623 | error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); | 660 | if (sysfs_ns_type(parent_sd)) |
| 661 | ns = kobj->ktype->namespace(kobj); | ||
| 662 | type = sysfs_read_ns_type(kobj); | ||
| 663 | |||
| 664 | error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd); | ||
| 624 | if (!error) | 665 | if (!error) |
| 625 | kobj->sd = sd; | 666 | kobj->sd = sd; |
| 626 | return error; | 667 | return error; |
| @@ -630,13 +671,19 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 630 | struct nameidata *nd) | 671 | struct nameidata *nd) |
| 631 | { | 672 | { |
| 632 | struct dentry *ret = NULL; | 673 | struct dentry *ret = NULL; |
| 633 | struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; | 674 | struct dentry *parent = dentry->d_parent; |
| 675 | struct sysfs_dirent *parent_sd = parent->d_fsdata; | ||
| 634 | struct sysfs_dirent *sd; | 676 | struct sysfs_dirent *sd; |
| 635 | struct inode *inode; | 677 | struct inode *inode; |
| 678 | enum kobj_ns_type type; | ||
| 679 | const void *ns; | ||
| 636 | 680 | ||
| 637 | mutex_lock(&sysfs_mutex); | 681 | mutex_lock(&sysfs_mutex); |
| 638 | 682 | ||
| 639 | sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); | 683 | type = sysfs_ns_type(parent_sd); |
| 684 | ns = sysfs_info(dir->i_sb)->ns[type]; | ||
| 685 | |||
| 686 | sd = sysfs_find_dirent(parent_sd, ns, dentry->d_name.name); | ||
| 640 | 687 | ||
| 641 | /* no such entry */ | 688 | /* no such entry */ |
| 642 | if (!sd) { | 689 | if (!sd) { |
| @@ -735,7 +782,8 @@ void sysfs_remove_dir(struct kobject * kobj) | |||
| 735 | } | 782 | } |
| 736 | 783 | ||
| 737 | int sysfs_rename(struct sysfs_dirent *sd, | 784 | int sysfs_rename(struct sysfs_dirent *sd, |
| 738 | struct sysfs_dirent *new_parent_sd, const char *new_name) | 785 | struct sysfs_dirent *new_parent_sd, const void *new_ns, |
| 786 | const char *new_name) | ||
| 739 | { | 787 | { |
| 740 | const char *dup_name = NULL; | 788 | const char *dup_name = NULL; |
| 741 | int error; | 789 | int error; |
| @@ -743,12 +791,12 @@ int sysfs_rename(struct sysfs_dirent *sd, | |||
| 743 | mutex_lock(&sysfs_mutex); | 791 | mutex_lock(&sysfs_mutex); |
| 744 | 792 | ||
| 745 | error = 0; | 793 | error = 0; |
| 746 | if ((sd->s_parent == new_parent_sd) && | 794 | if ((sd->s_parent == new_parent_sd) && (sd->s_ns == new_ns) && |
| 747 | (strcmp(sd->s_name, new_name) == 0)) | 795 | (strcmp(sd->s_name, new_name) == 0)) |
| 748 | goto out; /* nothing to rename */ | 796 | goto out; /* nothing to rename */ |
| 749 | 797 | ||
| 750 | error = -EEXIST; | 798 | error = -EEXIST; |
| 751 | if (sysfs_find_dirent(new_parent_sd, new_name)) | 799 | if (sysfs_find_dirent(new_parent_sd, new_ns, new_name)) |
| 752 | goto out; | 800 | goto out; |
| 753 | 801 | ||
| 754 | /* rename sysfs_dirent */ | 802 | /* rename sysfs_dirent */ |
| @@ -770,6 +818,7 @@ int sysfs_rename(struct sysfs_dirent *sd, | |||
| 770 | sd->s_parent = new_parent_sd; | 818 | sd->s_parent = new_parent_sd; |
| 771 | sysfs_link_sibling(sd); | 819 | sysfs_link_sibling(sd); |
| 772 | } | 820 | } |
| 821 | sd->s_ns = new_ns; | ||
| 773 | 822 | ||
| 774 | error = 0; | 823 | error = 0; |
| 775 | out: | 824 | out: |
| @@ -780,19 +829,28 @@ int sysfs_rename(struct sysfs_dirent *sd, | |||
| 780 | 829 | ||
| 781 | int sysfs_rename_dir(struct kobject *kobj, const char *new_name) | 830 | int sysfs_rename_dir(struct kobject *kobj, const char *new_name) |
| 782 | { | 831 | { |
| 783 | return sysfs_rename(kobj->sd, kobj->sd->s_parent, new_name); | 832 | struct sysfs_dirent *parent_sd = kobj->sd->s_parent; |
| 833 | const void *new_ns = NULL; | ||
| 834 | |||
| 835 | if (sysfs_ns_type(parent_sd)) | ||
| 836 | new_ns = kobj->ktype->namespace(kobj); | ||
| 837 | |||
| 838 | return sysfs_rename(kobj->sd, parent_sd, new_ns, new_name); | ||
| 784 | } | 839 | } |
| 785 | 840 | ||
| 786 | int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) | 841 | int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) |
| 787 | { | 842 | { |
| 788 | struct sysfs_dirent *sd = kobj->sd; | 843 | struct sysfs_dirent *sd = kobj->sd; |
| 789 | struct sysfs_dirent *new_parent_sd; | 844 | struct sysfs_dirent *new_parent_sd; |
| 845 | const void *new_ns = NULL; | ||
| 790 | 846 | ||
| 791 | BUG_ON(!sd->s_parent); | 847 | BUG_ON(!sd->s_parent); |
| 848 | if (sysfs_ns_type(sd->s_parent)) | ||
| 849 | new_ns = kobj->ktype->namespace(kobj); | ||
| 792 | new_parent_sd = new_parent_kobj && new_parent_kobj->sd ? | 850 | new_parent_sd = new_parent_kobj && new_parent_kobj->sd ? |
| 793 | new_parent_kobj->sd : &sysfs_root; | 851 | new_parent_kobj->sd : &sysfs_root; |
| 794 | 852 | ||
| 795 | return sysfs_rename(sd, new_parent_sd, sd->s_name); | 853 | return sysfs_rename(sd, new_parent_sd, new_ns, sd->s_name); |
| 796 | } | 854 | } |
| 797 | 855 | ||
| 798 | /* Relationship between s_mode and the DT_xxx types */ | 856 | /* Relationship between s_mode and the DT_xxx types */ |
| @@ -807,32 +865,35 @@ static int sysfs_dir_release(struct inode *inode, struct file *filp) | |||
| 807 | return 0; | 865 | return 0; |
| 808 | } | 866 | } |
| 809 | 867 | ||
| 810 | static struct sysfs_dirent *sysfs_dir_pos(struct sysfs_dirent *parent_sd, | 868 | static struct sysfs_dirent *sysfs_dir_pos(const void *ns, |
| 811 | ino_t ino, struct sysfs_dirent *pos) | 869 | struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) |
| 812 | { | 870 | { |
| 813 | if (pos) { | 871 | if (pos) { |
| 814 | int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && | 872 | int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && |
| 815 | pos->s_parent == parent_sd && | 873 | pos->s_parent == parent_sd && |
| 816 | ino == pos->s_ino; | 874 | ino == pos->s_ino; |
| 817 | sysfs_put(pos); | 875 | sysfs_put(pos); |
| 818 | if (valid) | 876 | if (!valid) |
| 819 | return pos; | 877 | pos = NULL; |
| 820 | } | 878 | } |
| 821 | pos = NULL; | 879 | if (!pos && (ino > 1) && (ino < INT_MAX)) { |
| 822 | if ((ino > 1) && (ino < INT_MAX)) { | ||
| 823 | pos = parent_sd->s_dir.children; | 880 | pos = parent_sd->s_dir.children; |
| 824 | while (pos && (ino > pos->s_ino)) | 881 | while (pos && (ino > pos->s_ino)) |
| 825 | pos = pos->s_sibling; | 882 | pos = pos->s_sibling; |
| 826 | } | 883 | } |
| 884 | while (pos && pos->s_ns && pos->s_ns != ns) | ||
| 885 | pos = pos->s_sibling; | ||
| 827 | return pos; | 886 | return pos; |
| 828 | } | 887 | } |
| 829 | 888 | ||
| 830 | static struct sysfs_dirent *sysfs_dir_next_pos(struct sysfs_dirent *parent_sd, | 889 | static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, |
| 831 | ino_t ino, struct sysfs_dirent *pos) | 890 | struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) |
| 832 | { | 891 | { |
| 833 | pos = sysfs_dir_pos(parent_sd, ino, pos); | 892 | pos = sysfs_dir_pos(ns, parent_sd, ino, pos); |
| 834 | if (pos) | 893 | if (pos) |
| 835 | pos = pos->s_sibling; | 894 | pos = pos->s_sibling; |
| 895 | while (pos && pos->s_ns && pos->s_ns != ns) | ||
| 896 | pos = pos->s_sibling; | ||
| 836 | return pos; | 897 | return pos; |
| 837 | } | 898 | } |
| 838 | 899 | ||
| @@ -841,8 +902,13 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
| 841 | struct dentry *dentry = filp->f_path.dentry; | 902 | struct dentry *dentry = filp->f_path.dentry; |
| 842 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 903 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
| 843 | struct sysfs_dirent *pos = filp->private_data; | 904 | struct sysfs_dirent *pos = filp->private_data; |
| 905 | enum kobj_ns_type type; | ||
| 906 | const void *ns; | ||
| 844 | ino_t ino; | 907 | ino_t ino; |
| 845 | 908 | ||
| 909 | type = sysfs_ns_type(parent_sd); | ||
| 910 | ns = sysfs_info(dentry->d_sb)->ns[type]; | ||
| 911 | |||
| 846 | if (filp->f_pos == 0) { | 912 | if (filp->f_pos == 0) { |
| 847 | ino = parent_sd->s_ino; | 913 | ino = parent_sd->s_ino; |
| 848 | if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) | 914 | if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) |
| @@ -857,9 +923,9 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
| 857 | filp->f_pos++; | 923 | filp->f_pos++; |
| 858 | } | 924 | } |
| 859 | mutex_lock(&sysfs_mutex); | 925 | mutex_lock(&sysfs_mutex); |
| 860 | for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos); | 926 | for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos); |
| 861 | pos; | 927 | pos; |
| 862 | pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) { | 928 | pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) { |
| 863 | const char * name; | 929 | const char * name; |
| 864 | unsigned int type; | 930 | unsigned int type; |
| 865 | int len, ret; | 931 | int len, ret; |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index e222b2582746..1beaa739d0a6 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
| @@ -478,9 +478,12 @@ void sysfs_notify(struct kobject *k, const char *dir, const char *attr) | |||
| 478 | mutex_lock(&sysfs_mutex); | 478 | mutex_lock(&sysfs_mutex); |
| 479 | 479 | ||
| 480 | if (sd && dir) | 480 | if (sd && dir) |
| 481 | sd = sysfs_find_dirent(sd, dir); | 481 | /* Only directories are tagged, so no need to pass |
| 482 | * a tag explicitly. | ||
| 483 | */ | ||
| 484 | sd = sysfs_find_dirent(sd, NULL, dir); | ||
| 482 | if (sd && attr) | 485 | if (sd && attr) |
| 483 | sd = sysfs_find_dirent(sd, attr); | 486 | sd = sysfs_find_dirent(sd, NULL, attr); |
| 484 | if (sd) | 487 | if (sd) |
| 485 | sysfs_notify_dirent(sd); | 488 | sysfs_notify_dirent(sd); |
| 486 | 489 | ||
| @@ -569,7 +572,7 @@ int sysfs_add_file_to_group(struct kobject *kobj, | |||
| 569 | int error; | 572 | int error; |
| 570 | 573 | ||
| 571 | if (group) | 574 | if (group) |
| 572 | dir_sd = sysfs_get_dirent(kobj->sd, group); | 575 | dir_sd = sysfs_get_dirent(kobj->sd, NULL, group); |
| 573 | else | 576 | else |
| 574 | dir_sd = sysfs_get(kobj->sd); | 577 | dir_sd = sysfs_get(kobj->sd); |
| 575 | 578 | ||
| @@ -599,7 +602,7 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | |||
| 599 | mutex_lock(&sysfs_mutex); | 602 | mutex_lock(&sysfs_mutex); |
| 600 | 603 | ||
| 601 | rc = -ENOENT; | 604 | rc = -ENOENT; |
| 602 | sd = sysfs_find_dirent(kobj->sd, attr->name); | 605 | sd = sysfs_find_dirent(kobj->sd, NULL, attr->name); |
| 603 | if (!sd) | 606 | if (!sd) |
| 604 | goto out; | 607 | goto out; |
| 605 | 608 | ||
| @@ -624,7 +627,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); | |||
| 624 | 627 | ||
| 625 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) | 628 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) |
| 626 | { | 629 | { |
| 627 | sysfs_hash_and_remove(kobj->sd, attr->name); | 630 | sysfs_hash_and_remove(kobj->sd, NULL, attr->name); |
| 628 | } | 631 | } |
| 629 | 632 | ||
| 630 | void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) | 633 | void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) |
| @@ -646,11 +649,11 @@ void sysfs_remove_file_from_group(struct kobject *kobj, | |||
| 646 | struct sysfs_dirent *dir_sd; | 649 | struct sysfs_dirent *dir_sd; |
| 647 | 650 | ||
| 648 | if (group) | 651 | if (group) |
| 649 | dir_sd = sysfs_get_dirent(kobj->sd, group); | 652 | dir_sd = sysfs_get_dirent(kobj->sd, NULL, group); |
| 650 | else | 653 | else |
| 651 | dir_sd = sysfs_get(kobj->sd); | 654 | dir_sd = sysfs_get(kobj->sd); |
| 652 | if (dir_sd) { | 655 | if (dir_sd) { |
| 653 | sysfs_hash_and_remove(dir_sd, attr->name); | 656 | sysfs_hash_and_remove(dir_sd, NULL, attr->name); |
| 654 | sysfs_put(dir_sd); | 657 | sysfs_put(dir_sd); |
| 655 | } | 658 | } |
| 656 | } | 659 | } |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index fe611949a7f7..23c1e598792a 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
| @@ -23,7 +23,7 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, | |||
| 23 | int i; | 23 | int i; |
| 24 | 24 | ||
| 25 | for (i = 0, attr = grp->attrs; *attr; i++, attr++) | 25 | for (i = 0, attr = grp->attrs; *attr; i++, attr++) |
| 26 | sysfs_hash_and_remove(dir_sd, (*attr)->name); | 26 | sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, | 29 | static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, |
| @@ -39,7 +39,7 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, | |||
| 39 | * visibility. Do this by first removing then | 39 | * visibility. Do this by first removing then |
| 40 | * re-adding (if required) the file */ | 40 | * re-adding (if required) the file */ |
| 41 | if (update) | 41 | if (update) |
| 42 | sysfs_hash_and_remove(dir_sd, (*attr)->name); | 42 | sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); |
| 43 | if (grp->is_visible) { | 43 | if (grp->is_visible) { |
| 44 | mode = grp->is_visible(kobj, *attr, i); | 44 | mode = grp->is_visible(kobj, *attr, i); |
| 45 | if (!mode) | 45 | if (!mode) |
| @@ -132,7 +132,7 @@ void sysfs_remove_group(struct kobject * kobj, | |||
| 132 | struct sysfs_dirent *sd; | 132 | struct sysfs_dirent *sd; |
| 133 | 133 | ||
| 134 | if (grp->name) { | 134 | if (grp->name) { |
| 135 | sd = sysfs_get_dirent(dir_sd, grp->name); | 135 | sd = sysfs_get_dirent(dir_sd, NULL, grp->name); |
| 136 | if (!sd) { | 136 | if (!sd) { |
| 137 | WARN(!sd, KERN_WARNING "sysfs group %p not found for " | 137 | WARN(!sd, KERN_WARNING "sysfs group %p not found for " |
| 138 | "kobject '%s'\n", grp, kobject_name(kobj)); | 138 | "kobject '%s'\n", grp, kobject_name(kobj)); |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index a4a0a9419711..bbd77e95cf7f 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -324,7 +324,7 @@ void sysfs_delete_inode(struct inode *inode) | |||
| 324 | sysfs_put(sd); | 324 | sysfs_put(sd); |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) | 327 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name) |
| 328 | { | 328 | { |
| 329 | struct sysfs_addrm_cxt acxt; | 329 | struct sysfs_addrm_cxt acxt; |
| 330 | struct sysfs_dirent *sd; | 330 | struct sysfs_dirent *sd; |
| @@ -334,7 +334,9 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) | |||
| 334 | 334 | ||
| 335 | sysfs_addrm_start(&acxt, dir_sd); | 335 | sysfs_addrm_start(&acxt, dir_sd); |
| 336 | 336 | ||
| 337 | sd = sysfs_find_dirent(dir_sd, name); | 337 | sd = sysfs_find_dirent(dir_sd, ns, name); |
| 338 | if (sd && (sd->s_ns != ns)) | ||
| 339 | sd = NULL; | ||
| 338 | if (sd) | 340 | if (sd) |
| 339 | sysfs_remove_one(&acxt, sd); | 341 | sysfs_remove_one(&acxt, sd); |
| 340 | 342 | ||
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 776137828dca..281c0c9bc39f 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
| @@ -35,7 +35,7 @@ static const struct super_operations sysfs_ops = { | |||
| 35 | struct sysfs_dirent sysfs_root = { | 35 | struct sysfs_dirent sysfs_root = { |
| 36 | .s_name = "", | 36 | .s_name = "", |
| 37 | .s_count = ATOMIC_INIT(1), | 37 | .s_count = ATOMIC_INIT(1), |
| 38 | .s_flags = SYSFS_DIR, | 38 | .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT), |
| 39 | .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, | 39 | .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, |
| 40 | .s_ino = 1, | 40 | .s_ino = 1, |
| 41 | }; | 41 | }; |
| @@ -72,18 +72,107 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 72 | return 0; | 72 | return 0; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | static int sysfs_test_super(struct super_block *sb, void *data) | ||
| 76 | { | ||
| 77 | struct sysfs_super_info *sb_info = sysfs_info(sb); | ||
| 78 | struct sysfs_super_info *info = data; | ||
| 79 | enum kobj_ns_type type; | ||
| 80 | int found = 1; | ||
| 81 | |||
| 82 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) { | ||
| 83 | if (sb_info->ns[type] != info->ns[type]) | ||
| 84 | found = 0; | ||
| 85 | } | ||
| 86 | return found; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int sysfs_set_super(struct super_block *sb, void *data) | ||
| 90 | { | ||
| 91 | int error; | ||
| 92 | error = set_anon_super(sb, data); | ||
| 93 | if (!error) | ||
| 94 | sb->s_fs_info = data; | ||
| 95 | return error; | ||
| 96 | } | ||
| 97 | |||
| 75 | static int sysfs_get_sb(struct file_system_type *fs_type, | 98 | static int sysfs_get_sb(struct file_system_type *fs_type, |
| 76 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 99 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
| 77 | { | 100 | { |
| 78 | return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); | 101 | struct sysfs_super_info *info; |
| 102 | enum kobj_ns_type type; | ||
| 103 | struct super_block *sb; | ||
| 104 | int error; | ||
| 105 | |||
| 106 | error = -ENOMEM; | ||
| 107 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
| 108 | if (!info) | ||
| 109 | goto out; | ||
| 110 | |||
| 111 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) | ||
| 112 | info->ns[type] = kobj_ns_current(type); | ||
| 113 | |||
| 114 | sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info); | ||
| 115 | if (IS_ERR(sb) || sb->s_fs_info != info) | ||
| 116 | kfree(info); | ||
| 117 | if (IS_ERR(sb)) { | ||
| 118 | error = PTR_ERR(sb); | ||
| 119 | goto out; | ||
| 120 | } | ||
| 121 | if (!sb->s_root) { | ||
| 122 | sb->s_flags = flags; | ||
| 123 | error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | ||
| 124 | if (error) { | ||
| 125 | deactivate_locked_super(sb); | ||
| 126 | goto out; | ||
| 127 | } | ||
| 128 | sb->s_flags |= MS_ACTIVE; | ||
| 129 | } | ||
| 130 | |||
| 131 | simple_set_mnt(mnt, sb); | ||
| 132 | error = 0; | ||
| 133 | out: | ||
| 134 | return error; | ||
| 135 | } | ||
| 136 | |||
| 137 | static void sysfs_kill_sb(struct super_block *sb) | ||
| 138 | { | ||
| 139 | struct sysfs_super_info *info = sysfs_info(sb); | ||
| 140 | |||
| 141 | /* Remove the superblock from fs_supers/s_instances | ||
| 142 | * so we can't find it, before freeing sysfs_super_info. | ||
| 143 | */ | ||
| 144 | kill_anon_super(sb); | ||
| 145 | kfree(info); | ||
| 79 | } | 146 | } |
| 80 | 147 | ||
| 81 | static struct file_system_type sysfs_fs_type = { | 148 | static struct file_system_type sysfs_fs_type = { |
| 82 | .name = "sysfs", | 149 | .name = "sysfs", |
| 83 | .get_sb = sysfs_get_sb, | 150 | .get_sb = sysfs_get_sb, |
| 84 | .kill_sb = kill_anon_super, | 151 | .kill_sb = sysfs_kill_sb, |
| 85 | }; | 152 | }; |
| 86 | 153 | ||
| 154 | void sysfs_exit_ns(enum kobj_ns_type type, const void *ns) | ||
| 155 | { | ||
| 156 | struct super_block *sb; | ||
| 157 | |||
| 158 | mutex_lock(&sysfs_mutex); | ||
| 159 | spin_lock(&sb_lock); | ||
| 160 | list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { | ||
| 161 | struct sysfs_super_info *info = sysfs_info(sb); | ||
| 162 | /* | ||
| 163 | * If we see a superblock on the fs_supers/s_instances | ||
| 164 | * list the unmount has not completed and sb->s_fs_info | ||
| 165 | * points to a valid struct sysfs_super_info. | ||
| 166 | */ | ||
| 167 | /* Ignore superblocks with the wrong ns */ | ||
| 168 | if (info->ns[type] != ns) | ||
| 169 | continue; | ||
| 170 | info->ns[type] = NULL; | ||
| 171 | } | ||
| 172 | spin_unlock(&sb_lock); | ||
| 173 | mutex_unlock(&sysfs_mutex); | ||
| 174 | } | ||
| 175 | |||
| 87 | int __init sysfs_init(void) | 176 | int __init sysfs_init(void) |
| 88 | { | 177 | { |
| 89 | int err = -ENOMEM; | 178 | int err = -ENOMEM; |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 942f239a2132..f71246bebfe4 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
| @@ -58,6 +58,8 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, | |||
| 58 | if (!sd) | 58 | if (!sd) |
| 59 | goto out_put; | 59 | goto out_put; |
| 60 | 60 | ||
| 61 | if (sysfs_ns_type(parent_sd)) | ||
| 62 | sd->s_ns = target->ktype->namespace(target); | ||
| 61 | sd->s_symlink.target_sd = target_sd; | 63 | sd->s_symlink.target_sd = target_sd; |
| 62 | target_sd = NULL; /* reference is now owned by the symlink */ | 64 | target_sd = NULL; /* reference is now owned by the symlink */ |
| 63 | 65 | ||
| @@ -107,6 +109,26 @@ int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, | |||
| 107 | } | 109 | } |
| 108 | 110 | ||
| 109 | /** | 111 | /** |
| 112 | * sysfs_delete_link - remove symlink in object's directory. | ||
| 113 | * @kobj: object we're acting for. | ||
| 114 | * @targ: object we're pointing to. | ||
| 115 | * @name: name of the symlink to remove. | ||
| 116 | * | ||
| 117 | * Unlike sysfs_remove_link sysfs_delete_link has enough information | ||
| 118 | * to successfully delete symlinks in tagged directories. | ||
| 119 | */ | ||
| 120 | void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, | ||
| 121 | const char *name) | ||
| 122 | { | ||
| 123 | const void *ns = NULL; | ||
| 124 | spin_lock(&sysfs_assoc_lock); | ||
| 125 | if (targ->sd) | ||
| 126 | ns = targ->sd->s_ns; | ||
| 127 | spin_unlock(&sysfs_assoc_lock); | ||
| 128 | sysfs_hash_and_remove(kobj->sd, ns, name); | ||
| 129 | } | ||
| 130 | |||
| 131 | /** | ||
| 110 | * sysfs_remove_link - remove symlink in object's directory. | 132 | * sysfs_remove_link - remove symlink in object's directory. |
| 111 | * @kobj: object we're acting for. | 133 | * @kobj: object we're acting for. |
| 112 | * @name: name of the symlink to remove. | 134 | * @name: name of the symlink to remove. |
| @@ -121,7 +143,7 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) | |||
| 121 | else | 143 | else |
| 122 | parent_sd = kobj->sd; | 144 | parent_sd = kobj->sd; |
| 123 | 145 | ||
| 124 | sysfs_hash_and_remove(parent_sd, name); | 146 | sysfs_hash_and_remove(parent_sd, NULL, name); |
| 125 | } | 147 | } |
| 126 | 148 | ||
| 127 | /** | 149 | /** |
| @@ -137,6 +159,7 @@ int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, | |||
| 137 | const char *old, const char *new) | 159 | const char *old, const char *new) |
| 138 | { | 160 | { |
| 139 | struct sysfs_dirent *parent_sd, *sd = NULL; | 161 | struct sysfs_dirent *parent_sd, *sd = NULL; |
| 162 | const void *old_ns = NULL, *new_ns = NULL; | ||
| 140 | int result; | 163 | int result; |
| 141 | 164 | ||
| 142 | if (!kobj) | 165 | if (!kobj) |
| @@ -144,8 +167,11 @@ int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, | |||
| 144 | else | 167 | else |
| 145 | parent_sd = kobj->sd; | 168 | parent_sd = kobj->sd; |
| 146 | 169 | ||
| 170 | if (targ->sd) | ||
| 171 | old_ns = targ->sd->s_ns; | ||
| 172 | |||
| 147 | result = -ENOENT; | 173 | result = -ENOENT; |
| 148 | sd = sysfs_get_dirent(parent_sd, old); | 174 | sd = sysfs_get_dirent(parent_sd, old_ns, old); |
| 149 | if (!sd) | 175 | if (!sd) |
| 150 | goto out; | 176 | goto out; |
| 151 | 177 | ||
| @@ -155,7 +181,10 @@ int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, | |||
| 155 | if (sd->s_symlink.target_sd->s_dir.kobj != targ) | 181 | if (sd->s_symlink.target_sd->s_dir.kobj != targ) |
| 156 | goto out; | 182 | goto out; |
| 157 | 183 | ||
| 158 | result = sysfs_rename(sd, parent_sd, new); | 184 | if (sysfs_ns_type(parent_sd)) |
| 185 | new_ns = targ->ktype->namespace(targ); | ||
| 186 | |||
| 187 | result = sysfs_rename(sd, parent_sd, new_ns, new); | ||
| 159 | 188 | ||
| 160 | out: | 189 | out: |
| 161 | sysfs_put(sd); | 190 | sysfs_put(sd); |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 30f5a44fb5d3..6a13105b5594 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
| @@ -58,6 +58,7 @@ struct sysfs_dirent { | |||
| 58 | struct sysfs_dirent *s_sibling; | 58 | struct sysfs_dirent *s_sibling; |
| 59 | const char *s_name; | 59 | const char *s_name; |
| 60 | 60 | ||
| 61 | const void *s_ns; /* namespace tag */ | ||
| 61 | union { | 62 | union { |
| 62 | struct sysfs_elem_dir s_dir; | 63 | struct sysfs_elem_dir s_dir; |
| 63 | struct sysfs_elem_symlink s_symlink; | 64 | struct sysfs_elem_symlink s_symlink; |
| @@ -81,14 +82,27 @@ struct sysfs_dirent { | |||
| 81 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) | 82 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) |
| 82 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) | 83 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) |
| 83 | 84 | ||
| 84 | #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK | 85 | /* identify any namespace tag on sysfs_dirents */ |
| 85 | #define SYSFS_FLAG_REMOVED 0x0200 | 86 | #define SYSFS_NS_TYPE_MASK 0xff00 |
| 87 | #define SYSFS_NS_TYPE_SHIFT 8 | ||
| 88 | |||
| 89 | #define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK) | ||
| 90 | #define SYSFS_FLAG_REMOVED 0x020000 | ||
| 86 | 91 | ||
| 87 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | 92 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) |
| 88 | { | 93 | { |
| 89 | return sd->s_flags & SYSFS_TYPE_MASK; | 94 | return sd->s_flags & SYSFS_TYPE_MASK; |
| 90 | } | 95 | } |
| 91 | 96 | ||
| 97 | /* | ||
| 98 | * Return any namespace tags on this dirent. | ||
| 99 | * enum kobj_ns_type is defined in linux/kobject.h | ||
| 100 | */ | ||
| 101 | static inline enum kobj_ns_type sysfs_ns_type(struct sysfs_dirent *sd) | ||
| 102 | { | ||
| 103 | return (sd->s_flags & SYSFS_NS_TYPE_MASK) >> SYSFS_NS_TYPE_SHIFT; | ||
| 104 | } | ||
| 105 | |||
| 92 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 106 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 93 | #define sysfs_dirent_init_lockdep(sd) \ | 107 | #define sysfs_dirent_init_lockdep(sd) \ |
| 94 | do { \ | 108 | do { \ |
| @@ -114,6 +128,16 @@ struct sysfs_addrm_cxt { | |||
| 114 | /* | 128 | /* |
| 115 | * mount.c | 129 | * mount.c |
| 116 | */ | 130 | */ |
| 131 | |||
| 132 | /* | ||
| 133 | * Each sb is associated with a set of namespace tags (i.e. | ||
| 134 | * the network namespace of the task which mounted this sysfs | ||
| 135 | * instance). | ||
| 136 | */ | ||
| 137 | struct sysfs_super_info { | ||
| 138 | const void *ns[KOBJ_NS_TYPES]; | ||
| 139 | }; | ||
| 140 | #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) | ||
| 117 | extern struct sysfs_dirent sysfs_root; | 141 | extern struct sysfs_dirent sysfs_root; |
| 118 | extern struct kmem_cache *sysfs_dir_cachep; | 142 | extern struct kmem_cache *sysfs_dir_cachep; |
| 119 | 143 | ||
| @@ -137,8 +161,10 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | |||
| 137 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); | 161 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); |
| 138 | 162 | ||
| 139 | struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | 163 | struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, |
| 164 | const void *ns, | ||
| 140 | const unsigned char *name); | 165 | const unsigned char *name); |
| 141 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | 166 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, |
| 167 | const void *ns, | ||
| 142 | const unsigned char *name); | 168 | const unsigned char *name); |
| 143 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); | 169 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); |
| 144 | 170 | ||
| @@ -149,7 +175,7 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name, | |||
| 149 | void sysfs_remove_subdir(struct sysfs_dirent *sd); | 175 | void sysfs_remove_subdir(struct sysfs_dirent *sd); |
| 150 | 176 | ||
| 151 | int sysfs_rename(struct sysfs_dirent *sd, | 177 | int sysfs_rename(struct sysfs_dirent *sd, |
| 152 | struct sysfs_dirent *new_parent_sd, const char *new_name); | 178 | struct sysfs_dirent *new_parent_sd, const void *ns, const char *new_name); |
| 153 | 179 | ||
| 154 | static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) | 180 | static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) |
| 155 | { | 181 | { |
| @@ -179,7 +205,7 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | |||
| 179 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); | 205 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); |
| 180 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 206 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
| 181 | size_t size, int flags); | 207 | size_t size, int flags); |
| 182 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); | 208 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name); |
| 183 | int sysfs_inode_init(void); | 209 | int sysfs_inode_init(void); |
| 184 | 210 | ||
| 185 | /* | 211 | /* |
