view src/impl/fs_impl_private.cbc @ 309:c6cbe4711e02

tweak
author menikon
date Mon, 03 Feb 2020 15:29:54 +0900
parents 4cf83e6ce534
children b40deb55b7db
line wrap: on
line source

#include "types.h"
#include "defs.h"
#include "param.h"
#include "stat.h"
#include "mmu.h"
#include "proc.h"
#include "spinlock.h"
#include "buf.h"
#include "fs.h"
#include "file.h"
#interface "fs_impl.h"

/*
fs_impl* createfs_impl2();
*/

__code allocinode(struct fs_impl* fs_impl, uint dev, struct superblock* sb, __code next(int iget_val, ...)){ //:skip

    readsb(dev, sb);
    Gearef(cbc_context, fs_impl)->inum = 1; 
    goto allocinode_loopcheck(fs_impl, inum, dev, sb, bp, dip, next(iget_val, ...));

}

typedef struct buf buf;
typedef struct dinode dinode;

__code allocinode_loopcheck(struct fs_impl* fs_impl, int inum, uint dev, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int iget_val, ...)){ //:skip
    if( inum < sb->ninodes){
        goto allocinode_loop(fs_impl, inum, dev, type, sb, bp, dip, next(iget_val, ...));
    }
/*
    goto cbc_context->panic(...);
*/
}

__code allocinode_loop(struct fs_impl* fs_impl, int inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int iget_val, ...)){ //:skip
    bp = bread(dev, IBLOCK(inum));
    dip = (struct dinode*) bp->data + inum % IPB;
    if(dip->type = 0){
        goto allocinode_noloop(fs_impl, inum, dev, sb, bp, dip, next(iget_val, ...));
    }
    
    brelse(bp);    
    inum++;
    goto allocinode_loopcheck(fs_impl, inum, dev, type, sb, bp, dip, next(iget_val, ...));
}

struct {
    struct spinlock lock;
    struct inode inode[NINODE];
} icache;

static struct inode* iget (uint dev, uint inum)
{
    struct inode *ip, *empty;

    acquire(&icache.lock);

    // Is the inode already cached?
    empty = 0;

    for (ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++) {
        if (ip->ref > 0 && ip->dev == dev && ip->inum == inum) {
            ip->ref++;
            release(&icache.lock);
            return ip;
        }

        if (empty == 0 && ip->ref == 0) {   // Remember empty slot.
            empty = ip;
        }
    }

    // Recycle an inode cache entry.
    if (empty == 0) {
        panic("iget: no inodes");
    }

    ip = empty;
    ip->dev = dev;
    ip->inum = inum;
    ip->ref = 1;
    ip->flags = 0;
    release(&icache.lock);

    return ip;
}

__code allocinode_noloop(struct fs_impl* fs_impl, int inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int iget_val, ...)){ //:skip

    memset(dip, 0, sizeof(*dip));
    dip->type = type;
    log_write(bp);   
    brelse(bp);
    
    iget_val = iget(dev, inum);
    goto next(iget_val, ...);

}

__code lockinode1(struct fs_impl* fs_impl, struct inode* ip, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip

    if (ip == 0 || ip->ref < 1) {
       
    /*
    panic("ilock");
    goto panic();
    */
     }
    acquire(&icache.lock);

    goto lockinode_sleepcheck(fs_impl, ip, next(...));
    
}


__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(...);
}