view src/impl/fs_impl.cbc @ 323:f0b337cb6024 default tip

use goto err->panic
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sat, 08 Feb 2020 20:37:42 +0900
parents 98902fad1e2e
children
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 "Err.h"
#interface "fs.dg"

// ----
// typedef struct fs_impl<Impl, Isa> impl fs{
//     union Data* fs_impl;
// 
// 
// 
// 
// } fs_impl;
// ----

fs* createfs_impl(struct Context* cbc_context) {
    struct fs* fs  = new fs();
    struct fs_impl* fs_impl = new fs_impl();
    fs->fs = (union Data*)fs_impl;
    fs_impl->fs_impl = NULL;
    fs_impl->sb = NULL;
    fs_impl->ret  = 0;
    fs_impl->dev  = 0;
    fs_impl->type  = 0;
    fs_impl->bp = NULL;
    fs_impl->dip = NULL;
    fs_impl->inum  = 0;
    fs_impl->dp = NULL;
    fs_impl->name = NULL;
    fs_impl->off  = 0;
    fs_impl->poff = NULL;
    fs_impl->de = NULL;
    fs_impl->tot  = 0;
    fs_impl->m  = 0;
    fs_impl->dst = NULL;
    fs_impl->n  = 0;
    fs_impl->src = NULL;
    fs_impl->allocinode = C_allocinode;
    fs_impl->allocinode_loop = C_allocinode_loop;
    fs_impl->allocinode_loopcheck = C_allocinode_loopcheck;
    fs_impl->allocinode_noloop = C_allocinode_noloop;
    fs_impl->lockinode1 = C_lockinode1;
    fs_impl->lockinode2 = C_lockinode2;
    fs_impl->lockinode_sleepcheck = C_lockinode_sleepcheck;
    fs_impl->iput_check = C_iput_check;
    fs_impl->iput_inode_nolink = C_iput_inode_nolink;
    fs_impl->readi_check_diskinode = C_readi_check_diskinode;
    fs_impl->readi_loopcheck = C_readi_loopcheck;
    fs_impl->readi_loop = C_readi_loop;
    fs_impl->readi_noloop = C_readi_noloop;
    fs_impl->writei_check_diskinode = C_writei_check_diskinode;
    fs_impl->writei_loopcheck = C_writei_loopcheck;
    fs_impl->writei_loop = C_writei_loop;
    fs_impl->writei_noloop = C_writei_noloop;
    fs_impl->dirlookup_loopcheck = C_dirlookup_loopcheck;
    fs_impl->dirlookup_loop = C_dirlookup_loop;
    fs_impl->dirlookup_noloop = C_dirlookup_noloop;
    fs_impl->dirlink_namecheck = C_dirlink_namecheck;
    fs_impl->dirlink_loopcheck = C_dirlink_loopcheck;
    fs_impl->dirlink_loop = C_dirlink_loop;
    fs_impl->dirlink_noloop = C_dirlink_noloop;
    fs->readsb = C_readsbfs_impl;
    fs->iinit = C_iinitfs_impl;
    fs->ialloc = C_iallocfs_impl;
    fs->iupdate = C_iupdatefs_impl;
    fs->idup = C_idupfs_impl;
    fs->ilock = C_ilockfs_impl;
    fs->iunlock = C_iunlockfs_impl;
    fs->iput = C_iputfs_impl;
    fs->iunlockput = C_iunlockputfs_impl;
    fs->stati = C_statifs_impl;
    fs->readi = C_readifs_impl;
    fs->writei = C_writeifs_impl;
    fs->namecmp = C_namecmpfs_impl;
    fs->dirlookup = C_dirlookupfs_impl;
    fs->dirlink = C_dirlinkfs_impl;
    fs->namei = C_nameifs_impl;
    fs->nameiparent = C_nameiparentfs_impl;
    return fs;
}

typedef struct superblock superblock;
__code readsbfs_impl(struct fs_impl* fs, uint dev, struct superblock* sb, __code next(...)) { //:skip

    struct buf* bp;

    bp = bread(dev, 1);
    memmove(sb, bp->data, sizeof(*sb));
    brelse(bp);

    goto next(...);
}

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

__code iinitfs_impl(struct fs_impl* fs, __code next(...)) {

     initlock(&icache.lock, "icache");

    goto next(...);
}

__code iallocfs_impl(struct fs_impl* fs, uint dev, short type, __code next(...)) {
    goto allocinode(fs, dev, sb, next(...));
}

__code iupdatefs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {

    struct buf *bp;
    struct dinode *dip;

    bp = bread(ip->dev, IBLOCK(ip->inum));

    dip = (struct dinode*) bp->data + ip->inum % IPB;
    dip->type = ip->type;
    dip->major = ip->major;
    dip->minor = ip->minor;
    dip->nlink = ip->nlink;
    dip->size = ip->size;

    memmove(dip->addrs, ip->addrs, sizeof(ip->addrs));
    log_write(bp);
    brelse(bp);


    goto next(...);
}

__code idupfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {

    acquire(&icache.lock);
    ip->ref++;
    release(&icache.lock);
    
    goto next(ip, ...);

}

__code ilockfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {

    goto lockinode1(fs, ip, bp, dip, next(...));
}

