view src/impl/fs_impl.cbc @ 254:66a6aedf60f9

add CodeGear dirlink_loopcheck etc
author menikon
date Wed, 05 Feb 2020 17:39:17 +0900
parents b527f27761bf
children 8c8f092e4f52
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.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->readsb = C_readsbfs_impl;
    fs->iinit = C_iinitfs_impl;
    fs->ialloc = C_iallocfs_impl;
    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->iupdate = C_iupdatefs_impl;
    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;
    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) {
        /*
        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 iput_check(fs, ip, next(...));   

}

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

    goto next(...);
}

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 n, __code next(...)) {

    goto next(...);
}

__code writeifs_impl(struct fs_impl* fs, struct inode* ip, char* src, uint off, uint n, __code next(...)) {

    goto 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) { 
        /*
        panic("dirlookup not DIR");
        */
    }
    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(...));
    }
    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, ...);

}