From d49d897ff293621673ee8dab9efc8c8fd0a0d0dc Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Fri, 20 Dec 2024 23:01:01 +0800 Subject: [PATCH] LU-18588 obdclass: keep track of cl_page's bufsize When a cl_page is allocated, the slab cache size to be used is a rounding-up value of the cl_object's coh_page_bufsize, while the object's coh_page_bufsize could change if the layout is changed, and when the cl_page on the LRU list got shrank, cl_page_free() would find that its bufsize does not match the current coh_page_bufsize value. LustreError: 949:0:(cl_page.c:178:__cl_page_free()) ASSERTION( cl_page_kmem_size_array[index] == bufsize) failed: lbug_with_loc.cold+0x5/0x58 [libcfs] __cl_page_free+0x1c2/0x260 [obdclass] cl_page_free+0x96/0x4d0 [obdclass] cl_batch_put+0x1ac/0x3d0 [obdclass] discard_cl_pages+0x99/0x150 [osc] osc_lru_shrink+0x34a/0x930 [osc] lru_queue_work+0xea/0x220 [osc] work_interpreter+0x32/0x170 [ptlrpc] ptlrpc_check_set+0x40e/0x1ef0 [ptlrpc] ptlrpcd_check+0x3b4/0x5a0 [ptlrpc] ptlrpcd+0x1ba/0x4d0 [ptlrpc] This patch would keep track of the page's bufsize by referring to cl_page_kmem_size_array if its in the array or reusing cp_kmem_index to store its bufsize. Signed-off-by: Bobi Jam Change-Id: I433a5601851da3c3d9ec8578005a262f29e979ea Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/57565 Tested-by: jenkins Tested-by: Maloo Tested-by: Qian Yingjin Reviewed-by: Qian Yingjin Reviewed-by: Patrick Farrell Reviewed-by: Oleg Drokin --- lustre/include/cl_object.h | 11 ++++++++--- lustre/obdclass/cl_page.c | 26 ++++++++++++++++++++------ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index 67dc435..26dce98 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -767,9 +767,14 @@ struct cl_page { enum cl_page_type cp_type:CP_TYPE_BITS; unsigned cp_defer_uptodate:1, cp_ra_updated:1, - cp_ra_used:1; - /* which slab kmem index this memory allocated from */ - short int cp_kmem_index; + cp_ra_used:1, + cp_in_kmem_array:1; + union { + /* which slab kmem index this memory allocated from */ + short int cp_kmem_index; + /* or the page size if it's not in the slab kmem array */ + short int cp_kmem_size; + }; /** * Owning IO in cl_page_state::CPS_OWNED state. Sub-page can be owned diff --git a/lustre/obdclass/cl_page.c b/lustre/obdclass/cl_page.c index c3b6a07..ba371e3 100644 --- a/lustre/obdclass/cl_page.c +++ b/lustre/obdclass/cl_page.c @@ -129,9 +129,9 @@ cl_page_slice_get(const struct cl_page *cl_page, int index) static void __cl_page_free(struct cl_page *cl_page, unsigned short bufsize) { - int index = cl_page->cp_kmem_index; + if (cl_page->cp_in_kmem_array) { + int index = cl_page->cp_kmem_index; - if (index >= 0) { LASSERT(index < ARRAY_SIZE(cl_page_kmem_array)); LASSERT(cl_page_kmem_size_array[index] == bufsize); OBD_SLAB_FREE(cl_page, cl_page_kmem_array[index], bufsize); @@ -144,7 +144,7 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *cp, struct folio_batch *fbatch) { struct cl_object *obj = cp->cp_obj; - unsigned short bufsize = cl_object_header(obj)->coh_page_bufsize; + unsigned short bufsize; struct page *vmpage; ENTRY; @@ -174,6 +174,16 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *cp, cs_pagestate_dec(obj, cp->cp_state); if (cp->cp_type != CPT_TRANSIENT) cl_object_put(env, obj); + + if (cp->cp_in_kmem_array) + bufsize = cl_page_kmem_size_array[cp->cp_kmem_index]; + else + bufsize = cp->cp_kmem_size; + if (unlikely(bufsize != cl_object_header(obj)->coh_page_bufsize)) + CWARN("%s:"DFID" page bufsize %d, object bufsize now %d\n", + obj->co_lu.lo_dev->ld_obd->obd_name, + PFID(&cl_object_header(obj)->coh_lu.loh_fid), + bufsize, cl_object_header(obj)->coh_page_bufsize); __cl_page_free(cp, bufsize); EXIT; } @@ -195,8 +205,10 @@ check: if (smp_load_acquire(&cl_page_kmem_size_array[i]) == bufsize) { OBD_SLAB_ALLOC_GFP(cl_page, cl_page_kmem_array[i], bufsize, GFP_NOFS); - if (cl_page) + if (cl_page) { + cl_page->cp_in_kmem_array = 1; cl_page->cp_kmem_index = i; + } return cl_page; } if (cl_page_kmem_size_array[i] == 0) @@ -225,8 +237,10 @@ check: goto check; } else { OBD_ALLOC_GFP(cl_page, bufsize, GFP_NOFS); - if (cl_page) - cl_page->cp_kmem_index = -1; + if (cl_page) { + cl_page->cp_in_kmem_array = 0; + cl_page->cp_kmem_size = bufsize; + } } return cl_page; -- 1.8.3.1