|
David Sterba |
03bbaf |
From: David Sterba <dsterba@suse.com>
|
|
David Sterba |
03bbaf |
Date: Wed, 27 Oct 2021 10:44:21 +0200
|
|
David Sterba |
03bbaf |
Subject: [PATCH 132/132] Revert "btrfs: compression: drop kmap/kunmap from
|
|
David Sterba |
03bbaf |
lzo"
|
|
David Sterba |
03bbaf |
Git-commit: ccaa66c8dd277ac02f96914168bb7177f7ea8117
|
|
David Sterba |
03bbaf |
Patch-mainline: 5.15
|
|
David Sterba |
03bbaf |
References: bsc#1193852
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
This reverts commit 8c945d32e60427cbc0859cf7045bbe6196bb03d8.
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
The kmaps in compression code are still needed and cause crashes on
|
|
David Sterba |
03bbaf |
32bit machines (ARM, x86). Reproducible eg. by running fstest btrfs/004
|
|
David Sterba |
03bbaf |
with enabled LZO or ZSTD compression.
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
The revert does not apply cleanly due to changes in a6e66e6f8c1b
|
|
David Sterba |
03bbaf |
("btrfs: rework lzo_decompress_bio() to make it subpage compatible")
|
|
David Sterba |
03bbaf |
that reworked the page iteration so the revert is done to be equivalent
|
|
David Sterba |
03bbaf |
to the original code.
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
Link: https://lore.kernel.org/all/CAJCQCtT+OuemovPO7GZk8Y8=qtOObr0XTDp8jh4OHD6y84AFxw@mail.gmail.com/
|
|
David Sterba |
03bbaf |
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=214839
|
|
David Sterba |
03bbaf |
Tested-by: Qu Wenruo <wqu@suse.com>
|
|
David Sterba |
03bbaf |
Signed-off-by: Qu Wenruo <wqu@suse.com>
|
|
David Sterba |
03bbaf |
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
David Sterba |
03bbaf |
---
|
|
David Sterba |
03bbaf |
fs/btrfs/lzo.c | 36 +++++++++++++++++++++++++-----------
|
|
David Sterba |
03bbaf |
1 file changed, 25 insertions(+), 11 deletions(-)
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
|
|
David Sterba |
03bbaf |
index c25dfd1a8a54..3dbe6eb5fda7 100644
|
|
David Sterba |
03bbaf |
--- a/fs/btrfs/lzo.c
|
|
David Sterba |
03bbaf |
+++ b/fs/btrfs/lzo.c
|
|
David Sterba |
03bbaf |
@@ -141,7 +141,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
|
|
David Sterba |
03bbaf |
*total_in = 0;
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
in_page = find_get_page(mapping, start >> PAGE_SHIFT);
|
|
David Sterba |
03bbaf |
- data_in = page_address(in_page);
|
|
David Sterba |
03bbaf |
+ data_in = kmap(in_page);
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
/*
|
|
David Sterba |
03bbaf |
* store the size of all chunks of compressed data in
|
|
David Sterba |
03bbaf |
@@ -152,7 +152,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
|
|
David Sterba |
03bbaf |
ret = -ENOMEM;
|
|
David Sterba |
03bbaf |
goto out;
|
|
David Sterba |
03bbaf |
}
|
|
David Sterba |
03bbaf |
- cpage_out = page_address(out_page);
|
|
David Sterba |
03bbaf |
+ cpage_out = kmap(out_page);
|
|
David Sterba |
03bbaf |
out_offset = LZO_LEN;
|
|
David Sterba |
03bbaf |
tot_out = LZO_LEN;
|
|
David Sterba |
03bbaf |
pages[0] = out_page;
|
|
David Sterba |
03bbaf |
@@ -210,6 +210,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
|
|
David Sterba |
03bbaf |
if (out_len == 0 && tot_in >= len)
|
|
David Sterba |
03bbaf |
break;
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
+ kunmap(out_page);
|
|
David Sterba |
03bbaf |
if (nr_pages == nr_dest_pages) {
|
|
David Sterba |
03bbaf |
out_page = NULL;
|
|
David Sterba |
03bbaf |
ret = -E2BIG;
|
|
David Sterba |
03bbaf |
@@ -221,7 +222,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
|
|
David Sterba |
03bbaf |
ret = -ENOMEM;
|
|
David Sterba |
03bbaf |
goto out;
|
|
David Sterba |
03bbaf |
}
|
|
David Sterba |
03bbaf |
- cpage_out = page_address(out_page);
|
|
David Sterba |
03bbaf |
+ cpage_out = kmap(out_page);
|
|
David Sterba |
03bbaf |
pages[nr_pages++] = out_page;
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
pg_bytes_left = PAGE_SIZE;
|
|
David Sterba |
03bbaf |
@@ -243,11 +244,12 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
|
|
David Sterba |
03bbaf |
break;
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
bytes_left = len - tot_in;
|
|
David Sterba |
03bbaf |
+ kunmap(in_page);
|
|
David Sterba |
03bbaf |
put_page(in_page);
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
start += PAGE_SIZE;
|
|
David Sterba |
03bbaf |
in_page = find_get_page(mapping, start >> PAGE_SHIFT);
|
|
David Sterba |
03bbaf |
- data_in = page_address(in_page);
|
|
David Sterba |
03bbaf |
+ data_in = kmap(in_page);
|
|
David Sterba |
03bbaf |
in_len = min(bytes_left, PAGE_SIZE);
|
|
David Sterba |
03bbaf |
}
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
@@ -257,17 +259,22 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
|
|
David Sterba |
03bbaf |
}
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
/* store the size of all chunks of compressed data */
|
|
David Sterba |
03bbaf |
- sizes_ptr = page_address(pages[0]);
|
|
David Sterba |
03bbaf |
+ sizes_ptr = kmap_local_page(pages[0]);
|
|
David Sterba |
03bbaf |
write_compress_length(sizes_ptr, tot_out);
|
|
David Sterba |
03bbaf |
+ kunmap_local(sizes_ptr);
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
ret = 0;
|
|
David Sterba |
03bbaf |
*total_out = tot_out;
|
|
David Sterba |
03bbaf |
*total_in = tot_in;
|
|
David Sterba |
03bbaf |
out:
|
|
David Sterba |
03bbaf |
*out_pages = nr_pages;
|
|
David Sterba |
03bbaf |
+ if (out_page)
|
|
David Sterba |
03bbaf |
+ kunmap(out_page);
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
- if (in_page)
|
|
David Sterba |
03bbaf |
+ if (in_page) {
|
|
David Sterba |
03bbaf |
+ kunmap(in_page);
|
|
David Sterba |
03bbaf |
put_page(in_page);
|
|
David Sterba |
03bbaf |
+ }
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
return ret;
|
|
David Sterba |
03bbaf |
}
|
|
David Sterba |
03bbaf |
@@ -283,6 +290,7 @@ static void copy_compressed_segment(struct compressed_bio *cb,
|
|
David Sterba |
03bbaf |
u32 orig_in = *cur_in;
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
while (*cur_in < orig_in + len) {
|
|
David Sterba |
03bbaf |
+ char *kaddr;
|
|
David Sterba |
03bbaf |
struct page *cur_page;
|
|
David Sterba |
03bbaf |
u32 copy_len = min_t(u32, PAGE_SIZE - offset_in_page(*cur_in),
|
|
David Sterba |
03bbaf |
orig_in + len - *cur_in);
|
|
David Sterba |
03bbaf |
@@ -290,9 +298,11 @@ static void copy_compressed_segment(struct compressed_bio *cb,
|
|
David Sterba |
03bbaf |
ASSERT(copy_len);
|
|
David Sterba |
03bbaf |
cur_page = cb->compressed_pages[*cur_in / PAGE_SIZE];
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
+ kaddr = kmap(cur_page);
|
|
David Sterba |
03bbaf |
memcpy(dest + *cur_in - orig_in,
|
|
David Sterba |
03bbaf |
- page_address(cur_page) + offset_in_page(*cur_in),
|
|
David Sterba |
03bbaf |
+ kaddr + offset_in_page(*cur_in),
|
|
David Sterba |
03bbaf |
copy_len);
|
|
David Sterba |
03bbaf |
+ kunmap(cur_page);
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
*cur_in += copy_len;
|
|
David Sterba |
03bbaf |
}
|
|
David Sterba |
03bbaf |
@@ -303,6 +313,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
|
|
David Sterba |
03bbaf |
struct workspace *workspace = list_entry(ws, struct workspace, list);
|
|
David Sterba |
03bbaf |
const struct btrfs_fs_info *fs_info = btrfs_sb(cb->inode->i_sb);
|
|
David Sterba |
03bbaf |
const u32 sectorsize = fs_info->sectorsize;
|
|
David Sterba |
03bbaf |
+ char *kaddr;
|
|
David Sterba |
03bbaf |
int ret;
|
|
David Sterba |
03bbaf |
/* Compressed data length, can be unaligned */
|
|
David Sterba |
03bbaf |
u32 len_in;
|
|
David Sterba |
03bbaf |
@@ -311,7 +322,9 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
|
|
David Sterba |
03bbaf |
/* Bytes decompressed so far */
|
|
David Sterba |
03bbaf |
u32 cur_out = 0;
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
- len_in = read_compress_length(page_address(cb->compressed_pages[0]));
|
|
David Sterba |
03bbaf |
+ kaddr = kmap(cb->compressed_pages[0]);
|
|
David Sterba |
03bbaf |
+ len_in = read_compress_length(kaddr);
|
|
David Sterba |
03bbaf |
+ kunmap(cb->compressed_pages[0]);
|
|
David Sterba |
03bbaf |
cur_in += LZO_LEN;
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
/*
|
|
David Sterba |
03bbaf |
@@ -344,9 +357,9 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
|
|
David Sterba |
03bbaf |
ASSERT(cur_in / sectorsize ==
|
|
David Sterba |
03bbaf |
(cur_in + LZO_LEN - 1) / sectorsize);
|
|
David Sterba |
03bbaf |
cur_page = cb->compressed_pages[cur_in / PAGE_SIZE];
|
|
David Sterba |
03bbaf |
+ kaddr = kmap(cur_page);
|
|
David Sterba |
03bbaf |
ASSERT(cur_page);
|
|
David Sterba |
03bbaf |
- seg_len = read_compress_length(page_address(cur_page) +
|
|
David Sterba |
03bbaf |
- offset_in_page(cur_in));
|
|
David Sterba |
03bbaf |
+ seg_len = read_compress_length(kaddr + offset_in_page(cur_in));
|
|
David Sterba |
03bbaf |
cur_in += LZO_LEN;
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
/* Copy the compressed segment payload into workspace */
|
|
David Sterba |
03bbaf |
@@ -431,7 +444,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in,
|
|
David Sterba |
03bbaf |
destlen = min_t(unsigned long, destlen, PAGE_SIZE);
|
|
David Sterba |
03bbaf |
bytes = min_t(unsigned long, destlen, out_len - start_byte);
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
- kaddr = page_address(dest_page);
|
|
David Sterba |
03bbaf |
+ kaddr = kmap_local_page(dest_page);
|
|
David Sterba |
03bbaf |
memcpy(kaddr, workspace->buf + start_byte, bytes);
|
|
David Sterba |
03bbaf |
|
|
David Sterba |
03bbaf |
/*
|
|
David Sterba |
03bbaf |
@@ -441,6 +454,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in,
|
|
David Sterba |
03bbaf |
*/
|
|
David Sterba |
03bbaf |
if (bytes < destlen)
|
|
David Sterba |
03bbaf |
memset(kaddr+bytes, 0, destlen-bytes);
|
|
David Sterba |
03bbaf |
+ kunmap_local(kaddr);
|
|
David Sterba |
03bbaf |
out:
|
|
David Sterba |
03bbaf |
return ret;
|
|
David Sterba |
03bbaf |
}
|
|
David Sterba |
03bbaf |
--
|
|
David Sterba |
03bbaf |
2.33.0
|
|
David Sterba |
03bbaf |
|