diff options
author | Tejun Heo <tj@kernel.org> | 2013-10-01 17:42:08 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-05 20:27:40 -0400 |
commit | 49fe604781cbb03eb6ff12a7bc4ad8eef8b830c4 (patch) | |
tree | 7133e49e6c491130044498d6c22e5fb7d1a8006b /fs/sysfs/file.c | |
parent | 73d9714627adced2942e8d53ce0e73d9699a996c (diff) |
sysfs: prepare open path for unified regular / bin file handling
sysfs bin file handling will be merged into the regular file support.
This patch prepares the open path.
This patch updates sysfs_open_file() such that it can handle both
regular and bin files.
This is a preparation and the new bin file path isn't used yet.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r-- | fs/sysfs/file.c | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 02797a134cf8..417d005955d9 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -610,38 +610,40 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
610 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 610 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
611 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 611 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
612 | struct sysfs_open_file *of; | 612 | struct sysfs_open_file *of; |
613 | const struct sysfs_ops *ops; | 613 | bool has_read, has_write; |
614 | int error = -EACCES; | 614 | int error = -EACCES; |
615 | 615 | ||
616 | /* need attr_sd for attr and ops, its parent for kobj */ | 616 | /* need attr_sd for attr and ops, its parent for kobj */ |
617 | if (!sysfs_get_active(attr_sd)) | 617 | if (!sysfs_get_active(attr_sd)) |
618 | return -ENODEV; | 618 | return -ENODEV; |
619 | 619 | ||
620 | /* every kobject with an attribute needs a ktype assigned */ | 620 | if (sysfs_is_bin(attr_sd)) { |
621 | ops = sysfs_file_ops(attr_sd); | 621 | struct bin_attribute *battr = attr_sd->s_bin_attr.bin_attr; |
622 | if (WARN(!ops, KERN_ERR | ||
623 | "missing sysfs attribute operations for kobject: %s\n", | ||
624 | kobject_name(kobj))) | ||
625 | goto err_out; | ||
626 | 622 | ||
627 | /* File needs write support. | 623 | has_read = battr->read || battr->mmap; |
628 | * The inode's perms must say it's ok, | 624 | has_write = battr->write || battr->mmap; |
629 | * and we must have a store method. | 625 | } else { |
630 | */ | 626 | const struct sysfs_ops *ops = sysfs_file_ops(attr_sd); |
631 | if (file->f_mode & FMODE_WRITE) { | ||
632 | if (!(inode->i_mode & S_IWUGO) || !ops->store) | ||
633 | goto err_out; | ||
634 | } | ||
635 | 627 | ||
636 | /* File needs read support. | 628 | /* every kobject with an attribute needs a ktype assigned */ |
637 | * The inode's perms must say it's ok, and we there | 629 | if (WARN(!ops, KERN_ERR |
638 | * must be a show method for it. | 630 | "missing sysfs attribute operations for kobject: %s\n", |
639 | */ | 631 | kobject_name(kobj))) |
640 | if (file->f_mode & FMODE_READ) { | ||
641 | if (!(inode->i_mode & S_IRUGO) || !ops->show) | ||
642 | goto err_out; | 632 | goto err_out; |
633 | |||
634 | has_read = ops->show; | ||
635 | has_write = ops->store; | ||
643 | } | 636 | } |
644 | 637 | ||
638 | /* check perms and supported operations */ | ||
639 | if ((file->f_mode & FMODE_WRITE) && | ||
640 | (!(inode->i_mode & S_IWUGO) || !has_write)) | ||
641 | goto err_out; | ||
642 | |||
643 | if ((file->f_mode & FMODE_READ) && | ||
644 | (!(inode->i_mode & S_IRUGO) || !has_read)) | ||
645 | goto err_out; | ||
646 | |||
645 | /* allocate a sysfs_open_file for the file */ | 647 | /* allocate a sysfs_open_file for the file */ |
646 | error = -ENOMEM; | 648 | error = -ENOMEM; |
647 | of = kzalloc(sizeof(struct sysfs_open_file), GFP_KERNEL); | 649 | of = kzalloc(sizeof(struct sysfs_open_file), GFP_KERNEL); |
@@ -653,11 +655,14 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
653 | of->file = file; | 655 | of->file = file; |
654 | 656 | ||
655 | /* | 657 | /* |
656 | * Always instantiate seq_file even if read access is not | 658 | * Always instantiate seq_file even if read access doesn't use |
657 | * implemented or requested. This unifies private data access and | 659 | * seq_file or is not requested. This unifies private data access |
658 | * most files are readable anyway. | 660 | * and readable regular files are the vast majority anyway. |
659 | */ | 661 | */ |
660 | error = single_open(file, sysfs_seq_show, of); | 662 | if (sysfs_is_bin(attr_sd)) |
663 | error = single_open(file, NULL, of); | ||
664 | else | ||
665 | error = single_open(file, sysfs_seq_show, of); | ||
661 | if (error) | 666 | if (error) |
662 | goto err_free; | 667 | goto err_free; |
663 | 668 | ||
@@ -807,6 +812,9 @@ const struct file_operations sysfs_bin_operations = { | |||
807 | .write = sysfs_write_file, | 812 | .write = sysfs_write_file, |
808 | .llseek = generic_file_llseek, | 813 | .llseek = generic_file_llseek, |
809 | .mmap = sysfs_bin_mmap, | 814 | .mmap = sysfs_bin_mmap, |
815 | .open = sysfs_open_file, | ||
816 | .release = sysfs_release, | ||
817 | .poll = sysfs_poll, | ||
810 | }; | 818 | }; |
811 | 819 | ||
812 | int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, | 820 | int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, |