Commit 67cf5b09a46f72e048501b84996f2f77bc42e947

Authored by Tao Ma
Committed by Theodore Ts'o
1 parent 879b38257b

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: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

Showing 5 changed files with 534 additions and 3 deletions Side-by-side Diff

... ... @@ -9,7 +9,7 @@
9 9 ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
10 10 mmp.o indirect.o extents_status.o
11 11  
12   -ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
  12 +ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o inline.o
13 13 ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
14 14 ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
... ... @@ -402,6 +402,7 @@
402 402 #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
403 403 #define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */
404 404 #define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */
  405 +#define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */
405 406 #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
406 407  
407 408 #define EXT4_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */
... ... @@ -458,6 +459,7 @@
458 459 EXT4_INODE_EXTENTS = 19, /* Inode uses extents */
459 460 EXT4_INODE_EA_INODE = 21, /* Inode used for large EA */
460 461 EXT4_INODE_EOFBLOCKS = 22, /* Blocks allocated beyond EOF */
  462 + EXT4_INODE_INLINE_DATA = 28, /* Data in inode. */
461 463 EXT4_INODE_RESERVED = 31, /* reserved for ext4 lib */
462 464 };
463 465  
... ... @@ -504,6 +506,7 @@
504 506 CHECK_FLAG_VALUE(EXTENTS);
505 507 CHECK_FLAG_VALUE(EA_INODE);
506 508 CHECK_FLAG_VALUE(EOFBLOCKS);
  509 + CHECK_FLAG_VALUE(INLINE_DATA);
507 510 CHECK_FLAG_VALUE(RESERVED);
508 511 }
509 512  
... ... @@ -918,6 +921,10 @@
918 921 /* on-disk additional length */
919 922 __u16 i_extra_isize;
920 923  
  924 + /* Indicate the inline data space. */
  925 + u16 i_inline_off;
  926 + u16 i_inline_size;
  927 +
921 928 #ifdef CONFIG_QUOTA
922 929 /* quota space reservation, managed internally by quota code */
923 930 qsize_t i_reserved_quota;
... ... @@ -1376,6 +1383,7 @@
1376 1383 EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */
1377 1384 EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read
1378 1385 nolocking */
  1386 + EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */
1379 1387 };
1380 1388  
1381 1389 #define EXT4_INODE_BIT_FNS(name, field, offset) \
... ... @@ -1497,7 +1505,7 @@
1497 1505 #define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */
1498 1506 #define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM 0x2000 /* use crc32c for bg */
1499 1507 #define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */
1500   -#define EXT4_FEATURE_INCOMPAT_INLINEDATA 0x8000 /* data in inode */
  1508 +#define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */
1501 1509  
1502 1510 #define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR
1503 1511 #define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \
  1 +/*
  2 + * Copyright (c) 2012 Taobao.
  3 + * Written by Tao Ma <boyu.mt@taobao.com>
  4 + *
  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.
  8 + *
  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.
  13 + */
  14 +#include "ext4_jbd2.h"
  15 +#include "ext4.h"
  16 +#include "xattr.h"
  17 +
  18 +#define EXT4_XATTR_SYSTEM_DATA "data"
  19 +#define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS))
  20 +
  21 +int ext4_get_inline_size(struct inode *inode)
  22 +{
  23 + if (EXT4_I(inode)->i_inline_off)
  24 + return EXT4_I(inode)->i_inline_size;
  25 +
  26 + return 0;
  27 +}
  28 +
  29 +static int get_max_inline_xattr_value_size(struct inode *inode,
  30 + struct ext4_iloc *iloc)
  31 +{
  32 + struct ext4_xattr_ibody_header *header;
  33 + struct ext4_xattr_entry *entry;
  34 + struct ext4_inode *raw_inode;
  35 + int free, min_offs;
  36 +
  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);
  41 +
  42 + /*
  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.
  46 + */
  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));
  51 +
  52 + raw_inode = ext4_raw_inode(iloc);
  53 + header = IHDR(inode, raw_inode);
  54 + entry = IFIRST(header);
  55 +
  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);
  60 + if (offs < min_offs)
  61 + min_offs = offs;
  62 + }
  63 + }
  64 + free = min_offs -
  65 + ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);
  66 +
  67 + if (EXT4_I(inode)->i_inline_off) {
  68 + entry = (struct ext4_xattr_entry *)
  69 + ((void *)raw_inode + EXT4_I(inode)->i_inline_off);
  70 +
  71 + free += le32_to_cpu(entry->e_value_size);
  72 + goto out;
  73 + }
  74 +
  75 + free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA));
  76 +
  77 + if (free > EXT4_XATTR_ROUND)
  78 + free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND);
  79 + else
  80 + free = 0;
  81 +
  82 +out:
  83 + return free;
  84 +}
  85 +
  86 +/*
  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.
  90 + */
  91 +int ext4_get_max_inline_size(struct inode *inode)
  92 +{
  93 + int error, max_inline_size;
  94 + struct ext4_iloc iloc;
  95 +
  96 + if (EXT4_I(inode)->i_extra_isize == 0)
  97 + return 0;
  98 +
  99 + error = ext4_get_inode_loc(inode, &iloc);
  100 + if (error) {
  101 + ext4_error_inode(inode, __func__, __LINE__, 0,
  102 + "can't get inode location %lu",
  103 + inode->i_ino);
  104 + return 0;
  105 + }
  106 +
  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);
  110 +
  111 + brelse(iloc.bh);
  112 +
  113 + if (!max_inline_size)
  114 + return 0;
  115 +
  116 + return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE;
  117 +}
  118 +
  119 +int ext4_has_inline_data(struct inode *inode)
  120 +{
  121 + return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) &&
  122 + EXT4_I(inode)->i_inline_off;
  123 +}
  124 +
  125 +/*
  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
  129 + */
  130 +int ext4_find_inline_data_nolock(struct inode *inode)
  131 +{
  132 + struct ext4_xattr_ibody_find is = {
  133 + .s = { .not_found = -ENODATA, },
  134 + };
  135 + struct ext4_xattr_info i = {
  136 + .name_index = EXT4_XATTR_INDEX_SYSTEM,
  137 + .name = EXT4_XATTR_SYSTEM_DATA,
  138 + };
  139 + int error;
  140 +
  141 + if (EXT4_I(inode)->i_extra_isize == 0)
  142 + return 0;
  143 +
  144 + error = ext4_get_inode_loc(inode, &is.iloc);
  145 + if (error)
  146 + return error;
  147 +
  148 + error = ext4_xattr_ibody_find(inode, &i, &is);
  149 + if (error)
  150 + goto out;
  151 +
  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);
  158 + }
  159 +out:
  160 + brelse(is.iloc.bh);
  161 + return error;
  162 +}
  163 +
  164 +static int ext4_read_inline_data(struct inode *inode, void *buffer,
  165 + unsigned int len,
  166 + struct ext4_iloc *iloc)
  167 +{
  168 + struct ext4_xattr_entry *entry;
  169 + struct ext4_xattr_ibody_header *header;
  170 + int cp_len = 0;
  171 + struct ext4_inode *raw_inode;
  172 +
  173 + if (!len)
  174 + return 0;
  175 +
  176 + BUG_ON(len > EXT4_I(inode)->i_inline_size);
  177 +
  178 + cp_len = len < EXT4_MIN_INLINE_DATA_SIZE ?
  179 + len : EXT4_MIN_INLINE_DATA_SIZE;
  180 +
  181 + raw_inode = ext4_raw_inode(iloc);
  182 + memcpy(buffer, (void *)(raw_inode->i_block), cp_len);
  183 +
  184 + len -= cp_len;
  185 + buffer += cp_len;
  186 +
  187 + if (!len)
  188 + goto out;
  189 +
  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));
  195 +
  196 + memcpy(buffer,
  197 + (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len);
  198 + cp_len += len;
  199 +
  200 +out:
  201 + return cp_len;
  202 +}
  203 +
  204 +/*
  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
  208 + * us one memcpy.
  209 + */
  210 +void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,
  211 + void *buffer, loff_t pos, unsigned int len)
  212 +{
  213 + struct ext4_xattr_entry *entry;
  214 + struct ext4_xattr_ibody_header *header;
  215 + struct ext4_inode *raw_inode;
  216 + int cp_len = 0;
  217 +
  218 + BUG_ON(!EXT4_I(inode)->i_inline_off);
  219 + BUG_ON(pos + len > EXT4_I(inode)->i_inline_size);
  220 +
  221 + raw_inode = ext4_raw_inode(iloc);
  222 + buffer += pos;
  223 +
  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);
  228 +
  229 + len -= cp_len;
  230 + buffer += cp_len;
  231 + pos += cp_len;
  232 + }
  233 +
  234 + if (!len)
  235 + return;
  236 +
  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);
  241 +
  242 + memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos,
  243 + buffer, len);
  244 +}
  245 +
  246 +static int ext4_create_inline_data(handle_t *handle,
  247 + struct inode *inode, unsigned len)
  248 +{
  249 + int error;
  250 + void *value = NULL;
  251 + struct ext4_xattr_ibody_find is = {
  252 + .s = { .not_found = -ENODATA, },
  253 + };
  254 + struct ext4_xattr_info i = {
  255 + .name_index = EXT4_XATTR_INDEX_SYSTEM,
  256 + .name = EXT4_XATTR_SYSTEM_DATA,
  257 + };
  258 +
  259 + error = ext4_get_inode_loc(inode, &is.iloc);
  260 + if (error)
  261 + return error;
  262 +
  263 + error = ext4_journal_get_write_access(handle, is.iloc.bh);
  264 + if (error)
  265 + goto out;
  266 +
  267 + if (len > EXT4_MIN_INLINE_DATA_SIZE) {
  268 + value = (void *)empty_zero_page;
  269 + len -= EXT4_MIN_INLINE_DATA_SIZE;
  270 + } else {
  271 + value = "";
  272 + len = 0;
  273 + }
  274 +
  275 + /* Insert the the xttr entry. */
  276 + i.value = value;
  277 + i.value_len = len;
  278 +
  279 + error = ext4_xattr_ibody_find(inode, &i, &is);
  280 + if (error)
  281 + goto out;
  282 +
  283 + BUG_ON(!is.s.not_found);
  284 +
  285 + error = ext4_xattr_ibody_set(handle, inode, &i, &is);
  286 + if (error) {
  287 + if (error == -ENOSPC)
  288 + ext4_clear_inode_state(inode,
  289 + EXT4_STATE_MAY_INLINE_DATA);
  290 + goto out;
  291 + }
  292 +
  293 + memset((void *)ext4_raw_inode(&is.iloc)->i_block,
  294 + 0, EXT4_MIN_INLINE_DATA_SIZE);
  295 +
  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);
  301 + get_bh(is.iloc.bh);
  302 + error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
  303 +
  304 +out:
  305 + brelse(is.iloc.bh);
  306 + return error;
  307 +}
  308 +
  309 +static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
  310 + unsigned int len)
  311 +{
  312 + int error;
  313 + void *value = NULL;
  314 + struct ext4_xattr_ibody_find is = {
  315 + .s = { .not_found = -ENODATA, },
  316 + };
  317 + struct ext4_xattr_info i = {
  318 + .name_index = EXT4_XATTR_INDEX_SYSTEM,
  319 + .name = EXT4_XATTR_SYSTEM_DATA,
  320 + };
  321 +
  322 + /* If the old space is ok, write the data directly. */
  323 + if (len <= EXT4_I(inode)->i_inline_size)
  324 + return 0;
  325 +
  326 + error = ext4_get_inode_loc(inode, &is.iloc);
  327 + if (error)
  328 + return error;
  329 +
  330 + error = ext4_xattr_ibody_find(inode, &i, &is);
  331 + if (error)
  332 + goto out;
  333 +
  334 + BUG_ON(is.s.not_found);
  335 +
  336 + len -= EXT4_MIN_INLINE_DATA_SIZE;
  337 + value = kzalloc(len, GFP_NOFS);
  338 + if (!value)
  339 + goto out;
  340 +
  341 + error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
  342 + value, len);
  343 + if (error == -ENODATA)
  344 + goto out;
  345 +
  346 + error = ext4_journal_get_write_access(handle, is.iloc.bh);
  347 + if (error)
  348 + goto out;
  349 +
  350 + /* Update the xttr entry. */
  351 + i.value = value;
  352 + i.value_len = len;
  353 +
  354 + error = ext4_xattr_ibody_set(handle, inode, &i, &is);
  355 + if (error)
  356 + goto out;
  357 +
  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);
  363 + get_bh(is.iloc.bh);
  364 + error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
  365 +
  366 +out:
  367 + kfree(value);
  368 + brelse(is.iloc.bh);
  369 + return error;
  370 +}
  371 +
  372 +int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
  373 + unsigned int len)
  374 +{
  375 + int ret, size;
  376 + struct ext4_inode_info *ei = EXT4_I(inode);
  377 +
  378 + if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA))
  379 + return -ENOSPC;
  380 +
  381 + size = ext4_get_max_inline_size(inode);
  382 + if (size < len)
  383 + return -ENOSPC;
  384 +
  385 + down_write(&EXT4_I(inode)->xattr_sem);
  386 +
  387 + if (ei->i_inline_off)
  388 + ret = ext4_update_inline_data(handle, inode, len);
  389 + else
  390 + ret = ext4_create_inline_data(handle, inode, len);
  391 +
  392 + up_write(&EXT4_I(inode)->xattr_sem);
  393 +
  394 + return ret;
  395 +}
  396 +
  397 +static int ext4_destroy_inline_data_nolock(handle_t *handle,
  398 + struct inode *inode)
  399 +{
  400 + struct ext4_inode_info *ei = EXT4_I(inode);
  401 + struct ext4_xattr_ibody_find is = {
  402 + .s = { .not_found = 0, },
  403 + };
  404 + struct ext4_xattr_info i = {
  405 + .name_index = EXT4_XATTR_INDEX_SYSTEM,
  406 + .name = EXT4_XATTR_SYSTEM_DATA,
  407 + .value = NULL,
  408 + .value_len = 0,
  409 + };
  410 + int error;
  411 +
  412 + if (!ei->i_inline_off)
  413 + return 0;
  414 +
  415 + error = ext4_get_inode_loc(inode, &is.iloc);
  416 + if (error)
  417 + return error;
  418 +
  419 + error = ext4_xattr_ibody_find(inode, &i, &is);
  420 + if (error)
  421 + goto out;
  422 +
  423 + error = ext4_journal_get_write_access(handle, is.iloc.bh);
  424 + if (error)
  425 + goto out;
  426 +
  427 + error = ext4_xattr_ibody_set(handle, inode, &i, &is);
  428 + if (error)
  429 + goto out;
  430 +
  431 + memset((void *)ext4_raw_inode(&is.iloc)->i_block,
  432 + 0, EXT4_MIN_INLINE_DATA_SIZE);
  433 +
  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);
  440 + }
  441 + }
  442 + ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);
  443 +
  444 + get_bh(is.iloc.bh);
  445 + error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
  446 +
  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);
  450 +out:
  451 + brelse(is.iloc.bh);
  452 + if (error == -ENODATA)
  453 + error = 0;
  454 + return error;
  455 +}
  456 +
  457 +int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)
  458 +{
  459 + int ret;
  460 +
  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);
  464 +
  465 + return ret;
  466 +}
