Commit 6e8451cb authored by Justin Maggard's avatar Justin Maggard Committed by Jiri Slaby

btrfs: fix defrag 32-bit integer overflow

commit c41570c9 upstream.

When defragging a very large file, the cluster variable can wrap its 32-bit
signed int type and become negative, which eventually gets passed to
btrfs_force_ra() as a very large unsigned long value.  On 32-bit platforms,
this eventually results in an Oops from the SLAB allocator.

Change the cluster and max_cluster signed int variables to unsigned long to
match the readahead functions.  This also allows the min() comparison in
btrfs_defrag_file() to work as intended.
Signed-off-by: default avatarJosef Bacik <jbacik@fb.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
parent 649066ce
......@@ -1014,7 +1014,7 @@ static int should_defrag_range(struct inode *inode, u64 start, int thresh,
static int cluster_pages_for_defrag(struct inode *inode,
struct page **pages,
unsigned long start_index,
int num_pages)
unsigned long num_pages)
{
unsigned long file_end;
u64 isize = i_size_read(inode);
......@@ -1172,8 +1172,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
int defrag_count = 0;
int compress_type = BTRFS_COMPRESS_ZLIB;
int extent_thresh = range->extent_thresh;
int max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT;
int cluster = max_cluster;
unsigned long max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT;
unsigned long cluster = max_cluster;
u64 new_align = ~((u64)128 * 1024 - 1);
struct page **pages = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment