📄 kernel.c
字号:
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 + -