On Fri, Apr 1, 2022 at 6:36 AM NeilBrown <neilb@xxxxxxx> wrote: > > On Thu, 31 Mar 2022, Muchun Song wrote: > > > > Thanks for your report. I knew the reason. It is because the following > > patch in this series was missed upstream. Could you help me test if it > > works properly? > > > > [v6,06/16] nfs42: use a specific kmem_cache to allocate nfs4_xattr_entry > > > > Thanks for the quick response! That patch helps, but has a bug. My > testing resulted in refcount underflow errors. > > Problem is that kref_init() is called in nfs4_xattr_entry_init_once(). > This means that it is initialised to '1' the first time an entry is > allocated, but it is left as zero the second time. > I applied: > --- a/fs/nfs/nfs42xattr.c > +++ b/fs/nfs/nfs42xattr.c > @@ -191,6 +191,7 @@ nfs4_xattr_alloc_entry(const char *name, const void *value, > entry = kmem_cache_alloc_lru(nfs4_xattr_entry_cachep, lru, gfp); > if (!entry) > return NULL; > + kref_init(&entry->ref); > namep = kstrdup_const(name, gfp); > if (!namep && name) > goto free_buf; > @@ -974,7 +975,6 @@ static void nfs4_xattr_entry_init_once(void *p) > { > struct nfs4_xattr_entry *entry = p; > > - kref_init(&entry->ref); > entry->bucket = NULL; > INIT_LIST_HEAD(&entry->lru); > INIT_LIST_HEAD(&entry->dispose); > > and now it seems to work. > > The complete patch that I applied is below. I haven't reviewed it, just > tested it. > Tested-by: NeilBrown <neilb@xxxxxxx> > Thanks for your test. I have looked at the latest code. I found the following patch has removed GFP_ACCOUNT on allocation. 5c60e89e71f8 ("NFSv4.2: Fix up an invalid combination of memory allocation flags") But this commit forgot to remove SLAB_ACCOUNT when creating nfs4_xattr_cache_cachep (I think it is a bug). So I think the following patch could work. diff --git a/fs/nfs/nfs42xattr.c b/fs/nfs/nfs42xattr.c index ad3405c64b9e..e7b34f7e0614 100644 --- a/fs/nfs/nfs42xattr.c +++ b/fs/nfs/nfs42xattr.c @@ -997,7 +997,7 @@ int __init nfs4_xattr_cache_init(void) nfs4_xattr_cache_cachep = kmem_cache_create("nfs4_xattr_cache_cache", sizeof(struct nfs4_xattr_cache), 0, - (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|SLAB_ACCOUNT), + (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), nfs4_xattr_cache_init_once); if (nfs4_xattr_cache_cachep == NULL) return -ENOMEM;