]> git.hungrycats.org Git - linux/commitdiff
sysfs: fixup merge
authorPatrick Mochel <mochel@osdl.org>
Mon, 3 Mar 2003 10:59:28 +0000 (04:59 -0600)
committerPatrick Mochel <mochel@osdl.org>
Mon, 3 Mar 2003 10:59:28 +0000 (04:59 -0600)
1  2 
fs/sysfs/Makefile
fs/sysfs/inode.c

index c355b8ecfe158ee4a2c81910ab4dd7b601088708,f59d87866332fca41612ae82fe4d0995595feb20..32fa9dfbfb0bbd3b7c74e97bd9df29b2edd9fec6
@@@ -2,4 -2,6 +2,4 @@@
  # Makefile for the sysfs virtual filesystem
  #
  
- obj-y         := inode.o
 -export-objs   := file.o dir.o symlink.o bin.o
 -
+ obj-y         := inode.o file.o dir.o symlink.o mount.o bin.o
index 6b3427f50039f842c0b2d148de79add96293336b,2fbdc1ccc2e1d2e3975358e9f86b564c067ddeec..b40a0a4c2be7e83733eb4cf6ae92575d79bbdc35
  
  #undef DEBUG 
  
- #include <linux/list.h>
- #include <linux/init.h>
  #include <linux/pagemap.h>
- #include <linux/stat.h>
- #include <linux/fs.h>
- #include <linux/dcache.h>
  #include <linux/namei.h>
- #include <linux/module.h>
- #include <linux/slab.h>
  #include <linux/backing-dev.h>
- #include <linux/kobject.h>
- #include <linux/mount.h>
- #include <linux/dnotify.h>
- #include <asm/uaccess.h>
 -
+ extern struct super_block * sysfs_sb;
  
