Mercurial > hg > Members > menikon > CbC_xv6
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, ...); }