diff options
author | Tahsin Erdogan <tahsin@google.com> | 2017-06-29 18:31:59 -0700 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2017-07-05 00:06:30 -0400 |
commit | cf0be23436880a7c9658e2e24259e93cdcb4cc86 (patch) | |
tree | e6bdfe7133ab2c69095b59cbe2c9281abe1751b7 /e2fsck/pass1.c | |
parent | 0446b9907fbdc8f130ec35726bc8b9cdd493a1cb (diff) | |
download | android_external_e2fsprogs-cf0be23436880a7c9658e2e24259e93cdcb4cc86.tar.gz android_external_e2fsprogs-cf0be23436880a7c9658e2e24259e93cdcb4cc86.tar.bz2 android_external_e2fsprogs-cf0be23436880a7c9658e2e24259e93cdcb4cc86.zip |
Use i_size to determine whether a symlink is a fast symlink
Current way of determining whether a symlink is in fast symlink
format is to call ext2fs_inode_data_blocks2(). If number of data
blocks is zero and EXT4_INLINE_DATA_FL flag is not set, then symlink
data must be in inode->i_block.
This heuristic is becoming increasingly hard to maintain because
inode->i_blocks count can also be incremented for blocks used by
extended attributes. Before ea_inode feature, extra block could come
from xattr block, now more blocks can be added because of xattr
inodes.
To address the issue, add a ext2fs_is_fast_symlink() function that
gives a direct answer based on inode->i_size field. This is
equivalent to kernel's ext4_inode_is_fast_symlink() function.
This patch also fixes a few issues related to fast symlink handling:
- Both rdump_symlink() and follow_link() interpreted symlinks with
0 data blocks to always mean fast symlinks. This is incorrect
because symlinks that are stored as inline data also have
0 data blocks. Thus, they try to read everything from
inode->i_block and miss the symlink suffix in inode extra area.
- e2fsck_pass1_check_symlink() had code to handle inode with
EXT4_INLINE_DATA_FL flag twice. The first if block always returns
from the function so the second one is unreachable code.
Signed-off-by: Tahsin Erdogan <tahsin@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'e2fsck/pass1.c')
-rw-r--r-- | e2fsck/pass1.c | 42 |
1 files changed, 8 insertions, 34 deletions
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 4ea7962f..6deaab20 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -179,7 +179,6 @@ int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino, { unsigned int len; int i; - blk64_t blocks; ext2_extent_handle_t handle; struct ext2_extent_info info; struct ext2fs_extent extent; @@ -223,12 +222,15 @@ int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino, return 1; } - blocks = ext2fs_inode_data_blocks2(fs, inode); - if (blocks) { - if (inode->i_flags & EXT4_INLINE_DATA_FL) + if (ext2fs_is_fast_symlink(inode)) { + if (inode->i_size >= sizeof(inode->i_block)) + return 0; + + len = strnlen((char *)inode->i_block, sizeof(inode->i_block)); + if (len == sizeof(inode->i_block)) return 0; + } else { if ((inode->i_size >= fs->blocksize) || - (blocks != fs->blocksize >> 9) || (inode->i_block[0] < fs->super->s_first_data_block) || (inode->i_block[0] >= ext2fs_blocks_count(fs->super))) return 0; @@ -247,34 +249,6 @@ int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino, } if (len == fs->blocksize) return 0; - } else if (inode->i_flags & EXT4_INLINE_DATA_FL) { - char *inline_buf = NULL; - size_t inline_sz = 0; - - if (ext2fs_inline_data_size(fs, ino, &inline_sz)) - return 0; - if (inode->i_size != inline_sz) - return 0; - if (ext2fs_get_mem(inline_sz + 1, &inline_buf)) - return 0; - i = 0; - if (ext2fs_inline_data_get(fs, ino, inode, inline_buf, NULL)) - goto exit_inline; - inline_buf[inline_sz] = 0; - len = strnlen(inline_buf, inline_sz); - if (len != inline_sz) - goto exit_inline; - i = 1; -exit_inline: - ext2fs_free_mem(&inline_buf); - return i; - } else { - if (inode->i_size >= sizeof(inode->i_block)) - return 0; - - len = strnlen((char *)inode->i_block, sizeof(inode->i_block)); - if (len == sizeof(inode->i_block)) - return 0; } if (len != inode->i_size) if ((inode->i_flags & EXT4_ENCRYPT_FL) == 0) @@ -1911,7 +1885,7 @@ void e2fsck_pass1(e2fsck_t ctx) if (inode->i_flags & EXT4_INLINE_DATA_FL) { FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum); continue; - } else if (ext2fs_inode_data_blocks(fs, inode) == 0) { + } else if (ext2fs_is_fast_symlink(inode)) { ctx->fs_fast_symlinks_count++; check_blocks(ctx, &pctx, block_buf, ea_ibody_quota_blocks); |