Skip to content

Commit fd919bb

Browse files
committed
Merge tag 'for-5.15-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
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"
2 parents 6f11521 + ccaa66c commit fd919bb

File tree

5 files changed

+72
-33
lines changed

5 files changed

+72
-33
lines changed

fs/btrfs/compression.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,10 @@ static int check_compressed_csum(struct btrfs_inode *inode, struct bio *bio,
172172
/* Hash through the page sector by sector */
173173
for (pg_offset = 0; pg_offset < bytes_left;
174174
pg_offset += sectorsize) {
175-
kaddr = page_address(page);
175+
kaddr = kmap_atomic(page);
176176
crypto_shash_digest(shash, kaddr + pg_offset,
177177
sectorsize, csum);
178+
kunmap_atomic(kaddr);
178179

179180
if (memcmp(&csum, cb_sum, csum_size) != 0) {
180181
btrfs_print_data_csum_error(inode, disk_start,

fs/btrfs/inode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,9 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
287287
cur_size = min_t(unsigned long, compressed_size,
288288
PAGE_SIZE);
289289

290-
kaddr = page_address(cpage);
290+
kaddr = kmap_atomic(cpage);
291291
write_extent_buffer(leaf, kaddr, ptr, cur_size);
292+
kunmap_atomic(kaddr);
292293

293294
i++;
294295
ptr += cur_size;

fs/btrfs/lzo.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
141141
*total_in = 0;
142142

143143
in_page = find_get_page(mapping, start >> PAGE_SHIFT);
144-
data_in = page_address(in_page);
144+
data_in = kmap(in_page);
145145

146146
/*
147147
* 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,
152152
ret = -ENOMEM;
153153
goto out;
154154
}
155-
cpage_out = page_address(out_page);
155+
cpage_out = kmap(out_page);
156156
out_offset = LZO_LEN;
157157
tot_out = LZO_LEN;
158158
pages[0] = out_page;
@@ -210,6 +210,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
210210
if (out_len == 0 && tot_in >= len)
211211
break;
212212

213+
kunmap(out_page);
213214
if (nr_pages == nr_dest_pages) {
214215
out_page = NULL;
215216
ret = -E2BIG;
@@ -221,7 +222,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
221222
ret = -ENOMEM;
222223
goto out;
223224
}
224-
cpage_out = page_address(out_page);
225+
cpage_out = kmap(out_page);
225226
pages[nr_pages++] = out_page;
226227

227228
pg_bytes_left = PAGE_SIZE;
@@ -243,11 +244,12 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
243244
break;
244245

245246
bytes_left = len - tot_in;
247+
kunmap(in_page);
246248
put_page(in_page);
247249

248250
start += PAGE_SIZE;
249251
in_page = find_get_page(mapping, start >> PAGE_SHIFT);
250-
data_in = page_address(in_page);
252+
data_in = kmap(in_page);
251253
in_len = min(bytes_left, PAGE_SIZE);
252254
}
253255

@@ -257,17 +259,22 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
257259
}
258260

259261
/* store the size of all chunks of compressed data */
260-
sizes_ptr = page_address(pages[0]);
262+
sizes_ptr = kmap_local_page(pages[0]);
261263
write_compress_length(sizes_ptr, tot_out);
264+
kunmap_local(sizes_ptr);
262265

263266
ret = 0;
264267
*total_out = tot_out;
265268
*total_in = tot_in;
266269
out:
267270
*out_pages = nr_pages;
271+
if (out_page)
272+
kunmap(out_page);
268273

269-
if (in_page)
274+
if (in_page) {
275+
kunmap(in_page);
270276
put_page(in_page);
277+
}
271278

272279
return ret;
273280
}
@@ -283,16 +290,19 @@ static void copy_compressed_segment(struct compressed_bio *cb,
283290
u32 orig_in = *cur_in;
284291

285292
while (*cur_in < orig_in + len) {
293+
char *kaddr;
286294
struct page *cur_page;
287295
u32 copy_len = min_t(u32, PAGE_SIZE - offset_in_page(*cur_in),
288296
orig_in + len - *cur_in);
289297

290298
ASSERT(copy_len);
291299
cur_page = cb->compressed_pages[*cur_in / PAGE_SIZE];
292300

301+
kaddr = kmap(cur_page);
293302
memcpy(dest + *cur_in - orig_in,
294-
page_address(cur_page) + offset_in_page(*cur_in),
303+
kaddr + offset_in_page(*cur_in),
295304
copy_len);
305+
kunmap(cur_page);
296306

297307
*cur_in += copy_len;
298308
}
@@ -303,6 +313,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
303313
struct workspace *workspace = list_entry(ws, struct workspace, list);
304314
const struct btrfs_fs_info *fs_info = btrfs_sb(cb->inode->i_sb);
305315
const u32 sectorsize = fs_info->sectorsize;
316+
char *kaddr;
306317
int ret;
307318
/* Compressed data length, can be unaligned */
308319
u32 len_in;
@@ -311,7 +322,9 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
311322
/* Bytes decompressed so far */
312323
u32 cur_out = 0;
313324

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]);
315328
cur_in += LZO_LEN;
316329

317330
/*
@@ -344,9 +357,9 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
344357
ASSERT(cur_in / sectorsize ==
345358
(cur_in + LZO_LEN - 1) / sectorsize);
346359
cur_page = cb->compressed_pages[cur_in / PAGE_SIZE];
360+
kaddr = kmap(cur_page);
347361
ASSERT(cur_page);
348-
seg_len = read_compress_length(page_address(cur_page) +
349-
offset_in_page(cur_in));
362+
seg_len = read_compress_length(kaddr + offset_in_page(cur_in));
350363
cur_in += LZO_LEN;
351364

352365
/* Copy the compressed segment payload into workspace */
@@ -431,7 +444,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in,
431444
destlen = min_t(unsigned long, destlen, PAGE_SIZE);
432445
bytes = min_t(unsigned long, destlen, out_len - start_byte);
433446

434-
kaddr = page_address(dest_page);
447+
kaddr = kmap_local_page(dest_page);
435448
memcpy(kaddr, workspace->buf + start_byte, bytes);
436449

437450
/*
@@ -441,6 +454,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in,
441454
*/
442455
if (bytes < destlen)
443456
memset(kaddr+bytes, 0, destlen-bytes);
457+
kunmap_local(kaddr);
444458
out:
445459
return ret;
446460
}

fs/btrfs/zlib.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
126126
ret = -ENOMEM;
127127
goto out;
128128
}
129-
cpage_out = page_address(out_page);
129+
cpage_out = kmap(out_page);
130130
pages[0] = out_page;
131131
nr_pages = 1;
132132

