tolerate running out of disk blocks
This commit is contained in:
parent
7d573bae2a
commit
872fa88e8a
42
kernel/fs.c
42
kernel/fs.c
|
@ -61,6 +61,7 @@ bzero(int dev, int bno)
|
||||||
// Blocks.
|
// Blocks.
|
||||||
|
|
||||||
// Allocate a zeroed disk block.
|
// Allocate a zeroed disk block.
|
||||||
|
// returns 0 if out of disk space.
|
||||||
static uint
|
static uint
|
||||||
balloc(uint dev)
|
balloc(uint dev)
|
||||||
{
|
{
|
||||||
|
@ -82,7 +83,8 @@ balloc(uint dev)
|
||||||
}
|
}
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
}
|
}
|
||||||
panic("balloc: out of blocks");
|
printf("balloc: out of blocks\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free a disk block.
|
// Free a disk block.
|
||||||
|
@ -109,8 +111,8 @@ bfree(int dev, uint b)
|
||||||
// its size, the number of links referring to it, and the
|
// its size, the number of links referring to it, and the
|
||||||
// list of blocks holding the file's content.
|
// list of blocks holding the file's content.
|
||||||
//
|
//
|
||||||
// The inodes are laid out sequentially on disk at
|
// The inodes are laid out sequentially on disk at block
|
||||||
// sb.startinode. Each inode has a number, indicating its
|
// sb.inodestart. Each inode has a number, indicating its
|
||||||
// position on the disk.
|
// position on the disk.
|
||||||
//
|
//
|
||||||
// The kernel keeps a table of in-use inodes in memory
|
// The kernel keeps a table of in-use inodes in memory
|
||||||
|
@ -374,6 +376,7 @@ iunlockput(struct inode *ip)
|
||||||
|
|
||||||
// Return the disk block address of the nth block in inode ip.
|
// Return the disk block address of the nth block in inode ip.
|
||||||
// If there is no such block, bmap allocates one.
|
// If there is no such block, bmap allocates one.
|
||||||
|
// returns 0 if out of disk space.
|
||||||
static uint
|
static uint
|
||||||
bmap(struct inode *ip, uint bn)
|
bmap(struct inode *ip, uint bn)
|
||||||
{
|
{
|
||||||
|
@ -381,21 +384,32 @@ bmap(struct inode *ip, uint bn)
|
||||||
struct buf *bp;
|
struct buf *bp;
|
||||||
|
|
||||||
if(bn < NDIRECT){
|
if(bn < NDIRECT){
|
||||||
if((addr = ip->addrs[bn]) == 0)
|
if((addr = ip->addrs[bn]) == 0){
|
||||||
ip->addrs[bn] = addr = balloc(ip->dev);
|
addr = balloc(ip->dev);
|
||||||
|
if(addr == 0)
|
||||||
|
return 0;
|
||||||
|
ip->addrs[bn] = addr;
|
||||||
|
}
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
bn -= NDIRECT;
|
bn -= NDIRECT;
|
||||||
|
|
||||||
if(bn < NINDIRECT){
|
if(bn < NINDIRECT){
|
||||||
// Load indirect block, allocating if necessary.
|
// Load indirect block, allocating if necessary.
|
||||||
if((addr = ip->addrs[NDIRECT]) == 0)
|
if((addr = ip->addrs[NDIRECT]) == 0){
|
||||||
ip->addrs[NDIRECT] = addr = balloc(ip->dev);
|
addr = balloc(ip->dev);
|
||||||
|
if(addr == 0)
|
||||||
|
return 0;
|
||||||
|
ip->addrs[NDIRECT] = addr;
|
||||||
|
}
|
||||||
bp = bread(ip->dev, addr);
|
bp = bread(ip->dev, addr);
|
||||||
a = (uint*)bp->data;
|
a = (uint*)bp->data;
|
||||||
if((addr = a[bn]) == 0){
|
if((addr = a[bn]) == 0){
|
||||||
a[bn] = addr = balloc(ip->dev);
|
addr = balloc(ip->dev);
|
||||||
log_write(bp);
|
if(addr){
|
||||||
|
a[bn] = addr;
|
||||||
|
log_write(bp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
return addr;
|
return addr;
|
||||||
|
@ -464,7 +478,10 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n)
|
||||||
n = ip->size - off;
|
n = ip->size - off;
|
||||||
|
|
||||||
for(tot=0; tot<n; tot+=m, off+=m, dst+=m){
|
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);
|
m = min(n - tot, BSIZE - off%BSIZE);
|
||||||
if(either_copyout(user_dst, dst, bp->data + (off % BSIZE), m) == -1) {
|
if(either_copyout(user_dst, dst, bp->data + (off % BSIZE), m) == -1) {
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
|
@ -495,7 +512,10 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for(tot=0; tot<n; tot+=m, off+=m, src+=m){
|
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);
|
m = min(n - tot, BSIZE - off%BSIZE);
|
||||||
if(either_copyin(bp->data + (off % BSIZE), user_src, src, m) == -1) {
|
if(either_copyin(bp->data + (off % BSIZE), user_src, src, m) == -1) {
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
|
|
|
@ -2706,6 +2706,49 @@ execout(char *s)
|
||||||
exit(0);
|
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.
|
// use sbrk() to count how many free physical memory pages there are.
|
||||||
// touches the pages to force allocation.
|
// touches the pages to force allocation.
|
||||||
|
@ -2818,7 +2861,7 @@ main(int argc, char *argv[])
|
||||||
void (*f)(char *);
|
void (*f)(char *);
|
||||||
char *s;
|
char *s;
|
||||||
} tests[] = {
|
} tests[] = {
|
||||||
{MAXVAplus, "MAXVAplus"},
|
{diskfull, "diskfull"},
|
||||||
{manywrites, "manywrites"},
|
{manywrites, "manywrites"},
|
||||||
{execout, "execout"},
|
{execout, "execout"},
|
||||||
{copyin, "copyin"},
|
{copyin, "copyin"},
|
||||||
|
@ -2880,6 +2923,7 @@ main(int argc, char *argv[])
|
||||||
{dirfile, "dirfile"},
|
{dirfile, "dirfile"},
|
||||||
{iref, "iref"},
|
{iref, "iref"},
|
||||||
{forktest, "forktest"},
|
{forktest, "forktest"},
|
||||||
|
{MAXVAplus, "MAXVAplus"},
|
||||||
{bigdir, "bigdir"}, // slow
|
{bigdir, "bigdir"}, // slow
|
||||||
{ 0, 0},
|
{ 0, 0},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue