vserver 1.9.5.x5
[linux-2.6.git] / fs / sysfs / bin.c
index d455725..d4aaa88 100644 (file)
@@ -1,5 +1,9 @@
 /*
  * 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
 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 -EINVAL;
 
        return attr->read(kobj, buffer, off, count);
 }
@@ -60,8 +67,11 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
 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 -EINVAL;
 
        return attr->write(kobj, buffer, offset, count);
 }
@@ -92,10 +102,22 @@ static ssize_t write(struct file * file, const char __user * userbuf,
        return count;
 }
 
+static int mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct dentry *dentry = file->f_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 = sysfs_get_kobject(file->f_dentry->d_parent);
-       struct bin_attribute * attr = file->f_dentry->d_fsdata;
+       struct bin_attribute * attr = to_bin_attr(file->f_dentry);
        int error = -EINVAL;
 
        if (!kobj || !attr)
@@ -107,9 +129,9 @@ static int open(struct inode * inode, struct file * file)
                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;
@@ -130,8 +152,8 @@ static int open(struct inode * inode, struct file * file)
 
 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_dentry->d_parent);
+       struct bin_attribute * attr = to_bin_attr(file->f_dentry);
        u8 * buffer = file->private_data;
 
        if (kobj) 
@@ -141,9 +163,10 @@ static int release(struct inode * inode, struct file * file)
        return 0;
 }
 
-static struct file_operations bin_fops = {
+struct file_operations bin_fops = {
        .read           = read,
        .write          = write,
+       .mmap           = mmap,
        .llseek         = generic_file_llseek,
        .open           = open,
        .release        = release,
@@ -158,31 +181,9 @@ static struct file_operations bin_fops = {
 
 int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
 {
-       struct dentry * dentry;
-       struct dentry * parent;
-       int error = 0;
+       BUG_ON(!kobj || !kobj->dentry || !attr);
 
-       if (!kobj || !attr)
-               return -EINVAL;
-
-       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);
 }
 
 
@@ -199,5 +200,5 @@ int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
        return 0;
 }
 
-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);