Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks...
[pandora-kernel.git] / fs / ecryptfs / inode.c
index 11f8582..32f90a3 100644 (file)
@@ -172,22 +172,23 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode,
  * it. It will also update the eCryptfs directory inode to mimic the
  * stat of the lower directory inode.
  *
- * Returns zero on success; non-zero on error condition
+ * Returns the new eCryptfs inode on success; an ERR_PTR on error condition
  */
-static int
+static struct inode *
 ecryptfs_do_create(struct inode *directory_inode,
                   struct dentry *ecryptfs_dentry, int mode)
 {
        int rc;
        struct dentry *lower_dentry;
        struct dentry *lower_dir_dentry;
+       struct inode *inode;
 
        lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
        if (IS_ERR(lower_dir_dentry)) {
                ecryptfs_printk(KERN_ERR, "Error locking directory of "
                                "dentry\n");
-               rc = PTR_ERR(lower_dir_dentry);
+               inode = ERR_CAST(lower_dir_dentry);
                goto out;
        }
        rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
@@ -195,20 +196,19 @@ ecryptfs_do_create(struct inode *directory_inode,
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
                       "rc = [%d]\n", __func__, rc);
+               inode = ERR_PTR(rc);
                goto out_lock;
        }
-       rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
-                               directory_inode->i_sb);
-       if (rc) {
-               ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n");
+       inode = __ecryptfs_get_inode(lower_dentry->d_inode,
+                                    directory_inode->i_sb);
+       if (IS_ERR(inode))
                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:
        unlock_dir(lower_dir_dentry);
 out:
-       return rc;
+       return inode;
 }
 
 /**
@@ -219,26 +219,26 @@ out:
  *
  * Returns zero on success
  */
-static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
+static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
+                                   struct inode *ecryptfs_inode)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
-               &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+               &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        int rc = 0;
 
-       if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
+       if (S_ISDIR(ecryptfs_inode->i_mode)) {
                ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
                crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
                goto out;
        }
        ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
-       rc = ecryptfs_new_file_context(ecryptfs_dentry);
+       rc = ecryptfs_new_file_context(ecryptfs_inode);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error creating new file "
                                "context; rc = [%d]\n", rc);
                goto out;
        }
-       rc = ecryptfs_get_lower_file(ecryptfs_dentry,
-                                    ecryptfs_dentry->d_inode);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
                        "the lower file for the dentry with name "
@@ -246,10 +246,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                        ecryptfs_dentry->d_name.name, rc);
                goto out;
        }
-       rc = ecryptfs_write_metadata(ecryptfs_dentry);
+       rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode);
        if (rc)
                printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
-       ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
+       ecryptfs_put_lower_file(ecryptfs_inode);
 out:
        return rc;
 }
@@ -269,18 +269,28 @@ static int
 ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
                int mode, struct nameidata *nd)
 {
+       struct inode *ecryptfs_inode;
        int rc;
 
-       /* ecryptfs_do_create() calls ecryptfs_interpose() */
-       rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode);
-       if (unlikely(rc)) {
+       ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry,
+                                           mode);
+       if (unlikely(IS_ERR(ecryptfs_inode))) {
                ecryptfs_printk(KERN_WARNING, "Failed to create file in"
                                "lower filesystem\n");
+               rc = PTR_ERR(ecryptfs_inode);
                goto out;
        }
        /* At this point, a file exists on "disk"; we need to make sure
         * that this on disk file is prepared to be an ecryptfs file */
-       rc = ecryptfs_initialize_file(ecryptfs_dentry);
+       rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode);
+       if (rc) {
+               drop_nlink(ecryptfs_inode);
+               unlock_new_inode(ecryptfs_inode);
+               iput(ecryptfs_inode);
+               goto out;
+       }
+       d_instantiate(ecryptfs_dentry, ecryptfs_inode);
+       unlock_new_inode(ecryptfs_inode);
 out:
        return rc;
 }
@@ -474,8 +484,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
                goto out_lock;
        fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
        fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
-       old_dentry->d_inode->i_nlink =
-               ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink;
+       set_nlink(old_dentry->d_inode,
+                 ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink);
        i_size_write(new_dentry->d_inode, file_size_save);
 out_lock:
        unlock_dir(lower_dir_dentry);
@@ -499,8 +509,8 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
                goto out_unlock;
        }
        fsstack_copy_attr_times(dir, lower_dir_inode);
-       dentry->d_inode->i_nlink =
-               ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
+       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:
@@ -565,7 +575,7 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                goto out;
        fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
        fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
-       dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+       set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
 out:
        unlock_dir(lower_dir_dentry);
        if (!dentry->d_inode)
@@ -588,7 +598,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
        if (!rc && dentry->d_inode)
                clear_nlink(dentry->d_inode);
        fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-       dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+       set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
        unlock_dir(lower_dir_dentry);
        if (!rc)
                d_drop(dentry);