Skip to content

Commit

Permalink
fs/affs: add rename exchange
Browse files Browse the repository at this point in the history
Process RENAME_EXCHANGE in affs_rename2() adding static
affs_xrename() based on affs_rename().

We remove headers from respective directories then
affect bh to other inode directory entries for swapping.

Signed-off-by: Fabian Frederick <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
Fabian Frederick authored and Al Viro committed May 5, 2017
1 parent c618402 commit 6b46576
Showing 1 changed file with 57 additions and 1 deletion.
58 changes: 57 additions & 1 deletion fs/affs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,17 +441,73 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
return retval;
}

static int
affs_xrename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{

struct super_block *sb = old_dir->i_sb;
struct buffer_head *bh_old = NULL;
struct buffer_head *bh_new = NULL;
int retval;

bh_old = affs_bread(sb, d_inode(old_dentry)->i_ino);
if (!bh_old)
return -EIO;

bh_new = affs_bread(sb, d_inode(new_dentry)->i_ino);
if (!bh_new)
return -EIO;

/* Remove old header from its parent directory. */
affs_lock_dir(old_dir);
retval = affs_remove_hash(old_dir, bh_old);
affs_unlock_dir(old_dir);
if (retval)
goto done;

/* Remove new header from its parent directory. */
affs_lock_dir(new_dir);
retval = affs_remove_hash(new_dir, bh_new);
affs_unlock_dir(new_dir);
if (retval)
goto done;

/* Insert old into the new directory with the new name. */
affs_copy_name(AFFS_TAIL(sb, bh_old)->name, new_dentry);
affs_fix_checksum(sb, bh_old);
affs_lock_dir(new_dir);
retval = affs_insert_hash(new_dir, bh_old);
affs_unlock_dir(new_dir);

/* Insert new into the old directory with the old name. */
affs_copy_name(AFFS_TAIL(sb, bh_new)->name, old_dentry);
affs_fix_checksum(sb, bh_new);
affs_lock_dir(old_dir);
retval = affs_insert_hash(old_dir, bh_new);
affs_unlock_dir(old_dir);
done:
mark_buffer_dirty_inode(bh_old, new_dir);
mark_buffer_dirty_inode(bh_new, old_dir);
affs_brelse(bh_old);
affs_brelse(bh_new);
return retval;
}

int affs_rename2(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
{

if (flags & ~RENAME_NOREPLACE)
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
return -EINVAL;

pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry);

if (flags & RENAME_EXCHANGE)
return affs_xrename(old_dir, old_dentry, new_dir, new_dentry);

return affs_rename(old_dir, old_dentry, new_dir, new_dentry);
}

Expand Down

0 comments on commit 6b46576

Please sign in to comment.