From c372e8dc348e4bb30aae7642db92ecbeedbc83ab Mon Sep 17 00:00:00 2001 From: kaashoek Date: Sun, 13 Aug 2006 05:28:04 +0000 Subject: [PATCH] zero freed blocks multi-block directories track size of directory (size = number entries in use) should namei (and other code that scans through directories) scan through all blocks of a directory and not use size? --- fs.c | 27 +++++++++++++++++++-------- userfs.c | 15 +++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/fs.c b/fs.c index 7f0d2ea..dbecb41 100644 --- a/fs.c +++ b/fs.c @@ -76,6 +76,11 @@ bfree(int dev, uint b) ninodes = sb->ninodes; brelse(bp); + bp = bread(dev, b); + memset(bp->data, 0, BSIZE); + bwrite(bp, b); + brelse(bp); + bp = bread(dev, BBLOCK(b, ninodes)); bi = b % BPB; m = ~(0x1 << (bi %8)); @@ -446,6 +451,7 @@ wdir(struct inode *dp, char *name, uint ino) struct buf *bp = 0; struct dirent *ep = 0; int i; + int lb; for(off = 0; off < dp->size; off += BSIZE) { bp = bread(dp->dev, bmap(dp, off / BSIZE)); @@ -457,17 +463,23 @@ wdir(struct inode *dp, char *name, uint ino) } brelse(bp); } - - panic("mknod: XXXX no dir entry free\n"); - + lb = dp->size / BSIZE; + if (lb >= NDIRECT) { + panic ("wdir: too many entries"); + } + dp->addrs[lb] = balloc(dp->dev); + bp = bread(dp->dev, dp->addrs[lb]); + ep = (struct dirent *) (bp->data); found: ep->inum = ino; for(i = 0; i < DIRSIZ && name[i]; i++) ep->name[i] = name[i]; for( ; i < DIRSIZ; i++) ep->name[i] = '\0'; + dp->size += sizeof(struct dirent); bwrite (bp, bmap(dp, off/BSIZE)); // write directory block brelse(bp); + iupdate(dp); } struct inode * @@ -482,7 +494,6 @@ mknod(char *cp, short type, short major, short minor) iput(ip); return 0; } - cprintf("mknod: pinum = %d\n", pinum); dp = iget(rootdev, pinum); ip = ialloc(dp->dev, type); if (ip == 0) { @@ -495,11 +506,9 @@ mknod(char *cp, short type, short major, short minor) ip->nlink = 1; iupdate (ip); // write new inode to disk - + wdir(dp, cp, ip->inum); - iput(dp); - return ip; } @@ -537,12 +546,14 @@ unlink(char *cp) } brelse(bp); } - panic("mknod: XXXX no dir entry free\n"); + panic("unlink: entry doesn't exist\n"); found: ep->inum = 0; + memset(ep->name, '\0', DIRSIZ); bwrite (bp, bmap(dp, off/BSIZE)); // write directory block brelse(bp); + dp->size -= sizeof(struct dirent); iupdate (dp); iput(dp); iput(ip); diff --git a/userfs.c b/userfs.c index 90aa1fa..2726de7 100644 --- a/userfs.c +++ b/userfs.c @@ -7,6 +7,7 @@ // file system tests char buf[2000]; +char name[3]; char *echo_args[] = { "echo", "hello", "goodbye", 0 }; char *cat_args[] = { "cat", "README", 0 }; @@ -65,6 +66,20 @@ main(void) } close(fd); unlink("doesnotexist"); + name[0] = 'a'; + name[2] = '\0'; + for (i = 0; i < 52; i++) { + name[1] = '0' + i; + fd = open(name, O_CREATE|O_RDWR); + close(fd); + } + name[0] = 'a'; + name[2] = '\0'; + for (i = 0; i < 52; i++) { + name[1] = '0' + i; + unlink(name); + } + //exec("echo", echo_args); printf(stdout, "about to do exec\n"); exec("cat", cat_args);