⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernel.c

📁 be文件系统实现的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  This file contains the vnode layer used by the file system construction  kit.  It is the file system independent layer and managed hooking up  requests from the test program (fsh and tstfs) to the actual file system  routines.  It provides a rather posix-like interface generally with  the routines preceded by a "sys_" prefix.    THIS CODE COPYRIGHT DOMINIC GIAMPAOLO.  NO WARRANTY IS EXPRESSED   OR IMPLIED.  YOU MAY USE THIS CODE AND FREELY DISTRIBUTE IT FOR  NON-COMMERCIAL USE AS LONG AS THIS NOTICE REMAINS ATTACHED.  FOR COMMERCIAL USE, CONTACT DOMINIC GIAMPAOLO (dbg@be.com).  Dominic Giampaolo  dbg@be.com*/#include "compat.h"#include "skiplist.h"#include "lock.h"#include "fsproto.h"#include "kprotos.h"#include <sys/stat.h>#define     OMODE_MASK      (O_RDONLY | O_WRONLY | O_RDWR)#define     SLEEP_TIME      (10000.0)#define     MAX_SYM_LINKS   16#define     FREE_LIST       0#define     USED_LIST       1#define     LOCKED_LIST     2#define     LIST_NUM        3#define     FD_FILE         1#define     FD_DIR          2#define     FD_WD           4#define     FD_ALL          (FD_FILE | FD_DIR | FD_WD)#define     DEFAULT_FD_NUM  (128)#define     VNNUM           256typedef unsigned long       fsystem_id;typedef struct vnode vnode;typedef struct vnlist vnlist;typedef struct vnlink vnlink;typedef struct fsystem fsystem;typedef struct nspace nspace;typedef struct ofile ofile;typedef struct ioctx ioctx;typedef struct fdarray fdarray;struct vnlist {    vnode           *head;    vnode           *tail;    int             num;};struct vnlink {    vnode           *prev;    vnode           *next;};struct vnode {    vnode_id        vnid;    nspace *        ns;    nspace *        mounted;    char            remove;    char            busy;    char            inlist;    char            watched;    vnlink          nspace;    vnlink          list;    int             rcnt;    void *          data;};struct fsystem {    fsystem_id          fsid;    bool                fixed;    image_id            aid;    char                name[IDENT_NAME_LENGTH];    int                 rcnt;    vnode_ops           ops;};struct nspace {    nspace_id           nsid;    my_dev_t            dev;    my_ino_t            ino;    fsystem             *fs;    vnlist              vnodes;    void                *data;    vnode *             root;    vnode *             mount;    nspace *            prev;    nspace *            next;    char                shutdown;};struct ofile {    short           type;    ushort          flags;    vnode *         vn;    void *          cookie;    long            rcnt;    long            ocnt;    fs_off_t            pos;    int             omode;};struct ioctx {    lock            lock;    int             kerrno;    vnode *         cwd;    fdarray *       fds;};struct fdarray {    long            rcnt;    lock            lock;    int             num;    ulong           *alloc;    ulong           *coes;    ofile           *fds[1];};extern struct {    const char *    name;    vnode_ops *     ops;} fixed_fs[];static vnode_id     invalid_vnid = 0;static vnode *      rootvn;static int          max_glb_file;static fdarray *    global_fds;static vnlist       lists[LIST_NUM];static nspace *     nshead;static lock         vnlock;static lock         fstablock;static nspace **    nstab;static fsystem **   fstab;static int          nns;static int          nfs;static fsystem_id   nxfsid;static nspace_id    nxnsid;static SkipList     skiplist;static int          vnnum;static int          usdvnnum;int                 sys_rstat(bool kernel, int fd, const char *path,                              struct my_stat *st, bool eatlink);static fsystem *    inc_file_system(const char *name);static int          dec_file_system(fsystem *fs);static int      get_dir_fd(bool kernel, int fd, const char *path, char *filename,                    vnode **dvn);static int      get_file_fd(bool kernel, int fd, const char *path,                    int eatsymlink, vnode **vn);static int      get_file_vn(nspace_id nsid, vnode_id vnid, const char *path,                    int eatsymlink, vnode **vn);static int      parse_path_fd(bool kerne, int fd, char **pstart,                    int eatsymlink, vnode **vn);static int      parse_path_vn(nspace_id nsid, vnode_id vnid, char **start,                    int eatsymlink, vnode **vn);static int      parse_path(vnode *bvn, char **pstart, char *path,                    int eatsymlink, vnode **vn);static char *   cat_paths(char *a, char *b);static int      load_vnode(nspace_id nsid, vnode_id vnid, char r, vnode **vnp);static vnode *  lookup_vnode(nspace_id nsid, vnode_id vnid);static void     move_vnode(vnode *vn, int list);static vnode *  steal_vnode(int list);static void     flush_vnode(vnode *vn, char r);static int      sort_vnode(vnode *vn);static void     clear_vnode(vnode *vn);static void     inc_vnode(vnode *vn);static void     dec_vnode(vnode *vn, char r);static int      compare_vnode(vnode *vna, vnode *vnb);static nspace * nsidtons(nspace_id nsid);static int      alloc_wd_fd(bool kernel, vnode *vn, bool coe, int *fdp);static int      is_root(vnode *root, vnode **mount);static int      is_mount_vnode(vnode *mount, vnode **root);static int      is_mount_vnid(nspace_id nsid, vnode_id vnid, vnode_id *mount);static ofile *      get_fd(bool kernel, int fd, int type);static int          put_fd(ofile *f);static int          new_fd(bool kernel, int nfd, ofile *f, int fd, bool coe);static int          remove_fd(bool kernel, int fd, int type);static int          get_coe(bool kernel, int fd, int type, bool *coe);static int          set_coe(bool kernel, int fd, int type, bool coe);static int          get_omode(bool kernel, int fd, int type, int *omode);static int          invoke_close(ofile *f);static int          invoke_free(ofile *f);static fdarray *    new_fds(int num);static int          free_fds(fdarray *fds);#define BITSZ(n)        (((n) + 31) & ~31)#define SETBIT(a,i,v)   *((a)+(i)/32) = (*((a)+(i)/32) & ~(1<<((i)%32))) | (v<<((i)%32))#define GETBIT(a,i)     ((*((a)+(i)/32) & (1<<((i)%32))) >> ((i)%32))/* ---------------------------------------------------------------- */#include <stdio.h>static voidPANIC(char *s){    printf(s);}#ifdef DEBUGintdump_fsystem(int argc, char **argv){    struct fsystem *fs;    if (argv[1] == NULL) {        kprintf("%s needs an address argument\n", argv[0]);        return 1;    }    fs = (struct fsystem *)strtoul(argv[1], NULL, 0);        kprintf("fs @ 0x%x name %s rcnt %d ops @ 0x%x\n", fs, fs->name,            fs->rcnt, &fs->ops);}intdump_ioctx(int argc, char **argv){    struct ioctx *ioctx;    if (argv[1] == NULL) {        kprintf("%s needs an address argument\n", argv[0]);        return 1;    }    ioctx = (struct ioctx *)strtoul(argv[1], NULL, 0);        kprintf("ioctx @ 0x%x, kerrno %d, cwd 0x%x, fdarray 0x%x\n", ioctx,            ioctx->kerrno, ioctx->cwd, ioctx->fds);}intdump_vnode(int argc, char **argv){    struct vnode *vn;    if (argv[1] == NULL) {        kprintf("%s needs an address argument\n", argv[0]);        return 1;    }    vn = (vnode *)strtoul(argv[1], NULL, 0);        kprintf("vnode @ 0x%x vnid 0x%x ns 0x%x mounted 0x%x\n", vn, vn->vnid,            vn->ns, vn->mounted);    kprintf("remove %d busy %d inlist %d\n", vn->remove, vn->busy, vn->inlist);    kprintf("nspace 0x%x list 0x%x rcnt 0x%x data 0x%x\n", &vn->nspace,            &vn->list, vn->rcnt, vn->data);}intdump_fdarray(int argc, char **argv){    int             i;    struct fdarray *fds;    if (argv[1] == NULL) {        kprintf("%s needs an address argument\n", argv[0]);        return 1;    }    fds = (struct fdarray *)strtoul(argv[1], NULL, 0);        kprintf("fdarray @ 0x%x  rcnt %d lock %d num %d\n", fds, fds->rcnt,            fds->num);    kprintf("alloc 0x%x coes 0x%x\n", fds->alloc, fds->coes);    for(i=0; i < fds->num; i++)        if (fds->fds[i])            kprintf("fd %3d @ 0x%x\n", i, fds->fds[i]);}intdump_ofile(int argc, char **argv){    struct ofile *ofile;    if (argv[1] == NULL) {        kprintf("%s needs an address argument\n", argv[0]);        return 1;    }    ofile = (struct ofile *)strtoul(argv[1], NULL, 0);        kprintf("ofile @ 0x%x type %d flags %d vn 0x%x cookie 0x%x\n",            ofile, ofile->type, ofile->flags, ofile->vn, ofile->cookie);    kprintf("rcnt %d ocnt %d pos 0x%x omode 0x%x\n", ofile->rcnt, ofile->ocnt,            ofile->pos, ofile->omode);}intdump_nspace(int argc, char **argv){    struct nspace *ns;    if (argv[1] == NULL) {        kprintf("%s needs an address argument\n", argv[0]);        return 1;    }    ns = (struct nspace *)strtoul(argv[1], NULL, 0);        kprintf("ns @ 0x%x nsid %d vnlist @ 0x%x data 0x%x\n", ns, ns->nsid,            &ns->vnodes, ns->data);    kprintf("root 0x%x mount 0x%x prev 0x%x next 0x%x\n", ns->root, ns->mount,            ns->prev, ns->next);    kprintf("shutdown %d fs @ 0x%x\n", ns->shutdown, ns->fs);}voiddo_dump_io_info(thread_rec *thr){    int i;    struct fdarray *fds;    if (thr->ioctx == NULL || thr->ioctx->fds == NULL) {        kprintf("thread: %d (%s)\n  No io info?!?\n", thr->thid, thr->name);        return;    }            kprintf("thread: %d (%s)\n", thr->thid, thr->name);    fds = thr->ioctx->fds;    for(i=0; i < fds->num; i++)        if (fds->fds[i])            kprintf("  fd %3d vnode @ 0x%.8x (vnid 0x%.8x, data 0x%.8x)\n", i,                    fds->fds[i]->vn, fds->fds[i]->vn->vnid,                    fds->fds[i]->vn->data);}intdump_io_info(int argc, char **argv){    int             i;    thread_rec     *thr;    if (argv[1] == NULL) {        kprintf("%s needs an thread name/address argument\n", argv[0]);        return 1;    }    if (strcmp(argv[1], "-n") == 0) {        int len;                /* hunt for the name in argv[2] */        if (argv[2] == NULL) {            kprintf("thread: the `-name' option requires an argument\n");            return 0;        }        len = strlen(argv[2]);        for(i=0; i < nthreads; i++) {            if (thread_tab[i] == NULL)                 continue;            if (mystrstr(thread_tab[i]->name, argv[2]) != NULL) {                thr = thread_tab[i];                do_dump_io_info(thr);            }        }    } else {        ulong num;        num = strtoul(argv[2], NULL, 0);        if (num < 0x2ffff && isbadthid(num) == 0)            thr = thread_tab[thidtoslot(num)];        else            thr = (thread_rec *)num;                if (thr == 0)            return 0;        do_dump_io_info(thr);    }    return 1;}intfind_vn(int argc, char **argv){    nspace      *ns;    vnode       *vn;    vnode       fakevn;    vnode_id    vnid;    if (argv[1] == NULL) {        kprintf("%s needs a vnid argument\n", argv[0]);        return 1;    }    vnid = (vnode_id)strtoul(argv[1], NULL, 0);    for(ns=nshead; ns; ns=ns->next) {        fakevn.ns = ns;        fakevn.vnid = vnid;        vn = SearchSL(skiplist, &fakevn);        if (vn)            kprintf("vn = 0x%x (nsid = %d)\n", vn, vn->ns->nsid);    }    return 0;}#endif /* DEBUG *//* ---------------------------------------------------------------- */#ifdef USERint memsize = 8 * 1024 * 1024;#endifintinit_vnode_layer(void){    int         err;    vnode       *vns;    vnode_id    vnid;    int         i;    fsystem     *fs;    nspace      *ns;    void        *data;    size_t      sz;    extern vnode_ops rootfs;  /* XXXdbg */    /*    compute vnnum based on memsize. 256 vnodes with 8MB.    compute usdvnnum based on vnnum. only 1/4 of total vnodes should    remain unlocked.     */    vnnum = memsize >> 15;    usdvnnum = vnnum >> 2;    vns = (vnode *) calloc(sizeof(vnode) * vnnum, 1);    for(i=0; i<vnnum; i++) {        vns[i].vnid = invalid_vnid;        vns[i].ns = NULL;        vns[i].mounted = NULL;        vns[i].remove = FALSE;        vns[i].busy = FALSE;        vns[i].inlist = FREE_LIST;        vns[i].nspace.next = vns[i].nspace.prev = NULL;        vns[i].list.next = (i == vnnum-1 ? NULL : &vns[i+1]);        vns[i].list.prev = (i == 0 ? NULL : &vns[i-1]);        vns[i].rcnt = 0;        vns[i].data = NULL;    }    lists[FREE_LIST].head = &vns[0];    lists[FREE_LIST].tail = &vns[vnnum-1];    lists[FREE_LIST].num = vnnum;    lists[USED_LIST].head = NULL;    lists[USED_LIST].tail = NULL;    lists[USED_LIST].num = 0;    lists[LOCKED_LIST].head = NULL;    lists[LOCKED_LIST].tail = NULL;    lists[LOCKED_LIST].num = 0;        skiplist = NewSL(&compare_vnode, NULL, NO_DUPLICATES);    /*    set max # of file systems and mount points.    with 8MB, up to 32 fs and 64 mount points.    */    nns = memsize >> 17;    nfs = memsize >> 18;    nxfsid = 1;    nxnsid = 1;    nstab = (nspace **) malloc(nns * sizeof(void *));    memset(nstab, 0, nns * sizeof(void *));    fstab = (fsystem **) malloc(nfs * sizeof(void *));    memset(fstab, 0, nfs * sizeof(void *));    new_lock(&vnlock, "vnlock");    new_lock(&fstablock, "fstablock");    /*    determine the max number of files the kernel can open.    8MB -> 256    */    max_glb_file = memsize >> 15;    global_fds = new_fds(max_glb_file);    /*    install file systems    */    install_file_system(&rootfs, "rootfs", TRUE, -1);    /*    mount the root file system    */    fs = inc_file_system("rootfs");    ns = (nspace *) malloc(sizeof(nspace));    ns->fs = fs;    ns->nsid = nxnsid++;    nstab[ns->nsid % nns] = ns;    ns->vnodes.head = ns->vnodes.tail = NULL;    ns->data = NULL;    ns->root = NULL;    ns->mount = NULL;    ns->shutdown = FALSE;    ns->prev = ns->next = NULL;    nshead = ns;    err = (*fs->ops.mount)(ns->nsid, NULL, 0, NULL, 0, &data, &vnid);    ns->data = data;    ns->root = lookup_vnode(ns->nsid, vnid);    rootvn = ns->root;#ifdef DEBUG    add_debugger_cmd("ioctx",   dump_ioctx,   "dump a thread ioctx struct");    add_debugger_cmd("vnode",   dump_vnode,   "dump a vnode struct");    add_debugger_cmd("fdarray", dump_fdarray, "dump an fd array");    add_debugger_cmd("ofile",   dump_ofile,   "dump an ofile struct");    add_debugger_cmd("nspace",  dump_nspace,  "dump a nspace struct");    add_debugger_cmd("fsystem", dump_fsystem, "dump a fsystem struct");    add_debugger_cmd("ioinfo",  dump_io_info, "dump io info for a thread");    add_debugger_cmd("findvn",  find_vn,      "find a vnid (in all threads)");#endif /* DEBUG */    return 0;}/* ---------------------------------------------------------------- */intsys_sync(void){    nspace      *ns;    op_sync     *op;    LOCK(vnlock);    for(ns = nshead; ns; ns = ns->next) {        ns->root->rcnt++;        UNLOCK(vnlock);        op = ns->fs->ops.sync;        if (op)            (*op)(ns->data);        LOCK(vnlock);        ns->root->rcnt--;    }    UNLOCK(vnlock);    return 0;}static ioctx *get_cur_ioctx(void){    static int init = 0;    static ioctx io;    if (init == 0) {        init = 1;        memset(&io, 0, sizeof(io));    }    return &io;}/* * sys_chdir */intsys_chdir(bool kernel, int fd, const char *path){    int              err;    ioctx           *io;    vnode           *vn;    op_rstat        *op;    struct my_stat   st;    err = get_file_fd(kernel, fd, path, TRUE, &vn);    if (err)        goto error1;    op = vn->ns->fs->ops.rstat;    if (!op) {        err = EINVAL;        goto error2;    }    err = (*op)(vn->ns->data, vn->data, &st);    if (err)        goto error2;    if (!MY_S_ISDIR(st.mode)) {        err = ENOTDIR;        goto error2;    }    io = get_cur_ioctx();    LOCK(io->lock);    dec_vnode(io->cwd, FALSE);    io->cwd = vn;    UNLOCK(io->lock);    return 0;   error2:    dec_vnode(vn, FALSE);error1:    return err;}/* * sys_access */intsys_access(bool kernel, int fd, const char *path, int mode){    int         err;    vnode       *vn;    op_access   *op;    err = get_file_fd(kernel, fd, path, TRUE, &vn);    if (err)        goto error1;    op = vn->ns->fs->ops.access;    if (!op) {        err = EINVAL;        goto error2;    }    err = (*op)(vn->ns->data, vn->data, mode);    if (err)        goto error2;    dec_vnode(vn, FALSE);    return 0;error2:    dec_vnode(vn, FALSE);error1:    return err;}/* * sys_symlink */intsys_symlink(bool kernel, const char *oldpath, int nfd, const char *newpath){    int             err;    char            filename[FILE_NAME_LENGTH];    char            *buf;    vnode           *dvn;    op_symlink      *op;    err = get_dir_fd(kernel, nfd, newpath, filename, &dvn);    if (err)        goto error1;    err = new_path(oldpath, &buf);    if (err)        goto error2;    op = dvn->ns->fs->ops.symlink;    if (!op) {        err = EINVAL;        goto error3;    }    err = (*op)(dvn->ns->data, dvn->data, filename, buf);    if (err)        goto error3;    dec_vnode(dvn, FALSE);    free_path(buf);    return 0;error3:    free_path(buf);error2:    dec_vnode(dvn, FALSE);error1:    return err;}/* * sys_readlink */ssize_tsys_readlink(bool kernel, int fd, const char *path, char *buf, size_t bufsize){    int             err;    vnode           *vn;    op_readlink     *op;    size_t          sz;    err = get_file_fd(kernel, fd, path, FALSE, &vn);    if (err)        goto error1;    op = vn->ns->fs->ops.readlink;    if (!op) {        err = EINVAL;        goto error2;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -