summaryrefslogtreecommitdiff
path: root/kernel/fs.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2022-08-10 06:13:52 -0400
committerRobert Morris <[email protected]>2022-08-10 06:13:52 -0400
commit872fa88e8afd24a8f228ba431fad380d326b0f36 (patch)
tree8577fd7cfd9067a34eb6b8a2b41925cabcd0d014 /kernel/fs.c
parent7d573bae2ab70f0d0bd1807f0099c00e8f9e24f2 (diff)
downloadxv6-labs-872fa88e8afd24a8f228ba431fad380d326b0f36.tar.gz
xv6-labs-872fa88e8afd24a8f228ba431fad380d326b0f36.tar.bz2
xv6-labs-872fa88e8afd24a8f228ba431fad380d326b0f36.zip
tolerate running out of disk blocks
Diffstat (limited to 'kernel/fs.c')
-rw-r--r--kernel/fs.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/kernel/fs.c b/kernel/fs.c
index 40c9bd4..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.
@@ -109,8 +111,8 @@ bfree(int dev, uint b)
// its size, the number of links referring to it, and the
// list of blocks holding the file's content.
//
-// The inodes are laid out sequentially on disk at
-// sb.startinode. Each inode has a number, indicating its
+// The inodes are laid out sequentially on disk at block
+// sb.inodestart. Each inode has a number, indicating its
// position on the disk.
//
// 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.
// 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);