Skip to content

Commit

Permalink
HW9: increase inode capacity
Browse files Browse the repository at this point in the history
Sacrificed a direct block for a double-indirect block on the inode
  • Loading branch information
gw committed May 1, 2017
1 parent 0fb7777 commit 5c81f9f
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 17 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ mkfs: mkfs.c fs.h

UPROGS=\
_alarmtest\
_big\
_cat\
_date\
_echo\
Expand Down Expand Up @@ -220,6 +221,7 @@ QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
ifndef CPUS
CPUS := 1
endif
QEMUEXTRA = -snapshot
QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA)

qemu: fs.img xv6.img
Expand Down
62 changes: 62 additions & 0 deletions big.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "types.h"
#include "stat.h"
#include "user.h"
#include "fcntl.h"

/*
HW page: https://pdos.csail.mit.edu/6.828/2016/homework/xv6-big-files.html
Expected output in xv6 shell:
$ big
.....................................................................................................................................................................
wrote 16523 sectors
done; ok
*/

int
main()
{
char buf[512];
int fd, i, sectors;

fd = open("big.file", O_CREATE | O_WRONLY);
if(fd < 0){
printf(2, "big: cannot open big.file for writing\n");
exit();
}

sectors = 0;
while(1){
*(int*)buf = sectors;
int cc = write(fd, buf, sizeof(buf));
if(cc <= 0)
break;
sectors++;
if (sectors % 100 == 0)
printf(2, ".");
}

printf(1, "\nwrote %d sectors\n", sectors);

close(fd);
fd = open("big.file", O_RDONLY);
if(fd < 0){
printf(2, "big: cannot re-open big.file for reading\n");
exit();
}
for(i = 0; i < sectors; i++){
int cc = read(fd, buf, sizeof(buf));
if(cc <= 0){
printf(2, "big: read error at sector %d\n", i);
exit();
}
if(*(int*)buf != i){
printf(2, "big: read the wrong data (%d) for sector %d\n",
*(int*)buf, i);
exit();
}
}

printf(1, "done; ok\n");

exit();
}
6 changes: 3 additions & 3 deletions file.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ struct file {
struct inode {
uint dev; // Device number
uint inum; // Inode number
int ref; // Reference count
int ref; // num open FDs / proc->cwd's referring to it
struct sleeplock lock;
int flags; // I_VALID

short type; // copy of disk inode
short major;
short minor;
short nlink;
short nlink; // num hard links
uint size;
uint addrs[NDIRECT+1];
uint addrs[NDIRECT+2];
};
#define I_VALID 0x2

Expand Down
60 changes: 54 additions & 6 deletions fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ bzero(int dev, int bno)

// Blocks.

// Allocate a zeroed disk block.
// Allocate a zeroed disk block and return it, unlocked.
static uint
balloc(uint dev)
{
Expand Down Expand Up @@ -333,8 +333,8 @@ iput(struct inode *ip)
// inode has no links and no other references: truncate and free.
release(&icache.lock);
itrunc(ip);
ip->type = 0;
iupdate(ip);
ip->type = 0; // Why don't we just do this in itrunc?
iupdate(ip); // ...and avoid the need for this iupdate call?
acquire(&icache.lock);
ip->flags = 0;
}
Expand All @@ -358,35 +358,80 @@ iunlockput(struct inode *ip)
// are listed in ip->addrs[]. The next NINDIRECT blocks are
// listed in block ip->addrs[NDIRECT].

// Return the disk block address of the nth block in inode ip.
// If there is no such block, bmap allocates one.
// Return the disk block address of the nth logical block in inode ip.
// If there is no such block, bmap allocates one. Since bmap eagerly
// allocates like this, it's important for callers to be careful with bn
// if they don't want unexpected block allocations. See `readi` below.

// Note that bmap doesn't call iupdate--the caller must detect if
// bmap allocated blocks and then call it themselves (see writei below).
static uint
bmap(struct inode *ip, uint bn)
{
uint addr, *a;
struct buf *bp;

// Direct block
if(bn < NDIRECT){
if((addr = ip->addrs[bn]) == 0)
// Logical block not yet allocated
ip->addrs[bn] = addr = balloc(ip->dev);
return addr;
}

bn -= NDIRECT;

// Indirect block
if(bn < NINDIRECT){
// Load indirect block, allocating if necessary.
if((addr = ip->addrs[NDIRECT]) == 0)
// Indirect block itself not yet allocated
ip->addrs[NDIRECT] = addr = balloc(ip->dev);

// Read+lock indirect block
bp = bread(ip->dev, addr);
a = (uint*)bp->data;

if((addr = a[bn]) == 0){
// Logical block not yet allocated
a[bn] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
return addr;
}

bn -= NINDIRECT;

// Double-indirect block
if (bn < NINDIRECT*NINDIRECT) {
if((addr = ip->addrs[NDIRECT + 1]) == 0)
// First double-indirect block not yet allocated
ip->addrs[NDIRECT + 1] = addr = balloc(ip->dev);

// Read+lock first double-indirect block
bp = bread(ip->dev, addr);
a = (uint*)bp->data;

if((addr = a[bn / NINDIRECT]) == 0) {
// Second double-indirect block not yet allocated
a[bn / NINDIRECT] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);

// Read+lock second double-indirect block
bp = bread(ip->dev, addr);
a = (uint*)bp->data;

if((addr = a[bn % NINDIRECT]) == 0) {
// Logical block not yet allocated
a[bn % NINDIRECT] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
return addr;
}

panic("bmap: out of range");
}

Expand Down Expand Up @@ -456,6 +501,9 @@ readi(struct inode *ip, char *dst, uint off, uint n)
if(off > ip->size || off + n < off)
return -1;
if(off + n > ip->size)
// User tried to read past end of file.
// This would cause `bmap` to allocate blocks
// to accomodate. We don't want that.
n = ip->size - off;

for(tot=0; tot<n; tot+=m, off+=m, dst+=m){
Expand Down
11 changes: 5 additions & 6 deletions fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ struct superblock {
uint bmapstart; // Block number of first free map block
};

#define NDIRECT 12
#define NINDIRECT (BSIZE / sizeof(uint))
#define MAXFILE (NDIRECT + NINDIRECT)
#define NDIRECT 11 // Num direct block pointers on an inode
#define NINDIRECT (BSIZE / sizeof(uint)) // Num 4byte pointers per block
#define MAXFILE (NDIRECT + NINDIRECT + NINDIRECT*NINDIRECT) // Max num of blocks in a file

// On-disk inode structure
// On-disk inode structure.
struct dinode {
short type; // File type
short major; // Major device number (T_DEV only)
short minor; // Minor device number (T_DEV only)
short nlink; // Number of links to inode in file system
uint size; // Size of file (bytes)
uint addrs[NDIRECT+1]; // Data block addresses
uint addrs[NDIRECT+2]; // Data block addresses
};

// Inodes per block.
Expand All @@ -54,4 +54,3 @@ struct dirent {
ushort inum;
char name[DIRSIZ];
};

3 changes: 1 addition & 2 deletions param.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@
#define MAXOPBLOCKS 10 // max # of blocks any FS op writes
#define LOGSIZE (MAXOPBLOCKS*3) // max data blocks in on-disk log
#define NBUF (MAXOPBLOCKS*3) // size of disk block cache
#define FSSIZE 1000 // size of file system in blocks

#define FSSIZE 20000 // size of file system in blocks

0 comments on commit 5c81f9f

Please sign in to comment.