diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | kernel/exec.c | 1 | ||||
-rw-r--r-- | kernel/fs.c | 38 | ||||
-rw-r--r-- | user/ulib.c | 11 | ||||
-rw-r--r-- | user/usertests.c | 46 |
5 files changed, 87 insertions, 11 deletions
@@ -90,7 +90,7 @@ tags: $(OBJS) _init ULIB = $U/ulib.o $U/usys.o $U/printf.o $U/umalloc.o _%: %.o $(ULIB) - $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^ + $(LD) $(LDFLAGS) -N -e _main -Ttext 0 -o $@ $^ $(OBJDUMP) -S $@ > $*.asm $(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym diff --git a/kernel/exec.c b/kernel/exec.c index d62d29d..09b4bdc 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -65,6 +65,7 @@ exec(char *path, char **argv) uint64 oldsz = p->sz; // Allocate two pages at the next page boundary. + // Make the first inaccessible as a stack guard. // Use the second as the user stack. sz = PGROUNDUP(sz); uint64 sz1; diff --git a/kernel/fs.c b/kernel/fs.c index 53a3a0f..247a86f 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -61,6 +61,7 @@ bzero(int dev, int bno) // Blocks. // Allocate a zeroed disk block. +// returns 0 if out of disk space. static uint balloc(uint dev) { @@ -82,7 +83,8 @@ balloc(uint dev) } brelse(bp); } - panic("balloc: out of blocks"); + printf("balloc: out of blocks\n"); + return 0; } // Free a disk block. @@ -374,6 +376,7 @@ iunlockput(struct inode *ip) // Return the disk block address of the nth block in inode ip. // If there is no such block, bmap allocates one. +// returns 0 if out of disk space. static uint bmap(struct inode *ip, uint bn) { @@ -381,21 +384,32 @@ bmap(struct inode *ip, uint bn) struct buf *bp; if(bn < NDIRECT){ - if((addr = ip->addrs[bn]) == 0) - ip->addrs[bn] = addr = balloc(ip->dev); + if((addr = ip->addrs[bn]) == 0){ + addr = balloc(ip->dev); + if(addr == 0) + return 0; + ip->addrs[bn] = addr; + } return addr; } bn -= NDIRECT; if(bn < NINDIRECT){ // Load indirect block, allocating if necessary. - if((addr = ip->addrs[NDIRECT]) == 0) - ip->addrs[NDIRECT] = addr = balloc(ip->dev); + if((addr = ip->addrs[NDIRECT]) == 0){ + addr = balloc(ip->dev); + if(addr == 0) + return 0; + ip->addrs[NDIRECT] = addr; + } bp = bread(ip->dev, addr); a = (uint*)bp->data; if((addr = a[bn]) == 0){ - a[bn] = addr = balloc(ip->dev); - log_write(bp); + addr = balloc(ip->dev); + if(addr){ + a[bn] = addr; + log_write(bp); + } } brelse(bp); return addr; @@ -464,7 +478,10 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n) n = ip->size - off; for(tot=0; tot<n; tot+=m, off+=m, dst+=m){ - bp = bread(ip->dev, bmap(ip, off/BSIZE)); + uint addr = bmap(ip, off/BSIZE); + if(addr == 0) + break; + bp = bread(ip->dev, addr); m = min(n - tot, BSIZE - off%BSIZE); if(either_copyout(user_dst, dst, bp->data + (off % BSIZE), m) == -1) { brelse(bp); @@ -495,7 +512,10 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n) return -1; for(tot=0; tot<n; tot+=m, off+=m, src+=m){ - bp = bread(ip->dev, bmap(ip, off/BSIZE)); + uint addr = bmap(ip, off/BSIZE); + if(addr == 0) + break; + bp = bread(ip->dev, addr); m = min(n - tot, BSIZE - off%BSIZE); if(either_copyin(bp->data + (off % BSIZE), user_src, src, m) == -1) { brelse(bp); diff --git a/user/ulib.c b/user/ulib.c index 4775939..c7b66c4 100644 --- a/user/ulib.c +++ b/user/ulib.c @@ -3,6 +3,17 @@ #include "kernel/fcntl.h" #include "user/user.h" +// +// wrapper so that it's OK if main() does not call exit(). +// +void +_main() +{ + extern int main(); + main(); + exit(0); +} + char* strcpy(char *s, const char *t) { diff --git a/user/usertests.c b/user/usertests.c index 0fe7371..4ab34da 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -2706,6 +2706,49 @@ execout(char *s) exit(0); } +// can the kernel tolerate running out of disk space? +void +diskfull(char *s) +{ + int fi; + int done = 0; + + for(fi = 0; done == 0; fi++){ + char name[32]; + name[0] = 'b'; + name[1] = 'i'; + name[2] = 'g'; + name[3] = '0' + fi; + 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); + done = 1; + break; + } + for(int i = 0; i < MAXFILE; i++){ + char buf[BSIZE]; + if(write(fd, buf, BSIZE) != BSIZE){ + done = 1; + close(fd); + break; + } + } + close(fd); + } + + for(int i = 0; i < fi; i++){ + char name[32]; + name[0] = 'b'; + name[1] = 'i'; + name[2] = 'g'; + name[3] = '0' + i; + name[4] = '\0'; + unlink(name); + } +} + // // use sbrk() to count how many free physical memory pages there are. // touches the pages to force allocation. @@ -2818,7 +2861,7 @@ main(int argc, char *argv[]) void (*f)(char *); char *s; } tests[] = { - {MAXVAplus, "MAXVAplus"}, + {diskfull, "diskfull"}, {manywrites, "manywrites"}, {execout, "execout"}, {copyin, "copyin"}, @@ -2880,6 +2923,7 @@ main(int argc, char *argv[]) {dirfile, "dirfile"}, {iref, "iref"}, {forktest, "forktest"}, + {MAXVAplus, "MAXVAplus"}, {bigdir, "bigdir"}, // slow { 0, 0}, }; |