diff options
| -rw-r--r-- | kernel/file.h | 2 | ||||
| -rw-r--r-- | kernel/fs.c | 63 | ||||
| -rw-r--r-- | kernel/fs.h | 8 | 
3 files changed, 64 insertions, 9 deletions
| diff --git a/kernel/file.h b/kernel/file.h index 1eb5107..b993cc3 100644 --- a/kernel/file.h +++ b/kernel/file.h @@ -33,7 +33,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 6c4079e..57b36a1 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -396,7 +396,7 @@ bmap(struct inode *ip, uint bn)    }    bn -= NDIRECT; -  if(bn < NINDIRECT){ +  if(bn < NSG_INDIRECT){      // Load indirect block, allocating if necessary.      if((addr = ip->addrs[NDIRECT]) == 0){        addr = balloc(ip->dev); @@ -416,6 +416,38 @@ bmap(struct inode *ip, uint bn)      brelse(bp);      return addr;    } +  bn -= NSG_INDIRECT; + +  if(bn < NDB_INDIRECT){ +    // Load indirect block in each level, allocating if necessary. +    if((addr = ip->addrs[NDIRECT+1]) == 0){ +      addr = balloc(ip->dev); +      if(addr == 0) +        return 0; +      ip->addrs[NDIRECT+1] = addr; +    } +    bp = bread(ip->dev, addr); +    a = (uint*)bp->data; +    if((addr = a[bn/NSG_INDIRECT]) == 0){ +      addr = balloc(ip->dev); +      if(addr){ +        a[bn/NSG_INDIRECT] = addr; +        log_write(bp); +      } +    } +    brelse(bp); +    bp = bread(ip->dev, addr); +    a = (uint*)bp->data; +    if((addr = a[bn%NSG_INDIRECT]) == 0){ +      addr = balloc(ip->dev); +      if(addr){ +        a[bn%NSG_INDIRECT] = addr; +        log_write(bp); +      } +    } +    brelse(bp); +    return addr; +  }    panic("bmap: out of range");  } @@ -424,9 +456,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, *l2bp; +  uint *a, *l2a;    for(i = 0; i < NDIRECT; i++){      if(ip->addrs[i]){ @@ -438,7 +470,7 @@ itrunc(struct inode *ip)    if(ip->addrs[NDIRECT]){      bp = bread(ip->dev, ip->addrs[NDIRECT]);      a = (uint*)bp->data; -    for(j = 0; j < NINDIRECT; j++){ +    for(j = 0; j < NSG_INDIRECT; j++){        if(a[j])          bfree(ip->dev, a[j]);      } @@ -447,6 +479,27 @@ 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 < NSG_INDIRECT; j++){ +      if(a[j]){ +        l2bp = bread(ip->dev, a[j]); +        l2a = (uint*)l2bp->data; +        for(k = 0; k < NSG_INDIRECT; k++) +        { +          if(l2a[k]){ +            bfree(ip->dev, l2a[k]); +          } +        } +        brelse(l2bp);        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..9ae5ece 100644 --- a/kernel/fs.h +++ b/kernel/fs.h @@ -24,8 +24,10 @@ struct superblock {  #define FSMAGIC 0x10203040 -#define NDIRECT 12 -#define NINDIRECT (BSIZE / sizeof(uint)) +#define NDIRECT 11 +#define NSG_INDIRECT (BSIZE / sizeof(uint)) +#define NDB_INDIRECT (NSG_INDIRECT * NSG_INDIRECT) +#define NINDIRECT (NSG_INDIRECT + NDB_INDIRECT)  #define MAXFILE (NDIRECT + NINDIRECT)  // On-disk inode structure @@ -35,7 +37,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. | 
