forked from Minki/linux
fs/affs: add rename exchange
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 <fabf@skynet.be> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
c6184028a7
commit
6b4657667b
@ -441,17 +441,73 @@ done:
|
|||||||
return retval;
|
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,
|
int affs_rename2(struct inode *old_dir, struct dentry *old_dentry,
|
||||||
struct inode *new_dir, struct dentry *new_dentry,
|
struct inode *new_dir, struct dentry *new_dentry,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (flags & ~RENAME_NOREPLACE)
|
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
|
pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
|
||||||
old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry);
|
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);
|
return affs_rename(old_dir, old_dentry, new_dir, new_dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user