X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/270869139db617e29a35bb9ded41087bb702f9ac..95be6317c7ba61fc905f0f1a9bbe37e4340e969c:/lunaix-os/kernel/fs/vfs.c diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 415e36b..1696d6e 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; } @@ -270,12 +270,7 @@ vfs_pclose(struct v_file* file, pid_t pid) { struct v_inode* inode; int errno = 0; - - if (file->ref_count > 1) { - atomic_fetch_sub(&file->ref_count, 1); - return 0; - } - + inode = file->inode; /* @@ -296,29 +291,41 @@ vfs_pclose(struct v_file* file, pid_t pid) * process is writing to this file later after B exit. */ - if (mutex_on_hold(&inode->lock)) { - mutex_unlock_for(&inode->lock, pid); + mutex_unlock_for(&inode->lock, pid); + + if (vfs_check_duped_file(file)) { + vfs_unref_file(file); + return 0; } - lock_inode(inode); - - pcache_commit_all(inode); if ((errno = file->ops->close(file))) { - goto unlock; + goto done; + } + + vfs_unref_dnode(file->dnode); + cake_release(file_pile, file); + + /* + if the current inode is not being locked by other + threads that does not share same open context, + then we can try to do sync opportunistically + */ + if (mutex_on_hold(&inode->lock)) { + goto done; } + + lock_inode(inode); - atomic_fetch_sub(&file->dnode->ref_count, 1); + pcache_commit_all(inode); inode->open_count--; if (!inode->open_count) { __sync_inode_nolock(inode); } - mnt_chillax(file->dnode->mnt); - cake_release(file_pile, file); - -unlock: unlock_inode(inode); + +done: return errno; } @@ -375,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; } @@ -387,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; } @@ -401,6 +411,8 @@ vfs_sb_free(struct v_superblock* sb) } vfree(sb->i_cache); + vfree(sb->d_cache); + cake_release(superblock_pile, sb); } @@ -446,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); @@ -485,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); } @@ -558,7 +569,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); } @@ -1316,7 +1327,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; @@ -1423,31 +1434,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) { @@ -1652,20 +1638,20 @@ __DEFINE_LXSYSCALL2(int, fstat, int, fd, struct file_stat*, stat) if (check_device_node(vino)) { struct device* rdev = resolve_device(vino->data); - if (!rdev || rdev->magic != DEV_STRUCT_MAGIC) { + if (!rdev) { errno = EINVAL; goto done; } stat->st_rdev = (dev_t){.meta = rdev->ident.fn_grp, .unique = rdev->ident.unique, - .index = rdev->dev_uid}; + .index = dev_uid(rdev) }; } if (fdev) { stat->st_dev = (dev_t){.meta = fdev->ident.fn_grp, .unique = fdev->ident.unique, - .index = fdev->dev_uid}; + .index = dev_uid(fdev) }; } done: