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 = {
static struct super_operations s_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
.clear_inode = bm_clear_inode,
};
static int bm_fill_super(struct super_block * sb, void * data, int silent)
{
struct qstr names[2] = {{.name = "status"}, {.name = "register"}};
struct inode * inode;
struct dentry * dentry[3];
int i;
for (i=0; i<sizeof(names)/sizeof(names[0]); i++) {
names[i].len = strlen(names[i].name);
names[i].hash = full_name_hash(names[i].name, names[i].len);
}
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 tree_descr bm_files[] = {
[1] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
[2] = {"register", &bm_register_operations, S_IWUSR},
/* last one */ {""}
};
int err = simple_fill_super(sb, 0x42494e4d, bm_files);
if (!err)
sb->s_op = &s_ops;
return err;
}
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,
set_page_dirty(page);
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 {
NFSD_List,
NFSD_Fh,
NFSD_Threads,
NFSD_END
};
/*
......@@ -204,22 +203,6 @@ static struct file_operations exports_operations = {
.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
......@@ -431,64 +414,22 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
* 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)
{
struct inode *inode;
struct dentry *root;
struct dentry *dentry;
int i;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = 0x6e667364;
sb->s_op = &s_ops;
inode = new_inode(sb);
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 = 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 tree_descr nfsd_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},
/* last one */ {""}
};
return simple_fill_super(sb, 0x6e667364, nfsd_files);
}
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 *);
extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);
extern struct file_operations simple_dir_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
extern unsigned int real_root_dev;
......
......@@ -313,6 +313,7 @@ EXPORT_SYMBOL(simple_readpage);
EXPORT_SYMBOL(simple_prepare_write);
EXPORT_SYMBOL(simple_commit_write);
EXPORT_SYMBOL(simple_empty);
EXPORT_SYMBOL(simple_fill_super);
EXPORT_SYMBOL(fd_install);
EXPORT_SYMBOL(put_unused_fd);
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