summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJustin Maggard2014-01-21 20:18:29 +0100
committerChris Mason2014-01-28 22:20:43 +0100
commitc41570c9d29764f797fa35490d72b7395a0105c3 (patch)
tree899a43d2fe64b55478215fbb061f963cd87cf549 /fs
parentbtrfs: sysfs: list the NO_HOLES feature (diff)
downloadkernel-qcow2-linux-c41570c9d29764f797fa35490d72b7395a0105c3.tar.gz
kernel-qcow2-linux-c41570c9d29764f797fa35490d72b7395a0105c3.tar.xz
kernel-qcow2-linux-c41570c9d29764f797fa35490d72b7395a0105c3.zip
btrfs: fix defrag 32-bit integer overflow
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ioctl.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 62c62b4fa55b..34772cbcc7aa 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1036,7 +1036,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);
@@ -1194,8 +1194,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;