hostfs: don't keep a field in each inode when we are using it only in root

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2010-06-06 17:53:01 -04:00
parent e971a6d7b9
commit 601d2c38b9
1 changed files with 15 additions and 24 deletions

View File

@ -19,7 +19,6 @@
#include "kern.h" #include "kern.h"
struct hostfs_inode_info { struct hostfs_inode_info {
char *host_filename;
int fd; int fd;
fmode_t mode; fmode_t mode;
struct inode vfs_inode; struct inode vfs_inode;
@ -103,7 +102,7 @@ static char *dentry_name(struct dentry *dentry, int extra)
parent = parent->d_parent; parent = parent->d_parent;
} }
root = HOSTFS_I(parent->d_inode)->host_filename; root = parent->d_sb->s_fs_info;
len += strlen(root); len += strlen(root);
name = kmalloc(len + extra + 1, GFP_KERNEL); name = kmalloc(len + extra + 1, GFP_KERNEL);
if (name == NULL) if (name == NULL)
@ -266,7 +265,7 @@ int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
long long f_files; long long f_files;
long long f_ffree; long long f_ffree;
err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename, err = do_statfs(dentry->d_sb->s_fs_info,
&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
&sf->f_namelen, sf->f_spare); &sf->f_namelen, sf->f_spare);
@ -285,13 +284,10 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
{ {
struct hostfs_inode_info *hi; struct hostfs_inode_info *hi;
hi = kmalloc(sizeof(*hi), GFP_KERNEL); hi = kzalloc(sizeof(*hi), GFP_KERNEL);
if (hi == NULL) if (hi == NULL)
return NULL; return NULL;
hi->fd = -1;
*hi = ((struct hostfs_inode_info) { .host_filename = NULL,
.fd = -1,
.mode = 0 });
inode_init_once(&hi->vfs_inode); inode_init_once(&hi->vfs_inode);
return &hi->vfs_inode; return &hi->vfs_inode;
} }
@ -308,14 +304,12 @@ static void hostfs_evict_inode(struct inode *inode)
static void hostfs_destroy_inode(struct inode *inode) static void hostfs_destroy_inode(struct inode *inode)
{ {
kfree(HOSTFS_I(inode)->host_filename);
kfree(HOSTFS_I(inode)); kfree(HOSTFS_I(inode));
} }
static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs) static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
{ {
struct inode *root = vfs->mnt_sb->s_root->d_inode; const char *root_path = vfs->mnt_sb->s_fs_info;
const char *root_path = HOSTFS_I(root)->host_filename;
size_t offset = strlen(root_ino) + 1; size_t offset = strlen(root_ino) + 1;
if (strlen(root_path) > offset) if (strlen(root_path) > offset)
@ -978,8 +972,8 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
req_root = ""; req_root = "";
err = -ENOMEM; err = -ENOMEM;
host_root_path = kmalloc(strlen(root_ino) + 1 sb->s_fs_info = host_root_path =
+ strlen(req_root) + 1, GFP_KERNEL); kmalloc(strlen(root_ino) + strlen(req_root) + 2, GFP_KERNEL);
if (host_root_path == NULL) if (host_root_path == NULL)
goto out; goto out;
@ -988,20 +982,13 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
root_inode = hostfs_iget(sb); root_inode = hostfs_iget(sb);
if (IS_ERR(root_inode)) { if (IS_ERR(root_inode)) {
err = PTR_ERR(root_inode); err = PTR_ERR(root_inode);
goto out_free; goto out;
} }
err = init_inode(root_inode, NULL); err = init_inode(root_inode, NULL);
if (err) if (err)
goto out_put; goto out_put;
HOSTFS_I(root_inode)->host_filename = host_root_path;
/*
* Avoid that in the error path, iput(root_inode) frees again
* host_root_path through hostfs_destroy_inode!
*/
host_root_path = NULL;
err = -ENOMEM; err = -ENOMEM;
sb->s_root = d_alloc_root(root_inode); sb->s_root = d_alloc_root(root_inode);
if (sb->s_root == NULL) if (sb->s_root == NULL)
@ -1019,8 +1006,6 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
out_put: out_put:
iput(root_inode); iput(root_inode);
out_free:
kfree(host_root_path);
out: out:
return err; return err;
} }
@ -1032,11 +1017,17 @@ static int hostfs_read_sb(struct file_system_type *type,
return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt); return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt);
} }
static void hostfs_kill_sb(struct super_block *s)
{
kill_anon_super(s);
kfree(s->s_fs_info);
}
static struct file_system_type hostfs_type = { static struct file_system_type hostfs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "hostfs", .name = "hostfs",
.get_sb = hostfs_read_sb, .get_sb = hostfs_read_sb,
.kill_sb = kill_anon_super, .kill_sb = hostfs_kill_sb,
.fs_flags = 0, .fs_flags = 0,
}; };