Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
d41bb034
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
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看板
提交
d41bb034
编写于
3月 25, 2015
作者:
D
Dave Chinner
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'xfs-rename-whiteout' into for-next
Conflicts: fs/xfs/xfs_inode.c
上级
88e8fda9
7dcf5c3e
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
239 addition
and
171 deletion
+239
-171
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.c
+238
-170
fs/xfs/xfs_iops.c
fs/xfs/xfs_iops.c
+1
-1
未找到文件。
fs/xfs/xfs_inode.c
浏览文件 @
d41bb034
...
...
@@ -391,15 +391,14 @@ xfs_lock_inumorder(int lock_mode, int subclass)
}
/*
* The following routine will lock n inodes in exclusive mode.
*
We assume the
caller calls us with the inodes in i_ino order.
* The following routine will lock n inodes in exclusive mode.
We assume the
* caller calls us with the inodes in i_ino order.
*
* We need to detect deadlock where an inode that we lock
* is in the AIL and we start waiting for another inode that is locked
* by a thread in a long running transaction (such as truncate). This can
* result in deadlock since the long running trans might need to wait
* for the inode we just locked in order to push the tail and free space
* in the log.
* We need to detect deadlock where an inode that we lock is in the AIL and we
* start waiting for another inode that is locked by a thread in a long running
* transaction (such as truncate). This can result in deadlock since the long
* running trans might need to wait for the inode we just locked in order to
* push the tail and free space in the log.
*/
void
xfs_lock_inodes
(
...
...
@@ -410,30 +409,27 @@ xfs_lock_inodes(
int
attempts
=
0
,
i
,
j
,
try_lock
;
xfs_log_item_t
*
lp
;
ASSERT
(
ips
&&
(
inodes
>=
2
));
/* we need at least two */
/* currently supports between 2 and 5 inodes */
ASSERT
(
ips
&&
inodes
>=
2
&&
inodes
<=
5
);
try_lock
=
0
;
i
=
0
;
again:
for
(;
i
<
inodes
;
i
++
)
{
ASSERT
(
ips
[
i
]);
if
(
i
&&
(
ips
[
i
]
==
ips
[
i
-
1
]))
/* Already locked */
if
(
i
&&
(
ips
[
i
]
==
ips
[
i
-
1
]))
/* Already locked */
continue
;
/*
* If try_lock is not set yet, make sure all locked inodes
* are not in the AIL.
* If any are, set try_lock to be used later.
* If try_lock is not set yet, make sure all locked inodes are
* not in the AIL. If any are, set try_lock to be used later.
*/
if
(
!
try_lock
)
{
for
(
j
=
(
i
-
1
);
j
>=
0
&&
!
try_lock
;
j
--
)
{
lp
=
(
xfs_log_item_t
*
)
ips
[
j
]
->
i_itemp
;
if
(
lp
&&
(
lp
->
li_flags
&
XFS_LI_IN_AIL
))
{
if
(
lp
&&
(
lp
->
li_flags
&
XFS_LI_IN_AIL
))
try_lock
++
;
}
}
}
...
...
@@ -443,51 +439,42 @@ xfs_lock_inodes(
* we can't get any, we must release all we have
* and try again.
*/
if
(
!
try_lock
)
{
xfs_ilock
(
ips
[
i
],
xfs_lock_inumorder
(
lock_mode
,
i
));
continue
;
}
/* try_lock means we have an inode locked that is in the AIL. */
ASSERT
(
i
!=
0
);
if
(
xfs_ilock_nowait
(
ips
[
i
],
xfs_lock_inumorder
(
lock_mode
,
i
)))
continue
;
if
(
try_lock
)
{
/* try_lock must be 0 if i is 0. */
/*
* Unlock all previous guys and try again. xfs_iunlock will try
* to push the tail if the inode is in the AIL.
*/
attempts
++
;
for
(
j
=
i
-
1
;
j
>=
0
;
j
--
)
{
/*
* try_lock means we have an inode locked
* that is in the AIL.
* Check to see if we've already unlocked this one. Not
* the first one going back, and the inode ptr is the
* same.
*/
ASSERT
(
i
!=
0
);
if
(
!
xfs_ilock_nowait
(
ips
[
i
],
xfs_lock_inumorder
(
lock_mode
,
i
)))
{
attempts
++
;
/*
* Unlock all previous guys and try again.
* xfs_iunlock will try to push the tail
* if the inode is in the AIL.
*/
for
(
j
=
i
-
1
;
j
>=
0
;
j
--
)
{
/*
* Check to see if we've already
* unlocked this one.
* Not the first one going back,
* and the inode ptr is the same.
*/
if
((
j
!=
(
i
-
1
))
&&
ips
[
j
]
==
ips
[
j
+
1
])
continue
;
xfs_iunlock
(
ips
[
j
],
lock_mode
);
}
if
(
j
!=
(
i
-
1
)
&&
ips
[
j
]
==
ips
[
j
+
1
])
continue
;
if
((
attempts
%
5
)
==
0
)
{
delay
(
1
);
/* Don't just spin the CPU */
xfs_iunlock
(
ips
[
j
],
lock_mode
);
}
if
((
attempts
%
5
)
==
0
)
{
delay
(
1
);
/* Don't just spin the CPU */
#ifdef DEBUG
xfs_lock_delays
++
;
xfs_lock_delays
++
;
#endif
}
i
=
0
;
try_lock
=
0
;
goto
again
;
}
}
else
{
xfs_ilock
(
ips
[
i
],
xfs_lock_inumorder
(
lock_mode
,
i
));
}
i
=
0
;
try_lock
=
0
;
goto
again
;
}
#ifdef DEBUG
...
...
@@ -2681,19 +2668,22 @@ xfs_remove(
/*
* Enter all inodes for a rename transaction into a sorted array.
*/
#define __XFS_SORT_INODES 5
STATIC
void
xfs_sort_for_rename
(
xfs_inode_t
*
dp1
,
/* in: old (source) directory inode */
xfs_inode_t
*
dp2
,
/* in: new (target) directory inode */
xfs_inode_t
*
ip1
,
/* in: inode of old entry */
xfs_inode_t
*
ip2
,
/* in: inode of new entry, if it
already exists, NULL otherwise.
*/
xfs_inode_t
**
i_tab
,
/* out: array of inode returned, sorted
*/
int
*
num_inodes
)
/* out: number of
inodes in array */
struct
xfs_inode
*
dp1
,
/* in: old (source) directory inode */
struct
xfs_inode
*
dp2
,
/* in: new (target) directory inode */
struct
xfs_inode
*
ip1
,
/* in: inode of old entry */
struct
xfs_inode
*
ip2
,
/* in: inode of new entry */
struct
xfs_inode
*
wip
,
/* in: whiteout inode
*/
struct
xfs_inode
**
i_tab
,
/* out: sorted array of inodes
*/
int
*
num_inodes
)
/* in/out:
inodes in array */
{
xfs_inode_t
*
temp
;
int
i
,
j
;
ASSERT
(
*
num_inodes
==
__XFS_SORT_INODES
);
memset
(
i_tab
,
0
,
*
num_inodes
*
sizeof
(
struct
xfs_inode
*
));
/*
* i_tab contains a list of pointers to inodes. We initialize
* the table here & we'll sort it. We will then use it to
...
...
@@ -2701,25 +2691,24 @@ xfs_sort_for_rename(
*
* Note that the table may contain duplicates. e.g., dp1 == dp2.
*/
i_tab
[
0
]
=
dp1
;
i_tab
[
1
]
=
dp2
;
i_tab
[
2
]
=
ip1
;
if
(
ip2
)
{
*
num_inodes
=
4
;
i_tab
[
3
]
=
ip2
;
}
else
{
*
num_inodes
=
3
;
i_tab
[
3
]
=
NULL
;
}
i
=
0
;
i_tab
[
i
++
]
=
dp1
;
i_tab
[
i
++
]
=
dp2
;
i_tab
[
i
++
]
=
ip1
;
if
(
ip2
)
i_tab
[
i
++
]
=
ip2
;
if
(
wip
)
i_tab
[
i
++
]
=
wip
;
*
num_inodes
=
i
;
/*
* Sort the elements via bubble sort. (Remember, there are at
* most
4
elements to sort, so this is adequate.)
* most
5
elements to sort, so this is adequate.)
*/
for
(
i
=
0
;
i
<
*
num_inodes
;
i
++
)
{
for
(
j
=
1
;
j
<
*
num_inodes
;
j
++
)
{
if
(
i_tab
[
j
]
->
i_ino
<
i_tab
[
j
-
1
]
->
i_ino
)
{
temp
=
i_tab
[
j
];
struct
xfs_inode
*
temp
=
i_tab
[
j
];
i_tab
[
j
]
=
i_tab
[
j
-
1
];
i_tab
[
j
-
1
]
=
temp
;
}
...
...
@@ -2727,6 +2716,31 @@ xfs_sort_for_rename(
}
}
static
int
xfs_finish_rename
(
struct
xfs_trans
*
tp
,
struct
xfs_bmap_free
*
free_list
)
{
int
committed
=
0
;
int
error
;
/*
* If this is a synchronous mount, make sure that the rename transaction
* goes to disk before returning to the user.
*/
if
(
tp
->
t_mountp
->
m_flags
&
(
XFS_MOUNT_WSYNC
|
XFS_MOUNT_DIRSYNC
))
xfs_trans_set_sync
(
tp
);
error
=
xfs_bmap_finish
(
&
tp
,
free_list
,
&
committed
);
if
(
error
)
{
xfs_bmap_cancel
(
free_list
);
xfs_trans_cancel
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
);
return
error
;
}
return
xfs_trans_commit
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
);
}
/*
* xfs_cross_rename()
*
...
...
@@ -2755,14 +2769,14 @@ xfs_cross_rename(
ip2
->
i_ino
,
first_block
,
free_list
,
spaceres
);
if
(
error
)
goto
out
;
goto
out
_trans_abort
;
/* Swap inode number for dirent in second parent */
error
=
xfs_dir_replace
(
tp
,
dp2
,
name2
,
ip1
->
i_ino
,
first_block
,
free_list
,
spaceres
);
if
(
error
)
goto
out
;
goto
out
_trans_abort
;
/*
* If we're renaming one or more directories across different parents,
...
...
@@ -2777,16 +2791,16 @@ xfs_cross_rename(
dp1
->
i_ino
,
first_block
,
free_list
,
spaceres
);
if
(
error
)
goto
out
;
goto
out
_trans_abort
;
/* transfer ip2 ".." reference to dp1 */
if
(
!
S_ISDIR
(
ip1
->
i_d
.
di_mode
))
{
error
=
xfs_droplink
(
tp
,
dp2
);
if
(
error
)
goto
out
;
goto
out
_trans_abort
;
error
=
xfs_bumplink
(
tp
,
dp1
);
if
(
error
)
goto
out
;
goto
out
_trans_abort
;
}
/*
...
...
@@ -2804,16 +2818,16 @@ xfs_cross_rename(
dp2
->
i_ino
,
first_block
,
free_list
,
spaceres
);
if
(
error
)
goto
out
;
goto
out
_trans_abort
;
/* transfer ip1 ".." reference to dp2 */
if
(
!
S_ISDIR
(
ip2
->
i_d
.
di_mode
))
{
error
=
xfs_droplink
(
tp
,
dp1
);
if
(
error
)
goto
out
;
goto
out
_trans_abort
;
error
=
xfs_bumplink
(
tp
,
dp2
);
if
(
error
)
goto
out
;
goto
out
_trans_abort
;
}
/*
...
...
@@ -2841,66 +2855,108 @@ xfs_cross_rename(
}
xfs_trans_ichgtime
(
tp
,
dp1
,
XFS_ICHGTIME_MOD
|
XFS_ICHGTIME_CHG
);
xfs_trans_log_inode
(
tp
,
dp1
,
XFS_ILOG_CORE
);
out:
return
xfs_finish_rename
(
tp
,
free_list
);
out_trans_abort:
xfs_bmap_cancel
(
free_list
);
xfs_trans_cancel
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
);
return
error
;
}
/*
* xfs_rename_alloc_whiteout()
*
* Return a referenced, unlinked, unlocked inode that that can be used as a
* whiteout in a rename transaction. We use a tmpfile inode here so that if we
* crash between allocating the inode and linking it into the rename transaction
* recovery will free the inode and we won't leak it.
*/
static
int
xfs_rename_alloc_whiteout
(
struct
xfs_inode
*
dp
,
struct
xfs_inode
**
wip
)
{
struct
xfs_inode
*
tmpfile
;
int
error
;
error
=
xfs_create_tmpfile
(
dp
,
NULL
,
S_IFCHR
|
WHITEOUT_MODE
,
&
tmpfile
);
if
(
error
)
return
error
;
/* Satisfy xfs_bumplink that this is a real tmpfile */
xfs_finish_inode_setup
(
tmpfile
);
VFS_I
(
tmpfile
)
->
i_state
|=
I_LINKABLE
;
*
wip
=
tmpfile
;
return
0
;
}
/*
* xfs_rename
*/
int
xfs_rename
(
xfs_inode_t
*
src_dp
,
struct
xfs_name
*
src_name
,
xfs_inode_t
*
src_ip
,
xfs_inode_t
*
target_dp
,
struct
xfs_name
*
target_name
,
xfs_inode_t
*
target_ip
,
unsigned
int
flags
)
struct
xfs_inode
*
src_dp
,
struct
xfs_name
*
src_name
,
struct
xfs_inode
*
src_ip
,
struct
xfs_inode
*
target_dp
,
struct
xfs_name
*
target_name
,
struct
xfs_inode
*
target_ip
,
unsigned
int
flags
)
{
xfs_trans_t
*
tp
=
NULL
;
xfs_mount_t
*
mp
=
src_dp
->
i_mount
;
int
new_parent
;
/* moving to a new dir */
int
src_is_directory
;
/* src_name is a directory */
int
error
;
xfs_bmap_free_t
free_list
;
xfs_fsblock_t
first_block
;
int
cancel_flags
;
int
committed
;
xfs_inode_t
*
inodes
[
4
]
;
int
spaceres
;
int
num_inodes
;
struct
xfs_mount
*
mp
=
src_dp
->
i_mount
;
struct
xfs_trans
*
tp
;
struct
xfs_bmap_free
free_list
;
xfs_fsblock_t
first_block
;
struct
xfs_inode
*
wip
=
NULL
;
/* whiteout inode */
struct
xfs_inode
*
inodes
[
__XFS_SORT_INODES
]
;
int
num_inodes
=
__XFS_SORT_INODES
;
int
new_parent
=
(
src_dp
!=
target_dp
)
;
int
src_is_directory
=
S_ISDIR
(
src_ip
->
i_d
.
di_mode
)
;
int
cancel_flags
=
0
;
int
spaceres
;
int
error
;
trace_xfs_rename
(
src_dp
,
target_dp
,
src_name
,
target_name
);
new_parent
=
(
src_dp
!=
target_dp
);
src_is_directory
=
S_ISDIR
(
src_ip
->
i_d
.
di_mode
);
if
((
flags
&
RENAME_EXCHANGE
)
&&
!
target_ip
)
return
-
EINVAL
;
/*
* If we are doing a whiteout operation, allocate the whiteout inode
* we will be placing at the target and ensure the type is set
* appropriately.
*/
if
(
flags
&
RENAME_WHITEOUT
)
{
ASSERT
(
!
(
flags
&
(
RENAME_NOREPLACE
|
RENAME_EXCHANGE
)));
error
=
xfs_rename_alloc_whiteout
(
target_dp
,
&
wip
);
if
(
error
)
return
error
;
/* setup target dirent info as whiteout */
src_name
->
type
=
XFS_DIR3_FT_CHRDEV
;
}
xfs_sort_for_rename
(
src_dp
,
target_dp
,
src_ip
,
target_ip
,
xfs_sort_for_rename
(
src_dp
,
target_dp
,
src_ip
,
target_ip
,
wip
,
inodes
,
&
num_inodes
);
xfs_bmap_init
(
&
free_list
,
&
first_block
);
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_RENAME
);
cancel_flags
=
XFS_TRANS_RELEASE_LOG_RES
;
spaceres
=
XFS_RENAME_SPACE_RES
(
mp
,
target_name
->
len
);
error
=
xfs_trans_reserve
(
tp
,
&
M_RES
(
mp
)
->
tr_rename
,
spaceres
,
0
);
if
(
error
==
-
ENOSPC
)
{
spaceres
=
0
;
error
=
xfs_trans_reserve
(
tp
,
&
M_RES
(
mp
)
->
tr_rename
,
0
,
0
);
}
if
(
error
)
{
xfs_trans_cancel
(
tp
,
0
);
goto
std_return
;
}
if
(
error
)
goto
out_trans_cancel
;
cancel_flags
=
XFS_TRANS_RELEASE_LOG_RES
;
/*
* Attach the dquots to the inodes
*/
error
=
xfs_qm_vop_rename_dqattach
(
inodes
);
if
(
error
)
{
xfs_trans_cancel
(
tp
,
cancel_flags
);
goto
std_return
;
}
if
(
error
)
goto
out_trans_cancel
;
/*
* Lock all the participating inodes. Depending upon whether
...
...
@@ -2921,6 +2977,8 @@ xfs_rename(
xfs_trans_ijoin
(
tp
,
src_ip
,
XFS_ILOCK_EXCL
);
if
(
target_ip
)
xfs_trans_ijoin
(
tp
,
target_ip
,
XFS_ILOCK_EXCL
);
if
(
wip
)
xfs_trans_ijoin
(
tp
,
wip
,
XFS_ILOCK_EXCL
);
/*
* If we are using project inheritance, we only allow renames
...
...
@@ -2930,24 +2988,16 @@ xfs_rename(
if
(
unlikely
((
target_dp
->
i_d
.
di_flags
&
XFS_DIFLAG_PROJINHERIT
)
&&
(
xfs_get_projid
(
target_dp
)
!=
xfs_get_projid
(
src_ip
))))
{
error
=
-
EXDEV
;
goto
error_return
;
goto
out_trans_cancel
;
}
/*
* Handle RENAME_EXCHANGE flags
*/
if
(
flags
&
RENAME_EXCHANGE
)
{
if
(
target_ip
==
NULL
)
{
error
=
-
EINVAL
;
goto
error_return
;
}
error
=
xfs_cross_rename
(
tp
,
src_dp
,
src_name
,
src_ip
,
target_dp
,
target_name
,
target_ip
,
&
free_list
,
&
first_block
,
spaceres
);
if
(
error
)
goto
abort_return
;
goto
finish_rename
;
}
xfs_bmap_init
(
&
free_list
,
&
first_block
);
/* RENAME_EXCHANGE is unique from here on. */
if
(
flags
&
RENAME_EXCHANGE
)
return
xfs_cross_rename
(
tp
,
src_dp
,
src_name
,
src_ip
,
target_dp
,
target_name
,
target_ip
,
&
free_list
,
&
first_block
,
spaceres
);
/*
* Set up the target.
...
...
@@ -2960,7 +3010,7 @@ xfs_rename(
if
(
!
spaceres
)
{
error
=
xfs_dir_canenter
(
tp
,
target_dp
,
target_name
);
if
(
error
)
goto
error_return
;
goto
out_trans_cancel
;
}
/*
* If target does not exist and the rename crosses
...
...
@@ -2971,9 +3021,9 @@ xfs_rename(
src_ip
->
i_ino
,
&
first_block
,
&
free_list
,
spaceres
);
if
(
error
==
-
ENOSPC
)
goto
error_return
;
goto
out_bmap_cancel
;
if
(
error
)
goto
abort_return
;
goto
out_trans_abort
;
xfs_trans_ichgtime
(
tp
,
target_dp
,
XFS_ICHGTIME_MOD
|
XFS_ICHGTIME_CHG
);
...
...
@@ -2981,7 +3031,7 @@ xfs_rename(
if
(
new_parent
&&
src_is_directory
)
{
error
=
xfs_bumplink
(
tp
,
target_dp
);
if
(
error
)
goto
abort_return
;
goto
out_trans_abort
;
}
}
else
{
/* target_ip != NULL */
/*
...
...
@@ -2996,7 +3046,7 @@ xfs_rename(
if
(
!
(
xfs_dir_isempty
(
target_ip
))
||
(
target_ip
->
i_d
.
di_nlink
>
2
))
{
error
=
-
EEXIST
;
goto
error_return
;
goto
out_trans_cancel
;
}
}
...
...
@@ -3013,7 +3063,7 @@ xfs_rename(
src_ip
->
i_ino
,
&
first_block
,
&
free_list
,
spaceres
);
if
(
error
)
goto
abort_return
;
goto
out_trans_abort
;
xfs_trans_ichgtime
(
tp
,
target_dp
,
XFS_ICHGTIME_MOD
|
XFS_ICHGTIME_CHG
);
...
...
@@ -3024,7 +3074,7 @@ xfs_rename(
*/
error
=
xfs_droplink
(
tp
,
target_ip
);
if
(
error
)
goto
abort_return
;
goto
out_trans_abort
;
if
(
src_is_directory
)
{
/*
...
...
@@ -3032,7 +3082,7 @@ xfs_rename(
*/
error
=
xfs_droplink
(
tp
,
target_ip
);
if
(
error
)
goto
abort_return
;
goto
out_trans_abort
;
}
}
/* target_ip != NULL */
...
...
@@ -3049,7 +3099,7 @@ xfs_rename(
&
first_block
,
&
free_list
,
spaceres
);
ASSERT
(
error
!=
-
EEXIST
);
if
(
error
)
goto
abort_return
;
goto
out_trans_abort
;
}
/*
...
...
@@ -3075,49 +3125,67 @@ xfs_rename(
*/
error
=
xfs_droplink
(
tp
,
src_dp
);
if
(
error
)
goto
abort_return
;
goto
out_trans_abort
;
}
error
=
xfs_dir_removename
(
tp
,
src_dp
,
src_name
,
src_ip
->
i_ino
,
/*
* For whiteouts, we only need to update the source dirent with the
* inode number of the whiteout inode rather than removing it
* altogether.
*/
if
(
wip
)
{
error
=
xfs_dir_replace
(
tp
,
src_dp
,
src_name
,
wip
->
i_ino
,
&
first_block
,
&
free_list
,
spaceres
);
}
else
error
=
xfs_dir_removename
(
tp
,
src_dp
,
src_name
,
src_ip
->
i_ino
,
&
first_block
,
&
free_list
,
spaceres
);
if
(
error
)
goto
abort_return
;
xfs_trans_ichgtime
(
tp
,
src_dp
,
XFS_ICHGTIME_MOD
|
XFS_ICHGTIME_CHG
);
xfs_trans_log_inode
(
tp
,
src_dp
,
XFS_ILOG_CORE
);
if
(
new_parent
)
xfs_trans_log_inode
(
tp
,
target_dp
,
XFS_ILOG_CORE
);
goto
out_trans_abort
;
finish_rename:
/*
* If this is a synchronous mount, make sure that the
* rename transaction goes to disk before returning to
* the user.
* For whiteouts, we need to bump the link count on the whiteout inode.
* This means that failures all the way up to this point leave the inode
* on the unlinked list and so cleanup is a simple matter of dropping
* the remaining reference to it. If we fail here after bumping the link
* count, we're shutting down the filesystem so we'll never see the
* intermediate state on disk.
*/
if
(
mp
->
m_flags
&
(
XFS_MOUNT_WSYNC
|
XFS_MOUNT_DIRSYNC
))
{
xfs_trans_set_sync
(
tp
);
}
if
(
wip
)
{
ASSERT
(
wip
->
i_d
.
di_nlink
==
0
);
error
=
xfs_bumplink
(
tp
,
wip
);
if
(
error
)
goto
out_trans_abort
;
error
=
xfs_iunlink_remove
(
tp
,
wip
);
if
(
error
)
goto
out_trans_abort
;
xfs_trans_log_inode
(
tp
,
wip
,
XFS_ILOG_CORE
);
error
=
xfs_bmap_finish
(
&
tp
,
&
free_list
,
&
committed
);
if
(
error
)
{
xfs_bmap_cancel
(
&
free_list
);
xfs_trans_cancel
(
tp
,
(
XFS_TRANS_RELEASE_LOG_RES
|
XFS_TRANS_ABORT
));
goto
std_return
;
/*
* Now we have a real link, clear the "I'm a tmpfile" state
* flag from the inode so it doesn't accidentally get misused in
* future.
*/
VFS_I
(
wip
)
->
i_state
&=
~
I_LINKABLE
;
}
/*
* trans_commit will unlock src_ip, target_ip & decrement
* the vnode references.
*/
return
xfs_trans_commit
(
tp
,
XFS_TRANS_RELEASE_LOG_RES
);
xfs_trans_ichgtime
(
tp
,
src_dp
,
XFS_ICHGTIME_MOD
|
XFS_ICHGTIME_CHG
);
xfs_trans_log_inode
(
tp
,
src_dp
,
XFS_ILOG_CORE
);
if
(
new_parent
)
xfs_trans_log_inode
(
tp
,
target_dp
,
XFS_ILOG_CORE
);
abort_return:
error
=
xfs_finish_rename
(
tp
,
&
free_list
);
if
(
wip
)
IRELE
(
wip
);
return
error
;
out_trans_abort:
cancel_flags
|=
XFS_TRANS_ABORT
;
error_return
:
out_bmap_cancel
:
xfs_bmap_cancel
(
&
free_list
);
out_trans_cancel:
xfs_trans_cancel
(
tp
,
cancel_flags
);
std_return:
if
(
wip
)
IRELE
(
wip
);
return
error
;
}
...
...
fs/xfs/xfs_iops.c
浏览文件 @
d41bb034
...
...
@@ -394,7 +394,7 @@ xfs_vn_rename(
struct
xfs_name
oname
;
struct
xfs_name
nname
;
if
(
flags
&
~
(
RENAME_NOREPLACE
|
RENAME_EXCHANGE
))
if
(
flags
&
~
(
RENAME_NOREPLACE
|
RENAME_EXCHANGE
|
RENAME_WHITEOUT
))
return
-
EINVAL
;
/* if we are exchanging files, we need to set i_mode of both files */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录