Merge tag 'ecryptfs-3.6-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / fs / ecryptfs / inode.c
index c3ca12c33ca2aa3c504bcc3e415595d72b96c5d4..534b129ea676500c4df149d95cb9bd5be517dc54 100644 (file)
@@ -143,6 +143,31 @@ static int ecryptfs_interpose(struct dentry *lower_dentry,
        return 0;
 }
 
+static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry,
+                             struct inode *inode)
+{
+       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+       struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
+       struct dentry *lower_dir_dentry;
+       int rc;
+
+       dget(lower_dentry);
+       lower_dir_dentry = lock_parent(lower_dentry);
+       rc = vfs_unlink(lower_dir_inode, lower_dentry);
+       if (rc) {
+               printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
+               goto out_unlock;
+       }
+       fsstack_copy_attr_times(dir, lower_dir_inode);
+       set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink);
+       inode->i_ctime = dir->i_ctime;
+       d_drop(dentry);
+out_unlock:
+       unlock_dir(lower_dir_dentry);
+       dput(lower_dentry);
+       return rc;
+}
+
 /**
  * ecryptfs_do_create
  * @directory_inode: inode of the new file's dentry's parent in ecryptfs
@@ -182,8 +207,10 @@ ecryptfs_do_create(struct inode *directory_inode,
        }
        inode = __ecryptfs_get_inode(lower_dentry->d_inode,
                                     directory_inode->i_sb);
-       if (IS_ERR(inode))
+       if (IS_ERR(inode)) {
+               vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
                goto out_lock;
+       }
        fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
        fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
 out_lock:
@@ -200,8 +227,8 @@ out:
  *
  * Returns zero on success
  */
-static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
-                                   struct inode *ecryptfs_inode)
+int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
+                            struct inode *ecryptfs_inode)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
                &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
@@ -264,7 +291,9 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
         * that this on disk file is prepared to be an ecryptfs file */
        rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode);
        if (rc) {
-               drop_nlink(ecryptfs_inode);
+               ecryptfs_do_unlink(directory_inode, ecryptfs_dentry,
+                                  ecryptfs_inode);
+               make_bad_inode(ecryptfs_inode);
                unlock_new_inode(ecryptfs_inode);
                iput(ecryptfs_inode);
                goto out;
@@ -466,27 +495,7 @@ out_lock:
 
 static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       int rc = 0;
-       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
-       struct dentry *lower_dir_dentry;
-
-       dget(lower_dentry);
-       lower_dir_dentry = lock_parent(lower_dentry);
-       rc = vfs_unlink(lower_dir_inode, lower_dentry);
-       if (rc) {
-               printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
-               goto out_unlock;
-       }
-       fsstack_copy_attr_times(dir, lower_dir_inode);
-       set_nlink(dentry->d_inode,
-                 ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink);
-       dentry->d_inode->i_ctime = dir->i_ctime;
-       d_drop(dentry);
-out_unlock:
-       unlock_dir(lower_dir_dentry);
-       dput(lower_dentry);
-       return rc;
+       return ecryptfs_do_unlink(dir, dentry, dentry->d_inode);
 }
 
 static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
@@ -961,12 +970,6 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
                        goto out;
        }
 
-       if (S_ISREG(inode->i_mode)) {
-               rc = filemap_write_and_wait(inode->i_mapping);
-               if (rc)
-                       goto out;
-               fsstack_copy_attr_all(inode, lower_inode);
-       }
        memcpy(&lower_ia, ia, sizeof(lower_ia));
        if (ia->ia_valid & ATTR_FILE)
                lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);