Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'erofs-for-5.16-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs

Pull erofs fixes from Gao Xiang:

- fix unsafe pagevec reuse which could cause unexpected behaviors

- get rid of the unused DELAYEDALLOC strategy that has been replaced by
TRYALLOC

* tag 'erofs-for-5.16-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs:
erofs: remove useless cache strategy of DELAYEDALLOC
erofs: fix unsafe pagevec reuse of hooked pclusters

+17 -30
+7 -26
fs/erofs/zdata.c
··· 96 96 DBG_BUGON(1); 97 97 } 98 98 99 - /* 100 - * a compressed_pages[] placeholder in order to avoid 101 - * being filled with file pages for in-place decompression. 102 - */ 103 - #define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) 104 - 105 99 /* how to allocate cached pages for a pcluster */ 106 100 enum z_erofs_cache_alloctype { 107 101 DONTALLOC, /* don't allocate any cached pages */ 108 - DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ 109 102 /* 110 103 * try to use cached I/O if page allocation succeeds or fallback 111 104 * to in-place I/O instead to avoid any direct reclaim. ··· 260 267 /* I/O is needed, no possible to decompress directly */ 261 268 standalone = false; 262 269 switch (type) { 263 - case DELAYEDALLOC: 264 - t = tagptr_init(compressed_page_t, 265 - PAGE_UNALLOCATED); 266 - break; 267 270 case TRYALLOC: 268 271 newpage = erofs_allocpage(pagepool, gfp); 269 272 if (!newpage) ··· 360 371 361 372 /* callers must be with collection lock held */ 362 373 static int z_erofs_attach_page(struct z_erofs_collector *clt, 363 - struct page *page, 364 - enum z_erofs_page_type type) 374 + struct page *page, enum z_erofs_page_type type, 375 + bool pvec_safereuse) 365 376 { 366 377 int ret; 367 378 ··· 371 382 z_erofs_try_inplace_io(clt, page)) 372 383 return 0; 373 384 374 - ret = z_erofs_pagevec_enqueue(&clt->vector, page, type); 385 + ret = z_erofs_pagevec_enqueue(&clt->vector, page, type, 386 + pvec_safereuse); 375 387 clt->cl->vcnt += (unsigned int)ret; 376 - 377 388 return ret ? 0 : -EAGAIN; 378 389 } 379 390 ··· 716 727 tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); 717 728 718 729 retry: 719 - err = z_erofs_attach_page(clt, page, page_type); 730 + err = z_erofs_attach_page(clt, page, page_type, 731 + clt->mode >= COLLECT_PRIMARY_FOLLOWED); 720 732 /* should allocate an additional short-lived page for pagevec */ 721 733 if (err == -EAGAIN) { 722 734 struct page *const newpage = ··· 725 735 726 736 set_page_private(newpage, Z_EROFS_SHORTLIVED_PAGE); 727 737 err = z_erofs_attach_page(clt, newpage, 728 - Z_EROFS_PAGE_TYPE_EXCLUSIVE); 738 + Z_EROFS_PAGE_TYPE_EXCLUSIVE, true); 729 739 if (!err) 730 740 goto retry; 731 741 } ··· 1078 1088 1079 1089 if (!page) 1080 1090 goto out_allocpage; 1081 - 1082 - /* 1083 - * the cached page has not been allocated and 1084 - * an placeholder is out there, prepare it now. 1085 - */ 1086 - if (page == PAGE_UNALLOCATED) { 1087 - tocache = true; 1088 - goto out_allocpage; 1089 - } 1090 1091 1091 1092 /* process the target tagged pointer */ 1092 1093 t = tagptr_init(compressed_page_t, page);
-1
fs/erofs/zdata.h
··· 179 179 #define Z_EROFS_VMAP_GLOBAL_PAGES 2048 180 180 181 181 #endif 182 -
+10 -3
fs/erofs/zpvec.h
··· 106 106 107 107 static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, 108 108 struct page *page, 109 - enum z_erofs_page_type type) 109 + enum z_erofs_page_type type, 110 + bool pvec_safereuse) 110 111 { 111 - if (!ctor->next && type) 112 - if (ctor->index + 1 == ctor->nr) 112 + if (!ctor->next) { 113 + /* some pages cannot be reused as pvec safely without I/O */ 114 + if (type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && !pvec_safereuse) 115 + type = Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED; 116 + 117 + if (type != Z_EROFS_PAGE_TYPE_EXCLUSIVE && 118 + ctor->index + 1 == ctor->nr) 113 119 return false; 120 + } 114 121 115 122 if (ctor->index >= ctor->nr) 116 123 z_erofs_pagevec_ctor_pagedown(ctor, false);