f2fs: fix to check inline_xattr_size boundary correctly
authorChao Yu <yuchao0@huawei.com>
Thu, 14 Feb 2019 16:08:25 +0000 (00:08 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 6 Mar 2019 03:58:06 +0000 (19:58 -0800)
We use below condition to check inline_xattr_size boundary:

if (!F2FS_OPTION(sbi).inline_xattr_size ||
F2FS_OPTION(sbi).inline_xattr_size >=
DEF_ADDRS_PER_INODE -
F2FS_TOTAL_EXTRA_ATTR_SIZE -
DEF_INLINE_RESERVED_SIZE -
DEF_MIN_INLINE_SIZE)

There is there problems in that check:
- we should allow inline_xattr_size equaling to min size of inline
{data,dentry} area.
- F2FS_TOTAL_EXTRA_ATTR_SIZE and inline_xattr_size are based on
different size unit, previous one is 4 bytes, latter one is 1 bytes.
- DEF_MIN_INLINE_SIZE only indicate min size of inline data area,
however, we need to consider min size of inline dentry area as well,
minimal inline dentry should at least contain two entries: '.' and
'..', so that min inline_dentry size is 40 bytes.

.bitmap 1 * 1 = 1
.reserved 1 * 1 = 1
.dentry 11 * 2 = 22
.filename 8 * 2 = 16
total 40

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/super.c
include/linux/f2fs_fs.h

index 4665bff1bf5578466fe361417990043131277e7a..f1f0d28108522f159ba4caafd442e115957af3a6 100644 (file)
@@ -459,7 +459,6 @@ struct f2fs_flush_device {
 
 /* for inline stuff */
 #define DEF_INLINE_RESERVED_SIZE       1
-#define DEF_MIN_INLINE_SIZE            1
 static inline int get_extra_isize(struct inode *inode);
 static inline int get_inline_xattr_addrs(struct inode *inode);
 #define MAX_INLINE_DATA(inode) (sizeof(__le32) *                       \
index 83bbe7424fc1e19a1a165352860a70a38bc6a421..be8be445c6ed299f0464ea869302e57267818205 100644 (file)
@@ -834,12 +834,13 @@ static int parse_options(struct super_block *sb, char *options)
                                        "set with inline_xattr option");
                        return -EINVAL;
                }
-               if (!F2FS_OPTION(sbi).inline_xattr_size ||
-                       F2FS_OPTION(sbi).inline_xattr_size >=
-                                       DEF_ADDRS_PER_INODE -
-                                       F2FS_TOTAL_EXTRA_ATTR_SIZE -
-                                       DEF_INLINE_RESERVED_SIZE -
-                                       DEF_MIN_INLINE_SIZE) {
+               if (F2FS_OPTION(sbi).inline_xattr_size <
+                       sizeof(struct f2fs_xattr_header) / sizeof(__le32) ||
+                       F2FS_OPTION(sbi).inline_xattr_size >
+                       DEF_ADDRS_PER_INODE -
+                       F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) -
+                       DEF_INLINE_RESERVED_SIZE -
+                       MIN_INLINE_DENTRY_SIZE / sizeof(__le32)) {
                        f2fs_msg(sb, KERN_ERR,
                                        "inline xattr size is out of range");
                        return -EINVAL;
index 8d57aaee8166beac5d007cad7ed1609db004373d..666db8eb71e01b76a09f553ab5474beaa9c564a5 100644 (file)
@@ -490,12 +490,12 @@ typedef __le32    f2fs_hash_t;
 
 /*
  * space utilization of regular dentry and inline dentry (w/o extra reservation)
- *             regular dentry                  inline dentry
- * bitmap      1 * 27 = 27                     1 * 23 = 23
- * reserved    1 * 3 = 3                       1 * 7 = 7
- * dentry      11 * 214 = 2354                 11 * 182 = 2002
- * filename    8 * 214 = 1712                  8 * 182 = 1456
- * total       4096                            3488
+ *             regular dentry          inline dentry (def)     inline dentry (min)
+ * bitmap      1 * 27 = 27             1 * 23 = 23             1 * 1 = 1
+ * reserved    1 * 3 = 3               1 * 7 = 7               1 * 1 = 1
+ * dentry      11 * 214 = 2354         11 * 182 = 2002         11 * 2 = 22
+ * filename    8 * 214 = 1712          8 * 182 = 1456          8 * 2 = 16
+ * total       4096                    3488                    40
  *
  * Note: there are more reserved space in inline dentry than in regular
  * dentry, when converting inline dentry we should handle this carefully.
@@ -507,6 +507,7 @@ typedef __le32      f2fs_hash_t;
 #define SIZE_OF_RESERVED       (PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \
                                F2FS_SLOT_LEN) * \
                                NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
+#define MIN_INLINE_DENTRY_SIZE         40      /* just include '.' and '..' entries */
 
 /* One directory entry slot representing F2FS_SLOT_LEN-sized file name */
 struct f2fs_dir_entry {