summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--kernel/exec.c1
-rw-r--r--kernel/fs.c38
-rw-r--r--user/ulib.c11
-rw-r--r--user/usertests.c46
5 files changed, 87 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index 330f440..6f0f40e 100644
--- a/Makefile
+++ b/Makefile
@@ -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},
};