+ reiserfs_update_inode_transaction(old_dir);
+ reiserfs_update_inode_transaction(new_dir);
+
+ /* this makes it so an fsync on an open fd for the old name will
+ ** commit the rename operation
+ */
+ reiserfs_update_inode_transaction(old_inode);
+
+ if (new_dentry_inode)
+ reiserfs_update_inode_transaction(new_dentry_inode);
+
+ while (1) {
+ // look for old name using corresponding entry key (found by reiserfs_find_entry)
+ if ((retval =
+ search_by_entry_key(new_dir->i_sb, &old_de.de_entry_key,
+ &old_entry_path,
+ &old_de)) != NAME_FOUND) {
+ pathrelse(&old_entry_path);
+ journal_end(&th, old_dir->i_sb, jbegin_count);
+ reiserfs_write_unlock(old_dir->i_sb);
+ return -EIO;
+ }
+
+ copy_item_head(&old_entry_ih, get_ih(&old_entry_path));
+
+ reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1);
+
+ // look for new name by reiserfs_find_entry
+ new_de.de_gen_number_bit_string = NULL;
+ retval =
+ reiserfs_find_entry(new_dir, new_dentry->d_name.name,
+ new_dentry->d_name.len, &new_entry_path,
+ &new_de);
+ // reiserfs_add_entry should not return IO_ERROR, because it is called with essentially same parameters from
+ // reiserfs_add_entry above, and we'll catch any i/o errors before we get here.
+ if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) {
+ pathrelse(&new_entry_path);
+ pathrelse(&old_entry_path);
+ journal_end(&th, old_dir->i_sb, jbegin_count);
+ reiserfs_write_unlock(old_dir->i_sb);
+ return -EIO;
+ }
+
+ copy_item_head(&new_entry_ih, get_ih(&new_entry_path));
+
+ reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1);
+
+ if (S_ISDIR(old_inode->i_mode)) {
+ if ((retval =
+ search_by_entry_key(new_dir->i_sb,
+ &dot_dot_de.de_entry_key,
+ &dot_dot_entry_path,
+ &dot_dot_de)) != NAME_FOUND) {
+ pathrelse(&dot_dot_entry_path);
+ pathrelse(&new_entry_path);
+ pathrelse(&old_entry_path);
+ journal_end(&th, old_dir->i_sb, jbegin_count);
+ reiserfs_write_unlock(old_dir->i_sb);
+ return -EIO;
+ }
+ copy_item_head(&dot_dot_ih,
+ get_ih(&dot_dot_entry_path));
+ // node containing ".." gets into transaction
+ reiserfs_prepare_for_journal(old_inode->i_sb,
+ dot_dot_de.de_bh, 1);
+ }
+ /* we should check seals here, not do
+ this stuff, yes? Then, having
+ gathered everything into RAM we
+ should lock the buffers, yes? -Hans */
+ /* probably. our rename needs to hold more
+ ** than one path at once. The seals would
+ ** have to be written to deal with multi-path
+ ** issues -chris
+ */
+ /* sanity checking before doing the rename - avoid races many
+ ** of the above checks could have scheduled. We have to be
+ ** sure our items haven't been shifted by another process.
+ */
+ if (item_moved(&new_entry_ih, &new_entry_path) ||
+ !entry_points_to_object(new_dentry->d_name.name,
+ new_dentry->d_name.len,
+ &new_de, new_dentry_inode) ||
+ item_moved(&old_entry_ih, &old_entry_path) ||
+ !entry_points_to_object(old_dentry->d_name.name,
+ old_dentry->d_name.len,
+ &old_de, old_inode)) {
+ reiserfs_restore_prepared_buffer(old_inode->i_sb,
+ new_de.de_bh);
+ reiserfs_restore_prepared_buffer(old_inode->i_sb,
+ old_de.de_bh);
+ if (S_ISDIR(old_inode_mode))
+ reiserfs_restore_prepared_buffer(old_inode->
+ i_sb,
+ dot_dot_de.
+ de_bh);
+ continue;
+ }
+ if (S_ISDIR(old_inode_mode)) {
+ if (item_moved(&dot_dot_ih, &dot_dot_entry_path) ||
+ !entry_points_to_object("..", 2, &dot_dot_de,
+ old_dir)) {
+ reiserfs_restore_prepared_buffer(old_inode->
+ i_sb,
+ old_de.de_bh);
+ reiserfs_restore_prepared_buffer(old_inode->
+ i_sb,
+ new_de.de_bh);
+ reiserfs_restore_prepared_buffer(old_inode->
+ i_sb,
+ dot_dot_de.
+ de_bh);
+ continue;
+ }
+ }
+
+ RFALSE(S_ISDIR(old_inode_mode) &&
+ !buffer_journal_prepared(dot_dot_de.de_bh), "");
+
+ break;