diff options
author | Justin Maggard <jmaggard10@gmail.com> | 2014-01-21 11:18:29 -0800 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2014-06-20 17:33:46 +0200 |
commit | 6e8451cbf0d2e90d8cabac10b47848e3aaf8aa4e (patch) | |
tree | 619d518d4c59d49b71f91c59527d03d2b4cf04cf /fs | |
parent | 649066ce296368e2733ce1d4005f10dc673a9e8f (diff) |
btrfs: fix defrag 32-bit integer overflow
commit c41570c9d29764f797fa35490d72b7395a0105c3 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: Josef Bacik <jbacik@fb.com>
Signed-off-by: Chris Mason <clm@fb.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ioctl.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 669eb53273c..45301541349 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1014,7 +1014,7 @@ out: 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; |