diff options
author | Justin Maggard <jmaggard10@gmail.com> | 2014-01-21 14:18:29 -0500 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-01-28 16:20:43 -0500 |
commit | c41570c9d29764f797fa35490d72b7395a0105c3 (patch) | |
tree | 899a43d2fe64b55478215fbb061f963cd87cf549 /fs/btrfs | |
parent | c736c095de53c1a0a23909239d69bb56693df8ef (diff) |
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/btrfs')
-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 62c62b4fa55b..34772cbcc7aa 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -1036,7 +1036,7 @@ out: | |||
1036 | static int cluster_pages_for_defrag(struct inode *inode, | 1036 | static int cluster_pages_for_defrag(struct inode *inode, |
1037 | struct page **pages, | 1037 | struct page **pages, |
1038 | unsigned long start_index, | 1038 | unsigned long start_index, |
1039 | int num_pages) | 1039 | unsigned long num_pages) |
1040 | { | 1040 | { |
1041 | unsigned long file_end; | 1041 | unsigned long file_end; |
1042 | u64 isize = i_size_read(inode); | 1042 | u64 isize = i_size_read(inode); |
@@ -1194,8 +1194,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1194 | int defrag_count = 0; | 1194 | int defrag_count = 0; |
1195 | int compress_type = BTRFS_COMPRESS_ZLIB; | 1195 | int compress_type = BTRFS_COMPRESS_ZLIB; |
1196 | int extent_thresh = range->extent_thresh; | 1196 | int extent_thresh = range->extent_thresh; |
1197 | int max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT; | 1197 | unsigned long max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT; |
1198 | int cluster = max_cluster; | 1198 | unsigned long cluster = max_cluster; |
1199 | u64 new_align = ~((u64)128 * 1024 - 1); | 1199 | u64 new_align = ~((u64)128 * 1024 - 1); |
1200 | struct page **pages = NULL; | 1200 | struct page **pages = NULL; |
1201 | 1201 | ||