From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id oAGF5Z1Q069928 for ; Tue, 16 Nov 2010 09:05:35 -0600 Received: from estes.americas.sgi.com (estes.americas.sgi.com [128.162.236.10]) by relay3.corp.sgi.com (Postfix) with ESMTP id EAD71AC008 for ; Tue, 16 Nov 2010 07:07:04 -0800 (PST) Received: from augusta (augusta.americas.sgi.com [128.162.233.117]) by estes.americas.sgi.com (Postfix) with ESMTP id 72BB970017CA for ; Tue, 16 Nov 2010 09:07:04 -0600 (CST) Message-Id: <20101116150704.237582191@sgi.com> Date: Tue, 16 Nov 2010 09:05:05 -0600 From: wkendall@sgi.com Subject: [PATCH v3 3/9] xfsrestore: cache path lookups References: <20101116150502.179825893@sgi.com> Content-Disposition: inline; filename=node2path_caching List-Id: XFS Filesystem from SGI List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: xfs-bounces@oss.sgi.com Errors-To: xfs-bounces@oss.sgi.com To: xfs@oss.sgi.com In order to resolve a pathname, xfsrestore must work from an inode number (from the dump) and recurse up the directory entry tree that it has constructed. Each level of recursion requires a seek and read to get the name of the dirent, and possibly a mmap of a section of the directory entry tree if it is not already mapped (and in that case, possibly a munmap of another section). It's quite common to resolve pathnames in the same directory consecutively, so simply caching the parent directory pathname from the previous lookup saves quite a bit of overhead. Signed-off-by: Bill Kendall Reviewed-by: Alex Elder --- restore/tree.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) Index: xfsdump-kernel.org/restore/tree.c =================================================================== --- xfsdump-kernel.org.orig/restore/tree.c +++ xfsdump-kernel.org/restore/tree.c @@ -236,6 +236,14 @@ struct link_iter_context { }; typedef struct link_iter_context link_iter_context_t; +/* used for caching parent pathname from previous Node2path result + */ +struct path_cache { + nh_t nh; + intgen_t len; + char buf[MAXPATHLEN]; +}; +typedef struct path_cache path_cache_t; /* declarations of externally defined global symbols *************************/ @@ -254,7 +262,8 @@ static nh_t Node_alloc( xfs_ino_t ino, static void Node_free( nh_t *nhp ); static node_t * Node_map( nh_t nh ); static void Node_unmap( nh_t nh, node_t **npp ); -static intgen_t Node2path_recurse( nh_t nh, char *buf, intgen_t bufsz ); +static intgen_t Node2path_recurse( nh_t nh, char *buf, + intgen_t bufsz, intgen_t level ); static void adopt( nh_t parh, nh_t cldh, nrh_t nrh ); static nrh_t disown( nh_t cldh ); static void selsubtree( nh_t nh, bool_t sensepr ); @@ -3435,7 +3444,7 @@ Node2path( nh_t nh, char *path, char *er { intgen_t remainingcnt; path[ 0 ] = 0; /* in case root node passed in */ - remainingcnt = Node2path_recurse( nh, path, MAXPATHLEN ); + remainingcnt = Node2path_recurse( nh, path, MAXPATHLEN, 0 ); if ( remainingcnt <= 0 ) { node_t *np = Node_map( nh ); xfs_ino_t ino = np->n_ino; @@ -3459,13 +3468,15 @@ Node2path( nh_t nh, char *path, char *er * works because the buffer size is secretly 2 * MAXPATHLEN. */ static intgen_t -Node2path_recurse( nh_t nh, char *buf, intgen_t bufsz ) +Node2path_recurse( nh_t nh, char *buf, intgen_t bufsz, intgen_t level ) { + static path_cache_t cache = { NH_NULL, 0, "" }; node_t *np; nh_t parh; xfs_ino_t ino; gen_t gen; nrh_t nrh; + char *oldbuf; intgen_t oldbufsz; intgen_t namelen; @@ -3475,6 +3486,14 @@ Node2path_recurse( nh_t nh, char *buf, i return bufsz; } + /* if we have a cache hit, no need to recurse any further + */ + if ( nh == cache.nh ) { + ASSERT( bufsz > cache.len ); + strcpy( buf, cache.buf ); + return bufsz - cache.len; + } + /* extract useful node members */ np = Node_map( nh ); @@ -3486,8 +3505,9 @@ Node2path_recurse( nh_t nh, char *buf, i /* build path to parent */ + oldbuf = buf; oldbufsz = bufsz; - bufsz = Node2path_recurse( parh, buf, bufsz ); /* RECURSION */ + bufsz = Node2path_recurse( parh, buf, bufsz, level+1 ); /* RECURSION */ if ( bufsz <= 0 ) { return bufsz; } @@ -3517,10 +3537,22 @@ Node2path_recurse( nh_t nh, char *buf, i ASSERT( namelen > 0 ); } - /* return remaining buffer size + /* update remaining buffer size */ bufsz -= namelen; ASSERT( bufsz + MAXPATHLEN > 0 ); + + /* update the cache if we're the target's parent + * (and the pathname is not too long) + */ + if ( level == 1 && bufsz > 0 ) { + cache.nh = nh; + strcpy( cache.buf, oldbuf ); + cache.len = oldbufsz - bufsz; + } + + /* return remaining buffer size + */ return bufsz; } _______________________________________________ xfs mailing list xfs@oss.sgi.com http://oss.sgi.com/mailman/listinfo/xfs