__code iunlockfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {
    
    if (ip == 0 || !(ip->flags & I_BUSY) || ip->ref < 1) {
       char* msg = "iunlock";
       struct Err* err = createKernelError(&proc->cbc_context);
       Gearef(cbc_context, Err)->msg = msg;
       goto meta(cbc_context, err->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(...)) {
    if (next == C_iputfs_impl) {
        next = fs->next2;
    }
    goto iput_check(fs, ip, next(...));   

}

__code iunlockputfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) {    
    fs->next2 = next; 
    goto iunlockfs_impl(ip, fs->iput, ...);
}

typedef struct stat stat;
__code statifs_impl(struct fs_impl* fs , struct inode* ip, struct stat* st, __code next(...)) { //:skip
    st->dev = ip->dev;
    st->ino = ip->inum;
    st->type = ip->type;
    st->nlink = ip->nlink;
    st->size = ip->size;
    goto next(...);
}

__code readifs_impl(struct fs_impl* fs, struct inode* ip, char* dst, uint off, uint tot, uint n, __code next(int ret, ...)) {
    if (ip->type == T_DEV) {
        goto readi_check_diskinode(fs, ip, dst, n, next(...));
    }

    if (off > ip->size || off + n < off) {
        ret = -1;
        goto next(ret, ...);
    }

    if (off + n > ip->size) {
        n = ip->size - off;
    }
    Gearef(cbc_context, fs)->tot = 0;
    goto readi_loopcheck(fs, tot, m, dst, off, n, next(...));
}

__code writeifs_impl(struct fs_impl* fs, struct inode* ip, char* src, uint off, uint tot, uint n, __code next(int ret, ...)) {
    if (ip->type == T_DEV) { 
        goto writei_check_diskinode(fs, ip, src, n, next(...));
    }
    
    if (off > ip->size || off + n < off) {
        ret = -1;
        goto next(ret, ...);
    }
    
    if (off + n > MAXFILE * BSIZE) {
        ret = -1;
        goto next(ret, ...);
    }
    Gearef(cbc_context, fs)->tot = 0;
    goto writei_loopcheck(fs, tot, m, src, off, n, next(...));
}


__code namecmpfs_impl(struct fs_impl* fs, const char* s, const char* t, __code next(int strncmp_val, ...)) {
    strncmp_val = strncmp(s, t, DIRSIZ);
    goto next(strncmp_val, ...);
}

__code dirlookupfs_impl(struct fs_impl* fs, struct inode* dp, char* name, uint off, uint* poff, dirent* de,  __code next(...)) { //:skip
    if (dp->type != T_DIR) { 
       char* msg = "dirlookup not DIR";
       struct Err* err = createKernelError(&proc->cbc_context);
       Gearef(cbc_context, Err)->msg = msg;
       goto meta(cbc_context, err->panic);
    }
    Gearef(cbc_context, fs)->off = 0;
    goto dirlookup_loopcheck(fs, dp, name, off, poff, de, next(...));
}

__code dirlinkfs_impl(struct fs_impl* fs, struct inode* ip, struct dirent* de, struct inode* dp, char* name, uint off, uint inum, __code next(...)) { //:skip
    // Check that name is not present.
    if ((ip = dirlookup(dp, name, 0)) != 0) {
        goto dirlink_namecheck(fs, ip, next(...));
    }
    Gearef(cbc_context, fs)->off = 0;
    goto dirlink_loopcheck(fs, de, dp, off, next(...));
}

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;
}

static char* skipelem (char *path, char *name)
{
    char *s;
    int len;

    while (*path == '/') {
        path++;
    }

    if (*path == 0) {
        return 0;
    }

    s = path;

    while (*path != '/' && *path != 0) {
        path++;
    }

    len = path - s;

    if (len >= DIRSIZ) {
        memmove(name, s, DIRSIZ);
    } else {
        memmove(name, s, len);
        name[len] = 0;
    }

    while (*path == '/') {
        path++;
    }

    return path;
}


static struct inode* namex (char *path, int nameiparent, char *name)
{
    struct inode *ip, *next;

    if (*path == '/') {
        ip = iget(ROOTDEV, ROOTINO);
    } else {
        ip = idup(proc->cwd);
    }

    while ((path = skipelem(path, name)) != 0) {
        ilock(ip);

        if (ip->type != T_DIR) {
            iunlockput(ip);
            return 0;
        }

        if (nameiparent && *path == '\0') {
            // Stop one level early.
            iunlock(ip);
            return ip;
        }

        if ((next = dirlookup(ip, name, 0)) == 0) {
            iunlockput(ip);
            return 0;
        }

        iunlockput(ip);
        ip = next;
    }

    if (nameiparent) {
        iput(ip);
        return 0;
    }

    return ip;
}

__code nameifs_impl(struct fs_impl* fs, char* path, __code next(int namex_val, ...)) {
    char name[DIRSIZ];
    namex_val = namex(path, 0, name);
    goto next(namex_val, ...);
}

__code nameiparentfs_impl(struct fs_impl* fs, char* path, char* name, __code next(int namex_val, ...)) {

    namex_val = namex(path, 1, name);
    goto next(namex_val, ...);

}