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