@@ -148,22 +148,26 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
148148
int i;
149149

150150
for (i = 0; i < in_buf_pages; i++) {
151-
if (in_page)
151+
if (in_page) {
152+
kunmap(in_page);
152153
put_page(in_page);
154+
}
153155
in_page = find_get_page(mapping,
154156
start >> PAGE_SHIFT);
155-
data_in = page_address(in_page);
157+
data_in = kmap(in_page);
156158
memcpy(workspace->buf + i * PAGE_SIZE,
157159
data_in, PAGE_SIZE);
158160
start += PAGE_SIZE;
159161
}
160162
workspace->strm.next_in = workspace->buf;
161163
} else {
162-
if (in_page)
164+
if (in_page) {
165+
kunmap(in_page);
163166
put_page(in_page);
167+
}
164168
in_page = find_get_page(mapping,
165169
start >> PAGE_SHIFT);
166-
data_in = page_address(in_page);
170+
data_in = kmap(in_page);
167171
start += PAGE_SIZE;
168172
workspace->strm.next_in = data_in;
169173
}
@@ -192,6 +196,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
192196
* the stream end if required
193197
*/
194198
if (workspace->strm.avail_out == 0) {
199+
kunmap(out_page);
195200
if (nr_pages == nr_dest_pages) {
196201
out_page = NULL;
197202
ret = -E2BIG;
@@ -202,7 +207,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
202207
ret = -ENOMEM;
203208
goto out;
204209
}
205-
cpage_out = page_address(out_page);
210+
cpage_out = kmap(out_page);
206211
pages[nr_pages] = out_page;
207212
nr_pages++;
208213
workspace->strm.avail_out = PAGE_SIZE;
@@ -229,6 +234,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
229234
goto out;
230235
} else if (workspace->strm.avail_out == 0) {
231236
/* get another page for the stream end */
237+
kunmap(out_page);
232238
if (nr_pages == nr_dest_pages) {
233239
out_page = NULL;
234240
ret = -E2BIG;
@@ -239,7 +245,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
239245
ret = -ENOMEM;
240246
goto out;
241247
}
242-
cpage_out = page_address(out_page);
248+
cpage_out = kmap(out_page);
243249
pages[nr_pages] = out_page;
244250
nr_pages++;
245251
workspace->strm.avail_out = PAGE_SIZE;
@@ -258,8 +264,13 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
258264
*total_in = workspace->strm.total_in;
259265
out:
260266
*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);
262272
put_page(in_page);
273+
}
263274
return ret;
264275
}
265276

@@ -276,7 +287,7 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
276287
unsigned long buf_start;
277288
struct page **pages_in = cb->compressed_pages;
278289

279-
data_in = page_address(pages_in[page_in_index]);
290+
data_in = kmap(pages_in[page_in_index]);
280291
workspace->strm.next_in = data_in;
281292
workspace->strm.avail_in = min_t(size_t, srclen, PAGE_SIZE);
282293
workspace->strm.total_in = 0;
@@ -298,6 +309,7 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
298309

299310
if (Z_OK != zlib_inflateInit2(&workspace->strm, wbits)) {
300311
pr_warn("BTRFS: inflateInit failed\n");
312+
kunmap(pages_in[page_in_index]);
301313
return -EIO;
302314
}
303315
while (workspace->strm.total_in < srclen) {
@@ -324,13 +336,13 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
324336

325337
if (workspace->strm.avail_in == 0) {
326338
unsigned long tmp;
327-
339+
kunmap(pages_in[page_in_index]);
328340
page_in_index++;
329341
if (page_in_index >= total_pages_in) {
330342
data_in = NULL;
331343
break;
332344
}
333-
data_in = page_address(pages_in[page_in_index]);
345+
data_in = kmap(pages_in[page_in_index]);
334346
workspace->strm.next_in = data_in;
335347
tmp = srclen - workspace->strm.total_in;
336348
workspace->strm.avail_in = min(tmp, PAGE_SIZE);
@@ -342,6 +354,8 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
342354
ret = 0;
343355
done:
344356
zlib_inflateEnd(&workspace->strm);
357+
if (data_in)
358+
kunmap(pages_in[page_in_index]);
345359
if (!ret)
346360
zero_fill_bio(cb->orig_bio);
347361
return ret;

0 commit comments

Comments
 (0)