view src/impl/fs_impl_private.cbc @ 258:71c7bd0d047e

build success
author menikon
date Thu, 06 Feb 2020 17:21:04 +0900
parents d4ff2fb275b5
children 40e9dd5ff084
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"
#define min(a, b) ((a) < (b) ? (a) : (b))

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

__code readi_check_diskinode(struct fs_impl* fs_impl,struct inode* ip, char* dst, uint n, __code next(int ret, ...)){
    if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].read) {
        ret = -1;
        goto next(ret, ...);
    }

    ret = devsw[ip->major].read(ip, dst, n);
    goto next(ret, ...);
}

__code readi_loopcheck(struct fs_impl* fs_impl, uint tot, uint m, char* dst, uint off, uint n, __code next(...)){
    if(tot < n){
        goto readi_loop(fs_impl, ip, bp, tot, m, dst, off, n, next(...));
    }
    goto readi_noloop(fs_impl, next(...));
}

static void bzero (int dev, int bno)
{
    struct buf *bp;

    bp = bread(dev, bno);
    memset(bp->data, 0, BSIZE);
    log_write(bp);
    brelse(bp);
}

static uint balloc (uint dev)
{
    int b, bi, m;
    struct buf *bp;
    struct superblock sb;

    bp = 0;
    readsb(dev, &sb);

    for (b = 0; b < sb.size; b += BPB) {
        bp = bread(dev, BBLOCK(b, sb.ninodes));

        for (bi = 0; bi < BPB && b + bi < sb.size; bi++) {
            m = 1 << (bi % 8);

            if ((bp->data[bi / 8] & m) == 0) {  // Is block free?
                bp->data[bi / 8] |= m;  // Mark block in use.
                log_write(bp);
                brelse(bp);
                bzero(dev, b + bi);
                return b + bi;
            }
        }

        brelse(bp);
    }

    panic("balloc: out of blocks");
}


static uint bmap (struct inode *ip, uint bn)
{
    uint addr, *a;
    struct buf *bp;

    if (bn < NDIRECT) {
        if ((addr = ip->addrs[bn]) == 0) {
            ip->addrs[bn] = addr = balloc(ip->dev);
        }

        return addr;
    }

    bn -= NDIRECT;

    if (bn < NINDIRECT) {
        // Load indirect block, allocating if necessary.
        if ((addr = ip->addrs[NDIRECT]) == 0) {
            ip->addrs[NDIRECT] = addr = balloc(ip->dev);
        }

        bp = bread(ip->dev, addr);
        a = (uint*) bp->data;

        if ((addr = a[bn]) == 0) {
            a[bn] = addr = balloc(ip->dev);
            log_write(bp);
        }

        brelse(bp);
        return addr;
    }

    panic("bmap: out of range");
}


__code readi_loop(struct fs_impl* fs_impl, struct inode* ip, struct buf* bp, uint tot, uint m, char* dst, uint off, uint n, __code next(...)){ //:skip
    bp = bread(ip->dev, bmap(ip, off / BSIZE));
    m = min(n - tot, BSIZE - off%BSIZE);
    memmove(dst, bp->data + off % BSIZE, m);
    brelse(bp);
    tot += m;
    off += m; 
    dst += m;
    goto readi_loopcheck(fs_impl, tot, m, dst, off, n, next(...));
}

__code readi_noloop(struct fs_impl* fs_impl, uint n, __code next(int ret, ...)){
    ret = n;
    goto next(ret, ...);

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

__code dirlink_namecheck(struct fs_impl* fs_impl, struct inode* ip, __code next(int ret, ...)){
    iput(ip);
    ret = -1;
    goto next(ret, ...);
}

__code dirlink_loopcheck(struct fs_impl* fs_impl, struct dirent* de, struct inode* dp, uint off, __code next(...)){ //:skip
    if(off < dp->size){
        goto dirlink_loop(fs_impl, de, dp, off, inum, next(...));
    }
    goto dirlink_noloop(fs_impl, de, dp, off, inum, name, next(...));
}

__code dirlink_loop(struct fs_impl* fs_impl, struct dirent* de, struct inode* dp, uint off, uint inum, __code next(...)){ //:skip
    if (readi(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) {
        /*    
        panic("dirlink read");
        */
    }

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

__code dirlink_noloop(struct fs_impl* fs_impl, struct dirent* de, struct inode* dp, uint off, uint inum, char* name, __code next(int ret, ...)){ //:skip
    strncpy(de->name, name, DIRSIZ);
    de->inum = inum;

    if (writei(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) {
        /*
        panic("dirlink");
        */
    }
    ret = 0;
    goto next(ret, ...);
}