diff --git a/src/afs/afs_buffer.c b/src/afs/afs_buffer.c
index 4399473..2220ae3 100644
--- a/src/afs/afs_buffer.c
+++ b/src/afs/afs_buffer.c
@@ -379,6 +379,8 @@ afs_newslot(struct dcache *adc, afs_int32 apage, struct buffer *lp)
 	AFS_STATS(afs_stats_cmperf.bufFlushDirty++);
     }
 
+    /* Zero out the data so we don't leak something we shouldn't. */
+    memset(lp->data, 0, AFS_BUFFER_PAGESIZE);
     /* Now fill in the header. */
     lp->fid = adc->index;
     afs_copy_inode(&lp->inode, &adc->f.inode);
diff --git a/src/bozo/bos.c b/src/bozo/bos.c
index 54935a2..0e2e3f4 100644
--- a/src/bozo/bos.c
+++ b/src/bozo/bos.c
@@ -41,7 +41,7 @@ static int DoStat(char *aname, struct rx_connection *aconn,
 #include "bosprototypes.h"
 
 /* command offsets for bos salvage command */
-#define ADDPARMOFFSET 10
+#define ADDPARMOFFSET 11
 
 /* dummy routine for the audit work.  It should do nothing since audits */
 /* occur at the server level and bos is not a server. */
@@ -1039,7 +1039,7 @@ StopServer(struct cmd_syndesc *as, void *arock)
 static afs_int32
 DoSalvage(struct rx_connection * aconn, char * aparm1, char * aparm2,
 	  char * aoutName, afs_int32 showlog, char * parallel,
-	  char * atmpDir, char * orphans, int dafs)
+	  char * atmpDir, char * orphans, int dafs, int dodirs)
 {
     afs_int32 code;
     char *parms[6];
@@ -1170,6 +1170,14 @@ DoSalvage(struct rx_connection * aconn, char * aparm1, char * aparm2,
 	    strcat(tbuffer, " -orphans ");
 	    strcat(tbuffer, orphans);
 	}
+	/* add the salvagedirs option if given */
+	if (dodirs) {
+	    if (strlen(tbuffer) + 14 > BOZO_BSSIZE) {
+		fprintf(stderr, "bos: command line too big\n");
+		return (E2BIG);
+	    }
+	    strcat(tbuffer, " -salvagedirs");
+	}
     }
 
     parms[0] = tbuffer;
@@ -1307,6 +1315,7 @@ SalvageCmd(struct cmd_syndesc *as, void *arock)
     afs_int32 newID;
     extern struct ubik_client *cstruct;
     afs_int32 curGoal, showlog = 0, dafs = 0;
+    int dodirs = 0;
     char *parallel;
     char *tmpDir;
     char *orphans;
@@ -1371,6 +1380,15 @@ SalvageCmd(struct cmd_syndesc *as, void *arock)
 	}
     }
 
