summaryrefslogtreecommitdiff
path: root/kernel/fs.c
diff options
context:
space:
mode:
authorMole Shang <[email protected]>2024-02-19 14:10:32 +0800
committerMole Shang <[email protected]>2024-02-19 14:36:21 +0800
commitd86118fc80267649b4791c8c0c72ebd60edf1ef2 (patch)
treeb792b617b4df80a5803a9c1164d0e3fdfe9cfe31 /kernel/fs.c
parentb20ef9d0210fd7d9403acde1857eed1b9880c0b2 (diff)
parent0cf897cbe05fd8485162619db4244f4159d0eb52 (diff)
downloadxv6-labs-d86118fc80267649b4791c8c0c72ebd60edf1ef2.tar.gz
xv6-labs-d86118fc80267649b4791c8c0c72ebd60edf1ef2.tar.bz2
xv6-labs-d86118fc80267649b4791c8c0c72ebd60edf1ef2.zip
Merge branch 'fs' into mmap
Conflicts: .gitignore Makefile conf/lab.mk kernel/defs.h user/user.h
Diffstat (limited to 'kernel/fs.c')
-rw-r--r--kernel/fs.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/kernel/fs.c b/kernel/fs.c
index c6bab15..57b36a1 100644
--- a/kernel/fs.c
+++ b/kernel/fs.c
@@ -295,11 +295,11 @@ ilock(struct inode *ip)
struct buf *bp;
struct dinode *dip;
- if(ip == 0 || ip->ref < 1)
+ if(ip == 0 || atomic_read4(&ip->ref) < 1)
panic("ilock");
acquiresleep(&ip->lock);
-
+
if(ip->valid == 0){
bp = bread(ip->dev, IBLOCK(ip->inum, sb));
dip = (struct dinode*)bp->data + ip->inum%IPB;
@@ -320,7 +320,7 @@ ilock(struct inode *ip)
void
iunlock(struct inode *ip)
{
- if(ip == 0 || !holdingsleep(&ip->lock) || ip->ref < 1)
+ if(ip == 0 || !holdingsleep(&ip->lock) || atomic_read4(&ip->ref) < 1)
panic("iunlock");
releasesleep(&ip->lock);
@@ -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,7 +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");
}
@@ -425,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]){
@@ -439,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 +478,27 @@ itrunc(struct inode *ip)
bfree(ip->dev, ip->addrs[NDIRECT]);
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);