X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/35a7d633d3f16c1e0539af6ca5d8e7482926cd93..e2994a5332194a132c60db35c55a006bdd1f6566:/lunaix-os/kernel/fs/vfs.c?ds=sidebyside diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 0eec6bf..53c1efa 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -64,7 +64,6 @@ static struct cake_pile* superblock_pile; static struct cake_pile* fd_pile; struct v_dnode* vfs_sysroot; -static struct hbucket* dnode_cache; struct lru_zone *dnode_lru, *inode_lru; @@ -89,8 +88,6 @@ vfs_init() superblock_pile = cake_new_pile("sb_cache", sizeof(struct v_superblock), 1, 0); - dnode_cache = vzalloc(VFS_HASHTABLE_SIZE * sizeof(struct hbucket)); - dnode_lru = lru_new_zone("vfs_dnode", __vfs_try_evict_dnode); inode_lru = lru_new_zone("vfs_inode", __vfs_try_evict_inode); @@ -100,19 +97,23 @@ vfs_init() // 创建一个根dnode。 vfs_sysroot = vfs_d_alloc(NULL, &vfs_empty); vfs_sysroot->parent = vfs_sysroot; - atomic_fetch_add(&vfs_sysroot->ref_count, 1); + + vfs_ref_dnode(vfs_sysroot); } static inline struct hbucket* __dcache_hash(struct v_dnode* parent, u32_t* hash) { - u32_t _hash = *hash; - // 确保低位更加随机 + struct hbucket* d_cache; + u32_t _hash; + + d_cache = parent->super_block->d_cache; + _hash = *hash; _hash = _hash ^ (_hash >> VFS_HASHBITS); - // 与parent的指针值做加法,来减小碰撞的可能性。 _hash += (u32_t)__ptr(parent); + *hash = _hash; - return &dnode_cache[_hash & VFS_HASH_MASK]; + return &d_cache[_hash & VFS_HASH_MASK]; } static inline int @@ -156,7 +157,7 @@ vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode) { assert(parent); - atomic_fetch_add(&dnode->ref_count, 1); + dnode->ref_count = 1; dnode->parent = parent; llist_append(&parent->children, &dnode->siblings); @@ -175,7 +176,7 @@ vfs_dcache_remove(struct v_dnode* dnode) hlist_delete(&dnode->hash_list); dnode->parent = NULL; - atomic_fetch_sub(&dnode->ref_count, 1); + dnode->ref_count = 0; } void @@ -204,10 +205,10 @@ vfs_open(struct v_dnode* dnode, struct v_file** file) vfile->dnode = dnode; vfile->inode = inode; - vfile->ref_count = ATOMIC_VAR_INIT(1); + vfile->ref_count = 1; vfile->ops = inode->default_fops; - if (check_file_node(inode) && !inode->pg_cache) { + if (check_regfile_node(inode) && !inode->pg_cache) { struct pcache* pcache = vzalloc(sizeof(struct pcache)); pcache_init(pcache); pcache->master = inode; @@ -218,9 +219,8 @@ vfs_open(struct v_dnode* dnode, struct v_file** file) if (errno) { cake_release(file_pile, vfile); } else { - atomic_fetch_add(&dnode->ref_count, 1); + vfs_ref_dnode(dnode); inode->open_count++; - mnt_mkbusy(dnode->mnt); *file = vfile; } @@ -293,8 +293,8 @@ vfs_pclose(struct v_file* file, pid_t pid) mutex_unlock_for(&inode->lock, pid); - if (file->ref_count > 1) { - atomic_fetch_sub(&file->ref_count, 1); + if (vfs_check_duped_file(file)) { + vfs_unref_file(file); return 0; } @@ -302,8 +302,7 @@ vfs_pclose(struct v_file* file, pid_t pid) goto done; } - atomic_fetch_sub(&file->dnode->ref_count, 1); - mnt_chillax(file->dnode->mnt); + vfs_unref_dnode(file->dnode); cake_release(file_pile, file); /* @@ -383,7 +382,10 @@ vfs_sb_alloc() struct v_superblock* sb = cake_grab(superblock_pile); memset(sb, 0, sizeof(*sb)); llist_init_head(&sb->sb_list); + sb->i_cache = vzalloc(VFS_HASHTABLE_SIZE * sizeof(struct hbucket)); + sb->d_cache = vzalloc(VFS_HASHTABLE_SIZE * sizeof(struct hbucket)); + sb->ref_count = 1; return sb; } @@ -395,12 +397,12 @@ vfs_sb_ref(struct v_superblock* sb) } void -vfs_sb_free(struct v_superblock* sb) +vfs_sb_unref(struct v_superblock* sb) { assert(sb->ref_count); sb->ref_count--; - if (sb->ref_count) { + if (likely(sb->ref_count)) { return; } @@ -409,6 +411,8 @@ vfs_sb_free(struct v_superblock* sb) } vfree(sb->i_cache); + vfree(sb->d_cache); + cake_release(superblock_pile, sb); } @@ -454,7 +458,6 @@ vfs_d_alloc(struct v_dnode* parent, struct hstr* name) llist_init_head(&dnode->aka_list); mutex_init(&dnode->lock); - dnode->ref_count = ATOMIC_VAR_INIT(0); dnode->name = HHSTR(vzalloc(VFS_NAME_MAXLEN), 0, 0); hstrcpy(&dnode->name, name); @@ -493,7 +496,7 @@ vfs_d_free(struct v_dnode* dnode) dnode->destruct(dnode); } - vfs_sb_free(dnode->super_block); + vfs_sb_unref(dnode->super_block); vfree((void*)dnode->name.value); cake_release(dnode_pile, dnode); } @@ -555,6 +558,8 @@ vfs_i_alloc(struct v_superblock* sb) void vfs_i_free(struct v_inode* inode) { + assert(inode->link_count == 0); + if (inode->pg_cache) { pcache_release(inode->pg_cache); vfree(inode->pg_cache); @@ -566,7 +571,7 @@ vfs_i_free(struct v_inode* inode) inode->destruct(inode); } - vfs_sb_free(inode->sb); + vfs_sb_unref(inode->sb); hlist_delete(&inode->hash_list); cake_release(inode_pile, inode); } @@ -788,8 +793,12 @@ __vfs_readdir_callback(struct dir_context* dctx, const int dtype) { struct lx_dirent* dent = (struct lx_dirent*)dctx->cb_data; - strncpy(dent->d_name, name, MIN(len, DIRENT_NAME_MAX_LEN)); - dent->d_nlen = len; + int len_ = MIN(len, DIRENT_NAME_MAX_LEN - 1); + + strncpy(dent->d_name, name, len_); + dent->d_name[len_] = 0; + + dent->d_nlen = len_; dent->d_type = dtype; } @@ -829,6 +838,17 @@ done: return DO_STATUS_OR_RETURN(errno); } +static inline bool +check_pcache_eligibility(struct v_fd* fd_s) +{ + struct v_inode* inode; + + inode = fd_s->file->inode; + return !check_seqdev_node(inode) \ + && !fsm_check_pseudo_fs(inode->sb->fs) \ + && !(fd_s->flags & FO_DIRECT); +} + __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) { int errno = 0; @@ -847,7 +867,7 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) file->inode->atime = clock_unixtime(); - if (check_seqdev_node(file->inode) || (fd_s->flags & FO_DIRECT)) { + if (!check_pcache_eligibility(fd_s)) { errno = file->ops->read(file->inode, buf, count, file->f_pos); } else { errno = pcache_read(file->inode, buf, count, file->f_pos); @@ -893,7 +913,7 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) file->f_pos = inode->fsize; } - if (check_seqdev_node(inode) || (fd_s->flags & FO_DIRECT)) { + if (!check_pcache_eligibility(fd_s)) { errno = file->ops->write(inode, buf, count, file->f_pos); } else { errno = pcache_write(inode, buf, count, file->f_pos); @@ -990,6 +1010,8 @@ vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth) size_t cpy_size = MIN(dnode->name.len, size - len); strncpy(buf + len, dnode->name.value, cpy_size); + buf[len + cpy_size] = 0; + len += cpy_size; return len; @@ -1324,7 +1346,7 @@ vfs_dup_fd(struct v_fd* old, struct v_fd** new) memcpy(copied, old, sizeof(struct v_fd)); - atomic_fetch_add(&old->file->ref_count, 1); + vfs_ref_file(old->file); *new = copied; @@ -1431,31 +1453,6 @@ done: return DO_STATUS(errno); } -void -vfs_ref_file(struct v_file* file) -{ - atomic_fetch_add(&file->ref_count, 1); -} - -void -vfs_ref_dnode(struct v_dnode* dnode) -{ - atomic_fetch_add(&dnode->ref_count, 1); - - if (dnode->mnt) { - mnt_mkbusy(dnode->mnt); - } -} - -void -vfs_unref_dnode(struct v_dnode* dnode) -{ - atomic_fetch_sub(&dnode->ref_count, 1); - if (dnode->mnt) { - mnt_chillax(dnode->mnt); - } -} - int vfs_do_chdir(struct proc_info* proc, struct v_dnode* dnode) { @@ -1475,9 +1472,9 @@ vfs_do_chdir(struct proc_info* proc, struct v_dnode* dnode) vfs_ref_dnode(dnode); proc->cwd = dnode; +done: unlock_dnode(dnode); -done: return errno; }