+    if (as->parms[10].items) { /* -salvagedirs */
+	if (as->parms[4].items) { /* -all */
+	    dodirs = 1;
+	} else {
+	    fprintf(stderr, " -salvagedirs only possible with -all.\n");
+	    return EINVAL;
+	}
+    }
+
     if (as->parms[4].items) {
 	/* salvage whole enchilada */
 	curGoal = GetServerGoal(tconn, serviceName);
@@ -1389,7 +1407,7 @@ SalvageCmd(struct cmd_syndesc *as, void *arock)
 	/* now do the salvage operation */
 	printf("Starting salvage.\n");
 	rc = DoSalvage(tconn, NULL, NULL, outName, showlog, parallel, tmpDir,
-		       orphans, dafs);
+		       orphans, dafs, dodirs);
 	if (curGoal == BSTAT_NORMAL) {
 	    printf("bos: restarting %s.\n", serviceName);
 	    code = BOZO_SetTStatus(tconn, serviceName, BSTAT_NORMAL);
@@ -1431,7 +1449,7 @@ SalvageCmd(struct cmd_syndesc *as, void *arock)
 	/* now do the salvage operation */
 	printf("Starting salvage.\n");
 	rc = DoSalvage(tconn, as->parms[1].items->data, NULL, outName,
-		       showlog, parallel, tmpDir, orphans, dafs);
+		       showlog, parallel, tmpDir, orphans, dafs, 0);
 	if (curGoal == BSTAT_NORMAL) {
 	    printf("bos: restarting '%s'.\n", serviceName);
 	    code = BOZO_SetTStatus(tconn, serviceName, BSTAT_NORMAL);
@@ -1490,7 +1508,7 @@ SalvageCmd(struct cmd_syndesc *as, void *arock)
 	}
 	printf("Starting salvage.\n");
 	rc = DoSalvage(tconn, as->parms[1].items->data, tname, outName,
-		       showlog, parallel, tmpDir, orphans, dafs);
+		       showlog, parallel, tmpDir, orphans, dafs, 0);
 	if (rc)
 	    return rc;
     }
@@ -1918,6 +1936,8 @@ main(int argc, char **argv)
 		"ignore | remove | attach");
     cmd_AddParm(ts, "-forceDAFS", CMD_FLAG, CMD_OPTIONAL,
 		"(DAFS) force salvage of demand attach fileserver");
+    cmd_AddParm(ts, "-salvagedirs", CMD_FLAG, CMD_OPTIONAL,
+		"Force rebuild/salvage of all directories");
     add_std_args(ts);
 
     ts = cmd_CreateSyntax("getrestricted", GetRestrict, NULL, 0,
diff --git a/src/dir/buffer.c b/src/dir/buffer.c
index 889f07e..1a8da8f 100644
--- a/src/dir/buffer.c
+++ b/src/dir/buffer.c
@@ -313,6 +313,7 @@ newslot(dir_file_t dir, afs_int32 apage, struct buffer *lp)
     /* Now fill in the header. */
     FidZap(bufferDir(lp));
     FidCpy(bufferDir(lp), dir);	/* set this */
+    memset(lp->data, 0, BUFFER_PAGE_SIZE);  /* Don't leak stale data. */
     lp->page = apage;
     lp->accesstime = ++timecounter;
 
diff --git a/src/dir/dir.c b/src/dir/dir.c
index f930adc..6db96b2 100644
--- a/src/dir/dir.c
+++ b/src/dir/dir.c
@@ -191,7 +191,9 @@ afs_dir_Delete(dir_file_t dir, char *entry)
     DRelease(&prevbuf, 1);
     index = DVOffset(&entrybuf) / 32;
     nitems = afs_dir_NameBlobs(firstitem->name);
-    DRelease(&entrybuf, 0);
+    /* Clear entire DirEntry and any DirXEntry extensions */
+    memset(firstitem, 0, nitems * sizeof(*firstitem));
+    DRelease(&entrybuf, 1);
     FreeBlobs(dir, index, nitems);
     return 0;
 }
diff --git a/src/vol/salvaged.c b/src/vol/salvaged.c
index 753fc18..23239d7 100644
--- a/src/vol/salvaged.c
+++ b/src/vol/salvaged.c
@@ -212,6 +212,7 @@ handleit(struct cmd_syndesc *opts, void *arock)
     cmd_OptionAsFlag(opts, OPT_inodes, &ListInodeOption);
     cmd_OptionAsFlag(opts, OPT_oktozap, &OKToZap);
     cmd_OptionAsFlag(opts, OPT_rootinodes, &ShowRootFiles);
+    cmd_OptionAsFlag(opts, OPT_salvagedirs, &RebuildDirs);
     cmd_OptionAsFlag(opts, OPT_blockreads, &forceR);
     if (cmd_OptionAsString(opts, OPT_parallel, &optstring) == 0) {
 	if (strncmp(optstring, "all", 3) == 0) {
