tolerate running out of disk blocks
This commit is contained in:
		
							parent
							
								
									7d573bae2a
								
							
						
					
					
						commit
						872fa88e8a
					
				
					 2 changed files with 76 additions and 12 deletions
				
			
		
							
								
								
									
										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…
	
	Add table
		
		Reference in a new issue