aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2019-03-05 06:32:26 -0500
committerJaegeuk Kim <jaegeuk@kernel.org>2019-03-12 22:02:26 -0400
commit2c28aba8b2e2a51749fa66e01b68e1cd5b53e022 (patch)
tree618e6bebbaf4daaae08c21f26fbae247461100ef
parentdd6c89b5f2b93ceced4111e7b69d4efd8c312713 (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.c13
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