... ... @@ -3706,8 +3706,10 @@
3706 3706 {
3707 3707 __le32 *magic = (void *)raw_inode +
3708 3708 EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize;
3709   - if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
  3709 + if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
3710 3710 ext4_set_inode_state(inode, EXT4_STATE_XATTR);
  3711 + ext4_find_inline_data_nolock(inode);
  3712 + }
3711 3713 }
3712 3714  
3713 3715 struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
... ... @@ -3780,6 +3782,7 @@
3780 3782 set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
3781 3783  
3782 3784 ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */
  3785 + ei->i_inline_off = 0;
3783 3786 ei->i_dir_start_lookup = 0;
3784 3787 ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
3785 3788 /* We now have enough fields to check if the inode was active or not.
... ... @@ -21,6 +21,7 @@
21 21 #define EXT4_XATTR_INDEX_TRUSTED 4
22 22 #define EXT4_XATTR_INDEX_LUSTRE 5
23 23 #define EXT4_XATTR_INDEX_SECURITY 6
  24 +#define EXT4_XATTR_INDEX_SYSTEM 7
24 25  
25 26 struct ext4_xattr_header {
26 27 __le32 h_magic; /* magic number for identification */
... ... @@ -125,6 +126,19 @@
125 126 struct ext4_xattr_info *i,
126 127 struct ext4_xattr_ibody_find *is);
127 128  
  129 +extern int ext4_has_inline_data(struct inode *inode);
  130 +extern int ext4_get_inline_size(struct inode *inode);
  131 +extern int ext4_get_max_inline_size(struct inode *inode);
  132 +extern int ext4_find_inline_data_nolock(struct inode *inode);
  133 +extern void ext4_write_inline_data(struct inode *inode,
  134 + struct ext4_iloc *iloc,
  135 + void *buffer, loff_t pos,
  136 + unsigned int len);
  137 +extern int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
  138 + unsigned int len);
  139 +extern int ext4_init_inline_data(handle_t *handle, struct inode *inode,
  140 + unsigned int len);
  141 +extern int ext4_destroy_inline_data(handle_t *handle, struct inode *inode);
