aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authoralex chen <alex.chen@huawei.com>2014-06-23 16:22:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-23 19:47:45 -0400
commit5fb1beb069dcf616e88be9d330b86878a79aa4ff (patch)
treed14175b91979c4d64a433710f9a9e0168ef4919e /fs
parentd05f0cdcbe6388723f1900c549b4850360545201 (diff)
ocfs2: should add inode into orphan dir after updating entry in ocfs2_rename()
There are two files a and b in dir /mnt/ocfs2. node A node B mv a b In ocfs2_rename(), after calling ocfs2_orphan_add(), the inode of file b will be added into orphan dir. If ocfs2_update_entry() fails, ocfs2_rename return error and mv operation fails. But file b still exists in the parent dir. ocfs2_queue_orphan_scan -> ocfs2_queue_recovery_completion -> ocfs2_complete_recovery -> ocfs2_recover_orphans The inode of the file b will be put with iput(). ocfs2_evict_inode -> ocfs2_delete_inode -> ocfs2_wipe_inode -> ocfs2_remove_inode OCFS2_VALID_FL in the inode i_flags will be cleared. The file b still can be accessed on node B. ls /mnt/ocfs2 When first read the file b with ocfs2_read_inode_block(). It will validate the inode using ocfs2_validate_inode_block(). Because OCFS2_VALID_FL not set in the inode i_flags, so the file system will be readonly. So we should add inode into orphan dir after updating entry in ocfs2_rename(). Signed-off-by: alex.chen <alex.chen@huawei.com> Reviewed-by: Mark Fasheh <mfasheh@suse.de> Cc: Joel Becker <jlbec@evilplan.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/namei.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 2060fc398445..5819bb5d6483 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1098,6 +1098,7 @@ static int ocfs2_rename(struct inode *old_dir,
1098 struct ocfs2_dir_lookup_result old_entry_lookup = { NULL, }; 1098 struct ocfs2_dir_lookup_result old_entry_lookup = { NULL, };
1099 struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 1099 struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
1100 struct ocfs2_dir_lookup_result target_insert = { NULL, }; 1100 struct ocfs2_dir_lookup_result target_insert = { NULL, };
1101 bool should_add_orphan = false;
1101 1102
1102 /* At some point it might be nice to break this function up a 1103 /* At some point it might be nice to break this function up a
1103 * bit. */ 1104 * bit. */
@@ -1304,6 +1305,7 @@ static int ocfs2_rename(struct inode *old_dir,
1304 mlog_errno(status); 1305 mlog_errno(status);
1305 goto bail; 1306 goto bail;
1306 } 1307 }
1308 should_add_orphan = true;
1307 } 1309 }
1308 } else { 1310 } else {
1309 BUG_ON(new_dentry->d_parent->d_inode != new_dir); 1311 BUG_ON(new_dentry->d_parent->d_inode != new_dir);
@@ -1348,17 +1350,6 @@ static int ocfs2_rename(struct inode *old_dir,
1348 goto bail; 1350 goto bail;
1349 } 1351 }
1350 1352
1351 if (S_ISDIR(new_inode->i_mode) ||
1352 (ocfs2_read_links_count(newfe) == 1)) {
1353 status = ocfs2_orphan_add(osb, handle, new_inode,
1354 newfe_bh, orphan_name,
1355 &orphan_insert, orphan_dir);
1356 if (status < 0) {
1357 mlog_errno(status);
1358 goto bail;
1359 }
1360 }
1361
1362 /* change the dirent to point to the correct inode */ 1353 /* change the dirent to point to the correct inode */
1363 status = ocfs2_update_entry(new_dir, handle, &target_lookup_res, 1354 status = ocfs2_update_entry(new_dir, handle, &target_lookup_res,
1364 old_inode); 1355 old_inode);
@@ -1373,6 +1364,15 @@ static int ocfs2_rename(struct inode *old_dir,
1373 else 1364 else
1374 ocfs2_add_links_count(newfe, -1); 1365 ocfs2_add_links_count(newfe, -1);
1375 ocfs2_journal_dirty(handle, newfe_bh); 1366 ocfs2_journal_dirty(handle, newfe_bh);
1367 if (should_add_orphan) {
1368 status = ocfs2_orphan_add(osb, handle, new_inode,
1369 newfe_bh, orphan_name,
1370 &orphan_insert, orphan_dir);
1371 if (status < 0) {
1372 mlog_errno(status);
1373 goto bail;
1374 }
1375 }
1376 } else { 1376 } else {
1377 /* if the name was not found in new_dir, add it now */ 1377 /* if the name was not found in new_dir, add it now */
1378 status = ocfs2_add_entry(handle, new_dentry, old_inode, 1378 status = ocfs2_add_entry(handle, new_dentry, old_inode,