当前仓库属于关闭状态,部分功能使用受限,详情请查阅 仓库状态说明
7 Star 7 Fork 8

openEuler/eulerfs
关闭

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
dep.h 5.55 KB
一键复制 编辑 原始数据 按行查看 历史
Yu Kuai 提交于 2021-11-30 16:31 . eulerfs: initial import
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef EUFS_DEP_H
#define EUFS_DEP_H
#include <linux/llist.h>
#include <linux/list.h>
#include <linux/fs.h>
#include "euler.h"
#include "alloc_interface.h"
/**
* Dep type:
* - diradd (for create/symlink/link/mknod)
* - dirrem
*/
enum fsync_type {
FSYNC_DEP,
FSYNC_RENAME,
FSYNC_SYSCALL,
};
extern int disable_persisters;
extern int persist_period;
extern int persisters_per_socket;
#define eufs_dep_seq_after(a, b) ((s32)((b) - (a)) < 0)
#define eufs_dep_seq_after_eq(a, b) ((s32)((a) - (b)) >= 0)
void eufs_dir_fsync_oneshot(struct inode *dir);
void fsync_on_draining(struct inode *dir, struct inode *inode);
void fsync_rename_inodes(struct inode *old_inode, struct inode *new_inode,
struct inode **locked_inodes);
void fsync_oneshot(struct inode *inode);
enum dep_type {
DEP_DIRADD, /* Hard link is detected by checking inode->i_nlink */
DEP_DIRREM,
DEP_TYPE_COUNT,
};
struct dep_node {
struct list_head node;
struct list_head owner_node;
u32 seq;
/* Type of the dependency */
enum dep_type type;
/* Previous dentry */
struct nv_dict_entry *prevde;
/* header of the list */
u64 *nv_header;
/* Related Dentry, which also points to an inode */
struct nv_dict_entry __pmem *de;
/* inode for de->pi */
struct inode *inode;
struct inode *dir;
} __aligned(CACHELINE_SIZE);
int dep_init(struct super_block *sb);
void dep_fini(struct super_block *sb);
static __always_inline void request_persistence(struct inode *inode)
{
struct eufs_sb_info *sbi = EUFS_SB(inode->i_sb);
struct eufs_inode_info *vi = EUFS_I(inode);
int cpu;
BUG_ON(!inode_is_locked(inode));
if (!vi->i_is_dirty)
vi->i_is_dirty = true;
if (vi->i_is_persisting)
return;
cpu = get_cpu();
llist_add(&vi->i_persistee_node, per_cpu_ptr(sbi->persistee_list, cpu));
put_cpu();
eufs_dbg_vlimit("sbi->s_nr_dirty_inodes=%d ++ vi=%px @cpu=%d\n",
atomic_read(&sbi->s_nr_dirty_inodes), vi, cpu);
if (atomic_inc_return(&sbi->s_nr_dirty_inodes) > max_dirty_inodes &&
!sbi->s_draining)
sbi->s_draining = true;
vi->i_is_persisting = true;
ihold(inode);
}
/* precondition: dir inode is mutex-locked */
static __always_inline void dep_insert(struct inode *dir, struct dep_node *dep)
{
struct eufs_inode_info *dir_vi = EUFS_I(dir);
struct eufs_inode_info *child_vi = EUFS_I(dep->inode);
struct eufs_sb_info *sbi = EUFS_SB(dir->i_sb);
inode_dep_lock(dir);
inode_header_unlock(dir);
list_add_tail(&dep->node, &dir_vi->i_dep_list);
spin_lock(&child_vi->i_owner_lock);
list_add_tail(&dep->owner_node, &child_vi->i_owner_list);
spin_unlock(&child_vi->i_owner_lock);
inode_dep_unlock(dir);
eufs_dbg_vlimit("sbi->s_nr_dep_nodes=%d ++\n",
atomic_read(&sbi->s_nr_dep_nodes));
if (atomic_inc_return(&sbi->s_nr_dep_nodes) > max_dep_nodes &&
!sbi->s_draining) {
sbi->s_draining = true;
}
/* Request a persistence */
request_persistence(dir);
}
static __always_inline bool eufs_valid_inode_in_de(struct nv_dict_entry *de,
struct inode *inode)
{
return (le64_to_cpu(de->inode) == inode->i_ino);
}
static __always_inline void
dep_new_insert(struct dep_node *dep, struct inode *dir, enum dep_type type,
struct nv_dict_entry *prevde, u64 *nv_header,
struct nv_dict_entry *de, struct inode *inode, u32 seq)
{
dep->type = type;
dep->prevde = prevde;
dep->nv_header = nv_header;
dep->de = de;
dep->inode = inode;
dep->dir = dir;
dep->seq = seq;
NV_ASSERT(eufs_valid_inode_in_de(dep->de, dep->inode));
ihold(dep->inode);
dep_insert(dir, dep);
}
static __always_inline void persist_dentry(struct nv_dict_entry *de)
{
NV_ASSERT(de);
NV_ASSERT((u64)de % CACHELINE_SIZE == 0);
NV_ASSERT(sizeof(de) <= CACHELINE_SIZE);
eufs_flush_cacheline(de);
}
static __always_inline void persist_pinode(struct eufs_inode *pi)
{
WARN_ON(!EUFS_IS_HEAD_PI(pi));
NV_ASSERT(pi);
NV_ASSERT((u64)pi % CACHELINE_SIZE == 0);
NV_ASSERT(sizeof(pi) <= EUFS_INODE_SIZE);
eufs_flush_cacheline(EUFS_FRESH_PI(pi));
eufs_flush_cacheline(&EUFS_FRESH_PI(pi)->i_fresh);
}
static __always_inline void persist_name(struct super_block *sb,
const struct nv_dict_entry *de,
struct alloc_batch *ab)
{
size_t len = HASHLEN_LEN(de->hv);
struct nv_name_ext *next;
const char *name;
if (likely(len <= FIRST_LEN)) {
/* embedded in de */
return;
}
next = s2p(sb, de->nextname);
len -= FIRST_LEN;
name = next->name;
eufs_alloc_batch_add(sb, ab, (void *)name);
while (len > FOLLOW_LEN) {
next = s2p(sb, next->nextname);
eufs_flush_cacheline(name);
len -= FOLLOW_LEN;
name = next->name;
eufs_alloc_batch_add(sb, ab, (void *)name);
}
eufs_flush_cacheline(name);
}
static __always_inline void persist_symlink(void *root)
{
u64 len;
NV_ASSERT(root);
NV_ASSERT(((u64)root) % PAGE_SIZE == 0);
len = EUFS_SYMLINK_HASHLEN_LEN(*((u64 *)root));
NV_ASSERT(len <= EUFS_MAX_SYMLINK_LEN);
BUG_ON(len > EUFS_MAX_SYMLINK_LEN);
eufs_flush_range(root, EUFS_SYMLINK_SIZE(len));
}
static __always_inline void persist_page(const char *page)
{
NV_ASSERT(page);
NV_ASSERT(((u64)page) % PAGE_SIZE == 0);
eufs_flush_page(page);
}
#endif /* EUFS_DEP_H */
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/openeuler/eulerfs.git
git@gitee.com:openeuler/eulerfs.git
openeuler
eulerfs
eulerfs
master

搜索帮助