diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/file.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1ad8c93c1b85..07c1b4ec00df 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -488,17 +488,56 @@ const struct file_operations sysfs_file_operations = { | |||
488 | .poll = sysfs_poll, | 488 | .poll = sysfs_poll, |
489 | }; | 489 | }; |
490 | 490 | ||
491 | int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr, | ||
492 | const void **pns) | ||
493 | { | ||
494 | struct sysfs_dirent *dir_sd = kobj->sd; | ||
495 | const struct sysfs_ops *ops; | ||
496 | const void *ns = NULL; | ||
497 | int err; | ||
498 | |||
499 | err = 0; | ||
500 | if (!sysfs_ns_type(dir_sd)) | ||
501 | goto out; | ||
502 | |||
503 | err = -EINVAL; | ||
504 | if (!kobj->ktype) | ||
505 | goto out; | ||
506 | ops = kobj->ktype->sysfs_ops; | ||
507 | if (!ops) | ||
508 | goto out; | ||
509 | if (!ops->namespace) | ||
510 | goto out; | ||
511 | |||
512 | err = 0; | ||
513 | ns = ops->namespace(kobj, attr); | ||
514 | out: | ||
515 | if (err) { | ||
516 | WARN(1, KERN_ERR "missing sysfs namespace attribute operation for " | ||
517 | "kobject: %s\n", kobject_name(kobj)); | ||
518 | } | ||
519 | *pns = ns; | ||
520 | return err; | ||
521 | } | ||
522 | |||
491 | int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, | 523 | int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, |
492 | const struct attribute *attr, int type, mode_t amode) | 524 | const struct attribute *attr, int type, mode_t amode) |
493 | { | 525 | { |
494 | umode_t mode = (amode & S_IALLUGO) | S_IFREG; | 526 | umode_t mode = (amode & S_IALLUGO) | S_IFREG; |
495 | struct sysfs_addrm_cxt acxt; | 527 | struct sysfs_addrm_cxt acxt; |
496 | struct sysfs_dirent *sd; | 528 | struct sysfs_dirent *sd; |
529 | const void *ns; | ||
497 | int rc; | 530 | int rc; |
498 | 531 | ||
532 | rc = sysfs_attr_ns(dir_sd->s_dir.kobj, attr, &ns); | ||
533 | if (rc) | ||
534 | return rc; | ||
535 | |||
499 | sd = sysfs_new_dirent(attr->name, mode, type); | 536 | sd = sysfs_new_dirent(attr->name, mode, type); |
500 | if (!sd) | 537 | if (!sd) |
501 | return -ENOMEM; | 538 | return -ENOMEM; |
539 | |||
540 | sd->s_ns = ns; | ||
502 | sd->s_attr.attr = (void *)attr; | 541 | sd->s_attr.attr = (void *)attr; |
503 | sysfs_dirent_init_lockdep(sd); | 542 | sysfs_dirent_init_lockdep(sd); |
504 | 543 | ||
@@ -586,12 +625,17 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, | |||
586 | { | 625 | { |
587 | struct sysfs_dirent *sd; | 626 | struct sysfs_dirent *sd; |
588 | struct iattr newattrs; | 627 | struct iattr newattrs; |
628 | const void *ns; | ||
589 | int rc; | 629 | int rc; |
590 | 630 | ||
631 | rc = sysfs_attr_ns(kobj, attr, &ns); | ||
632 | if (rc) | ||
633 | return rc; | ||
634 | |||
591 | mutex_lock(&sysfs_mutex); | 635 | mutex_lock(&sysfs_mutex); |
592 | 636 | ||
593 | rc = -ENOENT; | 637 | rc = -ENOENT; |
594 | sd = sysfs_find_dirent(kobj->sd, NULL, attr->name); | 638 | sd = sysfs_find_dirent(kobj->sd, ns, attr->name); |
595 | if (!sd) | 639 | if (!sd) |
596 | goto out; | 640 | goto out; |
597 | 641 | ||
@@ -616,7 +660,12 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); | |||
616 | 660 | ||
617 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) | 661 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) |
618 | { | 662 | { |
619 | sysfs_hash_and_remove(kobj->sd, NULL, attr->name); | 663 | const void *ns; |
664 | |||
665 | if (sysfs_attr_ns(kobj, attr, &ns)) | ||
666 | return; | ||
667 | |||
668 | sysfs_hash_and_remove(kobj->sd, ns, attr->name); | ||
620 | } | 669 | } |
621 | 670 | ||
622 | void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) | 671 | void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) |