namei: Limit traversal when removing data dirs
authorAndrew Deason <adeason@sinenomine.net>
Thu, 2 Sep 2010 20:05:21 +0000 (15:05 -0500)
committerDerrick Brashear <shadow@dementia.org>
Wed, 8 Sep 2010 17:47:14 +0000 (10:47 -0700)
namei_RemoveDataDirectories currently calls delTree with 'tree'
pointing to the part of the path immediately following n_base (i.e.
starting at the beginning of n_voldir1). This causes delTree to
traverse all of n_voldir1, trying to delete every directory it finds.

Since we are typically only trying to remove a single volume when
calling namei_RemoveDataDirectories, instead call delTree with 'tree'
pointing to immediately after n_voldir1, and beginning at n_voldir2
and try to just rmdir n_voldir1 afterwards. This way, we do not
traverse a large fraction of the entire partition when just trying to
delete a single volume, and so can significantly speed up volume
removals.

Change-Id: I79d69e7f3d1b691ec1d55e02ee5e93c0a927cffe
Reviewed-on: http://gerrit.openafs.org/2651
Tested-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

src/vol/namei_ops.c

index 93b4f49..692a585 100644 (file)
@@ -415,15 +415,29 @@ namei_RemoveDataDirectories(namei_t * name)
 {
     char pbuf[MAXPATHLEN], *path = pbuf;
     int prefixlen = strlen(name->n_base), err = 0;
+    int vollen = strlen(name->n_voldir1);
+    int code, code2;
 
     strlcpy(path, name->n_path, sizeof(pbuf));
 
-    /* move past the prefix */
-    path = path + prefixlen + 1;       /* skip over the trailing / */
+    /* move past the prefix and n_voldir1 */
+    path = path + prefixlen + 1 + vollen + 1;  /* skip over the trailing / */
 
     /* now delete all dirs upto path */
-    return delTree(pbuf, path, &err);
+    code = delTree(pbuf, path, &err);
 
+    /* We deleted everything under /n_base/n_voldir1/n_voldir2 if we could,
+     * but now try to rmdir /n_base/n_voldir1 if we can. delTree modified
+     * pbuf, so just reconstruct /n_base/n_voldir1 from scratch oureslves. */
+    afs_snprintf(pbuf, sizeof(pbuf)-1, "%s/%s", name->n_base, name->n_voldir1);
+    pbuf[sizeof(pbuf)-1] = '\0';
+
+    code2 = rmdir(pbuf);
+    if (!code) {
+       code = code2;
+    }
+
+    return code;
 }
 
 /* Create the file in the name space.