Commit deddb7cb authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] simple_fill_super()

	New libfs.c helper - simple_fill_super().  Abstracted from
nfsd/nfsctl.c, couple of filesystems converted to it (nfsctl, binfmt_misc).

	Function takes an array of triples (name, file_operations, mode),
superblock and value for its ->s_magic.  It acts as fill_super() - populates
superblock or fails.  We get a ramfs-style flat tree - root directory and
a bunch of files in it.

	That animal allows to put together a simple filesystem without
touching any directory-related stuff - now it's as easy as implementing
file_operations for files you want to have and telling what to call them.
parent a113994e
...@@ -630,64 +630,20 @@ static struct file_operations bm_status_operations = { ...@@ -630,64 +630,20 @@ static struct file_operations bm_status_operations = {
static struct super_operations s_ops = { static struct super_operations s_ops = {
.statfs = simple_statfs, .statfs = simple_statfs,
.drop_inode = generic_delete_inode,
.clear_inode = bm_clear_inode, .clear_inode = bm_clear_inode,
}; };
static int bm_fill_super(struct super_block * sb, void * data, int silent) static int bm_fill_super(struct super_block * sb, void * data, int silent)
{ {
struct qstr names[2] = {{.name = "status"}, {.name = "register"}}; static struct tree_descr bm_files[] = {
struct inode * inode; [1] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
struct dentry * dentry[3]; [2] = {"register", &bm_register_operations, S_IWUSR},
int i; /* last one */ {""}
};
for (i=0; i<sizeof(names)/sizeof(names[0]); i++) { int err = simple_fill_super(sb, 0x42494e4d, bm_files);
names[i].len = strlen(names[i].name); if (!err)
names[i].hash = full_name_hash(names[i].name, names[i].len); sb->s_op = &s_ops;
} return err;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = 0x42494e4d;
sb->s_op = &s_ops;
inode = bm_get_inode(sb, S_IFDIR | 0755);
if (!inode)
return -ENOMEM;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
dentry[0] = d_alloc_root(inode);
if (!dentry[0]) {
iput(inode);
return -ENOMEM;
}
dentry[1] = d_alloc(dentry[0], &names[0]);
if (!dentry[1])
goto out1;
dentry[2] = d_alloc(dentry[0], &names[1]);
if (!dentry[2])
goto out2;
inode = bm_get_inode(sb, S_IFREG | 0644);
if (!inode)
goto out3;
inode->i_fop = &bm_status_operations;
d_add(dentry[1], inode);
inode = bm_get_inode(sb, S_IFREG | 0400);
if (!inode)
goto out3;
inode->i_fop = &bm_register_operations;
d_add(dentry[2], inode);
sb->s_root = dentry[0];
return 0;
out3:
dput(dentry[2]);
out2:
dput(dentry[1]);
out1:
dput(dentry[0]);
return -ENOMEM;
} }
static struct super_block *bm_get_sb(struct file_system_type *fs_type, static struct super_block *bm_get_sb(struct file_system_type *fs_type,
......
...@@ -332,3 +332,61 @@ int simple_commit_write(struct file *file, struct page *page, ...@@ -332,3 +332,61 @@ int simple_commit_write(struct file *file, struct page *page,
set_page_dirty(page); set_page_dirty(page);
return 0; return 0;
} }
int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
{
static struct super_operations s_ops = {statfs:simple_statfs};
struct inode *inode;
struct dentry *root;
struct dentry *dentry;
int i;
s->s_blocksize = PAGE_CACHE_SIZE;
s->s_blocksize_bits = PAGE_CACHE_SHIFT;
s->s_magic = magic;
s->s_op = &s_ops;
inode = new_inode(s);
if (!inode)
return -ENOMEM;
inode->i_mode = S_IFDIR | 0755;
inode->i_uid = inode->i_gid = 0;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
root = d_alloc_root(inode);
if (!root) {
iput(inode);
return -ENOMEM;
}
for (i = 0; !files->name || files->name[0]; i++, files++) {
struct qstr name;
if (!files->name)
continue;
name.name = files->name;
name.len = strlen(name.name);
name.hash = full_name_hash(name.name, name.len);
dentry = d_alloc(root, &name);
if (!dentry)
goto out;
inode = new_inode(s);
if (!inode)
goto out;
inode->i_mode = S_IFREG | files->mode;
inode->i_uid = inode->i_gid = 0;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_fop = files->ops;
inode->i_ino = i;
d_add(dentry, inode);
}
s->s_root = root;
return 0;
out:
d_genocide(root);
dput(root);
return -ENOMEM;
}
...@@ -48,7 +48,6 @@ enum { ...@@ -48,7 +48,6 @@ enum {
NFSD_List, NFSD_List,
NFSD_Fh, NFSD_Fh,
NFSD_Threads, NFSD_Threads,
NFSD_END
}; };
/* /*
...@@ -204,22 +203,6 @@ static struct file_operations exports_operations = { ...@@ -204,22 +203,6 @@ static struct file_operations exports_operations = {
.release = exports_release, .release = exports_release,
}; };
/*
* Description of fs contents.
*/
static struct { char *name; struct file_operations *ops; int mode; } files[] = {
[NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
[NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
[NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
[NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
[NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
};
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/* /*
* payload - write methods * payload - write methods
...@@ -431,64 +414,22 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) ...@@ -431,64 +414,22 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
* populating the filesystem. * populating the filesystem.
*/ */
static struct super_operations s_ops = {
.statfs = simple_statfs,
};
static int nfsd_fill_super(struct super_block * sb, void * data, int silent) static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
{ {
struct inode *inode; static struct tree_descr nfsd_files[] = {
struct dentry *root; [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
struct dentry *dentry; [NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
int i; [NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
[NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
sb->s_blocksize = PAGE_CACHE_SIZE; [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
sb->s_blocksize_bits = PAGE_CACHE_SHIFT; [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
sb->s_magic = 0x6e667364; [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
sb->s_op = &s_ops; [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
inode = new_inode(sb); [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
if (!inode) /* last one */ {""}
return -ENOMEM; };
inode->i_mode = S_IFDIR | 0755; return simple_fill_super(sb, 0x6e667364, nfsd_files);
inode->i_uid = inode->i_gid = 0;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
root = d_alloc_root(inode);
if (!root) {
iput(inode);
return -ENOMEM;
}
for (i = NFSD_Svc; i < NFSD_END; i++) {
struct qstr name;
name.name = files[i].name;
name.len = strlen(name.name);
name.hash = full_name_hash(name.name, name.len);
dentry = d_alloc(root, &name);
if (!dentry)
goto out;
inode = new_inode(sb);
if (!inode)
goto out;
inode->i_mode = S_IFREG | files[i].mode;
inode->i_uid = inode->i_gid = 0;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_fop = files[i].ops;
inode->i_ino = i;
d_add(dentry, inode);
}
sb->s_root = root;
return 0;
out:
d_genocide(root);
dput(root);
return -ENOMEM;
} }
static struct super_block *nfsd_get_sb(struct file_system_type *fs_type, static struct super_block *nfsd_get_sb(struct file_system_type *fs_type,
......
...@@ -1292,6 +1292,8 @@ extern struct dentry *simple_lookup(struct inode *, struct dentry *); ...@@ -1292,6 +1292,8 @@ extern struct dentry *simple_lookup(struct inode *, struct dentry *);
extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *); extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);
extern struct file_operations simple_dir_operations; extern struct file_operations simple_dir_operations;
extern struct inode_operations simple_dir_inode_operations; extern struct inode_operations simple_dir_inode_operations;
struct tree_descr { char *name; struct file_operations *ops; int mode; };
extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
extern unsigned int real_root_dev; extern unsigned int real_root_dev;
......
...@@ -313,6 +313,7 @@ EXPORT_SYMBOL(simple_readpage); ...@@ -313,6 +313,7 @@ EXPORT_SYMBOL(simple_readpage);
EXPORT_SYMBOL(simple_prepare_write); EXPORT_SYMBOL(simple_prepare_write);
EXPORT_SYMBOL(simple_commit_write); EXPORT_SYMBOL(simple_commit_write);
EXPORT_SYMBOL(simple_empty); EXPORT_SYMBOL(simple_empty);
EXPORT_SYMBOL(simple_fill_super);
EXPORT_SYMBOL(fd_install); EXPORT_SYMBOL(fd_install);
EXPORT_SYMBOL(put_unused_fd); EXPORT_SYMBOL(put_unused_fd);
EXPORT_SYMBOL(get_sb_bdev); EXPORT_SYMBOL(get_sb_bdev);
......
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