diff --git a/kernel/file.h b/kernel/file.h index b076d1d..5c4eb3a 100644 --- a/kernel/file.h +++ b/kernel/file.h @@ -26,7 +26,7 @@ struct inode { short minor; short nlink; uint size; - uint addrs[NDIRECT+1]; + uint addrs[NDIRECT+2]; }; // map major device number to device functions. diff --git a/kernel/fs.c b/kernel/fs.c index c6bab15..8c970e6 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -416,7 +416,43 @@ bmap(struct inode *ip, uint bn) brelse(bp); return addr; } - + bn -= NINDIRECT; + if (bn < NINDIRECT2) { + // Load doubly indirect block L1 + if ((addr = ip->addrs[NDIRECT+1]) == 0){ + addr = balloc(ip->dev); + if(addr == 0) + return 0; + ip->addrs[NDIRECT+1] = addr; + } + // load doubly indirect block L2 + // we have NINDIRECT blocks for per L1 entry + bp = bread(ip->dev, addr); + a = (uint*)bp->data; + if ((addr = a[bn / NINDIRECT]) == 0) { + addr = balloc(ip->dev); + if (addr == 0) { + brelse(bp); + return 0; + } + a[bn / NINDIRECT] = addr; + log_write(bp); + } + brelse(bp); + // Load finally the target block + bp = bread(ip->dev, addr); + a = (uint*)bp->data; + if ((addr = a[bn % NINDIRECT]) == 0) { + addr = balloc(ip->dev); + if (addr) { + a[bn % NINDIRECT] = addr; + log_write(bp); + } + } + brelse(bp); + return addr; + } + printf("bn=%d\n", bn); panic("bmap: out of range"); } @@ -425,9 +461,9 @@ bmap(struct inode *ip, uint bn) void itrunc(struct inode *ip) { - int i, j; - struct buf *bp; - uint *a; + int i, j, k; + struct buf *bp, *bp1; + uint *a, *a1; for(i = 0; i < NDIRECT; i++){ if(ip->addrs[i]){ @@ -448,6 +484,26 @@ itrunc(struct inode *ip) ip->addrs[NDIRECT] = 0; } + if (ip->addrs[NDIRECT+1]) { + bp = bread(ip->dev, ip->addrs[NDIRECT+1]); + a = (uint*)bp->data; + for(j = 0; j < NINDIRECT; j++){ + if(a[j]) { + bp1 = bread(ip->dev, a[j]); + a1 = (uint*)bp1->data; + for (k = 0; k < NINDIRECT; ++ k) { + if (a1[k]) { + bfree(ip->dev, a1[k]); + } + } + brelse(bp1); + bfree(ip->dev, a[j]); + } + } + brelse(bp); + bfree(ip->dev, ip->addrs[NDIRECT+1]); + ip->addrs[NDIRECT+1] = 0; + } ip->size = 0; iupdate(ip); } diff --git a/kernel/fs.h b/kernel/fs.h index 139dcc9..cd5de8a 100644 --- a/kernel/fs.h +++ b/kernel/fs.h @@ -24,9 +24,10 @@ struct superblock { #define FSMAGIC 0x10203040 -#define NDIRECT 12 +#define NDIRECT 11 #define NINDIRECT (BSIZE / sizeof(uint)) -#define MAXFILE (NDIRECT + NINDIRECT) +#define NINDIRECT2 (NINDIRECT * NINDIRECT) +#define MAXFILE (NDIRECT + NINDIRECT + NINDIRECT2) // On-disk inode structure struct dinode { @@ -35,7 +36,7 @@ struct dinode { short minor; // Minor device number (T_DEVICE 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. diff --git a/user/bigfile.c b/user/bigfile.c index 0755700..a484040 100644 --- a/user/bigfile.c +++ b/user/bigfile.c @@ -32,9 +32,11 @@ main() printf("bigfile: file is too small\n"); exit(-1); } - + printf("bef close fd\n"); close(fd); + printf("aft close fd\n"); fd = open("big.file", O_RDONLY); + printf("aft open\n"); if(fd < 0){ printf("bigfile: cannot re-open big.file for reading\n"); exit(-1);