Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
8bf396de
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
8bf396de
编写于
8月 24, 2009
作者:
T
Tao Ma
提交者:
Joel Becker
9月 22, 2009
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ocfs2: Basic tree root operation.
Add basic refcount tree root operation. Signed-off-by:
N
Tao Ma
<
tao.ma@oracle.com
>
上级
374a263e
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
353 addition
and
6 deletion
+353
-6
fs/ocfs2/journal.h
fs/ocfs2/journal.h
+14
-0
fs/ocfs2/refcounttree.c
fs/ocfs2/refcounttree.c
+339
-6
未找到文件。
fs/ocfs2/journal.h
浏览文件 @
8bf396de
...
...
@@ -490,6 +490,20 @@ static inline int ocfs2_calc_dxi_expand_credits(struct super_block *sb)
return
credits
;
}
/* inode update, new refcount block and its allocation credits. */
#define OCFS2_REFCOUNT_TREE_CREATE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1 \
+ OCFS2_SUBALLOC_ALLOC)
/* inode and the refcount block update. */
#define OCFS2_REFCOUNT_TREE_SET_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
/*
* inode and the refcount block update.
* It doesn't include the credits for sub alloc change.
* So if we need to free the bit, OCFS2_SUBALLOC_FREE needs to be added.
*/
#define OCFS2_REFCOUNT_TREE_REMOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
/*
* Please note that the caller must make sure that root_el is the root
* of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
...
...
fs/ocfs2/refcounttree.c
浏览文件 @
8bf396de
...
...
@@ -27,6 +27,7 @@
#include "buffer_head_io.h"
#include "blockcheck.h"
#include "refcounttree.h"
#include "sysfile.h"
#include "dlmglue.h"
static
inline
struct
ocfs2_refcount_tree
*
...
...
@@ -272,6 +273,22 @@ static inline void ocfs2_init_refcount_tree_lock(struct ocfs2_super *osb,
rf_blkno
,
generation
);
}
static
struct
ocfs2_refcount_tree
*
ocfs2_allocate_refcount_tree
(
struct
ocfs2_super
*
osb
,
u64
rf_blkno
)
{
struct
ocfs2_refcount_tree
*
new
;
new
=
kzalloc
(
sizeof
(
struct
ocfs2_refcount_tree
),
GFP_NOFS
);
if
(
!
new
)
return
NULL
;
new
->
rf_blkno
=
rf_blkno
;
kref_init
(
&
new
->
rf_getcnt
);
ocfs2_init_refcount_tree_ci
(
new
,
osb
->
sb
);
return
new
;
}
static
int
ocfs2_get_refcount_tree
(
struct
ocfs2_super
*
osb
,
u64
rf_blkno
,
struct
ocfs2_refcount_tree
**
ret_tree
)
{
...
...
@@ -291,16 +308,12 @@ static int ocfs2_get_refcount_tree(struct ocfs2_super *osb, u64 rf_blkno,
spin_unlock
(
&
osb
->
osb_lock
);
new
=
kzalloc
(
sizeof
(
struct
ocfs2_refcount_tree
),
GFP_NOFS
);
new
=
ocfs2_allocate_refcount_tree
(
osb
,
rf_blkno
);
if
(
!
new
)
{
ret
=
-
ENOMEM
;
mlog_errno
(
ret
);
return
ret
;
}
new
->
rf_blkno
=
rf_blkno
;
kref_init
(
&
new
->
rf_getcnt
);
ocfs2_init_refcount_tree_ci
(
new
,
osb
->
sb
);
/*
* We need the generation to create the refcount tree lock and since
* it isn't changed during the tree modification, we are safe here to
...
...
@@ -515,3 +528,323 @@ void ocfs2_purge_refcount_trees(struct ocfs2_super *osb)
ocfs2_free_refcount_tree
(
tree
);
}
}
/*
* Create a refcount tree for an inode.
* We take for granted that the inode is already locked.
*/
static
int
ocfs2_create_refcount_tree
(
struct
inode
*
inode
,
struct
buffer_head
*
di_bh
)
{
int
ret
;
handle_t
*
handle
=
NULL
;
struct
ocfs2_alloc_context
*
meta_ac
=
NULL
;
struct
ocfs2_dinode
*
di
=
(
struct
ocfs2_dinode
*
)
di_bh
->
b_data
;
struct
ocfs2_inode_info
*
oi
=
OCFS2_I
(
inode
);
struct
ocfs2_super
*
osb
=
OCFS2_SB
(
inode
->
i_sb
);
struct
buffer_head
*
new_bh
=
NULL
;
struct
ocfs2_refcount_block
*
rb
;
struct
ocfs2_refcount_tree
*
new_tree
=
NULL
,
*
tree
=
NULL
;
u16
suballoc_bit_start
;
u32
num_got
;
u64
first_blkno
;
BUG_ON
(
oi
->
ip_dyn_features
&
OCFS2_HAS_REFCOUNT_FL
);
mlog
(
0
,
"create tree for inode %lu
\n
"
,
inode
->
i_ino
);
ret
=
ocfs2_reserve_new_metadata_blocks
(
osb
,
1
,
&
meta_ac
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out
;
}
handle
=
ocfs2_start_trans
(
osb
,
OCFS2_REFCOUNT_TREE_CREATE_CREDITS
);
if
(
IS_ERR
(
handle
))
{
ret
=
PTR_ERR
(
handle
);
mlog_errno
(
ret
);
goto
out
;
}
ret
=
ocfs2_journal_access_di
(
handle
,
INODE_CACHE
(
inode
),
di_bh
,
OCFS2_JOURNAL_ACCESS_WRITE
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out_commit
;
}
ret
=
ocfs2_claim_metadata
(
osb
,
handle
,
meta_ac
,
1
,
&
suballoc_bit_start
,
&
num_got
,
&
first_blkno
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out_commit
;
}
new_tree
=
ocfs2_allocate_refcount_tree
(
osb
,
first_blkno
);
if
(
!
new_tree
)
{
ret
=
-
ENOMEM
;
mlog_errno
(
ret
);
goto
out_commit
;
}
new_bh
=
sb_getblk
(
inode
->
i_sb
,
first_blkno
);
ocfs2_set_new_buffer_uptodate
(
&
new_tree
->
rf_ci
,
new_bh
);
ret
=
ocfs2_journal_access_rb
(
handle
,
&
new_tree
->
rf_ci
,
new_bh
,
OCFS2_JOURNAL_ACCESS_CREATE
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out_commit
;
}
/* Initialize ocfs2_refcount_block. */
rb
=
(
struct
ocfs2_refcount_block
*
)
new_bh
->
b_data
;
memset
(
rb
,
0
,
inode
->
i_sb
->
s_blocksize
);
strcpy
((
void
*
)
rb
,
OCFS2_REFCOUNT_BLOCK_SIGNATURE
);
rb
->
rf_suballoc_slot
=
cpu_to_le16
(
osb
->
slot_num
);
rb
->
rf_suballoc_bit
=
cpu_to_le16
(
suballoc_bit_start
);
rb
->
rf_fs_generation
=
cpu_to_le32
(
osb
->
fs_generation
);
rb
->
rf_blkno
=
cpu_to_le64
(
first_blkno
);
rb
->
rf_count
=
cpu_to_le32
(
1
);
rb
->
rf_records
.
rl_count
=
cpu_to_le16
(
ocfs2_refcount_recs_per_rb
(
osb
->
sb
));
spin_lock
(
&
osb
->
osb_lock
);
rb
->
rf_generation
=
osb
->
s_next_generation
++
;
spin_unlock
(
&
osb
->
osb_lock
);
ocfs2_journal_dirty
(
handle
,
new_bh
);
spin_lock
(
&
oi
->
ip_lock
);
oi
->
ip_dyn_features
|=
OCFS2_HAS_REFCOUNT_FL
;
di
->
i_dyn_features
=
cpu_to_le16
(
oi
->
ip_dyn_features
);
di
->
i_refcount_loc
=
cpu_to_le64
(
first_blkno
);
spin_unlock
(
&
oi
->
ip_lock
);
mlog
(
0
,
"created tree for inode %lu, refblock %llu
\n
"
,
inode
->
i_ino
,
(
unsigned
long
long
)
first_blkno
);
ocfs2_journal_dirty
(
handle
,
di_bh
);
/*
* We have to init the tree lock here since it will use
* the generation number to create it.
*/
new_tree
->
rf_generation
=
le32_to_cpu
(
rb
->
rf_generation
);
ocfs2_init_refcount_tree_lock
(
osb
,
new_tree
,
first_blkno
,
new_tree
->
rf_generation
);
spin_lock
(
&
osb
->
osb_lock
);
tree
=
ocfs2_find_refcount_tree
(
osb
,
first_blkno
);
/*
* We've just created a new refcount tree in this block. If
* we found a refcount tree on the ocfs2_super, it must be
* one we just deleted. We free the old tree before
* inserting the new tree.
*/
BUG_ON
(
tree
&&
tree
->
rf_generation
==
new_tree
->
rf_generation
);
if
(
tree
)
ocfs2_erase_refcount_tree_from_list_no_lock
(
osb
,
tree
);
ocfs2_insert_refcount_tree
(
osb
,
new_tree
);
spin_unlock
(
&
osb
->
osb_lock
);
new_tree
=
NULL
;
if
(
tree
)
ocfs2_refcount_tree_put
(
tree
);
out_commit:
ocfs2_commit_trans
(
osb
,
handle
);
out:
if
(
new_tree
)
{
ocfs2_metadata_cache_exit
(
&
new_tree
->
rf_ci
);
kfree
(
new_tree
);
}
brelse
(
new_bh
);
if
(
meta_ac
)
ocfs2_free_alloc_context
(
meta_ac
);
return
ret
;
}
static
int
ocfs2_set_refcount_tree
(
struct
inode
*
inode
,
struct
buffer_head
*
di_bh
,
u64
refcount_loc
)
{
int
ret
;
handle_t
*
handle
=
NULL
;
struct
ocfs2_dinode
*
di
=
(
struct
ocfs2_dinode
*
)
di_bh
->
b_data
;
struct
ocfs2_inode_info
*
oi
=
OCFS2_I
(
inode
);
struct
ocfs2_super
*
osb
=
OCFS2_SB
(
inode
->
i_sb
);
struct
buffer_head
*
ref_root_bh
=
NULL
;
struct
ocfs2_refcount_block
*
rb
;
struct
ocfs2_refcount_tree
*
ref_tree
;
BUG_ON
(
oi
->
ip_dyn_features
&
OCFS2_HAS_REFCOUNT_FL
);
ret
=
ocfs2_lock_refcount_tree
(
osb
,
refcount_loc
,
1
,
&
ref_tree
,
&
ref_root_bh
);
if
(
ret
)
{
mlog_errno
(
ret
);
return
ret
;
}
handle
=
ocfs2_start_trans
(
osb
,
OCFS2_REFCOUNT_TREE_SET_CREDITS
);
if
(
IS_ERR
(
handle
))
{
ret
=
PTR_ERR
(
handle
);
mlog_errno
(
ret
);
goto
out
;
}
ret
=
ocfs2_journal_access_di
(
handle
,
INODE_CACHE
(
inode
),
di_bh
,
OCFS2_JOURNAL_ACCESS_WRITE
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out_commit
;
}
ret
=
ocfs2_journal_access_rb
(
handle
,
&
ref_tree
->
rf_ci
,
ref_root_bh
,
OCFS2_JOURNAL_ACCESS_WRITE
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out_commit
;
}
rb
=
(
struct
ocfs2_refcount_block
*
)
ref_root_bh
->
b_data
;
le32_add_cpu
(
&
rb
->
rf_count
,
1
);
ocfs2_journal_dirty
(
handle
,
ref_root_bh
);
spin_lock
(
&
oi
->
ip_lock
);
oi
->
ip_dyn_features
|=
OCFS2_HAS_REFCOUNT_FL
;
di
->
i_dyn_features
=
cpu_to_le16
(
oi
->
ip_dyn_features
);
di
->
i_refcount_loc
=
cpu_to_le64
(
refcount_loc
);
spin_unlock
(
&
oi
->
ip_lock
);
ocfs2_journal_dirty
(
handle
,
di_bh
);
out_commit:
ocfs2_commit_trans
(
osb
,
handle
);
out:
ocfs2_unlock_refcount_tree
(
osb
,
ref_tree
,
1
);
brelse
(
ref_root_bh
);
return
ret
;
}
int
ocfs2_remove_refcount_tree
(
struct
inode
*
inode
,
struct
buffer_head
*
di_bh
)
{
int
ret
,
delete_tree
=
0
;
handle_t
*
handle
=
NULL
;
struct
ocfs2_dinode
*
di
=
(
struct
ocfs2_dinode
*
)
di_bh
->
b_data
;
struct
ocfs2_inode_info
*
oi
=
OCFS2_I
(
inode
);
struct
ocfs2_super
*
osb
=
OCFS2_SB
(
inode
->
i_sb
);
struct
ocfs2_refcount_block
*
rb
;
struct
inode
*
alloc_inode
=
NULL
;
struct
buffer_head
*
alloc_bh
=
NULL
;
struct
buffer_head
*
blk_bh
=
NULL
;
struct
ocfs2_refcount_tree
*
ref_tree
;
int
credits
=
OCFS2_REFCOUNT_TREE_REMOVE_CREDITS
;
u64
blk
=
0
,
bg_blkno
=
0
,
ref_blkno
=
le64_to_cpu
(
di
->
i_refcount_loc
);
u16
bit
=
0
;
if
(
!
(
oi
->
ip_dyn_features
&
OCFS2_HAS_REFCOUNT_FL
))
return
0
;
BUG_ON
(
!
ref_blkno
);
ret
=
ocfs2_lock_refcount_tree
(
osb
,
ref_blkno
,
1
,
&
ref_tree
,
&
blk_bh
);
if
(
ret
)
{
mlog_errno
(
ret
);
return
ret
;
}
rb
=
(
struct
ocfs2_refcount_block
*
)
blk_bh
->
b_data
;
/*
* If we are the last user, we need to free the block.
* So lock the allocator ahead.
*/
if
(
le32_to_cpu
(
rb
->
rf_count
)
==
1
)
{
blk
=
le64_to_cpu
(
rb
->
rf_blkno
);
bit
=
le16_to_cpu
(
rb
->
rf_suballoc_bit
);
bg_blkno
=
ocfs2_which_suballoc_group
(
blk
,
bit
);
alloc_inode
=
ocfs2_get_system_file_inode
(
osb
,
EXTENT_ALLOC_SYSTEM_INODE
,
le16_to_cpu
(
rb
->
rf_suballoc_slot
));
if
(
!
alloc_inode
)
{
ret
=
-
ENOMEM
;
mlog_errno
(
ret
);
goto
out
;
}
mutex_lock
(
&
alloc_inode
->
i_mutex
);
ret
=
ocfs2_inode_lock
(
alloc_inode
,
&
alloc_bh
,
1
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out_mutex
;
}
credits
+=
OCFS2_SUBALLOC_FREE
;
}
handle
=
ocfs2_start_trans
(
osb
,
credits
);
if
(
IS_ERR
(
handle
))
{
ret
=
PTR_ERR
(
handle
);
mlog_errno
(
ret
);
goto
out_unlock
;
}
ret
=
ocfs2_journal_access_di
(
handle
,
INODE_CACHE
(
inode
),
di_bh
,
OCFS2_JOURNAL_ACCESS_WRITE
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out_commit
;
}
ret
=
ocfs2_journal_access_rb
(
handle
,
&
ref_tree
->
rf_ci
,
blk_bh
,
OCFS2_JOURNAL_ACCESS_WRITE
);
if
(
ret
)
{
mlog_errno
(
ret
);
goto
out_commit
;
}
spin_lock
(
&
oi
->
ip_lock
);
oi
->
ip_dyn_features
&=
~
OCFS2_HAS_REFCOUNT_FL
;
di
->
i_dyn_features
=
cpu_to_le16
(
oi
->
ip_dyn_features
);
di
->
i_refcount_loc
=
0
;
spin_unlock
(
&
oi
->
ip_lock
);
ocfs2_journal_dirty
(
handle
,
di_bh
);
le32_add_cpu
(
&
rb
->
rf_count
,
-
1
);
ocfs2_journal_dirty
(
handle
,
blk_bh
);
if
(
!
rb
->
rf_count
)
{
delete_tree
=
1
;
ocfs2_erase_refcount_tree_from_list
(
osb
,
ref_tree
);
ret
=
ocfs2_free_suballoc_bits
(
handle
,
alloc_inode
,
alloc_bh
,
bit
,
bg_blkno
,
1
);
if
(
ret
)
mlog_errno
(
ret
);
}
out_commit:
ocfs2_commit_trans
(
osb
,
handle
);
out_unlock:
if
(
alloc_inode
)
{
ocfs2_inode_unlock
(
alloc_inode
,
1
);
brelse
(
alloc_bh
);
}
out_mutex:
if
(
alloc_inode
)
{
mutex_unlock
(
&
alloc_inode
->
i_mutex
);
iput
(
alloc_inode
);
}
out:
ocfs2_unlock_refcount_tree
(
osb
,
ref_tree
,
1
);
if
(
delete_tree
)
ocfs2_refcount_tree_put
(
ref_tree
);
brelse
(
blk_bh
);
return
ret
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录