- /* Random magic number */
- #define SYSFS_MAGIC 0x62656572
- static struct super_operations sysfs_ops;
- static struct file_operations sysfs_file_operations;
- static struct address_space_operations sysfs_aops;
- static struct vfsmount *sysfs_mount;
+ static struct address_space_operations sysfs_aops = {
+       .readpage       = simple_readpage,
+       .prepare_write  = simple_prepare_write,
+       .commit_write   = simple_commit_write
+ };
  
  static struct backing_dev_info sysfs_backing_dev_info = {
        .ra_pages       = 0,    /* No readahead */
@@@ -91,346 -42,32 +41,29 @@@ struct inode * sysfs_new_inode(mode_t m
        return inode;
  }
  
static int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
  {
-       struct inode *inode;
        int error = 0;
 -
+       struct inode * inode = NULL;
 -              } else
+       if (dentry) {
+               if (!dentry->d_inode) {
+                       if ((inode = sysfs_new_inode(mode)))
+                               goto Proceed;
+                       else 
+                               error = -ENOMEM;
+                       error = -EEXIST;
+       } else 
+               error = -ENOENT;
+       goto Done;
  
-       if (!dentry->d_inode) {
-               inode = sysfs_get_inode(dir->i_sb, mode, dev);
-               if (inode)
-                       d_instantiate(dentry, inode);
-               else
-                       error = -ENOSPC;
-       } else
-               error = -EEXIST;
-       return error;
- }
- static int sysfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
- {
-       int res;
-       mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
-       res = sysfs_mknod(dir, dentry, mode, 0);
-       if (!res)
-               dir->i_nlink++;
-       return res;
- }
- static int sysfs_create(struct inode *dir, struct dentry *dentry, int mode)
- {
-       int res;
-       mode = (mode & S_IALLUGO) | S_IFREG;
-       res = sysfs_mknod(dir, dentry, mode, 0);
-       return res;
- }
- static int sysfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
- {
-       struct inode *inode;
-       int error = -ENOSPC;
-       if (dentry->d_inode)
-               return -EEXIST;
-       inode = sysfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
-       if (inode) {
-               int l = strlen(symname)+1;
-               error = page_symlink(inode, symname, l);
-               if (!error) {
-                       d_instantiate(dentry, inode);
-                       dget(dentry);
-               } else
-                       iput(inode);
-       }
-       return error;
- }
- #define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
- #define to_sattr(a) container_of(a,struct subsys_attribute,attr)
- /**
-  * Subsystem file operations.
-  * These operations allow subsystems to have files that can be 
-  * read/written. 
-  */
- static ssize_t 
- subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
- {
-       struct subsystem * s = to_subsys(kobj);
-       struct subsys_attribute * sattr = to_sattr(attr);
-       ssize_t ret = 0;
-       if (sattr->show)
-               ret = sattr->show(s,page);
-       return ret;
- }
- static ssize_t 
- subsys_attr_store(struct kobject * kobj, struct attribute * attr, 
-                 const char * page, size_t count)
- {
-       struct subsystem * s = to_subsys(kobj);
-       struct subsys_attribute * sattr = to_sattr(attr);
-       ssize_t ret = 0;
-       if (sattr->store)
-               ret = sattr->store(s,page,count);
-       return ret;
- }
- static struct sysfs_ops subsys_sysfs_ops = {
-       .show   = subsys_attr_show,
-       .store  = subsys_attr_store,
- };
- struct sysfs_buffer {
-       size_t                  count;
-       loff_t                  pos;
-       char                    * page;
-       struct sysfs_ops        * ops;
- };
- /**
-  *    fill_read_buffer - allocate and fill buffer from object.
-  *    @file:          file pointer.
-  *    @buffer:        data buffer for file.
-  *
-  *    Allocate @buffer->page, if it hasn't been already, then call the
-  *    kobject's show() method to fill the buffer with this attribute's 
-  *    data. 
-  *    This is called only once, on the file's first read. 
-  */
- static int fill_read_buffer(struct file * file, struct sysfs_buffer * buffer)
- {
-       struct attribute * attr = file->f_dentry->d_fsdata;
-       struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
-       struct sysfs_ops * ops = buffer->ops;
-       int ret = 0;
-       ssize_t count;
-       if (!buffer->page)
-               buffer->page = (char *) __get_free_page(GFP_KERNEL);
-       if (!buffer->page)
-               return -ENOMEM;
-       count = ops->show(kobj,attr,buffer->page);
-       if (count >= 0)
-               buffer->count = count;
-       else
-               ret = count;
-       return ret;
- }
- /**
-  *    flush_read_buffer - push buffer to userspace.
-  *    @buffer:        data buffer for file.
-  *    @userbuf:       user-passed buffer.
-  *    @count:         number of bytes requested.
-  *    @ppos:          file position.
-  *
-  *    Copy the buffer we filled in fill_read_buffer() to userspace.
-  *    This is done at the reader's leisure, copying and advancing 
-  *    the amount they specify each time.
-  *    This may be called continuously until the buffer is empty.
-  */
- static int flush_read_buffer(struct sysfs_buffer * buffer, char * buf, 
-                            size_t count, loff_t * ppos)
- {
-       int error;
-       if (count > (buffer->count - *ppos))
-               count = buffer->count - *ppos;
-       error = copy_to_user(buf,buffer->page + *ppos,count);
+  Proceed:
+       if (init)
+               error = init(inode);
 -      if (!error) {
 +      if (!error)
-               *ppos += count;
-       return error ? -EFAULT : count;
- }
- /**
-  *    sysfs_read_file - read an attribute. 
-  *    @file:  file pointer.
-  *    @buf:   buffer to fill.
-  *    @count: number of bytes to read.
-  *    @ppos:  starting offset in file.
-  *
-  *    Userspace wants to read an attribute file. The attribute descriptor
-  *    is in the file's ->d_fsdata. The target object is in the directory's
-  *    ->d_fsdata.
-  *
-  *    We call fill_read_buffer() to allocate and fill the buffer from the
-  *    object's show() method exactly once (if the read is happening from
-  *    the beginning of the file). That should fill the entire buffer with
-  *    all the data the object has to offer for that attribute.
-  *    We then call flush_read_buffer() to copy the buffer to userspace
-  *    in the increments specified.
-  */
- static ssize_t
- sysfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
- {
-       struct sysfs_buffer * buffer = file->private_data;
-       ssize_t retval = 0;
-       if (!*ppos) {
-               if ((retval = fill_read_buffer(file,buffer)))
-                       return retval;
-       }
-       pr_debug("%s: count = %d, ppos = %lld, buf = %s\n",
-                __FUNCTION__,count,*ppos,buffer->page);
-       return flush_read_buffer(buffer,buf,count,ppos);
- }
- /**
-  *    fill_write_buffer - copy buffer from userspace.
-  *    @buffer:        data buffer for file.
-  *    @userbuf:       data from user.
-  *    @count:         number of bytes in @userbuf.
-  *
-  *    Allocate @buffer->page if it hasn't been already, then
-  *    copy the user-supplied buffer into it.
-  */
- static int 
- fill_write_buffer(struct sysfs_buffer * buffer, const char * buf, size_t count)
- {
-       int error;
-       if (!buffer->page)
-               buffer->page = (char *)__get_free_page(GFP_KERNEL);
-       if (!buffer->page)
-               return -ENOMEM;
-       if (count >= PAGE_SIZE)
-               count = PAGE_SIZE - 1;
-       error = copy_from_user(buffer->page,buf,count);
-       return error ? -EFAULT : count;
- }
- /**
-  *    flush_write_buffer - push buffer to kobject.
-  *    @file:          file pointer.
-  *    @buffer:        data buffer for file.
-  *
-  *    Get the correct pointers for the kobject and the attribute we're
-  *    dealing with, then call the store() method for the attribute, 
-  *    passing the buffer that we acquired in fill_write_buffer().
-  */
- static int 
- flush_write_buffer(struct file * file, struct sysfs_buffer * buffer, size_t count)
- {
-       struct attribute * attr = file->f_dentry->d_fsdata;
-       struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
-       struct sysfs_ops * ops = buffer->ops;
-       return ops->store(kobj,attr,buffer->page,count);
- }
- /**
-  *    sysfs_write_file - write an attribute.
-  *    @file:  file pointer
-  *    @buf:   data to write
-  *    @count: number of bytes
-  *    @ppos:  starting offset
-  *
-  *    Similar to sysfs_read_file(), though working in the opposite direction.
-  *    We allocate and fill the data from the user in fill_write_buffer(),
-  *    then push it to the kobject in flush_write_buffer().
-  *    There is no easy way for us to know if userspace is only doing a partial
-  *    write, so we don't support them. We expect the entire buffer to come
-  *    on the first write. 
-  *    Hint: if you're writing a value, first read the file, modify only the
-  *    the value you're changing, then write entire buffer back. 
-  */
- static ssize_t
- sysfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
- {
-       struct sysfs_buffer * buffer = file->private_data;
-       count = fill_write_buffer(buffer,buf,count);
-       if (count > 0)
-               count = flush_write_buffer(file,buffer,count);
-       if (count > 0)
-               *ppos += count;
-       return count;
- }
- static int check_perm(struct inode * inode, struct file * file)
- {
-       struct kobject * kobj = kobject_get(file->f_dentry->d_parent->d_fsdata);
-       struct attribute * attr = file->f_dentry->d_fsdata;
-       struct sysfs_buffer * buffer;
-       struct sysfs_ops * ops = NULL;
-       int error = 0;
-       if (!kobj || !attr)
-               goto Einval;
-       /* if the kobject has no ktype, then we assume that it is a subsystem
-        * itself, and use ops for it.
-        */
-       if (kobj->kset && kobj->kset->ktype)
-               ops = kobj->kset->ktype->sysfs_ops;
-       else if (kobj->ktype)
-               ops = kobj->ktype->sysfs_ops;
+               d_instantiate(dentry, inode);
 -              dget(dentry);
 -      } else
 +      else
-               ops = &subsys_sysfs_ops;
-       /* No sysfs operations, either from having no subsystem,
-        * or the subsystem have no operations.
-        */
-       if (!ops)
-               goto Eaccess;
-       /* File needs write support.
-        * The inode's perms must say it's ok, 
-        * and we must have a store method.
-        */
-       if (file->f_mode & FMODE_WRITE) {
-               if (!(inode->i_mode & S_IWUGO) || !ops->store)
-                       goto Eaccess;
-       }
-       /* File needs read support.
-        * The inode's perms must say it's ok, and we there
-        * must be a show method for it.
-        */
-       if (file->f_mode & FMODE_READ) {
-               if (!(inode->i_mode & S_IRUGO) || !ops->show)
-                       goto Eaccess;
-       }
-       /* No error? Great, allocate a buffer for the file, and store it
-        * it in file->private_data for easy access.
-        */
-       buffer = kmalloc(sizeof(struct sysfs_buffer),GFP_KERNEL);
-       if (buffer) {
-               memset(buffer,0,sizeof(struct sysfs_buffer));
-               buffer->ops = ops;
-               file->private_data = buffer;
-       } else
-               error = -ENOMEM;
-       goto Done;
-  Einval:
-       error = -EINVAL;
-       goto Done;
-  Eaccess:
-       error = -EACCES;
+               iput(inode);
   Done:
-       if (error && kobj)
-               kobject_put(kobj);
        return error;
  }
  
@@@ -702,44 -101,10 +97,9 @@@ void sysfs_hash_and_remove(struct dentr
  
                        pr_debug("sysfs: Removing %s (%d)\n", victim->d_name.name,
                                 atomic_read(&victim->d_count));
-               }
-               
-               /**
-                * Drop the reference acquired from get_dentry() above.
-                */
-               dput(victim);
-       }
-       up(&dir->d_inode->i_sem);
- }
- /**
-  * sysfs_update_file - update the modified timestamp on an object attribute.
-  * @kobj: object we're acting for.
-  * @attr: attribute descriptor.
-  *
-  * Also call dnotify for the dentry, which lots of userspace programs
-  * use.
-  */
- int sysfs_update_file(struct kobject * kobj, struct attribute * attr)
- {
-       struct dentry * dir = kobj->dentry;
-       struct dentry * victim;
-       int res = -ENOENT;
-       down(&dir->d_inode->i_sem);
-       victim = get_dentry(dir, attr->name);
-       if (!IS_ERR(victim)) {
-               /* make sure dentry is really there */
-               if (victim->d_inode && 
-                   (victim->d_parent->d_inode == dir->d_inode)) {
-                       victim->d_inode->i_mtime = CURRENT_TIME;
-                       dnotify_parent(victim, DN_MODIFY);
--                      /**
-                        * Drop reference from initial get_dentry().
+                        * Drop reference from initial sysfs_get_dentry().
                         */
                        dput(victim);
-                       res = 0;
                }
                
                /**
                dput(victim);
        }
        up(&dir->d_inode->i_sem);
-       return res;
  }
  
- /**
-  *    sysfs_remove_file - remove an object attribute.
-  *    @kobj:  object we're acting for.
-  *    @attr:  attribute descriptor.
-  *
-  *    Hash the attribute name and kill the victim.
-  */
- void sysfs_remove_file(struct kobject * kobj, struct attribute * attr)
- {
-       hash_and_remove(kobj->dentry,attr->name);
- }
- /**
-  *    sysfs_remove_link - remove symlink in object's directory.
-  *    @kobj:  object we're acting for.
-  *    @name:  name of the symlink to remove.
-  */
- void sysfs_remove_link(struct kobject * kobj, char * name)
- {
-       hash_and_remove(kobj->dentry,name);
- }
- /**
-  *    sysfs_remove_dir - remove an object's directory.
-  *    @kobj:  object. 
-  *
-  *    The only thing special about this is that we remove any files in 
-  *    the directory before we remove the directory, and we've inlined
-  *    what used to be sysfs_rmdir() below, instead of calling separately.
-  */
- void sysfs_remove_dir(struct kobject * kobj)
- {
-       struct list_head * node;
-       struct dentry * dentry = dget(kobj->dentry);
-       struct dentry * parent;
-       if (!dentry)
-               return;
-       pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
-       parent = dget(dentry->d_parent);
-       down(&parent->d_inode->i_sem);
-       down(&dentry->d_inode->i_sem);
-       spin_lock(&dcache_lock);
-       node = dentry->d_subdirs.next;
-       while (node != &dentry->d_subdirs) {
-               struct dentry * d = list_entry(node,struct dentry,d_child);
-               list_del_init(node);
-               pr_debug(" o %s (%d): ",d->d_name.name,atomic_read(&d->d_count));
-               if (d->d_inode) {
-                       d = dget_locked(d);
-                       pr_debug("removing");
-                       /**
-                        * Unlink and unhash.
-                        */
-                       spin_unlock(&dcache_lock);
-                       d_delete(d);
-                       simple_unlink(dentry->d_inode,d);
-                       dput(d);
-                       spin_lock(&dcache_lock);
-               }
-               pr_debug(" done\n");
-               node = dentry->d_subdirs.next;
-       }
-       spin_unlock(&dcache_lock);
-       up(&dentry->d_inode->i_sem);
-       d_invalidate(dentry);
-       simple_rmdir(parent->d_inode,dentry);
-       d_delete(dentry);
-       pr_debug(" o %s removing done (%d)\n",dentry->d_name.name,
-                atomic_read(&dentry->d_count));
-       /**
-        * Drop reference from initial get_dentry().
-        */
-       dput(dentry);
-       /**
-        * Drop reference from dget() on entrance.
-        */
-       dput(dentry);
-       up(&parent->d_inode->i_sem);
-       dput(parent);
- }
- EXPORT_SYMBOL(sysfs_create_file);
- EXPORT_SYMBOL(sysfs_update_file);
- EXPORT_SYMBOL(sysfs_remove_file);
- EXPORT_SYMBOL(sysfs_create_link);
- EXPORT_SYMBOL(sysfs_remove_link);
- EXPORT_SYMBOL(sysfs_create_dir);
- EXPORT_SYMBOL(sysfs_remove_dir);
 +