Skip to content

Commit

Permalink
f2fs: avoid overflow when large directory feathure is enabled
Browse files Browse the repository at this point in the history
When large directory feathure is enable, We have one case which could cause
overflow in dir_buckets() as following:
special case: level + dir_level >= 32 and level < MAX_DIR_HASH_DEPTH / 2.

Here we define MAX_DIR_BUCKETS to limit the return value when the condition
could trigger potential overflow.

Changes from V1
 o modify description of calculation in f2fs.txt suggested by Changman Lee.

Suggested-by: Changman Lee <cm224.lee@samsung.com>
Signed-off-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
  • Loading branch information
Chao Yu authored and Jaegeuk Kim committed Jun 4, 2014
1 parent d631abd commit bfec07d
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 6 deletions.
8 changes: 4 additions & 4 deletions Documentation/filesystems/f2fs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,11 @@ The number of blocks and buckets are determined by,
# of blocks in level #n = |
`- 4, Otherwise

,- 2^ (n + dir_level),
| if n < MAX_DIR_HASH_DEPTH / 2,
,- 2^(n + dir_level),
| if n + dir_level < MAX_DIR_HASH_DEPTH / 2,
# of buckets in level #n = |
`- 2^((MAX_DIR_HASH_DEPTH / 2 + dir_level) - 1),
Otherwise
`- 2^((MAX_DIR_HASH_DEPTH / 2) - 1),
Otherwise

When F2FS finds a file name in a directory, at first a hash value of the file
name is calculated. Then, F2FS scans the hash table in level #0 to find the
Expand Down
4 changes: 2 additions & 2 deletions fs/f2fs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ static unsigned long dir_blocks(struct inode *inode)

static unsigned int dir_buckets(unsigned int level, int dir_level)
{
if (level < MAX_DIR_HASH_DEPTH / 2)
if (level + dir_level < MAX_DIR_HASH_DEPTH / 2)
return 1 << (level + dir_level);
else
return 1 << ((MAX_DIR_HASH_DEPTH / 2 + dir_level) - 1);
return MAX_DIR_BUCKETS;
}

static unsigned int bucket_blocks(unsigned int level)
Expand Down
3 changes: 3 additions & 0 deletions include/linux/f2fs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ typedef __le32 f2fs_hash_t;
/* MAX level for dir lookup */
#define MAX_DIR_HASH_DEPTH 63

/* MAX buckets in one level of dir */
#define MAX_DIR_BUCKETS (1 << ((MAX_DIR_HASH_DEPTH / 2) - 1))

#define SIZE_OF_DIR_ENTRY 11 /* by byte */
#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
BITS_PER_BYTE)
Expand Down

0 comments on commit bfec07d

Please sign in to comment.