2 * Copyright (c) 2012 Taobao.
3 * Written by Tao Ma <boyu.mt@taobao.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2.1 of the GNU Lesser General Public License
7 * as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 #include "ext4_jbd2.h"
18 #define EXT4_XATTR_SYSTEM_DATA "data"
19 #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS))
21 int ext4_get_inline_size(struct inode *inode)
23 if (EXT4_I(inode)->i_inline_off)
24 return EXT4_I(inode)->i_inline_size;
29 static int get_max_inline_xattr_value_size(struct inode *inode,
30 struct ext4_iloc *iloc)
32 struct ext4_xattr_ibody_header *header;
33 struct ext4_xattr_entry *entry;
34 struct ext4_inode *raw_inode;
37 min_offs = EXT4_SB(inode->i_sb)->s_inode_size -
38 EXT4_GOOD_OLD_INODE_SIZE -
39 EXT4_I(inode)->i_extra_isize -
40 sizeof(struct ext4_xattr_ibody_header);
43 * We need to subtract another sizeof(__u32) since an in-inode xattr
44 * needs an empty 4 bytes to indicate the gap between the xattr entry
45 * and the name/value pair.
47 if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
48 return EXT4_XATTR_SIZE(min_offs -
49 EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)) -
50 EXT4_XATTR_ROUND - sizeof(__u32));
52 raw_inode = ext4_raw_inode(iloc);
53 header = IHDR(inode, raw_inode);
54 entry = IFIRST(header);
56 /* Compute min_offs. */
57 for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
58 if (!entry->e_value_block && entry->e_value_size) {
59 size_t offs = le16_to_cpu(entry->e_value_offs);
65 ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);
67 if (EXT4_I(inode)->i_inline_off) {
68 entry = (struct ext4_xattr_entry *)
69 ((void *)raw_inode + EXT4_I(inode)->i_inline_off);
71 free += le32_to_cpu(entry->e_value_size);
75 free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA));
77 if (free > EXT4_XATTR_ROUND)
78 free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND);
87 * Get the maximum size we now can store in an inode.
88 * If we can't find the space for a xattr entry, don't use the space
89 * of the extents since we have no space to indicate the inline data.
91 int ext4_get_max_inline_size(struct inode *inode)
93 int error, max_inline_size;
94 struct ext4_iloc iloc;
96 if (EXT4_I(inode)->i_extra_isize == 0)
99 error = ext4_get_inode_loc(inode, &iloc);
101 ext4_error_inode(inode, __func__, __LINE__, 0,
102 "can't get inode location %lu",
107 down_read(&EXT4_I(inode)->xattr_sem);
108 max_inline_size = get_max_inline_xattr_value_size(inode, &iloc);
109 up_read(&EXT4_I(inode)->xattr_sem);
113 if (!max_inline_size)
116 return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE;
119 int ext4_has_inline_data(struct inode *inode)
121 return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) &&
122 EXT4_I(inode)->i_inline_off;
126 * this function does not take xattr_sem, which is OK because it is
127 * currently only used in a code path coming form ext4_iget, before
128 * the new inode has been unlocked
130 int ext4_find_inline_data_nolock(struct inode *inode)
132 struct ext4_xattr_ibody_find is = {
133 .s = { .not_found = -ENODATA, },
135 struct ext4_xattr_info i = {
136 .name_index = EXT4_XATTR_INDEX_SYSTEM,
137 .name = EXT4_XATTR_SYSTEM_DATA,
141 if (EXT4_I(inode)->i_extra_isize == 0)
144 error = ext4_get_inode_loc(inode, &is.iloc);
148 error = ext4_xattr_ibody_find(inode, &i, &is);
152 if (!is.s.not_found) {
153 EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
154 (void *)ext4_raw_inode(&is.iloc));
155 EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +
156 le32_to_cpu(is.s.here->e_value_size);
157 ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
164 static int ext4_read_inline_data(struct inode *inode, void *buffer,
166 struct ext4_iloc *iloc)
168 struct ext4_xattr_entry *entry;
169 struct ext4_xattr_ibody_header *header;
171 struct ext4_inode *raw_inode;
176 BUG_ON(len > EXT4_I(inode)->i_inline_size);
178 cp_len = len < EXT4_MIN_INLINE_DATA_SIZE ?
179 len : EXT4_MIN_INLINE_DATA_SIZE;
181 raw_inode = ext4_raw_inode(iloc);
182 memcpy(buffer, (void *)(raw_inode->i_block), cp_len);
190 header = IHDR(inode, raw_inode);
191 entry = (struct ext4_xattr_entry *)((void *)raw_inode +
192 EXT4_I(inode)->i_inline_off);
193 len = min_t(unsigned int, len,
194 (unsigned int)le32_to_cpu(entry->e_value_size));
197 (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len);
205 * write the buffer to the inline inode.
206 * If 'create' is set, we don't need to do the extra copy in the xattr
207 * value since it is already handled by ext4_xattr_ibody_set. That saves
210 void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,
211 void *buffer, loff_t pos, unsigned int len)
213 struct ext4_xattr_entry *entry;
214 struct ext4_xattr_ibody_header *header;
215 struct ext4_inode *raw_inode;
218 BUG_ON(!EXT4_I(inode)->i_inline_off);
219 BUG_ON(pos + len > EXT4_I(inode)->i_inline_size);
221 raw_inode = ext4_raw_inode(iloc);
224 if (pos < EXT4_MIN_INLINE_DATA_SIZE) {
225 cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ?
226 EXT4_MIN_INLINE_DATA_SIZE - pos : len;
227 memcpy((void *)raw_inode->i_block + pos, buffer, cp_len);
237 pos -= EXT4_MIN_INLINE_DATA_SIZE;
238 header = IHDR(inode, raw_inode);
239 entry = (struct ext4_xattr_entry *)((void *)raw_inode +
240 EXT4_I(inode)->i_inline_off);
242 memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos,
246 static int ext4_create_inline_data(handle_t *handle,
247 struct inode *inode, unsigned len)
251 struct ext4_xattr_ibody_find is = {
252 .s = { .not_found = -ENODATA, },
254 struct ext4_xattr_info i = {
255 .name_index = EXT4_XATTR_INDEX_SYSTEM,
256 .name = EXT4_XATTR_SYSTEM_DATA,
259 error = ext4_get_inode_loc(inode, &is.iloc);
263 error = ext4_journal_get_write_access(handle, is.iloc.bh);
267 if (len > EXT4_MIN_INLINE_DATA_SIZE) {
268 value = (void *)empty_zero_page;
269 len -= EXT4_MIN_INLINE_DATA_SIZE;
275 /* Insert the the xttr entry. */
279 error = ext4_xattr_ibody_find(inode, &i, &is);
283 BUG_ON(!is.s.not_found);
285 error = ext4_xattr_ibody_set(handle, inode, &i, &is);
287 if (error == -ENOSPC)
288 ext4_clear_inode_state(inode,
289 EXT4_STATE_MAY_INLINE_DATA);
293 memset((void *)ext4_raw_inode(&is.iloc)->i_block,
294 0, EXT4_MIN_INLINE_DATA_SIZE);
296 EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
297 (void *)ext4_raw_inode(&is.iloc));
298 EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE;
299 ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
300 ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA);
302 error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
309 static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
314 struct ext4_xattr_ibody_find is = {
315 .s = { .not_found = -ENODATA, },
317 struct ext4_xattr_info i = {
318 .name_index = EXT4_XATTR_INDEX_SYSTEM,
319 .name = EXT4_XATTR_SYSTEM_DATA,
322 /* If the old space is ok, write the data directly. */
323 if (len <= EXT4_I(inode)->i_inline_size)
326 error = ext4_get_inode_loc(inode, &is.iloc);
330 error = ext4_xattr_ibody_find(inode, &i, &is);
334 BUG_ON(is.s.not_found);
336 len -= EXT4_MIN_INLINE_DATA_SIZE;
337 value = kzalloc(len, GFP_NOFS);
341 error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
343 if (error == -ENODATA)
346 error = ext4_journal_get_write_access(handle, is.iloc.bh);
350 /* Update the xttr entry. */
354 error = ext4_xattr_ibody_set(handle, inode, &i, &is);
358 EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
359 (void *)ext4_raw_inode(&is.iloc));
360 EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +
361 le32_to_cpu(is.s.here->e_value_size);
362 ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
364 error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
372 int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
376 struct ext4_inode_info *ei = EXT4_I(inode);
378 if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA))
381 size = ext4_get_max_inline_size(inode);
385 down_write(&EXT4_I(inode)->xattr_sem);
387 if (ei->i_inline_off)
388 ret = ext4_update_inline_data(handle, inode, len);
390 ret = ext4_create_inline_data(handle, inode, len);
392 up_write(&EXT4_I(inode)->xattr_sem);
397 static int ext4_destroy_inline_data_nolock(handle_t *handle,
400 struct ext4_inode_info *ei = EXT4_I(inode);
401 struct ext4_xattr_ibody_find is = {
402 .s = { .not_found = 0, },
404 struct ext4_xattr_info i = {
405 .name_index = EXT4_XATTR_INDEX_SYSTEM,
406 .name = EXT4_XATTR_SYSTEM_DATA,
412 if (!ei->i_inline_off)
415 error = ext4_get_inode_loc(inode, &is.iloc);
419 error = ext4_xattr_ibody_find(inode, &i, &is);
423 error = ext4_journal_get_write_access(handle, is.iloc.bh);
427 error = ext4_xattr_ibody_set(handle, inode, &i, &is);
431 memset((void *)ext4_raw_inode(&is.iloc)->i_block,
432 0, EXT4_MIN_INLINE_DATA_SIZE);
434 if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb,
435 EXT4_FEATURE_INCOMPAT_EXTENTS)) {
436 if (S_ISDIR(inode->i_mode) ||
437 S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) {
438 ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);
439 ext4_ext_tree_init(handle, inode);
442 ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);
445 error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
447 EXT4_I(inode)->i_inline_off = 0;
448 EXT4_I(inode)->i_inline_size = 0;
449 ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
452 if (error == -ENODATA)
457 int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)
461 down_write(&EXT4_I(inode)->xattr_sem);
462 ret = ext4_destroy_inline_data_nolock(handle, inode);
463 up_write(&EXT4_I(inode)->xattr_sem);