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

📄 kernel.c

📁 be文件系统实现的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
        goto error1;    op = vn->ns->fs->ops.wstat;    if (!op) {        err = EINVAL;        goto error2;    }    err = (*op)(vn->ns->data, vn->data, st, mask);    if (err)        goto error2;    dec_vnode(vn, FALSE);    return 0;error2:    dec_vnode(vn, FALSE);error1:    return err;}/* * sys_mount */void *sys_mount(bool kernel, const char *filesystem, int fd, const char *where,        const char *device, ulong flags, void *parms, size_t len){    int                 err;    int                 i;    vnode_id            vnid;    vnode               *mount;    fsystem             *fs;    nspace              *ns, *ans;    void                *data;    struct stat         st;    struct my_stat      mst;    my_dev_t            dev;    my_ino_t            ino;        dev = -1;    ino = -1;    if (device) {        err = stat(device, &st);        if (err)            return NULL;        dev = st.st_dev;        ino = st.st_ino;    }    err = get_file_fd(TRUE, fd, where, TRUE, &mount);    if (err)        goto error1;    err = (*mount->ns->fs->ops.rstat)(mount->ns->data, mount->data, &mst);    if (err)        goto error2;    if (!MY_S_ISDIR(mst.mode)) {        err = ENOTDIR;        goto error2;    }    ns = (nspace *) malloc(sizeof(nspace));    if (!ns) {        err = ENOMEM;        goto error2;    }    fs = inc_file_system(filesystem);    if (!fs) {        err = ENODEV;        goto error3;    }    LOCK(vnlock);    if (device) {        for(ans=nshead; ans; ans=ans->next)            if ((ans->dev == dev) && (ans->ino == ino)) {                UNLOCK(vnlock);printf("KERNEL: trying to mount %s twice (already mounted as %s)\n", device, ans->fs->name);                err = ENODEV;                goto error4;            }    }    for(i=0; i<nns; i++, nxnsid++)        if (!nstab[nxnsid % nns]) {            nstab[nxnsid % nns] = ns;            ns->nsid = nxnsid;            nxnsid++;            break;        }    if (i == nns) {        UNLOCK(vnlock);        err = EMFILE;        goto error4;    }    nstab[ns->nsid % nns] = ns;    ns->fs = fs;    ns->vnodes.head = ns->vnodes.tail = NULL;    ns->data = NULL;    ns->root = NULL;    ns->mount = NULL;    ns->prev = NULL;    ns->next = nshead;    ns->shutdown = FALSE;    ns->dev = dev;    ns->ino = ino;    if (nshead)        nshead->prev = ns;    nshead = ns;    UNLOCK(vnlock);    err = (*fs->ops.mount)(ns->nsid, device, flags, parms, len, &data, &vnid);    if (err)        goto error5;            LOCK(vnlock);    ns->root = lookup_vnode(ns->nsid, vnid);    ns->data = data;        if ((mount == rootvn) || (mount->mounted)) {        err = EBUSY;        goto error6;    }    mount->mounted = ns;    ns->mount = mount;    UNLOCK(vnlock);    return data;error6:    dec_vnode(ns->root, FALSE);    (*fs->ops.unmount)(data);error5:    LOCK(vnlock);    nstab[ns->nsid % nns] = NULL;    if (ns->prev)        ns->prev->next = ns->next;    else        nshead = ns->next;    if (ns->next)        ns->next->prev = ns->prev;    UNLOCK(vnlock);error4:    dec_file_system(fs);error3:    free(ns);error2:    dec_vnode(mount, FALSE);error1:    errno = err;    return NULL;}/* * sys_unmount */intsys_unmount(bool kernel, int fd, const char *where){    int             err;    nspace          *ns;    fsystem         *fs;    vnode           *root, *vn, *mount;        err = get_file_fd(TRUE, fd, where, TRUE, &root);    if (err)        goto error1;    LOCK(vnlock);    ns = root->ns;    fs = ns->fs;    if (ns->root != root) {        err = EINVAL;        goto error2;    }    /*    don't allow to unmount the root file system    */    if (root == rootvn) {        err = EBUSY;        goto error2;    }    /*    decrement twice root: one for the mount, one for the get_file.    */    root->rcnt -= 2;    for(vn = ns->vnodes.head; vn; vn = vn->nspace.next)        if (vn->busy || (vn->rcnt != 0)) {            err = EBUSY;            goto error3;        }    mount = ns->mount;    mount->mounted = NULL;    ns->shutdown = TRUE;    for(vn = ns->vnodes.head; vn; vn = vn->nspace.next)        vn->busy = TRUE;            while (ns->vnodes.head) {        vn = ns->vnodes.head;        UNLOCK(vnlock);        err = (*fs->ops.release_vnode)(vn->ns->data, vn->data, FALSE);        LOCK(vnlock);        if (err)            PANIC("ERROR WRITING VNODE!!!\n");        vn->busy = FALSE;        clear_vnode(vn);        move_vnode(vn, FREE_LIST);    }    if (ns->prev)        ns->prev->next = ns->next;    else        nshead = ns->next;    if (ns->next)        ns->next->prev = ns->prev;    nstab[ns->nsid % nns] = NULL;    UNLOCK(vnlock);    (*fs->ops.unmount)(ns->data);    free(ns);    dec_file_system(fs);    dec_vnode(mount, FALSE);    return 0;error3:    root->rcnt++;error2:    UNLOCK(vnlock);error1:    return err;}/* * get_dir and get_file: basic functions to parse a path and get the vnode * for either the parent directory or the file itself. */static intget_dir_fd(bool kernel, int fd, const char *path, char *filename, vnode **dvn){    int         err;    char        *p, *np;    err = new_path(path, &p);    if (err)        goto error1;    np = strrchr(p, '/');    if (!np) {        strcpy(filename, p);        strcpy(p, ".");    } else {        strcpy(filename, np+1);        np[1] = '.';        np[2] = '\0';    }    err = parse_path_fd(kernel, fd, &p, TRUE, dvn);    if (err)        goto error2;    free_path(p);    return 0;    error2:    free_path(p);error1:    return err;}static intget_file_fd(bool kernel, int fd, const char *path, int eatsymlink, vnode **vn){    int         err;    char        *p;    err = new_path(path, &p);    if (err)        goto error1;    err = parse_path_fd(kernel, fd, &p, eatsymlink, vn);    if (err)        goto error2;    free_path(p);    return 0;    error2:    free_path(p);error1:    return err;}static intget_file_vn(nspace_id nsid, vnode_id vnid, const char *path, int eatsymlink,        vnode **vn){    int         err;    char        *p;    err = new_path(path, &p);    if (err)        goto error1;    err = parse_path_vn(nsid, vnid, &p, eatsymlink, vn);    if (err)        goto error2;    free_path(p);    return 0;    error2:    free_path(p);error1:    return err;}static intparse_path_fd(bool kernel, int fd, char **pstart, int eatsymlink, vnode **vnp){    vnode           *bvn;    ofile           *f;    ioctx           *io;    char            *path;    path = *pstart;    if (path && (*path == '/')) {        do            path++;        while (*path == '/');        bvn = rootvn;        inc_vnode(bvn);    } else        if (fd >= 0) {            f = get_fd(kernel, fd, FD_ALL);            if (!f)                return EBADF;            bvn = f->vn;            inc_vnode(bvn);            put_fd(f);        } else {            io = get_cur_ioctx();            LOCK(io->lock);            bvn = io->cwd;            inc_vnode(bvn);            UNLOCK(io->lock);        }    return parse_path(bvn, pstart, path, eatsymlink, vnp);}static intparse_path_vn(nspace_id nsid, vnode_id vnid, char **pstart, int eatsymlink,    vnode **vnp){    int             err;    vnode           *bvn;    char            *path;    path = *pstart;    if (path && (*path == '/')) {        do            path++;        while (*path == '/');        bvn = rootvn;        inc_vnode(bvn);    } else {        err = load_vnode(nsid, vnid, FALSE, &bvn);        if (err)            return err;    }    return parse_path(bvn, pstart, path, eatsymlink, vnp);error1:    dec_vnode(bvn, FALSE);    return err;}static intparse_path(vnode *bvn, char **pstart, char *path, int eatsymlink, vnode **vnp){    int             err;    int             iter;    char            *p, *np, *newpath, **fred;    vnode_id        vnid;    vnode           *vn;    if (!path) {        *vnp = bvn;        return 0;    }    iter = 0;    p = path;    vn = NULL;    while(TRUE) {    /*    exit if we're done    */        if (*p == '\0') {            err = 0;            break;        }    /*    isolate the next component    */        np = strchr(p+1, '/');        if (np) {            *np = '\0';            do                np++;            while (*np == '/');        } else            np = strchr(p+1, '\0');            /*    filter '..' if at the root of a namespace    */        if (!strcmp(p, "..") && is_root(bvn, &vn)) {            dec_vnode(bvn, FALSE);            bvn = vn;        }    /*    ask the file system to eat this component    */        newpath = NULL;        fred = &newpath;        if (!eatsymlink && (*np == '\0'))            fred = NULL;        err = (*bvn->ns->fs->ops.walk)(bvn->ns->data, bvn->data, p, fred,                &vnid);        p = np;        if (!err) {            if (newpath)                vn = bvn;            else {                LOCK(vnlock);                vn = lookup_vnode(bvn->ns->nsid, vnid);                UNLOCK(vnlock);                dec_vnode(bvn, FALSE);            }        } else {            dec_vnode(bvn, FALSE);            break;        }    /*    deal with symbolic links    */        if (newpath) {    /*    protection against cyclic graphs (with bad symbolic links).    */            iter++;            if (iter > MAX_SYM_LINKS) {                dec_vnode(vn, FALSE);                err = ELOOP;                break;            }            p = cat_paths(newpath, np);            if (!p) {                dec_vnode(vn, FALSE);                err = ENOMEM;                break;            }            free_path(*pstart);            *pstart = p;            if (*p == '/') {                do                    p++;                while (*p == '/');                dec_vnode(vn, FALSE);                bvn = rootvn;                inc_vnode(bvn);            } else                bvn = vn;            continue;        }    /*    reached a mounting point    */        if (is_mount_vnode(vn, &bvn)) {            dec_vnode(vn, FALSE);            continue;        }        bvn = vn;    }    if (!err)        *vnp = bvn;    return err;}/* * get_vnode */intget_vnode(nspace_id nsid, vnode_id vnid, void **data){    int         err;    vnode       *vn;    err = load_vnode(nsid, vnid, TRUE, &vn);    if (err)        return err;    *data = vn->data;    return 0;}/* * put_vnode */intput_vnode(nspace_id nsid, vnode_id vnid){    vnode           *vn;    LOCK(vnlock);    vn = lookup_vnode(nsid, vnid);    if (!vn) {        UNLOCK(vnlock);        return ENOENT;    }    UNLOCK(vnlock);    dec_vnode(vn, TRUE);    return 0;}/* * new_vnode */intnew_vnode(nspace_id nsid, vnode_id vnid, void *data){    int         err;    vnode       *vn;    LOCK(vnlock);    vn = steal_vnode(FREE_LIST);    if (!vn) {        vn = steal_vnode(USED_LIST);        if (!vn) {            PANIC("OUT OF VNODE!!!\n");            UNLOCK(vnlock);            return ENOMEM;        }        flush_vnode(vn, TRUE);    }    vn->ns = nsidtons(nsid);    if (!vn->ns) {        UNLOCK(vnlock);        return ENOENT;    }    vn->vnid = vnid;    vn->data = data;    vn->rcnt = 1;    err = sort_vnode(vn);    UNLOCK(vnlock);    return err;}/* * remove_vnode */intremove_vnode(nspace_id nsid, vnode_id vnid){    vnode       *vn;    LOCK(vnlock);    vn = lookup_vnode(nsid, vnid);    if (!vn || (vn->rcnt == 0)) {        UNLOCK(vnlock);        return ENOENT;    }    vn->remove = TRUE;    UNLOCK(vnlock);    return 0;}/* * unremove_vnode */intunremove_vnode(nspace_id nsid, vnode_id vnid){    vnode       *vn;    LOCK(vnlock);    vn = lookup_vnode(nsid, vnid);    if (!vn || (vn->rcnt == 0)) {        UNLOCK(vnlock);        return ENOENT;    }    vn->remove = FALSE;    UNLOCK(vnlock);    return 0;}/* * is_vnode_removed */intis_vnode_removed(nspace_id nsid, vnode_id vnid){    vnode       *vn;    int         res;    LOCK(vnlock);    vn = lookup_vnode(nsid, vnid);    if (!vn) {        UNLOCK(vnlock);        return ENOENT;    }    res = vn->remove;    UNLOCK(vnlock);    return res;}/* * miscelleanous vnode functions */static voidinc_vnode(vnode *vn){    LOCK(vnlock);    vn->rcnt++;    UNLOCK(vnlock);}static voiddec_vnode(vnode *vn, char r){    vnode       *ovn;    LOCK(vnlock);    vn->rcnt--;    if (vn->rcnt == 0)        if (vn->remove) {            vn->busy = TRUE;            move_vnode(vn, LOCKED_LIST);            UNLOCK(vnlock);            (*vn->ns->fs->ops.remove_vnode)(vn->ns->data, vn->data, r);            LOCK(vnlock);            clear_vnode(vn);            move_vnode(vn, FREE_LIST);        } else {            move_vnode(vn, USED_LIST);            if (lists[USED_LIST].num > usdvnnum) {                ovn = steal_vnode(USED_LIST);                flush_vnode(ovn, r);                move_vnode(ovn, FREE_LIST);            }        }    UNLOCK(vnlock);    return;}static voidclear_vnode(vnode *vn){    DeleteSL(skiplist, vn);    if (vn->nspace.prev)        vn->nspace.prev->nspace.next = vn->nspace.next;    else        vn->ns->vnodes.head = vn->nspace.next;    if (vn->nspace.next)        vn->nspace.next->nspace.prev = vn->nspace.prev;    else        vn->ns->vnodes.tail = vn->nspace.prev;    vn->nspace.next = vn->nspace.prev = NULL;    vn->vnid = invalid_vnid;    vn->ns = NULL;    vn->remove = FALSE;    vn->data = NULL;    vn->rcnt = 0;    vn->busy = FALSE;    vn->mounted = NULL;}static intsort_vnode(vnode *vn){    if (!InsertSL(skiplist, vn))        return ENOMEM;    vn->nspace.next = vn->ns->vnodes.head;    vn->nspace.prev = NULL;    if (vn->ns->vnodes.head)        vn->ns->vnodes.head->nspace.prev = vn;    else        vn->ns->vnodes.tail = vn;

⌨️ 快捷键说明

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