Browse Source

Merge tag 'ecryptfs-3.6-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs

Pull ecryptfs fixes from Tyler Hicks:

 - Fixes a regression, introduced in 3.6-rc1, when a file is closed
   before its shared memory mapping is dirtied and unmapped.  The lower
   file was being released when the eCryptfs file was closed and the
   dirtied pages could not be written out.
 - Adds a call to the lower filesystem's ->flush() from
   ecryptfs_flush().
 - Fixes a regression, introduced in 2.6.39, when a file is renamed on
   top of another file.  The target file's inode was not being evicted
   and the space taken by the file was not reclaimed until eCryptfs was
   unmounted.

* tag 'ecryptfs-3.6-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs:
  eCryptfs: Copy up attributes of the lower target inode after rename
  eCryptfs: Call lower ->flush() from ecryptfs_flush()
  eCryptfs: Write out all dirty pages just before releasing the lower file
Linus Torvalds 12 years ago
parent
commit
1547cb80db
3 changed files with 14 additions and 2 deletions
  1. 8 2
      fs/ecryptfs/file.c
  2. 5 0
      fs/ecryptfs/inode.c
  3. 1 0
      fs/ecryptfs/main.c

+ 8 - 2
fs/ecryptfs/file.c

@@ -275,8 +275,14 @@ out:
 
 
 static int ecryptfs_flush(struct file *file, fl_owner_t td)
 static int ecryptfs_flush(struct file *file, fl_owner_t td)
 {
 {
-	return file->f_mode & FMODE_WRITE
-	       ? filemap_write_and_wait(file->f_mapping) : 0;
+	struct file *lower_file = ecryptfs_file_to_lower(file);
+
+	if (lower_file->f_op && lower_file->f_op->flush) {
+		filemap_write_and_wait(file->f_mapping);
+		return lower_file->f_op->flush(lower_file, td);
+	}
+
+	return 0;
 }
 }
 
 
 static int ecryptfs_release(struct inode *inode, struct file *file)
 static int ecryptfs_release(struct inode *inode, struct file *file)

+ 5 - 0
fs/ecryptfs/inode.c

@@ -619,6 +619,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct dentry *lower_old_dir_dentry;
 	struct dentry *lower_old_dir_dentry;
 	struct dentry *lower_new_dir_dentry;
 	struct dentry *lower_new_dir_dentry;
 	struct dentry *trap = NULL;
 	struct dentry *trap = NULL;
+	struct inode *target_inode;
 
 
 	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
 	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
 	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
 	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
@@ -626,6 +627,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	dget(lower_new_dentry);
 	dget(lower_new_dentry);
 	lower_old_dir_dentry = dget_parent(lower_old_dentry);
 	lower_old_dir_dentry = dget_parent(lower_old_dentry);
 	lower_new_dir_dentry = dget_parent(lower_new_dentry);
 	lower_new_dir_dentry = dget_parent(lower_new_dentry);
+	target_inode = new_dentry->d_inode;
 	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
 	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
 	/* source should not be ancestor of target */
 	/* source should not be ancestor of target */
 	if (trap == lower_old_dentry) {
 	if (trap == lower_old_dentry) {
@@ -641,6 +643,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			lower_new_dir_dentry->d_inode, lower_new_dentry);
 			lower_new_dir_dentry->d_inode, lower_new_dentry);
 	if (rc)
 	if (rc)
 		goto out_lock;
 		goto out_lock;
+	if (target_inode)
+		fsstack_copy_attr_all(target_inode,
+				      ecryptfs_inode_to_lower(target_inode));
 	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
 	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
 	if (new_dir != old_dir)
 	if (new_dir != old_dir)
 		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
 		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);

+ 1 - 0
fs/ecryptfs/main.c

@@ -162,6 +162,7 @@ void ecryptfs_put_lower_file(struct inode *inode)
 	inode_info = ecryptfs_inode_to_private(inode);
 	inode_info = ecryptfs_inode_to_private(inode);
 	if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
 	if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
 				      &inode_info->lower_file_mutex)) {
 				      &inode_info->lower_file_mutex)) {
+		filemap_write_and_wait(inode->i_mapping);
 		fput(inode_info->lower_file);
 		fput(inode_info->lower_file);
 		inode_info->lower_file = NULL;
 		inode_info->lower_file = NULL;
 		mutex_unlock(&inode_info->lower_file_mutex);
 		mutex_unlock(&inode_info->lower_file_mutex);