/*
* bin.c - binary file operations for sysfs.
+ *
+ * Copyright (c) 2003 Patrick Mochel
+ * Copyright (c) 2003 Matthew Wilcox
+ * Copyright (c) 2004 Silicon Graphics, Inc.
*/
#undef DEBUG
#include <linux/errno.h>
#include <linux/fs.h>
+#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/slab.h>
static int
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
{
- struct bin_attribute * attr = dentry->d_fsdata;
- struct kobject * kobj = dentry->d_parent->d_fsdata;
+ struct bin_attribute * attr = to_bin_attr(dentry);
+ struct kobject * kobj = to_kobj(dentry->d_parent);
+
+ if (!attr->read)
+ return -EIO;
return attr->read(kobj, buffer, off, count);
}
read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
{
char *buffer = file->private_data;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
int ret;
static int
flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
{
- struct bin_attribute *attr = dentry->d_fsdata;
- struct kobject *kobj = dentry->d_parent->d_fsdata;
+ struct bin_attribute *attr = to_bin_attr(dentry);
+ struct kobject *kobj = to_kobj(dentry->d_parent);
+
+ if (!attr->write)
+ return -EIO;
return attr->write(kobj, buffer, offset, count);
}
size_t count, loff_t * off)
{
char *buffer = file->private_data;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
return count;
}
+static int mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct dentry *dentry = file->f_path.dentry;
+ struct bin_attribute *attr = to_bin_attr(dentry);
+ struct kobject *kobj = to_kobj(dentry->d_parent);
+
+ if (!attr->mmap)
+ return -EINVAL;
+
+ return attr->mmap(kobj, attr, vma);
+}
+
static int open(struct inode * inode, struct file * file)
{
- struct kobject * kobj = kobject_get(file->f_dentry->d_parent->d_fsdata);
- struct bin_attribute * attr = file->f_dentry->d_fsdata;
+ struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
+ struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
int error = -EINVAL;
if (!kobj || !attr)
goto Done;
error = -EACCES;
- if ((file->f_mode & FMODE_WRITE) && !attr->write)
+ if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
goto Error;
- if ((file->f_mode & FMODE_READ) && !attr->read)
+ if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
goto Error;
error = -ENOMEM;
static int release(struct inode * inode, struct file * file)
{
- struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
- struct bin_attribute * attr = file->f_dentry->d_fsdata;
+ struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
+ struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
u8 * buffer = file->private_data;
if (kobj)
return 0;
}
-static struct file_operations bin_fops = {
+const struct file_operations bin_fops = {
.read = read,
.write = write,
+ .mmap = mmap,
.llseek = generic_file_llseek,
.open = open,
.release = release,
* sysfs_create_bin_file - create binary file for object.
* @kobj: object.
* @attr: attribute descriptor.
- *
*/
int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
- struct dentry * dentry;
- struct dentry * parent;
- int error = 0;
-
- if (!kobj || !attr)
- return -EINVAL;
+ BUG_ON(!kobj || !kobj->dentry || !attr);
- parent = kobj->dentry;
-
- down(&parent->d_inode->i_sem);
- dentry = sysfs_get_dentry(parent,attr->attr.name);
- if (!IS_ERR(dentry)) {
- dentry->d_fsdata = (void *)attr;
- error = sysfs_create(dentry,
- (attr->attr.mode & S_IALLUGO) | S_IFREG,
- NULL);
- if (!error) {
- dentry->d_inode->i_size = attr->size;
- dentry->d_inode->i_fop = &bin_fops;
- }
- dput(dentry);
- } else
- error = PTR_ERR(dentry);
- up(&parent->d_inode->i_sem);
- return error;
+ return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
}
* sysfs_remove_bin_file - remove binary file for object.
* @kobj: object.
* @attr: attribute descriptor.
- *
*/
-int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
- sysfs_hash_and_remove(kobj->dentry,attr->attr.name);
- return 0;
+ if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) {
+ printk(KERN_ERR "%s: "
+ "bad dentry or inode or no such file: \"%s\"\n",
+ __FUNCTION__, attr->attr.name);
+ dump_stack();
+ }
}
-EXPORT_SYMBOL(sysfs_create_bin_file);
-EXPORT_SYMBOL(sysfs_remove_bin_file);
+EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
+EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);