128 142 # else /* CONFIG_EXT4_FS_XATTR */
129 143  
130 144 static inline int
... ... @@ -201,6 +215,46 @@
201 215 return -EOPNOTSUPP;
202 216 }
203 217  
  218 +static inline int ext4_find_inline_data_nolock(struct inode *inode)
  219 +{
  220 + return 0;
  221 +}
  222 +
  223 +static inline int ext4_has_inline_data(struct inode *inode)
  224 +{
  225 + return 0;
  226 +}
  227 +
  228 +static inline int ext4_get_inline_size(struct inode *inode)
  229 +{
  230 + return 0;
  231 +}
  232 +
  233 +static inline int ext4_get_max_inline_size(struct inode *inode)
  234 +{
  235 + return 0;
  236 +}
  237 +
  238 +static inline void ext4_write_inline_data(struct inode *inode,
  239 + struct ext4_iloc *iloc,
  240 + void *buffer, loff_t pos,
  241 + unsigned int len)
  242 +{
  243 + return;
  244 +}
  245 +
  246 +static inline int ext4_init_inline_data(handle_t *handle,
  247 + struct inode *inode,
  248 + unsigned int len)
  249 +{
  250 + return 0;
  251 +}
  252 +
  253 +static inline int ext4_destroy_inline_data(handle_t *handle,
  254 + struct inode *inode)
  255 +{
  256 + return 0;
  257 +}
204 258 # endif /* CONFIG_EXT4_FS_XATTR */
205 259  
206 260 #ifdef CONFIG_EXT4_FS_SECURITY