Commit 3ca5999f authored by Patrick Mochel's avatar Patrick Mochel

sysfs: further localize file creation.

- reanme sysfs_get_inode() to sysfs_create().
- Assume we're using the single sysfs superblock when creating something.
- move file object-specific init commands to callbacks.
- streamline file and directory creation to remove duplicate checks.
- clean up sysfs_fill_super() a bit. 
parent f7a5d012
...@@ -10,16 +10,15 @@ ...@@ -10,16 +10,15 @@
#include <linux/kobject.h> #include <linux/kobject.h>
#include "sysfs.h" #include "sysfs.h"
static int sysfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) static int init_dir(struct inode * inode)
{ {
int res; inode->i_op = &simple_dir_inode_operations;
mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR; inode->i_fop = &simple_dir_operations;
res = sysfs_mknod(dir, dentry, mode, 0);
if (!res)
dir->i_nlink++;
return res;
}
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inode->i_nlink++;
return 0;
}
/** /**
* sysfs_create_dir - create a directory for an object. * sysfs_create_dir - create a directory for an object.
...@@ -48,8 +47,10 @@ int sysfs_create_dir(struct kobject * kobj) ...@@ -48,8 +47,10 @@ int sysfs_create_dir(struct kobject * kobj)
if (!IS_ERR(dentry)) { if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)kobj; dentry->d_fsdata = (void *)kobj;
kobj->dentry = dentry; kobj->dentry = dentry;
error = sysfs_mkdir(parent->d_inode,dentry, error = sysfs_create(dentry,(S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
(S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO)); init_dir);
if (!error)
parent->d_inode->i_nlink++;
} else } else
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
up(&parent->d_inode->i_sem); up(&parent->d_inode->i_sem);
......
...@@ -8,12 +8,13 @@ ...@@ -8,12 +8,13 @@
#include "sysfs.h" #include "sysfs.h"
static int sysfs_create(struct inode *dir, struct dentry *dentry, int mode) static struct file_operations sysfs_file_operations;
static int init_file(struct inode * inode)
{ {
int res; inode->i_size = PAGE_SIZE;
mode = (mode & S_IALLUGO) | S_IFREG; inode->i_fop = &sysfs_file_operations;
res = sysfs_mknod(dir, dentry, mode, 0); return 0;
return res;
} }
#define to_subsys(k) container_of(k,struct subsystem,kset.kobj) #define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
...@@ -325,7 +326,7 @@ static int sysfs_release(struct inode * inode, struct file * filp) ...@@ -325,7 +326,7 @@ static int sysfs_release(struct inode * inode, struct file * filp)
return 0; return 0;
} }
struct file_operations sysfs_file_operations = { static struct file_operations sysfs_file_operations = {
.read = sysfs_read_file, .read = sysfs_read_file,
.write = sysfs_write_file, .write = sysfs_write_file,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
...@@ -354,7 +355,7 @@ int sysfs_create_file(struct kobject * kobj, struct attribute * attr) ...@@ -354,7 +355,7 @@ int sysfs_create_file(struct kobject * kobj, struct attribute * attr)
dentry = sysfs_get_dentry(parent,attr->name); dentry = sysfs_get_dentry(parent,attr->name);
if (!IS_ERR(dentry)) { if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)attr; dentry->d_fsdata = (void *)attr;
error = sysfs_create(parent->d_inode,dentry,attr->mode); error = sysfs_create(dentry,(attr->mode & S_IALLUGO) | S_IFREG,init_file);
} else } else
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
up(&parent->d_inode->i_sem); up(&parent->d_inode->i_sem);
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
extern struct file_operations sysfs_file_operations; extern struct super_block * sysfs_sb;
static struct address_space_operations sysfs_aops = { static struct address_space_operations sysfs_aops = {
.readpage = simple_readpage, .readpage = simple_readpage,
...@@ -20,17 +20,14 @@ static struct address_space_operations sysfs_aops = { ...@@ -20,17 +20,14 @@ static struct address_space_operations sysfs_aops = {
.commit_write = simple_commit_write .commit_write = simple_commit_write
}; };
static struct backing_dev_info sysfs_backing_dev_info = { static struct backing_dev_info sysfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */ .ra_pages = 0, /* No readahead */
.memory_backed = 1, /* Does not contribute to dirty memory */ .memory_backed = 1, /* Does not contribute to dirty memory */
}; };
struct inode *sysfs_get_inode(struct super_block *sb, int mode, int dev) struct inode * sysfs_new_inode(mode_t mode)
{ {
struct inode *inode = new_inode(sb); struct inode * inode = new_inode(sysfs_sb);
if (inode) { if (inode) {
inode->i_mode = mode; inode->i_mode = mode;
inode->i_uid = current->fsuid; inode->i_uid = current->fsuid;
...@@ -41,46 +38,44 @@ struct inode *sysfs_get_inode(struct super_block *sb, int mode, int dev) ...@@ -41,46 +38,44 @@ struct inode *sysfs_get_inode(struct super_block *sb, int mode, int dev)
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->a_ops = &sysfs_aops;
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
switch (mode & S_IFMT) {
default:
init_special_inode(inode, mode, dev);
break;
case S_IFREG:
inode->i_size = PAGE_SIZE;
inode->i_fop = &sysfs_file_operations;
break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inode->i_nlink++;
break;
case S_IFLNK:
inode->i_op = &page_symlink_inode_operations;
break;
}
} }
return inode; return inode;
} }
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; int error = 0;
struct inode * inode = NULL;
if (dentry) {
if (!dentry->d_inode) { if (!dentry->d_inode) {
inode = sysfs_get_inode(dir->i_sb, mode, dev); if ((inode = sysfs_new_inode(mode)))
if (inode) { goto Proceed;
else
error = -ENOMEM;
} else
error = -EEXIST;
} else
error = -ENOENT;
goto Done;
Proceed:
if (init)
error = init(inode);
if (!error) {
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
dget(dentry); dget(dentry);
} else } else
error = -ENOSPC; iput(inode);
} else Done:
error = -EEXIST;
return error; return error;
} }
int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
return sysfs_create(dentry, mode, NULL);
}
struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name) struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name)
{ {
struct qstr qstr; struct qstr qstr;
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
* mount.c - operations for initializing and mounting sysfs. * mount.c - operations for initializing and mounting sysfs.
*/ */
#define DEBUG
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
...@@ -12,6 +14,7 @@ ...@@ -12,6 +14,7 @@
#define SYSFS_MAGIC 0x62656572 #define SYSFS_MAGIC 0x62656572
struct vfsmount *sysfs_mount; struct vfsmount *sysfs_mount;
struct super_block * sysfs_sb = NULL;
static struct super_operations sysfs_ops = { static struct super_operations sysfs_ops = {
.statfs = simple_statfs, .statfs = simple_statfs,
...@@ -27,10 +30,16 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -27,10 +30,16 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = SYSFS_MAGIC; sb->s_magic = SYSFS_MAGIC;
sb->s_op = &sysfs_ops; sb->s_op = &sysfs_ops;
inode = sysfs_get_inode(sb, S_IFDIR | 0755, 0); sysfs_sb = sb;
if (!inode) { inode = sysfs_new_inode(S_IFDIR | S_IRUGO | S_IWUSR);
pr_debug("%s: could not get inode!\n",__FUNCTION__); if (inode) {
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inode->i_nlink++;
} else {
pr_debug("sysfs: could not get root inode\n");
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -9,23 +9,22 @@ ...@@ -9,23 +9,22 @@
#include "sysfs.h" #include "sysfs.h"
static int sysfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) static int init_symlink(struct inode * inode)
{ {
struct inode *inode; inode->i_op = &page_symlink_inode_operations;
int error = -ENOSPC; return 0;
}
if (dentry->d_inode) static int sysfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
return -EEXIST; {
int error;
inode = sysfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); error = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
if (inode) {
int l = strlen(symname)+1;
error = page_symlink(inode, symname, l);
if (!error) { if (!error) {
d_instantiate(dentry, inode); int l = strlen(symname)+1;
dget(dentry); error = page_symlink(dentry->d_inode, symname, l);
} else if (error)
iput(inode); iput(dentry->d_inode);
} }
return error; return error;
} }
......
extern struct vfsmount * sysfs_mount; extern struct vfsmount * sysfs_mount;
extern struct inode *sysfs_get_inode(struct super_block *sb, int mode, int dev); extern struct inode * sysfs_new_inode(mode_t mode);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
extern int sysfs_mknod(struct inode *, struct dentry *, int, dev_t);
extern struct dentry * sysfs_get_dentry(struct dentry *, char *); extern struct dentry * sysfs_get_dentry(struct dentry *, char *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment