aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/file.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2011-10-12 17:53:38 -0400
committerDavid S. Miller <davem@davemloft.net>2011-10-19 19:24:14 -0400
commit487505c257021fc06a7d05753cf27b011487f1dc (patch)
tree4fedc207c7e3d21bd394d9187fd1cc9f65768e2c /fs/sysfs/file.c
parentd5edf2906e0a251ddddd76caeb1b79de8bb5e3b8 (diff)
sysfs: Implement support for tagged files in sysfs.
Looking up files in sysfs is hard to understand and analyize because we currently allow placing untagged files in tagged directories. In the implementation of that we have two subtly different meanings of NULL. NULL meaning there is no tag on a directory entry and NULL meaning we don't care which namespace the lookup is performed for. This multiple uses of NULL have resulted in subtle bugs (since fixed) in the code. Currently it is only the bonding driver that needs to have an untagged file in a tagged directory. To untagle this mess I am adding support for tagged files to sysfs. Modifying the bonding driver to implement bonding_masters as a tagged file. Registering bonding_masters once for each network namespace. Then I am removing support for untagged entries in tagged sysfs directories. Resulting in code that is much easier to reason about. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r--fs/sysfs/file.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 1ad8c93c1b8..07c1b4ec00d 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
491int 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);
514out:
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
491int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, 523int 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
617void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) 661void 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
622void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) 671void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)