aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/inode.c
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>2011-05-24 03:16:51 -0400
committerTyler Hicks <tyhicks@linux.vnet.ibm.com>2011-05-29 13:51:17 -0400
commit5ccf92037c7c6e6f28175fd245284923f939259f (patch)
tree3d9d551131686c9b0f4c6f7ed31ce4db1dbd0327 /fs/ecryptfs/inode.c
parentc4f790736ca8d7d86883c5aee2ba1caa15cd8da3 (diff)
eCryptfs: Cleanup inode initialization code
The eCryptfs inode get, initialization, and dentry interposition code has two separate paths. One is for when dentry interposition is needed after doing things like a mkdir in the lower filesystem and the other is needed after a lookup. Unlocking new inodes and doing a d_add() needs to happen at different times, depending on which type of dentry interposing is being done. This patch cleans up the inode get and initialization code paths and splits them up so that the locking and d_add() differences mentioned above can be handled appropriately in a later patch. Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com> Tested-by: David <david@unsolicited.net>
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r--fs/ecryptfs/inode.c134
1 files changed, 69 insertions, 65 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 704a8c8fe19a..fc7d2b748503 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -58,85 +58,87 @@ static int ecryptfs_inode_test(struct inode *inode, void *lower_inode)
58 return 0; 58 return 0;
59} 59}
60 60
61static int ecryptfs_inode_set(struct inode *inode, void *lower_inode) 61static int ecryptfs_inode_set(struct inode *inode, void *opaque)
62{ 62{
63 ecryptfs_set_inode_lower(inode, (struct inode *)lower_inode); 63 struct inode *lower_inode = opaque;
64 inode->i_ino = ((struct inode *)lower_inode)->i_ino; 64
65 ecryptfs_set_inode_lower(inode, lower_inode);
66 fsstack_copy_attr_all(inode, lower_inode);
67 /* i_size will be overwritten for encrypted regular files */
68 fsstack_copy_inode_size(inode, lower_inode);
69 inode->i_ino = lower_inode->i_ino;
65 inode->i_version++; 70 inode->i_version++;
66 inode->i_op = &ecryptfs_main_iops;
67 inode->i_fop = &ecryptfs_main_fops;
68 inode->i_mapping->a_ops = &ecryptfs_aops; 71 inode->i_mapping->a_ops = &ecryptfs_aops;
72
73 if (S_ISLNK(inode->i_mode))
74 inode->i_op = &ecryptfs_symlink_iops;
75 else if (S_ISDIR(inode->i_mode))
76 inode->i_op = &ecryptfs_dir_iops;
77 else
78 inode->i_op = &ecryptfs_main_iops;
79
80 if (S_ISDIR(inode->i_mode))
81 inode->i_fop = &ecryptfs_dir_fops;
82 else if (special_file(inode->i_mode))
83 init_special_inode(inode, inode->i_mode, inode->i_rdev);
84 else
85 inode->i_fop = &ecryptfs_main_fops;
86
69 return 0; 87 return 0;
70} 88}
71 89
72struct inode *ecryptfs_get_inode(struct inode *lower_inode, 90static struct inode *__ecryptfs_get_inode(struct inode *lower_inode,
73 struct super_block *sb) 91 struct super_block *sb)
74{ 92{
75 struct inode *inode; 93 struct inode *inode;
76 int rc = 0;
77 94
78 if (lower_inode->i_sb != ecryptfs_superblock_to_lower(sb)) { 95 if (lower_inode->i_sb != ecryptfs_superblock_to_lower(sb))
79 rc = -EXDEV; 96 return ERR_PTR(-EXDEV);
80 goto out; 97 if (!igrab(lower_inode))
81 } 98 return ERR_PTR(-ESTALE);
82 if (!igrab(lower_inode)) {
83 rc = -ESTALE;
84 goto out;
85 }
86 inode = iget5_locked(sb, (unsigned long)lower_inode, 99 inode = iget5_locked(sb, (unsigned long)lower_inode,
87 ecryptfs_inode_test, ecryptfs_inode_set, 100 ecryptfs_inode_test, ecryptfs_inode_set,
88 lower_inode); 101 lower_inode);
89 if (!inode) { 102 if (!inode) {
90 rc = -EACCES;
91 iput(lower_inode); 103 iput(lower_inode);
92 goto out; 104 return ERR_PTR(-EACCES);
93 } 105 }
94 if (inode->i_state & I_NEW) 106 if (!(inode->i_state & I_NEW))
95 unlock_new_inode(inode);
96 else
97 iput(lower_inode); 107 iput(lower_inode);
98 if (S_ISLNK(lower_inode->i_mode)) 108
99 inode->i_op = &ecryptfs_symlink_iops; 109 return inode;
100 else if (S_ISDIR(lower_inode->i_mode)) 110}
101 inode->i_op = &ecryptfs_dir_iops; 111
102 if (S_ISDIR(lower_inode->i_mode)) 112struct inode *ecryptfs_get_inode(struct inode *lower_inode,
103 inode->i_fop = &ecryptfs_dir_fops; 113 struct super_block *sb)
104 if (special_file(lower_inode->i_mode)) 114{
105 init_special_inode(inode, lower_inode->i_mode, 115 struct inode *inode = __ecryptfs_get_inode(lower_inode, sb);
106 lower_inode->i_rdev); 116
107 fsstack_copy_attr_all(inode, lower_inode); 117 if (!IS_ERR(inode) && (inode->i_state & I_NEW))
108 /* This size will be overwritten for real files w/ headers and 118 unlock_new_inode(inode);
109 * other metadata */ 119
110 fsstack_copy_inode_size(inode, lower_inode);
111 return inode; 120 return inode;
112out:
113 return ERR_PTR(rc);
114} 121}
115 122
116#define ECRYPTFS_INTERPOSE_FLAG_D_ADD 0x00000001
117/** 123/**
118 * ecryptfs_interpose 124 * ecryptfs_interpose
119 * @lower_dentry: Existing dentry in the lower filesystem 125 * @lower_dentry: Existing dentry in the lower filesystem
120 * @dentry: ecryptfs' dentry 126 * @dentry: ecryptfs' dentry
121 * @sb: ecryptfs's super_block 127 * @sb: ecryptfs's super_block
122 * @flags: flags to govern behavior of interpose procedure
123 * 128 *
124 * Interposes upper and lower dentries. 129 * Interposes upper and lower dentries.
125 * 130 *
126 * Returns zero on success; non-zero otherwise 131 * Returns zero on success; non-zero otherwise
127 */ 132 */
128static int ecryptfs_interpose(struct dentry *lower_dentry, 133static int ecryptfs_interpose(struct dentry *lower_dentry,
129 struct dentry *dentry, struct super_block *sb, 134 struct dentry *dentry, struct super_block *sb)
130 u32 flags)
131{ 135{
132 struct inode *lower_inode = lower_dentry->d_inode; 136 struct inode *inode = ecryptfs_get_inode(lower_dentry->d_inode, sb);
133 struct inode *inode = ecryptfs_get_inode(lower_inode, sb); 137
134 if (IS_ERR(inode)) 138 if (IS_ERR(inode))
135 return PTR_ERR(inode); 139 return PTR_ERR(inode);
136 if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD) 140 d_instantiate(dentry, inode);
137 d_add(dentry, inode); 141
138 else
139 d_instantiate(dentry, inode);
140 return 0; 142 return 0;
141} 143}
142 144
@@ -218,7 +220,7 @@ ecryptfs_do_create(struct inode *directory_inode,
218 goto out_lock; 220 goto out_lock;
219 } 221 }
220 rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, 222 rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
221 directory_inode->i_sb, 0); 223 directory_inode->i_sb);
222 if (rc) { 224 if (rc) {
223 ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n"); 225 ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n");
224 goto out_lock; 226 goto out_lock;
@@ -305,15 +307,15 @@ out:
305} 307}
306 308
307/** 309/**
308 * ecryptfs_lookup_and_interpose_lower - Perform a lookup 310 * ecryptfs_lookup_interpose - Dentry interposition for a lookup
309 */ 311 */
310int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, 312static int ecryptfs_lookup_interpose(struct dentry *ecryptfs_dentry,
311 struct dentry *lower_dentry, 313 struct dentry *lower_dentry,
312 struct inode *ecryptfs_dir_inode) 314 struct inode *ecryptfs_dir_inode)
313{ 315{
314 struct dentry *lower_dir_dentry; 316 struct dentry *lower_dir_dentry;
315 struct vfsmount *lower_mnt; 317 struct vfsmount *lower_mnt;
316 struct inode *lower_inode; 318 struct inode *inode, *lower_inode;
317 struct ecryptfs_crypt_stat *crypt_stat; 319 struct ecryptfs_crypt_stat *crypt_stat;
318 char *page_virt = NULL; 320 char *page_virt = NULL;
319 int put_lower = 0, rc = 0; 321 int put_lower = 0, rc = 0;
@@ -341,14 +343,16 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
341 d_add(ecryptfs_dentry, NULL); 343 d_add(ecryptfs_dentry, NULL);
342 goto out; 344 goto out;
343 } 345 }
344 rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, 346 inode = __ecryptfs_get_inode(lower_inode, ecryptfs_dir_inode->i_sb);
345 ecryptfs_dir_inode->i_sb, 347 if (IS_ERR(inode)) {
346 ECRYPTFS_INTERPOSE_FLAG_D_ADD); 348 rc = PTR_ERR(inode);
347 if (rc) {
348 printk(KERN_ERR "%s: Error interposing; rc = [%d]\n", 349 printk(KERN_ERR "%s: Error interposing; rc = [%d]\n",
349 __func__, rc); 350 __func__, rc);
350 goto out; 351 goto out;
351 } 352 }
353 if (inode->i_state & I_NEW)
354 unlock_new_inode(inode);
355 d_add(ecryptfs_dentry, inode);
352 if (S_ISDIR(lower_inode->i_mode)) 356 if (S_ISDIR(lower_inode->i_mode))
353 goto out; 357 goto out;
354 if (S_ISLNK(lower_inode->i_mode)) 358 if (S_ISLNK(lower_inode->i_mode))
@@ -442,12 +446,12 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
442 goto out_d_drop; 446 goto out_d_drop;
443 } 447 }
444 if (lower_dentry->d_inode) 448 if (lower_dentry->d_inode)
445 goto lookup_and_interpose; 449 goto interpose;
446 mount_crypt_stat = &ecryptfs_superblock_to_private( 450 mount_crypt_stat = &ecryptfs_superblock_to_private(
447 ecryptfs_dentry->d_sb)->mount_crypt_stat; 451 ecryptfs_dentry->d_sb)->mount_crypt_stat;
448 if (!(mount_crypt_stat 452 if (!(mount_crypt_stat
449 && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) 453 && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)))
450 goto lookup_and_interpose; 454 goto interpose;
451 dput(lower_dentry); 455 dput(lower_dentry);
452 rc = ecryptfs_encrypt_and_encode_filename( 456 rc = ecryptfs_encrypt_and_encode_filename(
453 &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, 457 &encrypted_and_encoded_name, &encrypted_and_encoded_name_size,
@@ -470,9 +474,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
470 encrypted_and_encoded_name); 474 encrypted_and_encoded_name);
471 goto out_d_drop; 475 goto out_d_drop;
472 } 476 }
473lookup_and_interpose: 477interpose:
474 rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry, 478 rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry,
475 ecryptfs_dir_inode); 479 ecryptfs_dir_inode);
476 goto out; 480 goto out;
477out_d_drop: 481out_d_drop:
478 d_drop(ecryptfs_dentry); 482 d_drop(ecryptfs_dentry);
@@ -500,7 +504,7 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
500 lower_new_dentry); 504 lower_new_dentry);
501 if (rc || !lower_new_dentry->d_inode) 505 if (rc || !lower_new_dentry->d_inode)
502 goto out_lock; 506 goto out_lock;
503 rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0); 507 rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb);
504 if (rc) 508 if (rc)
505 goto out_lock; 509 goto out_lock;
506 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); 510 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
@@ -567,7 +571,7 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
567 kfree(encoded_symname); 571 kfree(encoded_symname);
568 if (rc || !lower_dentry->d_inode) 572 if (rc || !lower_dentry->d_inode)
569 goto out_lock; 573 goto out_lock;
570 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); 574 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
571 if (rc) 575 if (rc)
572 goto out_lock; 576 goto out_lock;
573 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); 577 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
@@ -591,7 +595,7 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
591 rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode); 595 rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
592 if (rc || !lower_dentry->d_inode) 596 if (rc || !lower_dentry->d_inode)
593 goto out; 597 goto out;
594 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); 598 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
595 if (rc) 599 if (rc)
596 goto out; 600 goto out;
597 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); 601 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
@@ -639,7 +643,7 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
639 rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev); 643 rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev);
640 if (rc || !lower_dentry->d_inode) 644 if (rc || !lower_dentry->d_inode)
641 goto out; 645 goto out;
642 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); 646 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
643 if (rc) 647 if (rc)
644 goto out; 648 goto out;
645 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); 649 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);