[PATCH] eCryptfs: Consolidate lower dentry_open's
Michael Halcrow [Tue, 31 Oct 2006 06:07:19 +0000 (22:07 -0800)]
Opens on lower dentry objects happen in several places in eCryptfs, and they
all involve the same steps (dget, mntget, dentry_open).  This patch
consolidates the lower open events into a single function call.

Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c

index 2a1b6aa..f49f105 100644 (file)
@@ -1191,28 +1191,28 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code)
 int ecryptfs_read_header_region(char *data, struct dentry *dentry,
                                struct vfsmount *mnt)
 {
-       struct file *file;
+       struct file *lower_file;
        mm_segment_t oldfs;
        int rc;
 
-       mnt = mntget(mnt);
-       file = dentry_open(dentry, mnt, O_RDONLY);
-       if (IS_ERR(file)) {
-               ecryptfs_printk(KERN_DEBUG, "Error opening file to "
-                               "read header region\n");
-               mntput(mnt);
-               rc = PTR_ERR(file);
+       if ((rc = ecryptfs_open_lower_file(&lower_file, dentry, mnt,
+                                          O_RDONLY))) {
+               printk(KERN_ERR
+                      "Error opening lower_file to read header region\n");
                goto out;
        }
-       file->f_pos = 0;
+       lower_file->f_pos = 0;
        oldfs = get_fs();
        set_fs(get_ds());
        /* For releases 0.1 and 0.2, all of the header information
         * fits in the first data extent-sized region. */
-       rc = file->f_op->read(file, (char __user *)data,
-                             ECRYPTFS_DEFAULT_EXTENT_SIZE, &file->f_pos);
+       rc = lower_file->f_op->read(lower_file, (char __user *)data,
+                             ECRYPTFS_DEFAULT_EXTENT_SIZE, &lower_file->f_pos);
        set_fs(oldfs);
-       fput(file);
+       if ((rc = ecryptfs_close_lower_file(lower_file))) {
+               printk(KERN_ERR "Error closing lower_file\n");
+               goto out;
+       }
        rc = 0;
 out:
        return rc;
index 199fcda..f992533 100644 (file)
@@ -482,5 +482,9 @@ ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name,
 int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode);
 int ecryptfs_inode_set(struct inode *inode, void *lower_inode);
 void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode);
+int ecryptfs_open_lower_file(struct file **lower_file,
+                            struct dentry *lower_dentry,
+                            struct vfsmount *lower_mnt, int flags);
+int ecryptfs_close_lower_file(struct file *lower_file);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
index c8550c9..a92ef05 100644 (file)
@@ -198,6 +198,33 @@ retry:
 
 struct kmem_cache *ecryptfs_file_info_cache;
 
+int ecryptfs_open_lower_file(struct file **lower_file,
+                            struct dentry *lower_dentry,
+                            struct vfsmount *lower_mnt, int flags)
+{
+       int rc = 0;
+
+       dget(lower_dentry);
+       mntget(lower_mnt);
+       *lower_file = dentry_open(lower_dentry, lower_mnt, flags);
+       if (IS_ERR(*lower_file)) {
+               printk(KERN_ERR "Error opening lower file for lower_dentry "
+                      "[0x%p], lower_mnt [0x%p], and flags [0x%x]\n",
+                      lower_dentry, lower_mnt, flags);
+               rc = PTR_ERR(*lower_file);
+               *lower_file = NULL;
+               goto out;
+       }
+out:
+       return rc;
+}
+
+int ecryptfs_close_lower_file(struct file *lower_file)
+{
+       fput(lower_file);
+       return 0;
+}
+
 /**
  * ecryptfs_open
  * @inode: inode speciying file to open
@@ -244,19 +271,15 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
        }
        mutex_unlock(&crypt_stat->cs_mutex);
-       /* This mntget & dget is undone via fput when the file is released */
-       dget(lower_dentry);
        lower_flags = file->f_flags;
        if ((lower_flags & O_ACCMODE) == O_WRONLY)
                lower_flags = (lower_flags & O_ACCMODE) | O_RDWR;
        if (file->f_flags & O_APPEND)
                lower_flags &= ~O_APPEND;
        lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
