diff --git a/kernel/fs.c b/kernel/fs.c index 247a86f..b220491 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -573,6 +573,7 @@ dirlookup(struct inode *dp, char *name, uint *poff) } // Write a new directory entry (name, inum) into the directory dp. +// Returns 0 on success, -1 on failure (e.g. out of disk blocks). int dirlink(struct inode *dp, char *name, uint inum) { @@ -597,7 +598,7 @@ dirlink(struct inode *dp, char *name, uint inum) strncpy(de.name, name, DIRSIZ); de.inum = inum; if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) - panic("dirlink"); + return -1; return 0; } diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 970a72a..4c0470e 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -279,8 +279,13 @@ create(char *path, short type, short major, short minor) panic("create dots"); } - if(dirlink(dp, name, ip->inum) < 0) - panic("create: dirlink"); + if(dirlink(dp, name, ip->inum) < 0){ + // oops. we don't need ip after all. + ip->nlink = 0; + iupdate(ip); + iunlockput(ip); + ip = 0; + } iunlockput(dp); diff --git a/user/usertests.c b/user/usertests.c index 4ab34da..968034a 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -2738,6 +2738,36 @@ diskfull(char *s) close(fd); } + // now that there are no free blocks, test that dirlink() + // merely fails (doesn't panic) if it can't extend + // directory content. + int nzz = 128; + for(int i = 0; i < nzz; i++){ + char name[32]; + name[0] = 'z'; + name[1] = 'z'; + name[2] = '0' + (i / 32); + name[3] = '0' + (i % 32); + name[4] = '\0'; + unlink(name); + int fd = open(name, O_CREATE|O_RDWR|O_TRUNC); + if(fd < 0){ + printf("%s: could not create file %s\n", s, name); + break; + } + close(fd); + } + + for(int i = 0; i < nzz; i++){ + char name[32]; + name[0] = 'z'; + name[1] = 'z'; + name[2] = '0' + (i / 32); + name[3] = '0' + (i % 32); + name[4] = '\0'; + unlink(name); + } + for(int i = 0; i < fi; i++){ char name[32]; name[0] = 'b';