aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r--fs/sysfs/file.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 1ad8c93c1b85..d4e6080b4b20 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -466,9 +466,6 @@ void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
466 mutex_lock(&sysfs_mutex); 466 mutex_lock(&sysfs_mutex);
467 467
468 if (sd && dir) 468 if (sd && dir)
469 /* Only directories are tagged, so no need to pass
470 * a tag explicitly.
471 */
472 sd = sysfs_find_dirent(sd, NULL, dir); 469 sd = sysfs_find_dirent(sd, NULL, dir);
473 if (sd && attr) 470 if (sd && attr)
474 sd = sysfs_find_dirent(sd, NULL, attr); 471 sd = sysfs_find_dirent(sd, NULL, attr);
@@ -488,17 +485,56 @@ const struct file_operations sysfs_file_operations = {
488 .poll = sysfs_poll, 485 .poll = sysfs_poll,
489}; 486};
490 487
488int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
489 const void **pns)
490{
491 struct sysfs_dirent *dir_sd = kobj->sd;
492 const struct sysfs_ops *ops;
493 const void *ns = NULL;
494 int err;
495
496 err = 0;
497 if (!sysfs_ns_type(dir_sd))
498 goto out;
499
500 err = -EINVAL;
501 if (!kobj->ktype)
502 goto out;
503 ops = kobj->ktype->sysfs_ops;
504 if (!ops)
505 goto out;
506 if (!ops->namespace)
507 goto out;
508
509 err = 0;
510 ns = ops->namespace(kobj, attr);
511out:
512 if (err) {
513 WARN(1, KERN_ERR "missing sysfs namespace attribute operation for "
514 "kobject: %s\n", kobject_name(kobj));
515 }
516 *pns = ns;
517 return err;
518}
519
491int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, 520int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
492 const struct attribute *attr, int type, mode_t amode) 521 const struct attribute *attr, int type, mode_t amode)
493{ 522{
494 umode_t mode = (amode & S_IALLUGO) | S_IFREG; 523 umode_t mode = (amode & S_IALLUGO) | S_IFREG;
495 struct sysfs_addrm_cxt acxt; 524 struct sysfs_addrm_cxt acxt;
496 struct sysfs_dirent *sd; 525 struct sysfs_dirent *sd;
526 const void *ns;
497 int rc; 527 int rc;
498 528
529 rc = sysfs_attr_ns(dir_sd->s_dir.kobj, attr, &ns);
530 if (rc)
531 return rc;
532
499 sd = sysfs_new_dirent(attr->name, mode, type); 533 sd = sysfs_new_dirent(attr->name, mode, type);
500 if (!sd) 534 if (!sd)
501 return -ENOMEM; 535 return -ENOMEM;
536
537 sd->s_ns = ns;
502 sd->s_attr.attr = (void *)attr; 538 sd->s_attr.attr = (void *)attr;
503 sysfs_dirent_init_lockdep(sd); 539 sysfs_dirent_init_lockdep(sd);
504 540
@@ -586,12 +622,17 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
586{ 622{
587 struct sysfs_dirent *sd; 623 struct sysfs_dirent *sd;
588 struct iattr newattrs; 624 struct iattr newattrs;
625 const void *ns;
589 int rc; 626 int rc;
590 627
628 rc = sysfs_attr_ns(kobj, attr, &ns);
629 if (rc)
630 return rc;
631
591 mutex_lock(&sysfs_mutex); 632 mutex_lock(&sysfs_mutex);
592 633
593 rc = -ENOENT; 634 rc = -ENOENT;
594 sd = sysfs_find_dirent(kobj->sd, NULL, attr->name); 635 sd = sysfs_find_dirent(kobj->sd, ns, attr->name);
595 if (!sd) 636 if (!sd)
596 goto out; 637 goto out;
597 638
@@ -616,7 +657,12 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
616 657
617void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) 658void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
618{ 659{
619 sysfs_hash_and_remove(kobj->sd, NULL, attr->name); 660 const void *ns;
661
662 if (sysfs_attr_ns(kobj, attr, &ns))
663 return;
664
665 sysfs_hash_and_remove(kobj->sd, ns, attr->name);
620} 666}
621 667
622void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) 668void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)