Pull btrfs fixes from David Sterba: "Last minute fixes for crash on 32bit architectures when compression is in use. It's a regression introduced in 5.15-rc and I'd really like not let this into the final release, fixes via stable trees would add unnecessary delay. The problem is on 32bit architectures with highmem enabled, the pages for compression may need to be kmapped, while the patches removed that as we don't use GFP_HIGHMEM allocations anymore. The pages that don't come from local allocation still may be from highmem. Despite being on 32bit there's enough such ARM machines in use so it's not a marginal issue. I did full reverts of the patches one by one instead of a huge one. There's one exception for the "lzo" revert as there was an intermediate patch touching the same code to make it compatible with subpage. I can't revert that one too, so the revert in lzo.c is manual. Qu Wenruo has worked on that with me and verified the changes" * tag 'for-5.15-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: Revert "btrfs: compression: drop kmap/kunmap from lzo" Revert "btrfs: compression: drop kmap/kunmap from zlib" Revert "btrfs: compression: drop kmap/kunmap from zstd" Revert "btrfs: compression: drop kmap/kunmap from generic helpers"
Unified · Split
| @@ -172,9 +172,10 @@ static int check_compressed_csum(struct btrfs_inode *inode, struct bio *bio, · 171 unmodified lines | |||
| 172 | /* Hash through the page sector by sector */ | 172 | /* Hash through the page sector by sector */ |
| 173 | for (pg_offset = 0; pg_offset < bytes_left; | 173 | for (pg_offset = 0; pg_offset < bytes_left; |
| 174 | pg_offset += sectorsize) { | 174 | pg_offset += sectorsize) { |
| 175 | kaddr = page_address(page); | 175 | kaddr = kmap_atomic(page); |
| 176 | crypto_shash_digest(shash, kaddr + pg_offset, | 176 | crypto_shash_digest(shash, kaddr + pg_offset, |
| 177 | sectorsize, csum); | 177 | sectorsize, csum); |
| 178 | kunmap_atomic(kaddr); | ||
| 178 | 179 | ||
| 179 | if (memcmp(&csum, cb_sum, csum_size) != 0) { | 180 | if (memcmp(&csum, cb_sum, csum_size) != 0) { |
| 180 | btrfs_print_data_csum_error(inode, disk_start, | 181 | btrfs_print_data_csum_error(inode, disk_start, |
| @@ -287,8 +287,9 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, · 286 unmodified lines | |||
| 287 | cur_size = min_t(unsigned long, compressed_size, | 287 | cur_size = min_t(unsigned long, compressed_size, |
| 288 | PAGE_SIZE); | 288 | PAGE_SIZE); |
| 289 | 289 | ||
| 290 | kaddr = page_address(cpage); | 290 | kaddr = kmap_atomic(cpage); |
| 291 | write_extent_buffer(leaf, kaddr, ptr, cur_size); | 291 | write_extent_buffer(leaf, kaddr, ptr, cur_size); |
| 292 | kunmap_atomic(kaddr); | ||
| 292 | 293 | ||
| 293 | i++; | 294 | i++; |
| 294 | ptr += cur_size; | 295 | ptr += cur_size; |
| @@ -141,7 +141,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping, · 140 unmodified lines | |||
| 141 | *total_in = 0; | 141 | *total_in = 0; |
| 142 | 142 | ||
| 143 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); | 143 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); |
| 144 | data_in = page_address(in_page); | 144 | data_in = kmap(in_page); |
| 145 | 145 | ||
| 146 | /* | 146 | /* |
| 147 | * store the size of all chunks of compressed data in | 147 | * store the size of all chunks of compressed data in |
| @@ -152,7 +152,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping, · 4 unmodified lines | |||
| 152 | ret = -ENOMEM; | 152 | ret = -ENOMEM; |
| 153 | goto out; | 153 | goto out; |
| 154 | } | 154 | } |
| 155 | cpage_out = page_address(out_page); | 155 | cpage_out = kmap(out_page); |
| 156 | out_offset = LZO_LEN; | 156 | out_offset = LZO_LEN; |
| 157 | tot_out = LZO_LEN; | 157 | tot_out = LZO_LEN; |
| 158 | pages[0] = out_page; | 158 | pages[0] = out_page; |
| @@ -210,6 +210,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping, · 51 unmodified lines | |||
| 210 | if (out_len == 0 && tot_in >= len) | 210 | if (out_len == 0 && tot_in >= len) |
| 211 | break; | 211 | break; |
| 212 | 212 | ||
| 213 | kunmap(out_page); | ||
| 213 | if (nr_pages == nr_dest_pages) { | 214 | if (nr_pages == nr_dest_pages) { |
| 214 | out_page = NULL; | 215 | out_page = NULL; |
| 215 | ret = -E2BIG; | 216 | ret = -E2BIG; |
| @@ -221,7 +222,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping, · 5 unmodified lines | |||
| 221 | ret = -ENOMEM; | 222 | ret = -ENOMEM; |
| 222 | goto out; | 223 | goto out; |
| 223 | } | 224 | } |
| 224 | cpage_out = page_address(out_page); | 225 | cpage_out = kmap(out_page); |
| 225 | pages[nr_pages++] = out_page; | 226 | pages[nr_pages++] = out_page; |
| 226 | 227 | ||
| 227 | pg_bytes_left = PAGE_SIZE; | 228 | pg_bytes_left = PAGE_SIZE; |
| @@ -243,11 +244,12 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping, · 15 unmodified lines | |||
| 243 | break; | 244 | break; |
| 244 | 245 | ||
| 245 | bytes_left = len - tot_in; | 246 | bytes_left = len - tot_in; |
| 247 | kunmap(in_page); | ||
| 246 | put_page(in_page); | 248 | put_page(in_page); |
| 247 | 249 | ||
| 248 | start += PAGE_SIZE; | 250 | start += PAGE_SIZE; |
| 249 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); | 251 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); |
| 250 | data_in = page_address(in_page); | 252 | data_in = kmap(in_page); |
| 251 | in_len = min(bytes_left, PAGE_SIZE); | 253 | in_len = min(bytes_left, PAGE_SIZE); |
| 252 | } | 254 | } |
| 253 | 255 | ||
| @@ -257,17 +259,22 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping, · 3 unmodified lines | |||
| 257 | } | 259 | } |
| 258 | 260 | ||
| 259 | /* store the size of all chunks of compressed data */ | 261 | /* store the size of all chunks of compressed data */ |
| 260 | sizes_ptr = page_address(pages[0]); | 262 | sizes_ptr = kmap_local_page(pages[0]); |
| 261 | write_compress_length(sizes_ptr, tot_out); | 263 | write_compress_length(sizes_ptr, tot_out); |
| 264 | kunmap_local(sizes_ptr); | ||
| 262 | 265 | ||
| 263 | ret = 0; | 266 | ret = 0; |
| 264 | *total_out = tot_out; | 267 | *total_out = tot_out; |
| 265 | *total_in = tot_in; | 268 | *total_in = tot_in; |
| 266 | out: | 269 | out: |
| 267 | *out_pages = nr_pages; | 270 | *out_pages = nr_pages; |
| 271 | if (out_page) | ||
| 272 | kunmap(out_page); | ||
| 268 | 273 | ||
| 269 | if (in_page) | 274 | if (in_page) { |
| 275 | kunmap(in_page); | ||
| 270 | put_page(in_page); | 276 | put_page(in_page); |
| 277 | } | ||
| 271 | 278 | ||
| 272 | return ret; | 279 | return ret; |
| 273 | } | 280 | } |
| @@ -283,6 +290,7 @@ static void copy_compressed_segment(struct compressed_bio *cb, · 9 unmodified lines | |||
| 283 | u32 orig_in = *cur_in; | 290 | u32 orig_in = *cur_in; |
| 284 | 291 | ||
| 285 | while (*cur_in < orig_in + len) { | 292 | while (*cur_in < orig_in + len) { |
| 293 | char *kaddr; | ||
| 286 | struct page *cur_page; | 294 | struct page *cur_page; |
| 287 | u32 copy_len = min_t(u32, PAGE_SIZE - offset_in_page(*cur_in), | 295 | u32 copy_len = min_t(u32, PAGE_SIZE - offset_in_page(*cur_in), |
| 288 | orig_in + len - *cur_in); | 296 | orig_in + len - *cur_in); |
| @@ -290,9 +298,11 @@ static void copy_compressed_segment(struct compressed_bio *cb, · 1 unmodified line | |||
| 290 | ASSERT(copy_len); | 298 | ASSERT(copy_len); |
| 291 | cur_page = cb->compressed_pages[*cur_in / PAGE_SIZE]; | 299 | cur_page = cb->compressed_pages[*cur_in / PAGE_SIZE]; |
| 292 | 300 | ||
| 301 | kaddr = kmap(cur_page); | ||
| 293 | memcpy(dest + *cur_in - orig_in, | 302 | memcpy(dest + *cur_in - orig_in, |
| 294 | page_address(cur_page) + offset_in_page(*cur_in), | 303 | kaddr + offset_in_page(*cur_in), |
| 295 | copy_len); | 304 | copy_len); |
| 305 | kunmap(cur_page); | ||
| 296 | 306 | ||
| 297 | *cur_in += copy_len; | 307 | *cur_in += copy_len; |
| 298 | } | 308 | } |
| @@ -303,6 +313,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 4 unmodified lines | |||
| 303 | struct workspace *workspace = list_entry(ws, struct workspace, list); | 313 | struct workspace *workspace = list_entry(ws, struct workspace, list); |
| 304 | const struct btrfs_fs_info *fs_info = btrfs_sb(cb->inode->i_sb); | 314 | const struct btrfs_fs_info *fs_info = btrfs_sb(cb->inode->i_sb); |
| 305 | const u32 sectorsize = fs_info->sectorsize; | 315 | const u32 sectorsize = fs_info->sectorsize; |
| 316 | char *kaddr; | ||
| 306 | int ret; | 317 | int ret; |
| 307 | /* Compressed data length, can be unaligned */ | 318 | /* Compressed data length, can be unaligned */ |
| 308 | u32 len_in; | 319 | u32 len_in; |
| @@ -311,7 +322,9 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 2 unmodified lines | |||
| 311 | /* Bytes decompressed so far */ | 322 | /* Bytes decompressed so far */ |
| 312 | u32 cur_out = 0; | 323 | u32 cur_out = 0; |
| 313 | 324 | ||
| 314 | len_in = read_compress_length(page_address(cb->compressed_pages[0])); | 325 | kaddr = kmap(cb->compressed_pages[0]); |
| 326 | len_in = read_compress_length(kaddr); | ||
| 327 | kunmap(cb->compressed_pages[0]); | ||
| 315 | cur_in += LZO_LEN; | 328 | cur_in += LZO_LEN; |
| 316 | 329 | ||
| 317 | /* | 330 | /* |
| @@ -344,9 +357,9 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 26 unmodified lines | |||
| 344 | ASSERT(cur_in / sectorsize == | 357 | ASSERT(cur_in / sectorsize == |
| 345 | (cur_in + LZO_LEN - 1) / sectorsize); | 358 | (cur_in + LZO_LEN - 1) / sectorsize); |
| 346 | cur_page = cb->compressed_pages[cur_in / PAGE_SIZE]; | 359 | cur_page = cb->compressed_pages[cur_in / PAGE_SIZE]; |
| 360 | kaddr = kmap(cur_page); | ||
| 347 | ASSERT(cur_page); | 361 | ASSERT(cur_page); |
| 348 | seg_len = read_compress_length(page_address(cur_page) + | 362 | seg_len = read_compress_length(kaddr + offset_in_page(cur_in)); |
| 349 | offset_in_page(cur_in)); | ||
| 350 | cur_in += LZO_LEN; | 363 | cur_in += LZO_LEN; |
| 351 | 364 | ||
| 352 | /* Copy the compressed segment payload into workspace */ | 365 | /* Copy the compressed segment payload into workspace */ |
| @@ -431,7 +444,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in, · 78 unmodified lines | |||
| 431 | destlen = min_t(unsigned long, destlen, PAGE_SIZE); | 444 | destlen = min_t(unsigned long, destlen, PAGE_SIZE); |
| 432 | bytes = min_t(unsigned long, destlen, out_len - start_byte); | 445 | bytes = min_t(unsigned long, destlen, out_len - start_byte); |
| 433 | 446 | ||
| 434 | kaddr = page_address(dest_page); | 447 | kaddr = kmap_local_page(dest_page); |
| 435 | memcpy(kaddr, workspace->buf + start_byte, bytes); | 448 | memcpy(kaddr, workspace->buf + start_byte, bytes); |
| 436 | 449 | ||
| 437 | /* | 450 | /* |
| @@ -441,6 +454,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in, · 3 unmodified lines | |||
| 441 | */ | 454 | */ |
| 442 | if (bytes < destlen) | 455 | if (bytes < destlen) |
| 443 | memset(kaddr+bytes, 0, destlen-bytes); | 456 | memset(kaddr+bytes, 0, destlen-bytes); |
| 457 | kunmap_local(kaddr); | ||
| 444 | out: | 458 | out: |
| 445 | return ret; | 459 | return ret; |
| 446 | } | 460 | } |
| @@ -126,7 +126,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 125 unmodified lines | |||
| 126 | ret = -ENOMEM; | 126 | ret = -ENOMEM; |
| 127 | goto out; | 127 | goto out; |
| 128 | } | 128 | } |
| 129 | cpage_out = page_address(out_page); | 129 | cpage_out = kmap(out_page); |
| 130 | pages[0] = out_page; | 130 | pages[0] = out_page; |
| 131 | nr_pages = 1; | 131 | nr_pages = 1; |
| 132 | 132 | ||
| @@ -148,22 +148,26 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 15 unmodified lines | |||
| 148 | int i; | 148 | int i; |
| 149 | 149 | ||
| 150 | for (i = 0; i < in_buf_pages; i++) { | 150 | for (i = 0; i < in_buf_pages; i++) { |
| 151 | if (in_page) | 151 | if (in_page) { |
| 152 | kunmap(in_page); | ||
| 152 | put_page(in_page); | 153 | put_page(in_page); |
| 154 | } | ||
| 153 | in_page = find_get_page(mapping, | 155 | in_page = find_get_page(mapping, |
| 154 | start >> PAGE_SHIFT); | 156 | start >> PAGE_SHIFT); |
| 155 | data_in = page_address(in_page); | 157 | data_in = kmap(in_page); |
| 156 | memcpy(workspace->buf + i * PAGE_SIZE, | 158 | memcpy(workspace->buf + i * PAGE_SIZE, |
| 157 | data_in, PAGE_SIZE); | 159 | data_in, PAGE_SIZE); |
| 158 | start += PAGE_SIZE; | 160 | start += PAGE_SIZE; |
| 159 | } | 161 | } |
| 160 | workspace->strm.next_in = workspace->buf; | 162 | workspace->strm.next_in = workspace->buf; |
| 161 | } else { | 163 | } else { |
| 162 | if (in_page) | 164 | if (in_page) { |
| 165 | kunmap(in_page); | ||
| 163 | put_page(in_page); | 166 | put_page(in_page); |
| 167 | } | ||
| 164 | in_page = find_get_page(mapping, | 168 | in_page = find_get_page(mapping, |
| 165 | start >> PAGE_SHIFT); | 169 | start >> PAGE_SHIFT); |
| 166 | data_in = page_address(in_page); | 170 | data_in = kmap(in_page); |
| 167 | start += PAGE_SIZE; | 171 | start += PAGE_SIZE; |
| 168 | workspace->strm.next_in = data_in; | 172 | workspace->strm.next_in = data_in; |
| 169 | } | 173 | } |
| @@ -192,6 +196,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 22 unmodified lines | |||
| 192 | * the stream end if required | 196 | * the stream end if required |
| 193 | */ | 197 | */ |
| 194 | if (workspace->strm.avail_out == 0) { | 198 | if (workspace->strm.avail_out == 0) { |
| 199 | kunmap(out_page); | ||
| 195 | if (nr_pages == nr_dest_pages) { | 200 | if (nr_pages == nr_dest_pages) { |
| 196 | out_page = NULL; | 201 | out_page = NULL; |
| 197 | ret = -E2BIG; | 202 | ret = -E2BIG; |
| @@ -202,7 +207,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 4 unmodified lines | |||
| 202 | ret = -ENOMEM; | 207 | ret = -ENOMEM; |
| 203 | goto out; | 208 | goto out; |
| 204 | } | 209 | } |
| 205 | cpage_out = page_address(out_page); | 210 | cpage_out = kmap(out_page); |
| 206 | pages[nr_pages] = out_page; | 211 | pages[nr_pages] = out_page; |
| 207 | nr_pages++; | 212 | nr_pages++; |
| 208 | workspace->strm.avail_out = PAGE_SIZE; | 213 | workspace->strm.avail_out = PAGE_SIZE; |
| @@ -229,6 +234,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 20 unmodified lines | |||
| 229 | goto out; | 234 | goto out; |
| 230 | } else if (workspace->strm.avail_out == 0) { | 235 | } else if (workspace->strm.avail_out == 0) { |
| 231 | /* get another page for the stream end */ | 236 | /* get another page for the stream end */ |
| 237 | kunmap(out_page); | ||
| 232 | if (nr_pages == nr_dest_pages) { | 238 | if (nr_pages == nr_dest_pages) { |
| 233 | out_page = NULL; | 239 | out_page = NULL; |
| 234 | ret = -E2BIG; | 240 | ret = -E2BIG; |
| @@ -239,7 +245,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 4 unmodified lines | |||
| 239 | ret = -ENOMEM; | 245 | ret = -ENOMEM; |
| 240 | goto out; | 246 | goto out; |
| 241 | } | 247 | } |
| 242 | cpage_out = page_address(out_page); | 248 | cpage_out = kmap(out_page); |
| 243 | pages[nr_pages] = out_page; | 249 | pages[nr_pages] = out_page; |
| 244 | nr_pages++; | 250 | nr_pages++; |
| 245 | workspace->strm.avail_out = PAGE_SIZE; | 251 | workspace->strm.avail_out = PAGE_SIZE; |
| @@ -258,8 +264,13 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 12 unmodified lines | |||
| 258 | *total_in = workspace->strm.total_in; | 264 | *total_in = workspace->strm.total_in; |
| 259 | out: | 265 | out: |
| 260 | *out_pages = nr_pages; | 266 | *out_pages = nr_pages; |
| 261 | if (in_page) | 267 | if (out_page) |
| 268 | kunmap(out_page); | ||
| 269 | |||
| 270 | if (in_page) { | ||
| 271 | kunmap(in_page); | ||
| 262 | put_page(in_page); | 272 | put_page(in_page); |
| 273 | } | ||
| 263 | return ret; | 274 | return ret; |
| 264 | } | 275 | } |
| 265 | 276 | ||
| @@ -276,7 +287,7 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 10 unmodified lines | |||
| 276 | unsigned long buf_start; | 287 | unsigned long buf_start; |
| 277 | struct page **pages_in = cb->compressed_pages; | 288 | struct page **pages_in = cb->compressed_pages; |
| 278 | 289 | ||
| 279 | data_in = page_address(pages_in[page_in_index]); | 290 | data_in = kmap(pages_in[page_in_index]); |
| 280 | workspace->strm.next_in = data_in; | 291 | workspace->strm.next_in = data_in; |
| 281 | workspace->strm.avail_in = min_t(size_t, srclen, PAGE_SIZE); | 292 | workspace->strm.avail_in = min_t(size_t, srclen, PAGE_SIZE); |
| 282 | workspace->strm.total_in = 0; | 293 | workspace->strm.total_in = 0; |
| @@ -298,6 +309,7 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 15 unmodified lines | |||
| 298 | 309 | ||
| 299 | if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) { | 310 | if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) { |
| 300 | pr_warn("BTRFS: inflateInit failed\n"); | 311 | pr_warn("BTRFS: inflateInit failed\n"); |
| 312 | kunmap(pages_in[page_in_index]); | ||
| 301 | return -EIO; | 313 | return -EIO; |
| 302 | } | 314 | } |
| 303 | while (workspace->strm.total_in < srclen) { | 315 | while (workspace->strm.total_in < srclen) { |
| @@ -324,13 +336,13 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 20 unmodified lines | |||
| 324 | 336 | ||
| 325 | if (workspace->strm.avail_in == 0) { | 337 | if (workspace->strm.avail_in == 0) { |
| 326 | unsigned long tmp; | 338 | unsigned long tmp; |
| 327 | 339 | kunmap(pages_in[page_in_index]); | |
| 328 | page_in_index++; | 340 | page_in_index++; |
| 329 | if (page_in_index >= total_pages_in) { | 341 | if (page_in_index >= total_pages_in) { |
| 330 | data_in = NULL; | 342 | data_in = NULL; |
| 331 | break; | 343 | break; |
| 332 | } | 344 | } |
| 333 | data_in = page_address(pages_in[page_in_index]); | 345 | data_in = kmap(pages_in[page_in_index]); |
| 334 | workspace->strm.next_in = data_in; | 346 | workspace->strm.next_in = data_in; |
| 335 | tmp = srclen - workspace->strm.total_in; | 347 | tmp = srclen - workspace->strm.total_in; |
| 336 | workspace->strm.avail_in = min(tmp, PAGE_SIZE); | 348 | workspace->strm.avail_in = min(tmp, PAGE_SIZE); |
| @@ -342,6 +354,8 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 5 unmodified lines | |||
| 342 | ret = 0; | 354 | ret = 0; |
| 343 | done: | 355 | done: |
| 344 | zlib_inflateEnd(&workspace->strm); | 356 | zlib_inflateEnd(&workspace->strm); |
| 357 | if (data_in) | ||
| 358 | kunmap(pages_in[page_in_index]); | ||
| 345 | if (!ret) | 359 | if (!ret) |
| 346 | zero_fill_bio(cb->orig_bio); | 360 | zero_fill_bio(cb->orig_bio); |
| 347 | return ret; | 361 | return ret; |
| @@ -399,7 +399,7 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, · 398 unmodified lines | |||
| 399 | 399 | ||
| 400 | /* map in the first page of input data */ | 400 | /* map in the first page of input data */ |
| 401 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); | 401 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); |
| 402 | workspace->in_buf.src = page_address(in_page); | 402 | workspace->in_buf.src = kmap(in_page); |
| 403 | workspace->in_buf.pos = 0; | 403 | workspace->in_buf.pos = 0; |
| 404 | workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE); | 404 | workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE); |
| 405 | 405 | ||
| @@ -411,7 +411,7 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, · 5 unmodified lines | |||
| 411 | goto out; | 411 | goto out; |
| 412 | } | 412 | } |
| 413 | pages[nr_pages++] = out_page; | 413 | pages[nr_pages++] = out_page; |
| 414 | workspace->out_buf.dst = page_address(out_page); | 414 | workspace->out_buf.dst = kmap(out_page); |
| 415 | workspace->out_buf.pos = 0; | 415 | workspace->out_buf.pos = 0; |
| 416 | workspace->out_buf.size = min_t(size_t, max_out, PAGE_SIZE); | 416 | workspace->out_buf.size = min_t(size_t, max_out, PAGE_SIZE); |
| 417 | 417 | ||
| @@ -446,6 +446,7 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, · 28 unmodified lines | |||
| 446 | if (workspace->out_buf.pos == workspace->out_buf.size) { | 446 | if (workspace->out_buf.pos == workspace->out_buf.size) { |
| 447 | tot_out += PAGE_SIZE; | 447 | tot_out += PAGE_SIZE; |
| 448 | max_out -= PAGE_SIZE; | 448 | max_out -= PAGE_SIZE; |
| 449 | kunmap(out_page); | ||
| 449 | if (nr_pages == nr_dest_pages) { | 450 | if (nr_pages == nr_dest_pages) { |
| 450 | out_page = NULL; | 451 | out_page = NULL; |
| 451 | ret = -E2BIG; | 452 | ret = -E2BIG; |
| @@ -457,7 +458,7 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, · 5 unmodified lines | |||
| 457 | goto out; | 458 | goto out; |
| 458 | } | 459 | } |
| 459 | pages[nr_pages++] = out_page; | 460 | pages[nr_pages++] = out_page; |
| 460 | workspace->out_buf.dst = page_address(out_page); | 461 | workspace->out_buf.dst = kmap(out_page); |
| 461 | workspace->out_buf.pos = 0; | 462 | workspace->out_buf.pos = 0; |
| 462 | workspace->out_buf.size = min_t(size_t, max_out, | 463 | workspace->out_buf.size = min_t(size_t, max_out, |
| 463 | PAGE_SIZE); | 464 | PAGE_SIZE); |
| @@ -472,12 +473,13 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, · 8 unmodified lines | |||
| 472 | /* Check if we need more input */ | 473 | /* Check if we need more input */ |
| 473 | if (workspace->in_buf.pos == workspace->in_buf.size) { | 474 | if (workspace->in_buf.pos == workspace->in_buf.size) { |
| 474 | tot_in += PAGE_SIZE; | 475 | tot_in += PAGE_SIZE; |
| 476 | kunmap(in_page); | ||
| 475 | put_page(in_page); | 477 | put_page(in_page); |
| 476 | 478 | ||
| 477 | start += PAGE_SIZE; | 479 | start += PAGE_SIZE; |
| 478 | len -= PAGE_SIZE; | 480 | len -= PAGE_SIZE; |
| 479 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); | 481 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); |
| 480 | workspace->in_buf.src = page_address(in_page); | 482 | workspace->in_buf.src = kmap(in_page); |
| 481 | workspace->in_buf.pos = 0; | 483 | workspace->in_buf.pos = 0; |
| 482 | workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE); | 484 | workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE); |
| 483 | } | 485 | } |
| @@ -504,6 +506,7 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, · 20 unmodified lines | |||
| 504 | 506 | ||
| 505 | tot_out += PAGE_SIZE; | 507 | tot_out += PAGE_SIZE; |
| 506 | max_out -= PAGE_SIZE; | 508 | max_out -= PAGE_SIZE; |
| 509 | kunmap(out_page); | ||
| 507 | if (nr_pages == nr_dest_pages) { | 510 | if (nr_pages == nr_dest_pages) { |
| 508 | out_page = NULL; | 511 | out_page = NULL; |
| 509 | ret = -E2BIG; | 512 | ret = -E2BIG; |
| @@ -515,7 +518,7 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, · 5 unmodified lines | |||
| 515 | goto out; | 518 | goto out; |
| 516 | } | 519 | } |
| 517 | pages[nr_pages++] = out_page; | 520 | pages[nr_pages++] = out_page; |
| 518 | workspace->out_buf.dst = page_address(out_page); | 521 | workspace->out_buf.dst = kmap(out_page); |
| 519 | workspace->out_buf.pos = 0; | 522 | workspace->out_buf.pos = 0; |
| 520 | workspace->out_buf.size = min_t(size_t, max_out, PAGE_SIZE); | 523 | workspace->out_buf.size = min_t(size_t, max_out, PAGE_SIZE); |
| 521 | } | 524 | } |
| @@ -531,8 +534,12 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, · 9 unmodified lines | |||
| 531 | out: | 534 | out: |
| 532 | *out_pages = nr_pages; | 535 | *out_pages = nr_pages; |
| 533 | /* Cleanup */ | 536 | /* Cleanup */ |
| 534 | if (in_page) | 537 | if (in_page) { |
| 538 | kunmap(in_page); | ||
| 535 | put_page(in_page); | 539 | put_page(in_page); |
| 540 | } | ||
| 541 | if (out_page) | ||
| 542 | kunmap(out_page); | ||
| 536 | return ret; | 543 | return ret; |
| 537 | } | 544 | } |
| 538 | 545 | ||
| @@ -556,7 +563,7 @@ int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 17 unmodified lines | |||
| 556 | goto done; | 563 | goto done; |
| 557 | } | 564 | } |
| 558 | 565 | ||
| 559 | workspace->in_buf.src = page_address(pages_in[page_in_index]); | 566 | workspace->in_buf.src = kmap(pages_in[page_in_index]); |
| 560 | workspace->in_buf.pos = 0; | 567 | workspace->in_buf.pos = 0; |
| 561 | workspace->in_buf.size = min_t(size_t, srclen, PAGE_SIZE); | 568 | workspace->in_buf.size = min_t(size_t, srclen, PAGE_SIZE); |
| 562 | 569 | ||
| @@ -592,14 +599,14 @@ int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 29 unmodified lines | |||
| 592 | break; | 599 | break; |
| 593 | 600 | ||
| 594 | if (workspace->in_buf.pos == workspace->in_buf.size) { | 601 | if (workspace->in_buf.pos == workspace->in_buf.size) { |
| 595 | page_in_index++; | 602 | kunmap(pages_in[page_in_index++]); |
| 596 | if (page_in_index >= total_pages_in) { | 603 | if (page_in_index >= total_pages_in) { |
| 597 | workspace->in_buf.src = NULL; | 604 | workspace->in_buf.src = NULL; |
| 598 | ret = -EIO; | 605 | ret = -EIO; |
| 599 | goto done; | 606 | goto done; |
| 600 | } | 607 | } |
| 601 | srclen -= PAGE_SIZE; | 608 | srclen -= PAGE_SIZE; |
| 602 | workspace->in_buf.src = page_address(pages_in[page_in_index]); | 609 | workspace->in_buf.src = kmap(pages_in[page_in_index]); |
| 603 | workspace->in_buf.pos = 0; | 610 | workspace->in_buf.pos = 0; |
| 604 | workspace->in_buf.size = min_t(size_t, srclen, PAGE_SIZE); | 611 | workspace->in_buf.size = min_t(size_t, srclen, PAGE_SIZE); |
| 605 | } | 612 | } |
| @@ -607,6 +614,8 @@ int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 1 unmodified line | |||
| 607 | ret = 0; | 614 | ret = 0; |
| 608 | zero_fill_bio(cb->orig_bio); | 615 | zero_fill_bio(cb->orig_bio); |
| 609 | done: | 616 | done: |
| 617 | if (workspace->in_buf.src) | ||
| 618 | kunmap(pages_in[page_in_index]); | ||
| 610 | return ret; | 619 | return ret; |
| 611 | } | 620 | } |
| 612 | 621 | ||