diff --git a/file.h b/file.h index c02f76c..0595ab7 100644 --- a/file.h +++ b/file.h @@ -21,7 +21,7 @@ struct inode { short minor; short nlink; uint size; - uint addrs[NDIRECT+1]; + uint addrs[NDIRECT+3]; }; #define I_BUSY 0x1 #define I_VALID 0x2 diff --git a/fs.c b/fs.c index 9d6dfd1..054e4fc 100644 --- a/fs.c +++ b/fs.c @@ -356,18 +356,25 @@ iunlockput(struct inode *ip) static uint bmap(struct inode *ip, uint bn) { - uint addr, *a; + uint addr, *a, i; struct buf *bp; + // We use 10 direct, two indirect and one double indirect pointer if(bn < NDIRECT){ + // If block number is less than direct pointers available + // allocate a disk block if not allocated/available + // then return the address of the block if((addr = ip->addrs[bn]) == 0) ip->addrs[bn] = addr = balloc(ip->dev); return addr; } + // The block number does not fall in the first 10 direct blocks + // Substract the number from the passed block number bn -= NDIRECT; if(bn < NINDIRECT){ // Load indirect block, allocating if necessary. + // This is the first indirect block range if((addr = ip->addrs[NDIRECT]) == 0) ip->addrs[NDIRECT] = addr = balloc(ip->dev); bp = bread(ip->dev, addr); @@ -378,6 +385,39 @@ bmap(struct inode *ip, uint bn) } brelse(bp); return addr; + } else if(bn < NINDIRECT * 2){ + bn -= NINDIRECT; + // Load indirect block, allocating if necessary. + // This is the second indirect block range + if((addr = ip->addrs[NDIRECT+1]) == 0) + ip->addrs[NDIRECT+1] = addr = balloc(ip->dev); + bp = bread(ip->dev, addr); + a = (uint*)bp->data; + if((addr = a[bn]) == 0){ + a[bn] = addr = balloc(ip->dev); + log_write(bp); + } + brelse(bp); + return addr; + } else { + // We are now in the double indirect block range + bn -= NINDIRECT * 2; + // Load indirect block, allocating if necessary. + if((addr = ip->addrs[NDIRECT+2]) == 0) + ip->addrs[NDIRECT+2] = addr = balloc(ip->dev); + bp = bread(ip->dev, addr); + a = (uint*)bp->data; + // This last double indirect block should contain addresses to + // other blocks and not data. Fig 6.4 of xv6 booklet + for (i = 0; i < BSIZE/4; i++){ + if((addr = a[i]) == 0){ + a[bn] = addr = balloc(ip->dev); + log_write(bp); + break; + } + } + brelse(bp); + return addr; } panic("bmap: out of range"); @@ -401,7 +441,7 @@ itrunc(struct inode *ip) ip->addrs[i] = 0; } } - + if(ip->addrs[NDIRECT]){ bp = bread(ip->dev, ip->addrs[NDIRECT]); a = (uint*)bp->data; diff --git a/fs.h b/fs.h index f191d43..970d829 100644 --- a/fs.h +++ b/fs.h @@ -19,9 +19,9 @@ struct superblock { uint nlog; // Number of log blocks }; -#define NDIRECT 12 +#define NDIRECT 10 #define NINDIRECT (BSIZE / sizeof(uint)) -#define MAXFILE (NDIRECT + NINDIRECT) +#define MAXFILE (NDIRECT + 2 * NINDIRECT + NINDIRECT * NINDIRECT) // On-disk inode structure struct dinode { @@ -30,7 +30,7 @@ struct dinode { 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+3]; // Data block addresses }; // Inodes per block.