📄 kernel.c
字号:
vn->ns->vnodes.head = vn; return 0;}static voidmove_vnode(vnode *vn, int list){ if (vn->list.prev) vn->list.prev->list.next = vn->list.next; else lists[vn->inlist].head = vn->list.next; if (vn->list.next) vn->list.next->list.prev = vn->list.prev; else lists[vn->inlist].tail = vn->list.prev; lists[vn->inlist].num--; vn->inlist = list; vn->list.next = NULL; vn->list.prev = lists[list].tail; if (vn->list.prev) vn->list.prev->list.next = vn; else lists[list].head = vn; lists[list].tail = vn; lists[list].num++;}static vnode *steal_vnode(int list){ vnode *vn; vn = lists[list].head; if (!vn) return NULL; move_vnode(vn, LOCKED_LIST); return vn;}static voidflush_vnode(vnode *vn, char r){ int err; vn->busy = TRUE; UNLOCK(vnlock); err = (*vn->ns->fs->ops.release_vnode)(vn->ns->data, vn->data, r); if (err) PANIC("ERROR WRITING VNODE!!!\n"); LOCK(vnlock); vn->busy = FALSE; clear_vnode(vn);}static vnode *lookup_vnode(nspace_id nsid, vnode_id vnid){ vnode fakevn; nspace fakens; fakens.nsid = nsid; fakevn.ns = &fakens; fakevn.vnid = vnid; return SearchSL(skiplist, &fakevn);}static intload_vnode(nspace_id nsid, vnode_id vnid, char r, vnode **vnp){ int err; vnode *vn; LOCK(vnlock); while (TRUE) { vn = lookup_vnode(nsid, vnid); if (vn) if (vn->busy) { UNLOCK(vnlock); snooze(SLEEP_TIME); LOCK(vnlock); continue; } else break; vn = steal_vnode(FREE_LIST); if (!vn) { vn = steal_vnode(USED_LIST); if (!vn) PANIC("OUT OF VNODE!!!\n"); } else break; flush_vnode(vn, r); move_vnode(vn, FREE_LIST); } if (vn->ns == NULL) { vn->ns = nsidtons(nsid); if (!vn->ns) { err = ENOENT; goto error1; } vn->vnid = vnid; vn->busy = TRUE; err = sort_vnode(vn); if (err) goto error2; move_vnode(vn, LOCKED_LIST); UNLOCK(vnlock); err = (*vn->ns->fs->ops.read_vnode)(vn->ns->data, vnid, r, &vn->data); LOCK(vnlock); vn->busy = FALSE; if (err) goto error2; vn->rcnt = 1; } else { vn->rcnt++; if (vn->rcnt == 1) move_vnode(vn, LOCKED_LIST); } *vnp = vn; UNLOCK(vnlock); return 0;error2: clear_vnode(vn);error1: move_vnode(vn, FREE_LIST); UNLOCK(vnlock); return err;}static intcompare_vnode(vnode *vna, vnode *vnb){ if (vna->vnid > vnb->vnid) return 1; else if (vna->vnid < vnb->vnid) return -1; else if (vna->ns->nsid > vnb->ns->nsid) return 1; else if (vna->ns->nsid < vnb->ns->nsid) return -1; else return 0;}/* * path management functions */intnew_path(const char *path, char **copy){ const char *q, *r; char *p; int l, s; if (!path) { *copy = NULL; return 0; } l = strlen(path); if (l == 0) return ENOENT; s = l; if (path[l-1] == '/') s++; if (l >= MAXPATHLEN) return ENAMETOOLONG; q = path; while(*q != '\0') { while (*q == '/') q++; r = q; while ((*q != '/') && (*q != '\0')) q++; if (q - r >= FILE_NAME_LENGTH) return ENAMETOOLONG; } p = (char *) malloc(s+1); if (!p) return ENOMEM; /* ### do real checking: MAXPATHLEN, max file name len, buffer address... */ strcpy(p, path); if (p[l-1] == '/') { p[l] = '.'; p[l+1] = '\0'; } *copy = p; return 0;}voidfree_path(char *p){ if (p) { free(p); }}static char *cat_paths(char *a, char *b){ char *p; p = (char *) realloc(a, strlen(a) + strlen(b) + 2); if (!p) return NULL; strcat(p, "/"); strcat(p, b); return p;}/* * mount point management functions */static intis_mount_vnode(vnode *mount, vnode **root){ nspace *ns; LOCK(vnlock); ns = mount->mounted; if (ns) { *root = ns->root; ns->root->rcnt++; } UNLOCK(vnlock); return (ns != NULL); }static intis_mount_vnid(nspace_id nsid, vnode_id vnid, vnode_id *mount){ nspace *ns; for(ns = nshead; ns; ns = ns->next) { if (!ns->mount) continue; if (ns->mount->ns->nsid != nsid) continue; if (ns->mount->vnid != vnid) continue; *mount = ns->root->vnid; return TRUE; } return FALSE;}static intis_root(vnode *root, vnode **mount){ if ((root->ns->root == root) && root->ns->mount) { *mount = root->ns->mount; inc_vnode(*mount); return TRUE; } else return FALSE;}/* * file descriptor management functions */ static ofile *get_fd(bool kernel, int fd, int type){ ofile *f; fdarray *fds; f = NULL; if (kernel) fds = global_fds; else fds = get_cur_ioctx()->fds; LOCK(fds->lock); if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { f = fds->fds[fd]; if (f->type & type) atomic_add(&f->rcnt, 1); else f = NULL; } UNLOCK(fds->lock); return f;}static intput_fd(ofile *f){ long cnt; cnt = atomic_add(&f->rcnt, -1); if (cnt == 1) invoke_free(f); return 0;}static intnew_fd(bool kernel, int nfd, ofile *f, int fd, bool coe){ int i, j, num, end; fdarray *fds; ofile *of; int err; long cnt; if (kernel) fds = global_fds; else fds = get_cur_ioctx()->fds; LOCK(fds->lock); num = fds->num; if (!f) { if ((fd < 0) || (fd >= num)) { err = EBADF; goto error1; } f = fds->fds[fd]; if (!f) { err = EBADF; goto error1; } } atomic_add(&f->rcnt, 1); atomic_add(&f->ocnt, 1); if (nfd >= 0) { if (nfd >= num) { err = EBADF; goto error2; } of = fds->fds[nfd]; fds->fds[nfd] = f; SETBIT(fds->alloc, nfd, TRUE); SETBIT(fds->coes, nfd, coe); UNLOCK(fds->lock); if (of) { cnt = atomic_add(&of->ocnt, -1); if (cnt == 1) invoke_close(of); cnt = atomic_add(&of->rcnt, -1); if (cnt == 1) invoke_free(of); } return nfd; } end = num & ~31; for(j=0; j<end; j+=32) if (fds->alloc[j/32] != 0xffffffff) for(i=j; i<j+32; i++) if (!GETBIT(fds->alloc, i)) goto found; for(i=end; i<num; i++) if (!GETBIT(fds->alloc, i)) goto found; err = EMFILE; goto error2;found: SETBIT(fds->alloc, i, 1); fds->fds[i] = f; SETBIT(fds->coes, i, coe); UNLOCK(fds->lock); return i;error2: atomic_add(&f->rcnt, -1); atomic_add(&f->ocnt, -1);error1: UNLOCK(fds->lock); return err;}static intremove_fd(bool kernel, int fd, int type){ ofile *f; fdarray *fds; long cnt; int err; f = NULL; if (kernel) fds = global_fds; else fds = get_cur_ioctx()->fds; LOCK(fds->lock); if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { f = fds->fds[fd]; if (f->type == type) { SETBIT(fds->alloc, fd, 0); fds->fds[fd] = NULL; } else f = NULL; } UNLOCK(fds->lock); if (f == NULL) return EBADF; err = 0; cnt = atomic_add(&f->ocnt, -1); if (cnt == 1) err = invoke_close(f); cnt = atomic_add(&f->rcnt, -1); if (cnt == 1) invoke_free(f); return err;}static intget_coe(bool kernel, int fd, int type, bool *coe){ ofile *f; fdarray *fds; f = NULL; if (kernel) fds = global_fds; else fds = get_cur_ioctx()->fds; LOCK(fds->lock); if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { f = fds->fds[fd]; if (f->type == type) { *coe = GETBIT(fds->coes, fd); UNLOCK(fds->lock); return 0; } } UNLOCK(fds->lock); return EBADF;}static intset_coe(bool kernel, int fd, int type, bool coe){ ofile *f; fdarray *fds; f = NULL; if (kernel) fds = global_fds; else fds = get_cur_ioctx()->fds; LOCK(fds->lock); if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { f = fds->fds[fd]; if (f->type == type) { SETBIT(fds->coes, fd, coe); UNLOCK(fds->lock); return 0; } } UNLOCK(fds->lock); return EBADF;}static intget_omode(bool kernel, int fd, int type, int *omode){ ofile *f; fdarray *fds; f = NULL; if (kernel) fds = global_fds; else fds = get_cur_ioctx()->fds; LOCK(fds->lock); if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { f = fds->fds[fd]; if (f->type == type) { *omode = f->omode; UNLOCK(fds->lock); return 0; } } UNLOCK(fds->lock); return EBADF;}static intinvoke_close(ofile *f){ int err; vnode *vn; vn = f->vn; switch (f->type) { case FD_FILE: err = (*vn->ns->fs->ops.close)(vn->ns->data, vn->data, f->cookie); break; case FD_DIR: err = (*vn->ns->fs->ops.closedir)(vn->ns->data, vn->data, f->cookie); break; case FD_WD: default: err = 0; break; } return err;}static intinvoke_free(ofile *f){ vnode *vn; op_free_cookie *op = NULL; vn = f->vn; switch(f->type) { case FD_FILE: op = vn->ns->fs->ops.free_cookie; break; case FD_DIR: op = vn->ns->fs->ops.free_dircookie; break; case FD_WD: op = NULL; break; } if (op) (*op)(vn->ns->data, vn->data, f->cookie); dec_vnode(vn, FALSE); free(f); return 0;}/* * other routines */static nspace *nsidtons(nspace_id nsid){ nspace *ns; ns = nstab[nsid % nns]; if (!ns || (ns->nsid != nsid) || ns->shutdown) return NULL; return ns;}static intalloc_wd_fd(bool kernel, vnode *vn, bool coe, int *fdp){ int err; ofile *f; int nfd; /* find a file descriptor */ f = (ofile *) calloc(sizeof(ofile), 1); if (!f) { err = ENOMEM; goto error1; } f->type = FD_WD; f->vn = vn; f->rcnt = 0; f->ocnt = 0; nfd = new_fd(kernel, -1, f, -1, coe); if (nfd < 0) { err = EMFILE; goto error2; } *fdp = nfd; return 0;error2: free(f);error1: return err;}/* * file system operations */void *install_file_system(vnode_ops *ops, const char *name, bool fixed, image_id aid){ fsystem *fs; int i; fs = (fsystem *) malloc(sizeof(fsystem)); if (!fs) return NULL; memcpy(&fs->ops, ops, sizeof(vnode_ops)); strcpy(fs->name, name); fs->rcnt = 1; fs->fixed = fixed; fs->aid = aid; for(i=0; i<nfs; i++, nxfsid++) if (!fstab[nxfsid % nfs]) { fstab[nxfsid % nfs] = fs; fs->fsid = nxfsid; nxfsid++; break; } if (i == nfs) { free(fs); return NULL; } return (void *)fs;}static fsystem *load_file_system(const char *name){ return NULL;}static intunload_file_system(fsystem *fs){ fstab[fs->fsid % nfs] = NULL; free(fs); return 0;}static fsystem *inc_file_system(const char *name){ fsystem *fs; int i; fs = NULL; LOCK(fstablock); for(i=0; i<nfs; i++) if (fstab[i] && !strcmp(fstab[i]->name, name)) { fs = fstab[i]; fs->rcnt++; break; } if (!fs) fs = load_file_system(name); UNLOCK(fstablock); return fs;}static intdec_file_system(fsystem *fs){ LOCK(fstablock); fs->rcnt--; if (!fs->fixed && (fs->rcnt == 0)) unload_file_system(fs); UNLOCK(fstablock); return 0;}static fdarray *new_fds(int num){ fdarray *fds; size_t sz; sz = sizeof(fdarray) + (num-1) * sizeof(void *) + 2*BITSZ(num); fds = (fdarray *) malloc(sz); if (!fds) return NULL; memset(fds, 0, sz); fds->rcnt = 1; if (new_lock(&fds->lock, "fdlock") < 0) { free(fds); return NULL; } fds->num = num; fds->alloc = (ulong *) &fds->fds[num]; fds->coes = &fds->alloc[BITSZ(num) / sizeof(ulong)]; return fds;}static intfree_fds(fdarray *fds){ long cnt; int i; ofile *f; for(i=0; i<fds->num; i++) if (fds->fds[i]) { f = fds->fds[i]; cnt = atomic_add(&f->ocnt, -1); if (cnt == 1) invoke_close(f); cnt = atomic_add(&f->rcnt, -1); if (cnt == 1) invoke_free(f); } delete_sem(fds->lock.s); free(fds); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -