diff options
| author | Chao Yu <yuchao0@huawei.com> | 2019-03-05 06:32:26 -0500 |
|---|---|---|
| committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2019-03-12 22:02:26 -0400 |
| commit | 2c28aba8b2e2a51749fa66e01b68e1cd5b53e022 (patch) | |
| tree | 618e6bebbaf4daaae08c21f26fbae247461100ef | |
| parent | dd6c89b5f2b93ceced4111e7b69d4efd8c312713 (diff) | |
f2fs: fix to adapt small inline xattr space in __find_inline_xattr()
With below testcase, we will fail to find existed xattr entry:
1. mkfs.f2fs -O extra_attr -O flexible_inline_xattr /dev/zram0
2. mount -t f2fs -o inline_xattr_size=1 /dev/zram0 /mnt/f2fs/
3. touch /mnt/f2fs/file
4. setfattr -n "user.name" -v 0 /mnt/f2fs/file
5. getfattr -n "user.name" /mnt/f2fs/file
/mnt/f2fs/file: user.name: No such attribute
The reason is for inode which has very small inline xattr size,
__find_inline_xattr() will fail to traverse any entry due to first
entry may not be loaded from xattr node yet, later, we may skip to
check entire xattr datas in __find_xattr(), result in such wrong
condition.
This patch adds condition to check such case to avoid this issue.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
| -rw-r--r-- | fs/f2fs/xattr.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index ca47224d78ab..848a785abe25 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
| @@ -224,11 +224,11 @@ static struct f2fs_xattr_entry *__find_inline_xattr(struct inode *inode, | |||
| 224 | { | 224 | { |
| 225 | struct f2fs_xattr_entry *entry; | 225 | struct f2fs_xattr_entry *entry; |
| 226 | unsigned int inline_size = inline_xattr_size(inode); | 226 | unsigned int inline_size = inline_xattr_size(inode); |
| 227 | void *max_addr = base_addr + inline_size; | ||
| 227 | 228 | ||
| 228 | list_for_each_xattr(entry, base_addr) { | 229 | list_for_each_xattr(entry, base_addr) { |
| 229 | if ((void *)entry + sizeof(__u32) > base_addr + inline_size || | 230 | if ((void *)entry + sizeof(__u32) > max_addr || |
| 230 | (void *)XATTR_NEXT_ENTRY(entry) + sizeof(__u32) > | 231 | (void *)XATTR_NEXT_ENTRY(entry) > max_addr) { |
| 231 | base_addr + inline_size) { | ||
| 232 | *last_addr = entry; | 232 | *last_addr = entry; |
| 233 | return NULL; | 233 | return NULL; |
| 234 | } | 234 | } |
| @@ -239,6 +239,13 @@ static struct f2fs_xattr_entry *__find_inline_xattr(struct inode *inode, | |||
| 239 | if (!memcmp(entry->e_name, name, len)) | 239 | if (!memcmp(entry->e_name, name, len)) |
| 240 | break; | 240 | break; |
| 241 | } | 241 | } |
| 242 | |||
| 243 | /* inline xattr header or entry across max inline xattr size */ | ||
| 244 | if (IS_XATTR_LAST_ENTRY(entry) && | ||
| 245 | (void *)entry + sizeof(__u32) > max_addr) { | ||
| 246 | *last_addr = entry; | ||
| 247 | return NULL; | ||
| 248 | } | ||
| 242 | return entry; | 249 | return entry; |
| 243 | } | 250 | } |
| 244 | 251 | ||
