Linus Torvalds wrote:
I really think you should update the "simple_xxx()" functions instead, and
thus make this happen for _any_ filesystem that uses the simple fs helper
functions.
Ok, I revised the patch. This is just the first step with changes to
libfs and ramfs.
To move the directory i_size handling completely to libfs it is
necessary to allocate the inodes in libfs. Therefore, simple_get_inode()
and simple_mknod_init() (honestly, I don't like that name) are
introduced. simple_mknod_init() uses a callback mechanism to initialize
the file system specific stuff of the inodes.
What do you think of it?
Jan
fs/libfs.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/fs.h | 7 +++++
2 files changed, 72 insertions(+), 1 deletion(-)
Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c
+++ linux-2.6/fs/libfs.c
@@ -238,13 +238,72 @@ Enomem:
return ERR_PTR(-ENOMEM);
}
+struct inode *simple_get_inode(struct super_block *sb, int mode,
+ int (*init)(struct inode *, void *), void *arg)
+{
+ struct inode * inode = new_inode(sb);
+
+ if (!inode)
+ return ERR_PTR(-ENOSPC);
+
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blksize = sb->s_blocksize;
+ inode->i_blocks = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+ if (S_ISDIR(mode)) {
+ /* directory inodes start with i_nlink == 2 (for "." entry) */
+ inode->i_nlink++;
+ /* i_size for "." and ".." */
+ inode->i_size = 2 * SIMPLE_BOGO_DIRENT_SIZE;
+ }
+
+ if (init) {
+ int error = init(inode, arg);
+ if (error) {
+ iput(inode);
+ inode = ERR_PTR(error);
+ }
+ }
+
+ return inode;
+}
+
+int simple_mknod_init(struct inode *dir, struct dentry *dentry, int mode,
+ int (*init)(struct inode *, void *), void *arg)
+{
+ struct inode * inode;
+
+ inode = simple_get_inode(dir->i_sb, mode, init, arg);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+
+ if (dir->i_mode & S_ISGID) {
+ inode->i_gid = dir->i_gid;
+ if (S_ISDIR(mode))
+ inode->i_mode |= S_ISGID;
+ }
+
+ if (S_ISDIR(mode))
+ dir->i_nlink++;
+
+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_size += SIMPLE_BOGO_DIRENT_SIZE;
+ d_instantiate(dentry, inode);
+ dget(dentry); /* pin the dentry in core */
+ return 0;
+}
+
int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ inode->i_ctime = dir->i_mtime = dir->i_ctime = CURRENT_TIME;
inode->i_nlink++;
atomic_inc(&inode->i_count);
+ dir->i_size += SIMPLE_BOGO_DIRENT_SIZE;
dget(dentry);
d_instantiate(dentry, inode);
return 0;
@@ -276,6 +335,7 @@ int simple_unlink(struct inode *dir, str
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
inode->i_nlink--;
+ dir->i_size -= SIMPLE_BOGO_DIRENT_SIZE;
dput(dentry);
return 0;
}
@@ -311,6 +371,8 @@ int simple_rename(struct inode *old_dir,
old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;
+ old_dir->i_size -= SIMPLE_BOGO_DIRENT_SIZE;
+ new_dir->i_size += SIMPLE_BOGO_DIRENT_SIZE;
return 0;
}
@@ -629,6 +691,8 @@ EXPORT_SYMBOL(simple_empty);
EXPORT_SYMBOL(d_alloc_name);
EXPORT_SYMBOL(simple_fill_super);
EXPORT_SYMBOL(simple_getattr);
+EXPORT_SYMBOL(simple_get_inode);
+EXPORT_SYMBOL(simple_mknod_init);
EXPORT_SYMBOL(simple_link);
EXPORT_SYMBOL(simple_lookup);
EXPORT_SYMBOL(simple_pin_fs);
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1624,6 +1624,11 @@ extern loff_t dcache_dir_lseek(struct fi
extern int dcache_readdir(struct file *, void *, filldir_t);
extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int simple_statfs(struct super_block *, struct kstatfs *);
+extern struct inode *simple_get_inode(struct super_block *, int ,
+ int (*init)(struct inode *, void *),
+ void *);
+extern int simple_mknod_init(struct inode *, struct dentry *, int ,
+ int (*init)(struct inode *, void *), void *);
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
extern int simple_unlink(struct inode *, struct dentry *);
extern int simple_rmdir(struct inode *, struct dentry *);
@@ -1744,6 +1749,8 @@ ssize_t simple_attr_read(struct file *fi
ssize_t simple_attr_write(struct file *file, const char __user *buf,
size_t len, loff_t *ppos);
+/* Pretend that each dirent is of this size in simple directories */
+#define SIMPLE_BOGO_DIRENT_SIZE 20
#ifdef CONFIG_SECURITY
static inline char *alloc_secdata(void)
fs/ramfs/inode.c | 118 ++++++++++++++++++++++---------------------------------
1 files changed, 48 insertions(+), 70 deletions(-)
Index: linux-2.6/fs/ramfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ramfs/inode.c
+++ linux-2.6/fs/ramfs/inode.c
@@ -50,40 +50,40 @@ static struct backing_dev_info ramfs_bac
BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
};
-struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
-{
- struct inode * inode = new_inode(sb);
-
- if (inode) {
- inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
- inode->i_blksize = PAGE_CACHE_SIZE;
- inode->i_blocks = 0;
- inode->i_mapping->a_ops = &ramfs_aops;
- inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- switch (mode & S_IFMT) {
- default:
- init_special_inode(inode, mode, dev);
- break;
- case S_IFREG:
- inode->i_op = &ramfs_file_inode_operations;
- inode->i_fop = &ramfs_file_operations;
- break;
- case S_IFDIR:
- inode->i_op = &ramfs_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;
- }
+struct ramfs_init_args {
+ dev_t dev;
+ const char *name;
+};
+
+static int ramfs_inode_init(struct inode *inode, void *__arg)
+{
+ struct ramfs_init_args *arg = (struct ramfs_init_args *)__arg;
+ int len;
+ int err = 0;
+
+ inode->i_mapping->a_ops = &ramfs_aops;
+ inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
+
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ inode->i_op = &ramfs_file_inode_operations;
+ inode->i_fop = &ramfs_file_operations;
+ break;
+ case S_IFDIR:
+ inode->i_op = &ramfs_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+ break;
+ case S_IFLNK:
+ inode->i_op = &page_symlink_inode_operations;
+ len = strlen(arg->symname)+1;
+ err = page_symlink(inode, arg->symname, len);
+ break;
+ default:
+ init_special_inode(inode, inode->i_mode, arg->dev);
+ break;
}
- return inode;
+
+ return err;
}
/*
@@ -93,53 +93,31 @@ struct inode *ramfs_get_inode(struct sup
static int
ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
- struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev);
- int error = -ENOSPC;
+ struct ramfs_init_args args = { .dev = dev };
- if (inode) {
- if (dir->i_mode & S_ISGID) {
- inode->i_gid = dir->i_gid;
- if (S_ISDIR(mode))
- inode->i_mode |= S_ISGID;
- }
- d_instantiate(dentry, inode);
- dget(dentry); /* Extra count - pin the dentry in core */
- error = 0;
- }
- return error;
+ return simple_mknod_init(dir, dentry, mode,
+ ramfs_inode_init, (void *) &args);
}
static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
- int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
- if (!retval)
- dir->i_nlink++;
- return retval;
+ return simple_mknod_init(dir, dentry, mode|S_IFDIR,
+ ramfs_inode_init, NULL);
}
static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
- return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
+ return simple_mknod_init(dir, dentry, mode|S_IFREG,
+ ramfs_inode_init, NULL);
}
-static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
+static int ramfs_symlink(struct inode *dir, struct dentry *dentry,
+ const char *name)
{
- struct inode *inode;
- int error = -ENOSPC;
+ struct ramfs_init_args args = { .name = name };
- inode = ramfs_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) {
- if (dir->i_mode & S_ISGID)
- inode->i_gid = dir->i_gid;
- d_instantiate(dentry, inode);
- dget(dentry);
- } else
- iput(inode);
- }
- return error;
+ return simple_mknod_init(dir, dentry, S_IFLNK|S_IRWXUGO,
+ ramfs_inode_init, (void *) &args);
}
static struct address_space_operations ramfs_aops = {
@@ -189,9 +167,9 @@ static int ramfs_fill_super(struct super
sb->s_magic = RAMFS_MAGIC;
sb->s_op = &ramfs_ops;
sb->s_time_gran = 1;
- inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0);
- if (!inode)
- return -ENOMEM;
+ inode = simple_get_inode(sb, S_IFDIR|0755, ramfs_inode_init, NULL);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode); // -ENOMEM
root = d_alloc_root(inode);
if (!root) {
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
|
|