aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@canonical.com>2012-09-13 15:00:56 -0400
committerTyler Hicks <tyhicks@canonical.com>2012-09-14 12:36:03 -0400
commit8335eafc2859e1a26282bef7c3d19f3d68868b8a (patch)
treea551e696fdf0fb75c975d45efe0d4b8729c5671c /fs/ecryptfs
parent64e6651dcc10e9d2cc6230208a8e6c2cfd19ae18 (diff)
eCryptfs: Copy up attributes of the lower target inode after rename
After calling into the lower filesystem to do a rename, the lower target inode's attributes were not copied up to the eCryptfs target inode. This resulted in the eCryptfs target inode staying around, rather than being evicted, because i_nlink was not updated for the eCryptfs inode. This also meant that eCryptfs didn't do the final iput() on the lower target inode so it stayed around, as well. This would result in a failure to free up space occupied by the target file in the rename() operation. Both target inodes would eventually be evicted when the eCryptfs filesystem was unmounted. This patch calls fsstack_copy_attr_all() after the lower filesystem does its ->rename() so that important inode attributes, such as i_nlink, are updated at the eCryptfs layer. ecryptfs_evict_inode() is now called and eCryptfs can drop its final reference on the lower inode. http://launchpad.net/bugs/561129 Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Tested-by: Colin Ian King <colin.king@canonical.com> Cc: <stable@vger.kernel.org> [2.6.39+]
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r--fs/ecryptfs/inode.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 534b129ea67..cc7709e7c50 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -619,6 +619,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
619 struct dentry *lower_old_dir_dentry; 619 struct dentry *lower_old_dir_dentry;
620 struct dentry *lower_new_dir_dentry; 620 struct dentry *lower_new_dir_dentry;
621 struct dentry *trap = NULL; 621 struct dentry *trap = NULL;
622 struct inode *target_inode;
622 623
623 lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); 624 lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
624 lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); 625 lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
@@ -626,6 +627,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
626 dget(lower_new_dentry); 627 dget(lower_new_dentry);
627 lower_old_dir_dentry = dget_parent(lower_old_dentry); 628 lower_old_dir_dentry = dget_parent(lower_old_dentry);
628 lower_new_dir_dentry = dget_parent(lower_new_dentry); 629 lower_new_dir_dentry = dget_parent(lower_new_dentry);
630 target_inode = new_dentry->d_inode;
629 trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); 631 trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
630 /* source should not be ancestor of target */ 632 /* source should not be ancestor of target */
631 if (trap == lower_old_dentry) { 633 if (trap == lower_old_dentry) {
@@ -641,6 +643,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
641 lower_new_dir_dentry->d_inode, lower_new_dentry); 643 lower_new_dir_dentry->d_inode, lower_new_dentry);
642 if (rc) 644 if (rc)
643 goto out_lock; 645 goto out_lock;
646 if (target_inode)
647 fsstack_copy_attr_all(target_inode,
648 ecryptfs_inode_to_lower(target_inode));
644 fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode); 649 fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
645 if (new_dir != old_dir) 650 if (new_dir != old_dir)
646 fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); 651 fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);