[PATCH 2/2 linux-next] fs/affs: add rename exchange

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 fs/affs/namei.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 49a8dc1..46d3ace 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -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);
 }
 
-- 
2.9.3




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux