Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Jun 2001 22:24:49 -0700 (PDT)
From:      mwatson@apple.com
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/27829: pax's uid/gid cache is read-only
Message-ID:  <200106020524.f525OnI10853@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         27829
>Category:       misc
>Synopsis:       pax's uid/gid cache is read-only
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jun 01 22:30:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Matt Watson
>Release:        4.2
>Organization:
Apple Computer, Inc.
>Environment:
>Description:
We found a bug in the Darwin pax where the uid/gid cache was not being used correctly. This resulted in a 10x slowdown of archive extraction in some cases. It's especially bad when archives contain unknown uid/gids
>How-To-Repeat:
Run pax under gdb. break on getpwuid() & getpwnam(). Notice how often you hit the breakpoints.
>Fix:
These diffs may need to be modified to sync up with the current version...

Index: cache.c
===================================================================
RCS file: /cvs/Darwin/Commands/BSD/file_cmds/pax/cache.c,v
retrieving revision 1.1
retrieving revision 1.3
diff -w -u -b -r1.1 -r1.3
--- cache.c     1999/04/23 02:39:07     1.1
+++ cache.c     2001/01/16 23:20:28     1.3
@@ -210,14 +210,15 @@
 {
        register struct passwd *pw;
        register UIDC *ptr;
-
+       register int hash;
        if ((uidtb == NULL) && (uidtb_start() < 0))
                return("");
 
        /*
         * see if we have this uid cached
         */
-       ptr = uidtb[uid % UID_SZ];
+       hash = uid % UID_SZ;
+       ptr = uidtb[hash];
        if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
                /*
                 * have an entry for this uid
@@ -252,6 +253,7 @@
                (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
                               (unsigned long)uid);
 #              endif
+               uidtb[hash] = ptr;
                if (frc == 0)
                        return("");
        } else {
@@ -264,6 +266,7 @@
                (void)strncpy(ptr->name, pw->pw_name, UNMLEN-1);
                ptr->name[UNMLEN-1] = '\0';
                ptr->valid = VALID;
+               uidtb[hash] = ptr;
        }
        return(ptr->name);
 }
@@ -288,6 +291,7 @@
 {
        register struct group *gr;
        register GIDC *ptr;
+       register int hash;
 
        if ((gidtb == NULL) && (gidtb_start() < 0))
                return("");
@@ -295,7 +299,8 @@
        /*
         * see if we have this gid cached
         */
-       ptr = gidtb[gid % GID_SZ];
+       hash = gid % GID_SZ;
+       ptr = gidtb[hash];
        if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
                /*
                 * have an entry for this gid
@@ -330,6 +335,7 @@
                (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
                               (unsigned long)gid);
 #              endif
+               gidtb[hash] = ptr;
                if (frc == 0)
                        return("");
        } else {
@@ -342,6 +348,7 @@
                (void)strncpy(ptr->name, gr->gr_name, GNMLEN-1);
                ptr->name[GNMLEN-1] = '\0';
                ptr->valid = VALID;
+               gidtb[hash] = ptr;
        }
        return(ptr->name);
 }
@@ -366,6 +373,7 @@
        register struct passwd *pw;
        register UIDC *ptr;
        register int namelen;
+       register int hash;
 
        /*
         * return -1 for mangled names
@@ -379,7 +387,8 @@
         * look up in hash table, if found and valid return the uid,
         * if found and invalid, return a -1
         */
-       ptr = usrtb[st_hash(name, namelen, UNM_SZ)];
+       hash = st_hash(name, namelen, UNM_SZ);
+       ptr = usrtb[hash];
        if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
                if (ptr->valid == INVALID)
                        return(-1);
@@ -405,6 +414,7 @@
                *uid = pw->pw_uid;
                return(0);
        }
+       usrtb[hash] = ptr;
        (void)strncpy(ptr->name, name, UNMLEN-1);
        ptr->name[UNMLEN-1] = '\0';
        if ((pw = getpwnam(name)) == NULL) {
@@ -436,6 +446,7 @@
        register struct group *gr;
        register GIDC *ptr;
        register int namelen;
+       register int hash;
 
        /*
         * return -1 for mangled names
@@ -449,7 +460,8 @@
         * look up in hash table, if found and valid return the uid,
         * if found and invalid, return a -1
         */
-       ptr = grptb[st_hash(name, namelen, GID_SZ)];
+       hash = st_hash(name, namelen, GID_SZ);
+       ptr = grptb[hash];
        if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
                if (ptr->valid == INVALID)
                        return(-1);
@@ -475,6 +487,7 @@
                return(0);
        }
 
+       grptb[hash] = ptr;
        (void)strncpy(ptr->name, name, GNMLEN-1);
        ptr->name[GNMLEN-1] = '\0';
        if ((gr = getgrnam(name)) == NULL) {

>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200106020524.f525OnI10853>