Skip to content

Commit 49db9b1

Browse files
jankaraAl Viro
authored andcommitted
reiserfs: Avoid touching renamed directory if parent does not change
The VFS will not be locking moved directory if its parent does not change. Change reiserfs rename code to avoid touching renamed directory if its parent does not change as without locking that can corrupt the filesystem. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 4a0b33f commit 49db9b1

File tree

1 file changed

+29
-25
lines changed

1 file changed

+29
-25
lines changed

fs/reiserfs/namei.c

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,8 +1324,8 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
13241324
struct inode *old_inode, *new_dentry_inode;
13251325
struct reiserfs_transaction_handle th;
13261326
int jbegin_count;
1327-
umode_t old_inode_mode;
13281327
unsigned long savelink = 1;
1328+
bool update_dir_parent = false;
13291329

13301330
if (flags & ~RENAME_NOREPLACE)
13311331
return -EINVAL;
@@ -1375,8 +1375,7 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
13751375
return -ENOENT;
13761376
}
13771377

1378-
old_inode_mode = old_inode->i_mode;
1379-
if (S_ISDIR(old_inode_mode)) {
1378+
if (S_ISDIR(old_inode->i_mode)) {
13801379
/*
13811380
* make sure that directory being renamed has correct ".."
13821381
* and that its new parent directory has not too many links
@@ -1389,24 +1388,28 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
13891388
}
13901389
}
13911390

1392-
/*
1393-
* directory is renamed, its parent directory will be changed,
1394-
* so find ".." entry
1395-
*/
1396-
dot_dot_de.de_gen_number_bit_string = NULL;
1397-
retval =
1398-
reiserfs_find_entry(old_inode, "..", 2, &dot_dot_entry_path,
1391+
if (old_dir != new_dir) {
1392+
/*
1393+
* directory is renamed, its parent directory will be
1394+
* changed, so find ".." entry
1395+
*/
1396+
dot_dot_de.de_gen_number_bit_string = NULL;
1397+
retval =
1398+
reiserfs_find_entry(old_inode, "..", 2,
1399+
&dot_dot_entry_path,
13991400
&dot_dot_de);
1400-
pathrelse(&dot_dot_entry_path);
1401-
if (retval != NAME_FOUND) {
1402-
reiserfs_write_unlock(old_dir->i_sb);
1403-
return -EIO;
1404-
}
1401+
pathrelse(&dot_dot_entry_path);
1402+
if (retval != NAME_FOUND) {
1403+
reiserfs_write_unlock(old_dir->i_sb);
1404+
return -EIO;
1405+
}
14051406

1406-
/* inode number of .. must equal old_dir->i_ino */
1407-
if (dot_dot_de.de_objectid != old_dir->i_ino) {
1408-
reiserfs_write_unlock(old_dir->i_sb);
1409-
return -EIO;
1407+
/* inode number of .. must equal old_dir->i_ino */
1408+
if (dot_dot_de.de_objectid != old_dir->i_ino) {
1409+
reiserfs_write_unlock(old_dir->i_sb);
1410+
return -EIO;
1411+
}
1412+
update_dir_parent = true;
14101413
}
14111414
}
14121415

@@ -1486,7 +1489,7 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
14861489

14871490
reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1);
14881491

1489-
if (S_ISDIR(old_inode->i_mode)) {
1492+
if (update_dir_parent) {
14901493
if ((retval =
14911494
search_by_entry_key(new_dir->i_sb,
14921495
&dot_dot_de.de_entry_key,
@@ -1534,14 +1537,14 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
15341537
new_de.de_bh);
15351538
reiserfs_restore_prepared_buffer(old_inode->i_sb,
15361539
old_de.de_bh);
1537-
if (S_ISDIR(old_inode_mode))
1540+
if (update_dir_parent)
15381541
reiserfs_restore_prepared_buffer(old_inode->
15391542
i_sb,
15401543
dot_dot_de.
15411544
de_bh);
15421545
continue;
15431546
}
1544-
if (S_ISDIR(old_inode_mode)) {
1547+
if (update_dir_parent) {
15451548
if (item_moved(&dot_dot_ih, &dot_dot_entry_path) ||
15461549
!entry_points_to_object("..", 2, &dot_dot_de,
15471550
old_dir)) {
@@ -1559,7 +1562,7 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
15591562
}
15601563
}
15611564

1562-
RFALSE(S_ISDIR(old_inode_mode) &&
1565+
RFALSE(update_dir_parent &&
15631566
!buffer_journal_prepared(dot_dot_de.de_bh), "");
15641567

15651568
break;
@@ -1592,11 +1595,12 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
15921595
savelink = new_dentry_inode->i_nlink;
15931596
}
15941597

1595-
if (S_ISDIR(old_inode_mode)) {
1598+
if (update_dir_parent) {
15961599
/* adjust ".." of renamed directory */
15971600
set_ino_in_dir_entry(&dot_dot_de, INODE_PKEY(new_dir));
15981601
journal_mark_dirty(&th, dot_dot_de.de_bh);
1599-
1602+
}
1603+
if (S_ISDIR(old_inode->i_mode)) {
16001604
/*
16011605
* there (in new_dir) was no directory, so it got new link
16021606
* (".." of renamed directory)

0 commit comments

Comments
 (0)