diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-11 12:15:58 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-11 12:15:58 -0500 |
| commit | 2b95550a4323e501e133dac1c9c9cad6ff17f4c1 (patch) | |
| tree | c68b793cfc897e003d08164cb3f03db274766e6f | |
| parent | 13ebfd0601228fbbd92707ce4944ab1a09a4d821 (diff) | |
| parent | 6e78b3f7a193546b1c00a6d084596e774f147169 (diff) | |
Merge branch 'for-linus-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason:
"This has two last minute fixes. The highest priority here is a
regression fix for the decompression code, but we also fixed up a
problem with the 32-bit compat ioctls.
The decompression bug could hand back the wrong data on big reads when
zlib was used. I have a larger cleanup to make the math here less
error prone, but at this stage in the release Omar's patch is the best
choice"
* 'for-linus-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
btrfs: fix btrfs_decompress_buf2page()
btrfs: fix btrfs_compat_ioctl failures on non-compat ioctls
| -rw-r--r-- | fs/btrfs/compression.c | 39 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 6 |
2 files changed, 28 insertions, 17 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 7f390849343b..c4444d6f439f 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
| @@ -1024,6 +1024,7 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, | |||
| 1024 | unsigned long buf_offset; | 1024 | unsigned long buf_offset; |
| 1025 | unsigned long current_buf_start; | 1025 | unsigned long current_buf_start; |
| 1026 | unsigned long start_byte; | 1026 | unsigned long start_byte; |
| 1027 | unsigned long prev_start_byte; | ||
| 1027 | unsigned long working_bytes = total_out - buf_start; | 1028 | unsigned long working_bytes = total_out - buf_start; |
| 1028 | unsigned long bytes; | 1029 | unsigned long bytes; |
| 1029 | char *kaddr; | 1030 | char *kaddr; |
| @@ -1071,26 +1072,34 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, | |||
| 1071 | if (!bio->bi_iter.bi_size) | 1072 | if (!bio->bi_iter.bi_size) |
| 1072 | return 0; | 1073 | return 0; |
| 1073 | bvec = bio_iter_iovec(bio, bio->bi_iter); | 1074 | bvec = bio_iter_iovec(bio, bio->bi_iter); |
| 1074 | 1075 | prev_start_byte = start_byte; | |
| 1075 | start_byte = page_offset(bvec.bv_page) - disk_start; | 1076 | start_byte = page_offset(bvec.bv_page) - disk_start; |
| 1076 | 1077 | ||
| 1077 | /* | 1078 | /* |
| 1078 | * make sure our new page is covered by this | 1079 | * We need to make sure we're only adjusting |
| 1079 | * working buffer | 1080 | * our offset into compression working buffer when |
| 1081 | * we're switching pages. Otherwise we can incorrectly | ||
| 1082 | * keep copying when we were actually done. | ||
| 1080 | */ | 1083 | */ |
| 1081 | if (total_out <= start_byte) | 1084 | if (start_byte != prev_start_byte) { |
| 1082 | return 1; | 1085 | /* |
| 1086 | * make sure our new page is covered by this | ||
| 1087 | * working buffer | ||
| 1088 | */ | ||
| 1089 | if (total_out <= start_byte) | ||
| 1090 | return 1; | ||
| 1083 | 1091 | ||
| 1084 | /* | 1092 | /* |
| 1085 | * the next page in the biovec might not be adjacent | 1093 | * the next page in the biovec might not be adjacent |
| 1086 | * to the last page, but it might still be found | 1094 | * to the last page, but it might still be found |
| 1087 | * inside this working buffer. bump our offset pointer | 1095 | * inside this working buffer. bump our offset pointer |
| 1088 | */ | 1096 | */ |
| 1089 | if (total_out > start_byte && | 1097 | if (total_out > start_byte && |
| 1090 | current_buf_start < start_byte) { | 1098 | current_buf_start < start_byte) { |
| 1091 | buf_offset = start_byte - buf_start; | 1099 | buf_offset = start_byte - buf_start; |
| 1092 | working_bytes = total_out - start_byte; | 1100 | working_bytes = total_out - start_byte; |
| 1093 | current_buf_start = buf_start + buf_offset; | 1101 | current_buf_start = buf_start + buf_offset; |
| 1102 | } | ||
| 1094 | } | 1103 | } |
| 1095 | } | 1104 | } |
| 1096 | 1105 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 33f967d30b2a..21e51b0ba188 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -5653,6 +5653,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 5653 | #ifdef CONFIG_COMPAT | 5653 | #ifdef CONFIG_COMPAT |
| 5654 | long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 5654 | long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 5655 | { | 5655 | { |
| 5656 | /* | ||
| 5657 | * These all access 32-bit values anyway so no further | ||
| 5658 | * handling is necessary. | ||
| 5659 | */ | ||
| 5656 | switch (cmd) { | 5660 | switch (cmd) { |
| 5657 | case FS_IOC32_GETFLAGS: | 5661 | case FS_IOC32_GETFLAGS: |
| 5658 | cmd = FS_IOC_GETFLAGS; | 5662 | cmd = FS_IOC_GETFLAGS; |
| @@ -5663,8 +5667,6 @@ long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 5663 | case FS_IOC32_GETVERSION: | 5667 | case FS_IOC32_GETVERSION: |
| 5664 | cmd = FS_IOC_GETVERSION; | 5668 | cmd = FS_IOC_GETVERSION; |
| 5665 | break; | 5669 | break; |
| 5666 | default: | ||
| 5667 | return -ENOIOCTLCMD; | ||
| 5668 | } | 5670 | } |
| 5669 | 5671 | ||
| 5670 | return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); | 5672 | return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); |
