aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/xattr.c
diff options
context:
space:
mode:
authorTao Ma <boyu.mt@taobao.com>2012-12-10 14:06:02 -0500
committerTheodore Ts'o <tytso@mit.edu>2012-12-10 14:06:02 -0500
commit0d812f77b36c16dff692390508155de2c7f95ea3 (patch)
tree18bf309f2e7a9fb6637ae8385a07f86eb5c05afd /fs/ext4/xattr.c
parent941919856c11d4dd11d4fcabb4dab58bd2b146bf (diff)
ext4: evict inline data out if we need to strore xattr in inode
Now we that store data in the inode, in case we need to store some xattrs and inode doesn't have enough space, Andreas suggested that we should keep the xattr(metadata) in and data should be pushed out. So this patch does the work. Signed-off-by: Tao Ma <boyu.mt@taobao.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r--fs/ext4/xattr.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index a47dc3883a23..2251769a3c53 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -958,9 +958,47 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
958 return 0; 958 return 0;
959} 959}
960 960
961int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, 961int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
962 struct ext4_xattr_info *i, 962 struct ext4_xattr_info *i,
963 struct ext4_xattr_ibody_find *is) 963 struct ext4_xattr_ibody_find *is)
964{
965 struct ext4_xattr_ibody_header *header;
966 struct ext4_xattr_search *s = &is->s;
967 int error;
968
969 if (EXT4_I(inode)->i_extra_isize == 0)
970 return -ENOSPC;
971 error = ext4_xattr_set_entry(i, s);
972 if (error) {
973 if (error == -ENOSPC &&
974 ext4_has_inline_data(inode)) {
975 error = ext4_try_to_evict_inline_data(handle, inode,
976 EXT4_XATTR_LEN(strlen(i->name) +
977 EXT4_XATTR_SIZE(i->value_len)));
978 if (error)
979 return error;
980 error = ext4_xattr_ibody_find(inode, i, is);
981 if (error)
982 return error;
983 error = ext4_xattr_set_entry(i, s);
984 }
985 if (error)
986 return error;
987 }
988 header = IHDR(inode, ext4_raw_inode(&is->iloc));
989 if (!IS_LAST_ENTRY(s->first)) {
990 header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
991 ext4_set_inode_state(inode, EXT4_STATE_XATTR);
992 } else {
993 header->h_magic = cpu_to_le32(0);
994 ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
995 }
996 return 0;
997}
998
999static int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
1000 struct ext4_xattr_info *i,
1001 struct ext4_xattr_ibody_find *is)
964{ 1002{
965 struct ext4_xattr_ibody_header *header; 1003 struct ext4_xattr_ibody_header *header;
966 struct ext4_xattr_search *s = &is->s; 1004 struct ext4_xattr_search *s = &is->s;
@@ -1116,9 +1154,17 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name,
1116{ 1154{
1117 handle_t *handle; 1155 handle_t *handle;
1118 int error, retries = 0; 1156 int error, retries = 0;
1157 int credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb);
1119 1158
1120retry: 1159retry:
1121 handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); 1160 /*
1161 * In case of inline data, we may push out the data to a block,
1162 * So reserve the journal space first.
1163 */
1164 if (ext4_has_inline_data(inode))
1165 credits += ext4_writepage_trans_blocks(inode) + 1;
1166
1167 handle = ext4_journal_start(inode, credits);
1122 if (IS_ERR(handle)) { 1168 if (IS_ERR(handle)) {
1123 error = PTR_ERR(handle); 1169 error = PTR_ERR(handle);
1124 } else { 1170 } else {