Commit 67cf5b09 authored by Tao Ma's avatar Tao Ma Committed by Theodore Ts'o

ext4: add the basic function for inline data support

Implement inline data with xattr.

Now we use "system.data" to store xattr, and the xattr will
be extended if the i_size is increased while we don't release
the space during truncate.
Signed-off-by: default avatarTao Ma <boyu.mt@taobao.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 879b3825
...@@ -9,6 +9,6 @@ ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \ ...@@ -9,6 +9,6 @@ ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \ ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
mmp.o indirect.o extents_status.o mmp.o indirect.o extents_status.o
ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o inline.o
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
...@@ -402,6 +402,7 @@ struct flex_groups { ...@@ -402,6 +402,7 @@ struct flex_groups {
#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
#define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */ #define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */
#define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */ #define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */
#define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */
#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
#define EXT4_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */ #define EXT4_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */
...@@ -458,6 +459,7 @@ enum { ...@@ -458,6 +459,7 @@ enum {
EXT4_INODE_EXTENTS = 19, /* Inode uses extents */ EXT4_INODE_EXTENTS = 19, /* Inode uses extents */
EXT4_INODE_EA_INODE = 21, /* Inode used for large EA */ EXT4_INODE_EA_INODE = 21, /* Inode used for large EA */
EXT4_INODE_EOFBLOCKS = 22, /* Blocks allocated beyond EOF */ EXT4_INODE_EOFBLOCKS = 22, /* Blocks allocated beyond EOF */
EXT4_INODE_INLINE_DATA = 28, /* Data in inode. */
EXT4_INODE_RESERVED = 31, /* reserved for ext4 lib */ EXT4_INODE_RESERVED = 31, /* reserved for ext4 lib */
}; };
...@@ -504,6 +506,7 @@ static inline void ext4_check_flag_values(void) ...@@ -504,6 +506,7 @@ static inline void ext4_check_flag_values(void)
CHECK_FLAG_VALUE(EXTENTS); CHECK_FLAG_VALUE(EXTENTS);
CHECK_FLAG_VALUE(EA_INODE); CHECK_FLAG_VALUE(EA_INODE);
CHECK_FLAG_VALUE(EOFBLOCKS); CHECK_FLAG_VALUE(EOFBLOCKS);
CHECK_FLAG_VALUE(INLINE_DATA);
CHECK_FLAG_VALUE(RESERVED); CHECK_FLAG_VALUE(RESERVED);
} }
...@@ -918,6 +921,10 @@ struct ext4_inode_info { ...@@ -918,6 +921,10 @@ struct ext4_inode_info {
/* on-disk additional length */ /* on-disk additional length */
__u16 i_extra_isize; __u16 i_extra_isize;
/* Indicate the inline data space. */
u16 i_inline_off;
u16 i_inline_size;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
/* quota space reservation, managed internally by quota code */ /* quota space reservation, managed internally by quota code */
qsize_t i_reserved_quota; qsize_t i_reserved_quota;
...@@ -1376,6 +1383,7 @@ enum { ...@@ -1376,6 +1383,7 @@ enum {
EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */ EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */
EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read
nolocking */ nolocking */
EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */
}; };
#define EXT4_INODE_BIT_FNS(name, field, offset) \ #define EXT4_INODE_BIT_FNS(name, field, offset) \
...@@ -1497,7 +1505,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) ...@@ -1497,7 +1505,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
#define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */ #define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */
#define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM 0x2000 /* use crc32c for bg */ #define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM 0x2000 /* use crc32c for bg */
#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */ #define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */
#define EXT4_FEATURE_INCOMPAT_INLINEDATA 0x8000 /* data in inode */ #define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */
#define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR #define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ #define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \
......
This diff is collapsed.
...@@ -3706,8 +3706,10 @@ static inline void ext4_iget_extra_inode(struct inode *inode, ...@@ -3706,8 +3706,10 @@ static inline void ext4_iget_extra_inode(struct inode *inode,
{ {
__le32 *magic = (void *)raw_inode + __le32 *magic = (void *)raw_inode +
EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize; EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize;
if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC)) if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
ext4_set_inode_state(inode, EXT4_STATE_XATTR); ext4_set_inode_state(inode, EXT4_STATE_XATTR);
ext4_find_inline_data_nolock(inode);
}
} }
struct inode *ext4_iget(struct super_block *sb, unsigned long ino) struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
...@@ -3780,6 +3782,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -3780,6 +3782,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
set_nlink(inode, le16_to_cpu(raw_inode->i_links_count)); set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */ ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */
ei->i_inline_off = 0;
ei->i_dir_start_lookup = 0; ei->i_dir_start_lookup = 0;
ei->i_dtime = le32_to_cpu(raw_inode->i_dtime); ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
/* We now have enough fields to check if the inode was active or not. /* We now have enough fields to check if the inode was active or not.
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define EXT4_XATTR_INDEX_TRUSTED 4 #define EXT4_XATTR_INDEX_TRUSTED 4
#define EXT4_XATTR_INDEX_LUSTRE 5 #define EXT4_XATTR_INDEX_LUSTRE 5
#define EXT4_XATTR_INDEX_SECURITY 6 #define EXT4_XATTR_INDEX_SECURITY 6
#define EXT4_XATTR_INDEX_SYSTEM 7
struct ext4_xattr_header { struct ext4_xattr_header {
__le32 h_magic; /* magic number for identification */ __le32 h_magic; /* magic number for identification */
...@@ -125,6 +126,19 @@ extern int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, ...@@ -125,6 +126,19 @@ extern int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
struct ext4_xattr_info *i, struct ext4_xattr_info *i,
struct ext4_xattr_ibody_find *is); struct ext4_xattr_ibody_find *is);
extern int ext4_has_inline_data(struct inode *inode);
extern int ext4_get_inline_size(struct inode *inode);
extern int ext4_get_max_inline_size(struct inode *inode);
extern int ext4_find_inline_data_nolock(struct inode *inode);
extern void ext4_write_inline_data(struct inode *inode,
struct ext4_iloc *iloc,
void *buffer, loff_t pos,
unsigned int len);
extern int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
unsigned int len);
extern int ext4_init_inline_data(handle_t *handle, struct inode *inode,
unsigned int len);
extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);
# else /* CONFIG_EXT4_FS_XATTR */ # else /* CONFIG_EXT4_FS_XATTR */
static inline int static inline int
...@@ -201,6 +215,46 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, ...@@ -201,6 +215,46 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int ext4_find_inline_data_nolock(struct inode *inode)
{
return 0;
}
static inline int ext4_has_inline_data(struct inode *inode)
{
return 0;
}
static inline int ext4_get_inline_size(struct inode *inode)
{
return 0;
}
static inline int ext4_get_max_inline_size(struct inode *inode)
{
return 0;
}
static inline void ext4_write_inline_data(struct inode *inode,
struct ext4_iloc *iloc,
void *buffer, loff_t pos,
unsigned int len)
{
return;
}
static inline int ext4_init_inline_data(handle_t *handle,
struct inode *inode,
unsigned int len)
{
return 0;
}
static inline int ext4_destroy_inline_data(handle_t *handle,
struct inode *inode)
{
return 0;
}
# endif /* CONFIG_EXT4_FS_XATTR */ # endif /* CONFIG_EXT4_FS_XATTR */
#ifdef CONFIG_EXT4_FS_SECURITY #ifdef CONFIG_EXT4_FS_SECURITY
......
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