public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: wkendall@sgi.com
To: xfs@oss.sgi.com
Subject: [PATCH v2 3/9] xfsrestore: cache path lookups
Date: Fri, 05 Nov 2010 11:35:03 -0500	[thread overview]
Message-ID: <20101105163643.571496225@sgi.com> (raw)
In-Reply-To: 20101105163500.747192954@sgi.com

[-- Attachment #1: node2path_caching --]
[-- Type: text/plain, Size: 3895 bytes --]

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 <wkendall@sgi.com>


---
 restore/tree.c |   41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 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,13 @@ 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 && bufsz > cache.len ) {
+		strcpy( buf, cache.buf );
+		return bufsz - cache.len;
+	}
+
 	/* extract useful node members
 	 */
 	np = Node_map( nh );
@@ -3486,8 +3504,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 +3536,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

  parent reply	other threads:[~2010-11-05 16:35 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-05 16:35 [PATCH v2 0/9] xfsrestore dirent limitations and scaling issues wkendall
2010-11-05 16:35 ` [PATCH v2 1/9] xfsrestore: turn off NODECHK wkendall
2010-11-12 23:23   ` Alex Elder
2010-11-05 16:35 ` [PATCH v2 2/9] xfsrestore: change nrh_t from 32 to 64 bits wkendall
2010-11-12 23:24   ` Alex Elder
2010-11-05 16:35 ` wkendall [this message]
2010-11-12 23:25   ` [PATCH v2 3/9] xfsrestore: cache path lookups Alex Elder
2010-11-05 16:35 ` [PATCH v2 4/9] xfsrestore: mmap dirent names for faster lookups wkendall
2010-11-12 23:25   ` Alex Elder
2010-11-15 21:51     ` Bill Kendall
2010-11-05 16:35 ` [PATCH v2 5/9] xfsrestore: cleanup node allocation wkendall
2010-11-15 20:38   ` Alex Elder
2010-11-15 21:36     ` Bill Kendall
2010-11-05 16:35 ` [PATCH v2 6/9] xfsrestore: fix node table setup wkendall
2010-11-15 20:38   ` Alex Elder
2010-11-15 21:30     ` Bill Kendall
2010-11-05 16:35 ` [PATCH v2 7/9] xfsrestore: make node lookup more efficient wkendall
2010-11-15 20:38   ` Alex Elder
2010-11-15 22:06     ` Bill Kendall
2010-11-05 16:35 ` [PATCH v2 8/9] xfsrestore: remove nix_t wkendall
2010-11-12 23:25   ` Alex Elder
2010-11-05 16:35 ` [PATCH v2 9/9] xfsrestore: check for compatible xfsrestore wkendall
2010-11-12 23:25   ` Alex Elder
2010-11-12 23:25 ` [PATCH v2 0/9] xfsrestore dirent limitations and scaling issues Alex Elder

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101105163643.571496225@sgi.com \
    --to=wkendall@sgi.com \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox