changeset 307:4cf83e6ce534

add iput codeGear
author menikon
date Sat, 01 Feb 2020 18:08:31 +0900
parents 5ea0b8b12aaf
children 1ba0ca4113e1
files src/impl/fs_impl.cbc src/impl/fs_impl.h src/impl/fs_impl_private.cbc
diffstat 3 files changed, 134 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/impl/fs_impl.cbc	Fri Jan 31 18:48:54 2020 +0900
+++ b/src/impl/fs_impl.cbc	Sat Feb 01 18:08:31 2020 +0900
@@ -36,9 +36,12 @@
     fs->idup = C_idupfs_impl;
     fs->ilock = C_ilockfs_impl;
     fs_impl->lockinode1 = C_lockinode1;
+    fs_impl->lockinode2 = C_lockinode2;
     fs_impl->lockinode_sleepcheck = C_lockinode_sleepcheck;
     fs->iunlock = C_iunlockfs_impl;
     fs->iput = C_iputfs_impl;
+    fs_impl->iput_check = C_iput_check;
+    fs_impl->iput_inode_nolink = C_iput_inode_nolink;
     fs->iunlockput = C_iunlockputfs_impl;
     fs->stati = C_statifs_impl;
     fs->readi = C_readifs_impl;
@@ -117,13 +120,26 @@
 }
 
 __code iunlockfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
+    
+    if (ip == 0 || !(ip->flags & I_BUSY) || ip->ref < 1) {
+        /*
+        panic("iunlock");
+        goto panic();
+        */
+    }
+
+    acquire(&icache.lock);
+    ip->flags &= ~I_BUSY;
+    wakeup(ip);
+    release(&icache.lock);
 
     goto next(...);
 }
 
 __code iputfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
 
-    goto next(...);
+    goto iput_check(fs, ip, next(...));   
+
 }
 
 __code iunlockputfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
--- a/src/impl/fs_impl.h	Fri Jan 31 18:48:54 2020 +0900
+++ b/src/impl/fs_impl.h	Sat Feb 01 18:08:31 2020 +0900
@@ -13,6 +13,9 @@
     __code allocinode_loopcheck(Type* fs_impl, int inum, uint dev, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int iget_val, ...));
     __code allocinode_noloop(struct fs_impl* fs_impl, int inum, uint dev, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int iget_val, ...));
     __code lockinode1(Type* fs_impl, struct inode *ip, struct buf *bp, struct dinode *dip, __code next(...));
+    __code lockinode2(struct fs_impl* fs_impl, struct inode* ip, struct buf* bp, struct dinode* dip, __code next(...));
     __code lockinode_sleepcheck(struct fs_impl* fs_impl, struct inode* ip, __code next(...));
+    __code iput_check(struct fs_impl* fs_impl, struct inode* ip, __code next(...));
+    __code iput_inode_nolink(struct fs_impl* fs_impl, struct inode* ip, __code next(...));
     __code next(...);
 } fs_impl;
--- a/src/impl/fs_impl_private.cbc	Fri Jan 31 18:48:54 2020 +0900
+++ b/src/impl/fs_impl_private.cbc	Sat Feb 01 18:08:31 2020 +0900
@@ -114,11 +114,125 @@
     
 }
 
+
+__code lockinode2(struct fs_impl* fs_impl, struct inode* ip, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip
+
+    ip->flags |= I_BUSY;
+    release(&icache.lock);
+
+    if (!(ip->flags & I_VALID)) {
+        bp = bread(ip->dev, IBLOCK(ip->inum));
+
+        dip = (struct dinode*) bp->data + ip->inum % IPB;
+        ip->type = dip->type;
+        ip->major = dip->major;
+        ip->minor = dip->minor;
+        ip->nlink = dip->nlink;
+        ip->size = dip->size;
+
+        memmove(ip->addrs, dip->addrs, sizeof(ip->addrs));
+        brelse(bp);
+        ip->flags |= I_VALID;
+
+        if (ip->type == 0) {
+             /*
+             panic("ilock: no type");
+             goto panic();
+             */
+        }
+    }
+    goto next(...);
+}
 __code lockinode_sleepcheck(struct fs_impl* fs_impl, struct inode* ip, __code next(...)){
     if(ip->flags & I_BUSY){
         sleep(ip, &icache.lock);
         goto lockinode_sleepcheck(fs_impl, ip, next(...));
     }
+    goto lockinode2(fs_impl, ip, bp, dip, next(...));
+}
+
+__code iput_check(struct fs_impl* fs_impl, struct inode* ip, __code next(...)){
+    acquire(&icache.lock);
+    if (ip->ref == 1 && (ip->flags & I_VALID) && ip->nlink == 0) { 
+        goto iput_inode_nolink(fs_impl, ip, next(...));
+    }
+    ip->ref--;
+    release(&icache.lock);
+    goto next(...);
+
+}
+
+static void bfree (int dev, uint b)
+{
+    struct buf *bp;
+    struct superblock sb;
+    int bi, m;
+
+    readsb(dev, &sb);
+    bp = bread(dev, BBLOCK(b, sb.ninodes));
+    bi = b % BPB;
+    m = 1 << (bi % 8);
+
+    if ((bp->data[bi / 8] & m) == 0) {
+        panic("freeing free block");
+    }
+
+    bp->data[bi / 8] &= ~m;
+    log_write(bp);
+    brelse(bp);
+}
+
+
+static void itrunc (struct inode *ip)
+{
+    int i, j;
+    struct buf *bp;
+    uint *a;
+
+    for (i = 0; i < NDIRECT; i++) {
+        if (ip->addrs[i]) {
+            bfree(ip->dev, ip->addrs[i]);
+            ip->addrs[i] = 0;
+        }
+    }
+
+    if (ip->addrs[NDIRECT]) {
+        bp = bread(ip->dev, ip->addrs[NDIRECT]);
+        a = (uint*) bp->data;
+
+        for (j = 0; j < NINDIRECT; j++) {
+            if (a[j]) {
+                bfree(ip->dev, a[j]);
+            }
+        }
+
+        brelse(bp);
+        bfree(ip->dev, ip->addrs[NDIRECT]);
+        ip->addrs[NDIRECT] = 0;
+    }
+
+    ip->size = 0;
+    iupdate(ip);
+}
+
+__code iput_inode_nolink(struct fs_impl* fs_impl, struct inode* ip, __code next(...)){
+    
+    if (ip->flags & I_BUSY) {
+        /*
+        panic("iput busy"); 
+        */
+    }   
+        
+    ip->flags |= I_BUSY;
+    release(&icache.lock);
+    itrunc(ip);
+    ip->type = 0;
+    iupdate(ip);
+        
+    acquire(&icache.lock);
+    ip->flags = 0;
+    wakeup(ip); 
     goto next(...);
 }
 
+