Commit 2cb1599f authored by David Chinner's avatar David Chinner Committed by Lachlan McIlroy

Inode: Allow external initialisers

To allow XFS to combine the XFS and linux inodes into a single
structure, we need to drive inode lookup from the XFS inode cache,
not the generic inode cache. This means that we need initialise a
struct inode from a context outside alloc_inode() as it is no longer
used by XFS.

Factor and export the struct inode initialisation code from
alloc_inode() to inode_init_always() as a counterpart to
inode_init_once().  i.e. we have to call this init function for each
inode instantiation (always), as opposed inode_init_once() which is
only called on slab object instantiation (once).
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
Signed-off-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
parent 94b97e39
...@@ -108,84 +108,100 @@ static void wake_up_inode(struct inode *inode) ...@@ -108,84 +108,100 @@ static void wake_up_inode(struct inode *inode)
wake_up_bit(&inode->i_state, __I_LOCK); wake_up_bit(&inode->i_state, __I_LOCK);
} }
static struct inode *alloc_inode(struct super_block *sb) /**
* inode_init_always - perform inode structure intialisation
* @sb - superblock inode belongs to.
* @inode - inode to initialise
*
* These are initializations that need to be done on every inode
* allocation as the fields are not initialised by slab allocation.
*/
struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
{ {
static const struct address_space_operations empty_aops; static const struct address_space_operations empty_aops;
static struct inode_operations empty_iops; static struct inode_operations empty_iops;
static const struct file_operations empty_fops; static const struct file_operations empty_fops;
struct inode *inode;
if (sb->s_op->alloc_inode)
inode = sb->s_op->alloc_inode(sb);
else
inode = (struct inode *) kmem_cache_alloc(inode_cachep, GFP_KERNEL);
if (inode) { struct address_space * const mapping = &inode->i_data;
struct address_space * const mapping = &inode->i_data;
inode->i_sb = sb;
inode->i_sb = sb; inode->i_blkbits = sb->s_blocksize_bits;
inode->i_blkbits = sb->s_blocksize_bits; inode->i_flags = 0;
inode->i_flags = 0; atomic_set(&inode->i_count, 1);
atomic_set(&inode->i_count, 1); inode->i_op = &empty_iops;
inode->i_op = &empty_iops; inode->i_fop = &empty_fops;
inode->i_fop = &empty_fops; inode->i_nlink = 1;
inode->i_nlink = 1; atomic_set(&inode->i_writecount, 0);
atomic_set(&inode->i_writecount, 0); inode->i_size = 0;
inode->i_size = 0; inode->i_blocks = 0;
inode->i_blocks = 0; inode->i_bytes = 0;
inode->i_bytes = 0; inode->i_generation = 0;
inode->i_generation = 0;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
#endif #endif
inode->i_pipe = NULL; inode->i_pipe = NULL;
inode->i_bdev = NULL; inode->i_bdev = NULL;
inode->i_cdev = NULL; inode->i_cdev = NULL;
inode->i_rdev = 0; inode->i_rdev = 0;
inode->dirtied_when = 0; inode->dirtied_when = 0;
if (security_inode_alloc(inode)) { if (security_inode_alloc(inode)) {
if (inode->i_sb->s_op->destroy_inode) if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode); inode->i_sb->s_op->destroy_inode(inode);
else else
kmem_cache_free(inode_cachep, (inode)); kmem_cache_free(inode_cachep, (inode));
return NULL; return NULL;
} }
spin_lock_init(&inode->i_lock); spin_lock_init(&inode->i_lock);
lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key);
mutex_init(&inode->i_mutex); mutex_init(&inode->i_mutex);
lockdep_set_class(&inode->i_mutex, &sb->s_type->i_mutex_key); lockdep_set_class(&inode->i_mutex, &sb->s_type->i_mutex_key);
init_rwsem(&inode->i_alloc_sem); init_rwsem(&inode->i_alloc_sem);
lockdep_set_class(&inode->i_alloc_sem, &sb->s_type->i_alloc_sem_key); lockdep_set_class(&inode->i_alloc_sem, &sb->s_type->i_alloc_sem_key);
mapping->a_ops = &empty_aops; mapping->a_ops = &empty_aops;
mapping->host = inode; mapping->host = inode;
mapping->flags = 0; mapping->flags = 0;
mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE); mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE);
mapping->assoc_mapping = NULL; mapping->assoc_mapping = NULL;
mapping->backing_dev_info = &default_backing_dev_info; mapping->backing_dev_info = &default_backing_dev_info;
mapping->writeback_index = 0; mapping->writeback_index = 0;
/* /*
* If the block_device provides a backing_dev_info for client * If the block_device provides a backing_dev_info for client
* inodes then use that. Otherwise the inode share the bdev's * inodes then use that. Otherwise the inode share the bdev's
* backing_dev_info. * backing_dev_info.
*/ */
if (sb->s_bdev) { if (sb->s_bdev) {
struct backing_dev_info *bdi; struct backing_dev_info *bdi;
bdi = sb->s_bdev->bd_inode_backing_dev_info; bdi = sb->s_bdev->bd_inode_backing_dev_info;
if (!bdi) if (!bdi)
bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info; bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
mapping->backing_dev_info = bdi; mapping->backing_dev_info = bdi;
}
inode->i_private = NULL;
inode->i_mapping = mapping;
} }
inode->i_private = NULL;
inode->i_mapping = mapping;
return inode; return inode;
} }
EXPORT_SYMBOL(inode_init_always);
static struct inode *alloc_inode(struct super_block *sb)
{
struct inode *inode;
if (sb->s_op->alloc_inode)
inode = sb->s_op->alloc_inode(sb);
else
inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL);
if (inode)
return inode_init_always(sb, inode);
return NULL;
}
void destroy_inode(struct inode *inode) void destroy_inode(struct inode *inode)
{ {
......
...@@ -1881,6 +1881,7 @@ extern loff_t default_llseek(struct file *file, loff_t offset, int origin); ...@@ -1881,6 +1881,7 @@ extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin);
extern struct inode * inode_init_always(struct super_block *, struct inode *);
extern void inode_init_once(struct inode *); extern void inode_init_once(struct inode *);
extern void iput(struct inode *); extern void iput(struct inode *);
extern struct inode * igrab(struct inode *); extern struct inode * igrab(struct inode *);
......
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