Whamcloud - gitweb
LU-18588 obdclass: keep track of cl_page's bufsize 65/57565/9
authorBobi Jam <bobijam@whamcloud.com>
Fri, 20 Dec 2024 15:01:01 +0000 (23:01 +0800)
committerOleg Drokin <green@whamcloud.com>
Sat, 22 Feb 2025 23:40:53 +0000 (23:40 +0000)
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 <bobijam@whamcloud.com>
Change-Id: I433a5601851da3c3d9ec8578005a262f29e979ea
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/57565
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Tested-by: Qian Yingjin <qian@ddn.com>
Reviewed-by: Qian Yingjin <qian@ddn.com>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/cl_object.h
lustre/obdclass/cl_page.c

index 67dc435..26dce98 100644 (file)
@@ -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
index c3b6a07..ba371e3 100644 (file)
@@ -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;