forked from Minki/linux
ocfs2: roll back the reference count modification of the parent directory if an error occurs
Under some conditions, the directory cannot be deleted. The specific scenarios are as follows: (for example, /mnt/ocfs2 is the mount point) 1. Create the /mnt/ocfs2/p_dir directory. At this time, the i_nlink corresponding to the inode of the /mnt/ocfs2/p_dir directory is equal to 2. 2. During the process of creating the /mnt/ocfs2/p_dir/s_dir directory, if the call to the inc_nlink function in ocfs2_mknod succeeds, the functions such as ocfs2_init_acl, ocfs2_init_security_set, and ocfs2_dentry_attach_lock fail. At this time, the i_nlink corresponding to the inode of the /mnt/ocfs2/p_dir directory is equal to 3, but /mnt/ocfs2/p_dir/s_dir is not added to the /mnt/ocfs2/p_dir directory entry. 3. Delete the /mnt/ocfs2/p_dir directory (rm -rf /mnt/ocfs2/p_dir). At this time, it is found that the i_nlink corresponding to the inode corresponding to the /mnt/ocfs2/p_dir directory is equal to 3. Therefore, the /mnt/ocfs2/p_dir directory cannot be deleted. Signed-off-by: Jian wang <wangjian161@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Jun Piao <piaojun@huawei.com> Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> Cc: Mark Fasheh <mark@fasheh.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Junxiao Bi <junxiao.bi@oracle.com> Cc: Changwei Ge <gechangwei@live.cn> Cc: Gang He <ghe@suse.com> Cc: Jun Piao <piaojun@huawei.com> Link: http://lkml.kernel.org/r/a44f6666-bbc4-405e-0e6c-0f4e922eeef6@huawei.com Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
95f3427c24
commit
0434c9f404
@ -406,7 +406,7 @@ static int ocfs2_mknod(struct inode *dir,
|
|||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto leave;
|
goto roll_back;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (si.enable) {
|
if (si.enable) {
|
||||||
@ -414,7 +414,7 @@ static int ocfs2_mknod(struct inode *dir,
|
|||||||
meta_ac, data_ac);
|
meta_ac, data_ac);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto leave;
|
goto roll_back;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +427,7 @@ static int ocfs2_mknod(struct inode *dir,
|
|||||||
OCFS2_I(dir)->ip_blkno);
|
OCFS2_I(dir)->ip_blkno);
|
||||||
if (status) {
|
if (status) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto leave;
|
goto roll_back;
|
||||||
}
|
}
|
||||||
|
|
||||||
dl = dentry->d_fsdata;
|
dl = dentry->d_fsdata;
|
||||||
@ -437,12 +437,19 @@ static int ocfs2_mknod(struct inode *dir,
|
|||||||
&lookup);
|
&lookup);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto leave;
|
goto roll_back;
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_inode_hash(inode);
|
insert_inode_hash(inode);
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
||||||
|
roll_back:
|
||||||
|
if (status < 0 && S_ISDIR(mode)) {
|
||||||
|
ocfs2_add_links_count(dirfe, -1);
|
||||||
|
drop_nlink(dir);
|
||||||
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
if (status < 0 && did_quota_inode)
|
if (status < 0 && did_quota_inode)
|
||||||
dquot_free_inode(inode);
|
dquot_free_inode(inode);
|
||||||
|
Loading…
Reference in New Issue
Block a user