static int pipe_root_lookup_parent(struct inode *node, char *path, struct inode **node_store, char **endp) { assert((path[0] == 'r' || path[0] == 'w') && path[1] == '_'); *node_store = node, *endp = path; vop_ref_inc(node); return 0; }
// 设置当前的目录 int vfs_set_curdir(struct inode *dir) { int ret = 0; lock_cfs(); struct inode *old_dir; if ((old_dir = get_cwd_nolock()) != dir) { // 得到当前的工作目录的inode if (dir != NULL) { uint32_t type; if ((ret = vop_gettype(dir, &type)) != 0) { goto out; } if (!S_ISDIR(type)) { ret = -E_NOTDIR; goto out; } vop_ref_inc(dir); } set_cwd_nolock(dir); if (old_dir != NULL) { vop_ref_dec(old_dir); } } out: unlock_cfs(); return ret; }
/* * vfs_get_root - Given a device name (stdin, stdout, etc.), hand * back an appropriate inode. */ int vfs_get_root(const char *devname, struct inode **node_store) { assert(devname != NULL); int ret = -E_NO_DEV; if (!list_empty(&vdev_list)) { lock_vdev_list(); { list_entry_t *list = &vdev_list, *le = list; while ((le = list_next(le)) != list) { vfs_dev_t *vdev = le2vdev(le, vdev_link); if (strcmp(devname, vdev->devname) == 0) { struct inode *found = NULL; if (vdev->fs != NULL) { found = fsop_get_root(vdev->fs); } else if (!vdev->mountable) { vop_ref_inc(vdev->devnode); found = vdev->devnode; } if (found != NULL) { ret = 0, *node_store = found; } else { ret = -E_NA_DEV; } break; } } } unlock_vdev_list(); } return ret; }
static int sfs_namefile(struct inode *node, struct iobuf *iob) { struct sfs_disk_entry *entry; if (iob->io_resid <= 2 || (entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { return -E_NO_MEM; } struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret; uint32_t ino; char *ptr = iob->io_base + iob->io_resid; size_t alen, resid = iob->io_resid - 2; vop_ref_inc(node); while ((ino = sin->ino) != SFS_BLKN_ROOT) { struct inode *parent; if ((ret = sfs_load_parent(sfs, sin, &parent)) != 0) { goto failed; } vop_ref_dec(node); node = parent, sin = vop_info(node, sfs_inode); assert(ino != sin->ino && sin->din->type == SFS_TYPE_DIR); if ((ret = trylock_sin(sin)) != 0) { goto failed; } ret = sfs_dirent_findino_nolock(sfs, sin, ino, entry); unlock_sin(sin); if (ret != 0) { goto failed; } if ((alen = strlen(entry->name) + 1) > resid) { goto failed_nomem; } resid -= alen, ptr -= alen; memcpy(ptr, entry->name, alen - 1); ptr[alen - 1] = '/'; } vop_ref_dec(node); alen = iob->io_resid - resid - 2; ptr = memmove(iob->io_base + 1, ptr, alen); ptr[-1] = '/', ptr[alen] = '\0'; iobuf_skip(iob, alen); kfree(entry); return 0; failed_nomem: ret = -E_NO_MEM; failed: vop_ref_dec(node); kfree(entry); return ret; }
/* * Name lookup. * * One interesting feature of device:name pathname syntax is that you * can implement pathnames on arbitrary devices. For instance, if you * had a graphics device that supported multiple resolutions (which we * don't), you might arrange things so that you could open it with * pathnames like "video:800x600/24bpp" in order to select the operating * mode. * * However, we have no support for this in the base system. */ static int dev_lookup(struct inode *node, char *path, struct inode **node_store) { if (*path != '\0') { return -E_NOENT; } vop_ref_inc(node); *node_store = node; return 0; }
/* * Given a device name (lhd0, emu0, somevolname, null, etc.), hand * back an appropriate inode. */ int vfs_get_root(const char *devname, struct inode **node_store) { assert(devname != NULL); int ret = -E_NO_DEV; if (!list_empty(&vdev_list)) { lock_vdev_list(); { list_entry_t *list = &vdev_list, *le = list; while ((le = list_next(le)) != list) { vfs_dev_t *vdev = le2vdev(le, vdev_link); if (strcmp(devname, vdev->devname) == 0) { struct inode *found = NULL; /* * If this device has a mounted filesystem, and * DEVNAME names either the filesystem or the device, * return the root of the filesystem. * * If it has no mounted filesystem, it's mountable, * and DEVNAME names the device, return -E_NA_DEV. */ if (vdev->fs != NULL) { found = fsop_get_root(vdev->fs); } else if (!vdev->mountable) { vop_ref_inc(vdev->devnode); found = vdev->devnode; } if (found != NULL) { /* * If DEVNAME names the device, and we get here, it * must have no fs and not be mountable. In this case, * we return the inode of device itself--node_store. */ ret = 0, *node_store = found; } else { /* * If we got here, the device specified by devname doesn't exist. */ ret = -E_NA_DEV; } break; } /* * If none of the above tests matched, we didn't name * any of the names of this device, so go on to the * next one. */ } } unlock_vdev_list(); } return ret; }
/* * * inode_init - initialize a inode structure * invoked by vop_init * */ void inode_init(struct inode *node, const struct inode_ops *ops, struct fs *fs) { atomic_set(&(node->ref_count), 0); atomic_set(&(node->open_count), 0); node->in_ops = ops, node->in_fs = fs; #ifdef UCONFIG_BIONIC_LIBC list_init(&(node->mapped_addr_list)); #endif //UCONFIG_BIONIC_LIBC vop_ref_inc(node); }
/* * Get current directory as a inode. * * We do not synchronize current->fs_struct->pwd, because it belongs exclusively * to its own process(or threads) with the holding lock. */ int vfs_get_curdir(struct inode **dir_store) { struct inode *node; if ((node = get_cwd_nolock()) != NULL) { vop_ref_inc(node); *dir_store = node; return 0; } return -E_NOENT; }
// 得到当前的目录所对应的inode int vfs_get_curdir(struct inode **dir_store) { struct inode *node; if ((node = get_cwd_nolock()) != NULL) { vop_ref_inc(node); // 增加对inode的ref_count计数 *dir_store = node; // 记录下这个node return 0; } return -E_NOENT; }
void filemap_dup_close(struct file *to, struct file *from) { assert(to->status == FD_CLOSED && from->status == FD_CLOSED); to->pos = from->pos; to->readable = from->readable; to->writable = from->writable; struct inode *node = from->node; vop_ref_inc(node), vop_open_inc(node); to->node = node; }
void filemap_dup(struct file *to, struct file *from) { assert(to->status == FD_INIT && from->status == FD_OPENED); to->pos = from->pos; to->readable = from->readable; to->writable = from->writable; struct inode *node = from->node; vop_ref_inc(node), vop_open_inc(node); to->node = node; filemap_open(to); }
//fs_array_dup - duplicate file 'from' to file 'to' void fd_array_dup(struct file *to, struct file *from) { //cprintf("[fd_array_dup]from fd=%d, to fd=%d\n",from->fd, to->fd); assert(to->status == FD_INIT && from->status == FD_OPENED); to->pos = from->pos; to->readable = from->readable; to->writable = from->writable; struct inode *node = from->node; vop_ref_inc(node), vop_open_inc(node); to->node = node; fd_array_open(to); }
int sfs_getpath(struct inode *node, char *path, int maxlen){ int ret, namelen; int pos = maxlen - 2; uint inum; char *ptr = path + maxlen; char namebuf[DIRSIZ]; struct sfs_inode *sin = vop_info(node, sfs_inode); vop_ref_inc(node); while(1){ struct inode *parent; if((parent = sfs_dirlookup(node, "..", 0)) == 0){ goto failed; } inum = sin->inum; vop_ref_dec(node); if(node == parent){ vop_ref_dec(node); break; } node = parent; sin = vop_info(node, sfs_inode); ret = sfs_inumtoname(node, inum, namebuf); if(ret != 0){ goto failed; } if((namelen = strlen(namebuf) + 1) > pos){ return -1; } pos -= namelen; ptr -= namelen; memcpy(ptr, namebuf, namelen -1); ptr[namelen -1] = '/'; } namelen = maxlen - pos - 2; ptr = memmove(path + 5, ptr, namelen); ptr[-1] = '/'; ptr[-2] = ':'; ptr[-3] = 's'; ptr[-4] = 'f'; ptr[-5] = 's'; ptr[namelen] = '\0'; return 0; failed: vop_ref_dec(node); return -1; }
/* * lookup_sfs_nolock - according ino, find related inode * * NOTICE: le2sin, info2node MACRO */ static struct inode * lookup_sfs_nolock(struct sfs_fs *sfs, uint32_t ino) { struct inode *node; list_entry_t *list = sfs_hash_list(sfs, ino), *le = list; while ((le = list_next(le)) != list) { struct sfs_inode *sin = le2sin(le, hash_link); if (sin->ino == ino) { node = info2node(sin, sfs_inode); if (vop_ref_inc(node) == 1) { sin->reclaim_count ++; } return node; } } return NULL; }
int vfs_get_bootfs(struct inode **node_store) { struct inode *node = NULL; if (bootfs_node != NULL) { lock_bootfs(); { if ((node = bootfs_node) != NULL) { vop_ref_inc(bootfs_node); } } unlock_bootfs(); } if (node == NULL) { return -E_NOENT; } *node_store = node; return 0; }
int dup_fs(struct fs_struct *to, struct fs_struct *from) { assert(to != NULL && from != NULL); assert(fs_count(to) == 0 && fs_count(from) > 0); if ((to->pwd = from->pwd) != NULL) { vop_ref_inc(to->pwd); } int i; struct file *to_file = to->filemap, *from_file = from->filemap; for (i = 0; i < FS_STRUCT_NENTRY; i ++, to_file ++, from_file ++) { if (from_file->status == FD_OPENED) { /* alloc_fd first */ to_file->status = FD_INIT; filemap_dup(to_file, from_file); } } return 0; }
static int sfs_lookup(struct inode *node, char *path, struct inode **node_store) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); assert(*path != '\0' && *path != '/'); vop_ref_inc(node); do { struct sfs_inode *sin = vop_info(node, sfs_inode); if (sin->din->type != SFS_TYPE_DIR) { vop_ref_dec(node); return -E_NOTDIR; } char *subpath; next: subpath = sfs_lookup_subpath(path); if (strcmp(path, ".") == 0) { if ((path = subpath) != NULL) { goto next; } break; } int ret; struct inode *subnode; if (strcmp(path, "..") == 0) { ret = sfs_load_parent(sfs, sin, &subnode); } else { if (strlen(path) > SFS_MAX_FNAME_LEN) { vop_ref_dec(node); return -E_TOO_BIG; } ret = sfs_lookup_once(sfs, sin, path, &subnode, NULL); } vop_ref_dec(node); if (ret != 0) { return ret; } node = subnode, path = subpath; } while (path != NULL); *node_store = node; return 0; }
// 我们来看一下复制files_struct的函数dup_fs int dup_fs(struct files_struct *to, struct files_struct *from) { // cprintf("[dup_fs]\n"); assert(to != NULL && from != NULL); assert(files_count(to) == 0 && files_count(from) > 0); if ((to->pwd = from->pwd) != NULL) { vop_ref_inc(to->pwd); // 增加引用就可以了 } int i; struct file *to_file = to->fd_array, *from_file = from->fd_array; for (i = 0; i < FILES_STRUCT_NENTRY; i ++, to_file ++, from_file ++) { if (from_file->status == FD_OPENED) { /* alloc_fd first */ to_file->status = FD_INIT; fd_array_dup(to_file, from_file); } } return 0; }
/* * sfs_lookup - Parse path relative to the passed directory * DIR, and hand back the inode for the file it * refers to. */ static int sfs_lookup(struct inode *node, char *path, struct inode **node_store) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); assert(*path != '\0' && *path != '/'); vop_ref_inc(node); struct sfs_inode *sin = vop_info(node, sfs_inode); if (sin->din->type != SFS_TYPE_DIR) { vop_ref_dec(node); return -E_NOTDIR; } struct inode *subnode; int ret = sfs_lookup_once(sfs, sin, path, &subnode, NULL); vop_ref_dec(node); if (ret != 0) { return ret; } *node_store = subnode; return 0; }
static void lookup_pipe_nolock(struct pipe_fs *pipe, const char *name, struct inode **rnode_store, struct inode **wnode_store) { list_entry_t *list = &(pipe->pipe_list), *le = list; *rnode_store = *wnode_store = NULL; while ((le = list_next(le)) != list) { struct pipe_inode *pin = le2pin(le, pipe_link); if (strcmp(pin->name, name) == 0) { struct inode *node = info2node(pin, pipe_inode); switch (pin->pin_type) { case PIN_RDONLY: assert(*rnode_store == NULL); *rnode_store = node; break; case PIN_WRONLY: assert(*wnode_store == NULL); *wnode_store = node; break; default: panic("unknown pipe_inode type %d.\n", pin->pin_type); } if (vop_ref_inc(node) == 1) { pin->reclaim_count ++; } } } }
static struct inode * pipe_get_root(struct fs *fs) { struct pipe_fs *pipe = fsop_info(fs, pipe); vop_ref_inc(pipe->root); return pipe->root; }