view src/impl/fs_impl_private.cbc @ 314:eb62acc627f1

continue fix goto
author menikon
date Wed, 05 Feb 2020 16:48:45 +0900
parents 9d7787e4e214
children 66a6aedf60f9
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(...)){ //:skip

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

}

typedef struct buf buf;
typedef struct dinode dinode;

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

__code allocinode_loop(struct fs_impl* fs_impl, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)){ //: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(...));
    }
    
    brelse(bp);    
    inum++;
    goto allocinode_loopcheck(fs_impl, inum, dev, type, sb, bp, dip, next(...));
}

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, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int ret, ...)){ //:skip

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

}

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

typedef struct dirent dirent;
__code dirlookup_loopcheck(struct fs_impl* fs_impl, struct inode* dp, char* name, uint off, uint* poff, dirent* de, __code next(...)){ //:skip
    if(off < dp->size){
        goto dirlookup_loop(fs_impl, dp, name, off, inum, poff, de, next(...));
    }
    goto dirlookup_noloop(fs_impl, next(...));
}

__code dirlookup_loop(struct fs_impl* fs_impl, struct inode* dp, char* name, uint off, uint inum, uint* poff, dirent* de, __code next(int ret, ...)){
    if (readi(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) {
        /*
        panic("dirlink read");
        goto panic(...);
        */
    }

    if (de->inum == 0) {
        off += sizeof(de);
        goto dirlookup_loopcheck(fs_impl, dp, name, poff, de, next(...));
    }

    if (namecmp(name, de->name) == 0) {
        // entry matches path element
        if (poff) {
            *poff = off;
        }

        inum = de->inum;
        ret = iget(dp->dev, inum);
        goto next(ret, ...);
    }

    off += sizeof(de);
    goto dirlookup_loopcheck(fs_impl, dp, name, poff, de, next(...));
}

__code dirlookup_noloop(struct fs_impl* fs_impl, __code next(int ret, ...)){
    ret = 0;
    goto next(ret, ...);
}