-       mntget(lower_mnt);
        /* Corresponding fput() in ecryptfs_release() */
-       lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags);
-       if (IS_ERR(lower_file)) {
-               rc = PTR_ERR(lower_file);
+       if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt,
+                                          lower_flags))) {
                ecryptfs_printk(KERN_ERR, "Error opening lower file\n");
                goto out_puts;
        }
@@ -341,11 +364,16 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
        struct file *lower_file = ecryptfs_file_to_lower(file);
        struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file);
        struct inode *lower_inode = ecryptfs_inode_to_lower(inode);
+       int rc;
 
-       fput(lower_file);
+       if ((rc = ecryptfs_close_lower_file(lower_file))) {
+               printk(KERN_ERR "Error closing lower_file\n");
+               goto out;
+       }
        inode->i_blocks = lower_inode->i_blocks;
        kmem_cache_free(ecryptfs_file_info_cache, file_info);
-       return 0;
+out:
+       return rc;
 }
 
 static int
index efdd2b7..2f2c6cf 100644 (file)
@@ -231,7 +231,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
        int lower_flags;
        struct ecryptfs_crypt_stat *crypt_stat;
        struct dentry *lower_dentry;
-       struct dentry *tlower_dentry = NULL;
        struct file *lower_file;
        struct inode *inode, *lower_inode;
        struct vfsmount *lower_mnt;
@@ -241,30 +240,19 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                        lower_dentry->d_name.name);
        inode = ecryptfs_dentry->d_inode;
        crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
-       tlower_dentry = dget(lower_dentry);
-       if (!tlower_dentry) {
-               rc = -ENOMEM;
-               ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry\n");
-               goto out;
-       }
        lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR;
 #if BITS_PER_LONG != 32
        lower_flags |= O_LARGEFILE;
 #endif
        lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
-       mntget(lower_mnt);
        /* Corresponding fput() at end of this function */
-       lower_file = dentry_open(tlower_dentry, lower_mnt, lower_flags);
-       if (IS_ERR(lower_file)) {
-               rc = PTR_ERR(lower_file);
+       if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt,
+                                          lower_flags))) {
                ecryptfs_printk(KERN_ERR,
                                "Error opening dentry; rc = [%i]\n", rc);
                goto out;
        }
-       /* fput(lower_file) should handle the puts if we do this */
-       lower_file->f_dentry = tlower_dentry;
-       lower_file->f_vfsmnt = lower_mnt;
-       lower_inode = tlower_dentry->d_inode;
+       lower_inode = lower_dentry->d_inode;
        if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
                ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
                ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
@@ -285,7 +273,8 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
        }
        rc = grow_file(ecryptfs_dentry, lower_file, inode, lower_inode);
 out_fput:
-       fput(lower_file);
+       if ((rc = ecryptfs_close_lower_file(lower_file)))
+               printk(KERN_ERR "Error closing lower_file\n");
 out:
        return rc;
 }
@@ -832,12 +821,11 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
        }
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        /* This dget & mntget is released through fput at out_fput: */
-       dget(lower_dentry);
        lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-       mntget(lower_mnt);
-       lower_file = dentry_open(lower_dentry, lower_mnt, O_RDWR);
-       if (unlikely(IS_ERR(lower_file))) {
-               rc = PTR_ERR(lower_file);
+       if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt,
+                                          O_RDWR))) {
+               ecryptfs_printk(KERN_ERR,
+                               "Error opening dentry; rc = [%i]\n", rc);
                goto out_free;
        }
        ecryptfs_set_file_lower(&fake_ecryptfs_file, lower_file);
@@ -879,7 +867,8 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
                = CURRENT_TIME;
        mark_inode_dirty_sync(inode);
 out_fput:
-       fput(lower_file);
+       if ((rc = ecryptfs_close_lower_file(lower_file)))
+               printk(KERN_ERR "Error closing lower_file\n");
 out_free:
        if (ecryptfs_file_to_private(&fake_ecryptfs_file))
                kmem_cache_free(ecryptfs_file_info_cache,