Commit 78085a46 authored by Alex Tomas's avatar Alex Tomas Committed by Linus Torvalds

[PATCH] ext3: support for EA in inode

1) intent of the patch is to get possibility to store EAs in the body of large
   inode. it saves space and improves performance in some cases

2) the patch is quite simple: it works the same way original xattr does, but
   using other storage (inode body). body has priority over separate block.
   original routines (ext3_xattr_get, ext3_xattr_list, ext3_xattr_set) are
   renamed to ext3_xattr_block_*. new routines that handle inode storate are
   added (ext3_xattr_ibody_get, ext3_xattr_ibody_list, ext3_xattr_ibody_set).
   routines ext3_xattr_get, ext3_xattr_list and ext3_xattr_set allow user to
   accesss both the storages transparently

3) the change makes sense on filesystem with inode size >= 256 bytes only.
   2.4 kernels don't support such a filesystems, AFAIK. 2.6 kernels do support
   and ignore EAs stored in a body w/o the patch

4) debugfs and e2fsck need to be patched to deal with EAs in inode
   the patch will be sent later

5) testing results:
	a) Andrew Samba Master (tridge) has done successful tests
	b) we've been using ea-in-inode feature in Lustre for many months
Signed-off-by: default avatarAndreas Dilger <adilger@clusterfs.com>
Signed-off-by: default avatarAlex Tomas <alex@clusterfs.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fbdce7d7
...@@ -596,6 +596,11 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode) ...@@ -596,6 +596,11 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
spin_unlock(&sbi->s_next_gen_lock); spin_unlock(&sbi->s_next_gen_lock);
ei->i_state = EXT3_STATE_NEW; ei->i_state = EXT3_STATE_NEW;
if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
ei->i_extra_isize = sizeof(__u16) /* i_extra_isize */
+ sizeof(__u16); /* i_pad1 */
} else
ei->i_extra_isize = 0;
ret = inode; ret = inode;
if(DQUOT_ALLOC_INODE(inode)) { if(DQUOT_ALLOC_INODE(inode)) {
......
...@@ -2275,7 +2275,7 @@ static unsigned long ext3_get_inode_block(struct super_block *sb, ...@@ -2275,7 +2275,7 @@ static unsigned long ext3_get_inode_block(struct super_block *sb,
* trying to determine the inode's location on-disk and no read need be * trying to determine the inode's location on-disk and no read need be
* performed. * performed.
*/ */
static int ext3_get_inode_loc(struct inode *inode, int ext3_get_inode_loc(struct inode *inode,
struct ext3_iloc *iloc, int in_mem) struct ext3_iloc *iloc, int in_mem)
{ {
unsigned long block; unsigned long block;
...@@ -2483,6 +2483,11 @@ void ext3_read_inode(struct inode * inode) ...@@ -2483,6 +2483,11 @@ void ext3_read_inode(struct inode * inode)
ei->i_data[block] = raw_inode->i_block[block]; ei->i_data[block] = raw_inode->i_block[block];
INIT_LIST_HEAD(&ei->i_orphan); INIT_LIST_HEAD(&ei->i_orphan);
if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
else
ei->i_extra_isize = 0;
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext3_file_inode_operations; inode->i_op = &ext3_file_inode_operations;
inode->i_fop = &ext3_file_operations; inode->i_fop = &ext3_file_operations;
...@@ -2618,6 +2623,9 @@ static int ext3_do_update_inode(handle_t *handle, ...@@ -2618,6 +2623,9 @@ static int ext3_do_update_inode(handle_t *handle,
} else for (block = 0; block < EXT3_N_BLOCKS; block++) } else for (block = 0; block < EXT3_N_BLOCKS; block++)
raw_inode->i_block[block] = ei->i_data[block]; raw_inode->i_block[block] = ei->i_data[block];
if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
rc = ext3_journal_dirty_metadata(handle, bh); rc = ext3_journal_dirty_metadata(handle, bh);
if (!err) if (!err)
......
This diff is collapsed.
...@@ -67,7 +67,8 @@ extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); ...@@ -67,7 +67,8 @@ extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t); extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
extern int ext3_xattr_list(struct inode *, char *, size_t); extern int ext3_xattr_list(struct inode *, char *, size_t);
extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int); extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int); extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *,const void *,size_t,int);
extern int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,const void *,size_t,int);
extern void ext3_xattr_delete_inode(handle_t *, struct inode *); extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
extern void ext3_xattr_put_super(struct super_block *); extern void ext3_xattr_put_super(struct super_block *);
......
...@@ -293,6 +293,8 @@ struct ext3_inode { ...@@ -293,6 +293,8 @@ struct ext3_inode {
__u32 m_i_reserved2[2]; __u32 m_i_reserved2[2];
} masix2; } masix2;
} osd2; /* OS dependent 2 */ } osd2; /* OS dependent 2 */
__u16 i_extra_isize;
__u16 i_pad1;
}; };
#define i_size_high i_dir_acl #define i_size_high i_dir_acl
...@@ -755,6 +757,7 @@ extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, in ...@@ -755,6 +757,7 @@ extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, in
extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *, int);
extern void ext3_read_inode (struct inode *); extern void ext3_read_inode (struct inode *);
extern int ext3_write_inode (struct inode *, int); extern int ext3_write_inode (struct inode *, int);
extern int ext3_setattr (struct dentry *, struct iattr *); extern int ext3_setattr (struct dentry *, struct iattr *);
......
...@@ -113,6 +113,9 @@ struct ext3_inode_info { ...@@ -113,6 +113,9 @@ struct ext3_inode_info {
*/ */
loff_t i_disksize; loff_t i_disksize;
/* on-disk additional length */
__u16 i_extra_isize;
/* /*
* truncate_sem is for serialising ext3_truncate() against * truncate_sem is for serialising ext3_truncate() against
* ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's
......
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