Project

General

Profile

Bug #13249

wasteful entry allocation in dnlc

Added by Mateusz Guzik 4 months ago. Updated 4 months ago.

Status:
New
Priority:
Normal
Assignee:
Category:
kernel
Start date:
Due date:
% Done:

80%

Estimated time:
Difficulty:
Bite-size
Tags:
Gerrit CR:

Description

The namecache entry has the following layout:

> ::print -a ncache_t
0 {
    0 hash_next 
    8 hash_prev 
    10 vp 
    18 dp 
    20 hash 
    24 namlen 
    25 name 
}

which implies:

> ::sizeof ncache_t
sizeof (ncache_t) = 0x28

but then dnlc_get:

        ncp = kmem_alloc(sizeof (ncache_t) + namlen, KM_NOSLEEP);

Requests 3 bytes more than expected. Instead the code should be using offsetof(ncache_t, name) here and in dnlc_free (and perhaps size computation could be deduped).

#1

Updated by Mateusz Guzik 4 months ago

Something of this sort should take care of it (not even compile tested):

diff --git a/usr/src/uts/common/fs/dnlc.c b/usr/src/uts/common/fs/dnlc.c
index 102375dedd..bf044082cf 100644
--- a/usr/src/uts/common/fs/dnlc.c
+++ b/usr/src/uts/common/fs/dnlc.c
@@ -256,7 +256,7 @@ vnode_t negative_cache_vnode;
  */
 #define        dnlc_free(ncp) \
 { \
-       kmem_free((ncp), sizeof (ncache_t) + (ncp)->namlen); \
+       kmem_free((ncp), offsetof(ncache_t, name) + (ncp)->namlen); \
        atomic_dec_32(&dnlc_nentries); \
 }

@@ -977,7 +977,7 @@ dnlc_get(uchar_t namlen)
                dnlc_max_nentries_cnt++; /* keep a statistic */
                return (NULL);
        }
-       ncp = kmem_alloc(sizeof (ncache_t) + namlen, KM_NOSLEEP);
+       ncp = kmem_alloc(offsetof(ncache_t, name) + namlen, KM_NOSLEEP);
        if (ncp == NULL) {
                return (NULL);
        }

#2

Updated by Electric Monk 4 months ago

  • Gerrit CR set to 1013
#3

Updated by Toomas Soome 4 months ago

  • Category set to kernel
  • Assignee set to Toomas Soome
  • % Done changed from 0 to 80
> ::print -ath ncache_t
0 ncache_t {
    0 struct ncache *hash_next 
    8 struct ncache *hash_prev 
    10 struct vnode *vp 
    18 struct vnode *dp 
    20 int hash 
    24 uchar_t namlen 
    25 char [0] name 
    25 unsigned <<HOLE>> :24 
}

> ::print -ath dcentry_t
0 dcentry_t {
    0 uint64_t de_handle 
    8 struct dcentry *de_next 
    10 int de_hash 
    14 uchar_t de_namelen 
    15 char [0] de_name 
    15 unsigned <<HOLE>> :24 
}

Testing done: build/install/boot.

Also available in: Atom PDF