diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-10-16 04:28:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:12 -0400 |
commit | 4981e081cfe2c3f4abcfa3924ebd999cdbed4914 (patch) | |
tree | 066d56ba49195eb0e733236fef4bb98f2d5f0114 | |
parent | 0216f7f7921759211e48e8b940eae29f0fe43902 (diff) |
eCryptfs: set up and destroy persistent lower file
This patch sets up and destroys the persistent lower file for each eCryptfs
inode.
Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/ecryptfs/inode.c | 23 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 65 | ||||
-rw-r--r-- | fs/ecryptfs/super.c | 22 |
3 files changed, 103 insertions, 7 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 7192a810bbe6..c746b5d8a336 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -119,10 +119,23 @@ ecryptfs_do_create(struct inode *directory_inode, | |||
119 | } | 119 | } |
120 | rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode, | 120 | rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode, |
121 | ecryptfs_dentry, mode, nd); | 121 | ecryptfs_dentry, mode, nd); |
122 | if (unlikely(rc)) { | 122 | if (rc) { |
123 | ecryptfs_printk(KERN_ERR, | 123 | struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; |
124 | "Failure to create underlying file\n"); | 124 | struct ecryptfs_inode_info *inode_info = |
125 | goto out_lock; | 125 | ecryptfs_inode_to_private(ecryptfs_inode); |
126 | |||
127 | printk(KERN_WARNING "%s: Error creating underlying file; " | ||
128 | "rc = [%d]; checking for existing\n", __FUNCTION__, rc); | ||
129 | if (inode_info) { | ||
130 | mutex_lock(&inode_info->lower_file_mutex); | ||
131 | if (!inode_info->lower_file) { | ||
132 | mutex_unlock(&inode_info->lower_file_mutex); | ||
133 | printk(KERN_ERR "%s: Failure to set underlying " | ||
134 | "file; rc = [%d]\n", __FUNCTION__, rc); | ||
135 | goto out_lock; | ||
136 | } | ||
137 | mutex_unlock(&inode_info->lower_file_mutex); | ||
138 | } | ||
126 | } | 139 | } |
127 | rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, | 140 | rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, |
128 | directory_inode->i_sb, 0); | 141 | directory_inode->i_sb, 0); |
@@ -252,6 +265,8 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, | |||
252 | { | 265 | { |
253 | int rc; | 266 | int rc; |
254 | 267 | ||
268 | /* ecryptfs_do_create() calls ecryptfs_interpose(), which opens | ||
269 | * the crypt_stat->lower_file (persistent file) */ | ||
255 | rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode, nd); | 270 | rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode, nd); |
256 | if (unlikely(rc)) { | 271 | if (unlikely(rc)) { |
257 | ecryptfs_printk(KERN_WARNING, "Failed to create file in" | 272 | ecryptfs_printk(KERN_WARNING, "Failed to create file in" |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 49545951912f..fb9d85b5c7b8 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -99,6 +99,64 @@ void __ecryptfs_printk(const char *fmt, ...) | |||
99 | } | 99 | } |
100 | 100 | ||
101 | /** | 101 | /** |
102 | * ecryptfs_init_persistent_file | ||
103 | * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with | ||
104 | * the lower dentry and the lower mount set | ||
105 | * | ||
106 | * eCryptfs only ever keeps a single open file for every lower | ||
107 | * inode. All I/O operations to the lower inode occur through that | ||
108 | * file. When the first eCryptfs dentry that interposes with the first | ||
109 | * lower dentry for that inode is created, this function creates the | ||
110 | * persistent file struct and associates it with the eCryptfs | ||
111 | * inode. When the eCryptfs inode is destroyed, the file is closed. | ||
112 | * | ||
113 | * The persistent file will be opened with read/write permissions, if | ||
114 | * possible. Otherwise, it is opened read-only. | ||
115 | * | ||
116 | * This function does nothing if a lower persistent file is already | ||
117 | * associated with the eCryptfs inode. | ||
118 | * | ||
119 | * Returns zero on success; non-zero otherwise | ||
120 | */ | ||
121 | int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | ||
122 | { | ||
123 | struct ecryptfs_inode_info *inode_info = | ||
124 | ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); | ||
125 | int rc = 0; | ||
126 | |||
127 | mutex_lock(&inode_info->lower_file_mutex); | ||
128 | if (!inode_info->lower_file) { | ||
129 | struct dentry *lower_dentry; | ||
130 | struct vfsmount *lower_mnt = | ||
131 | ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); | ||
132 | |||
133 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); | ||
134 | /* Corresponding dput() and mntput() are done when the | ||
135 | * persistent file is fput() when the eCryptfs inode | ||
136 | * is destroyed. */ | ||
137 | dget(lower_dentry); | ||
138 | mntget(lower_mnt); | ||
139 | inode_info->lower_file = dentry_open(lower_dentry, | ||
140 | lower_mnt, | ||
141 | (O_RDWR | O_LARGEFILE)); | ||
142 | if (IS_ERR(inode_info->lower_file)) | ||
143 | inode_info->lower_file = dentry_open(lower_dentry, | ||
144 | lower_mnt, | ||
145 | (O_RDONLY | ||
146 | | O_LARGEFILE)); | ||
147 | if (IS_ERR(inode_info->lower_file)) { | ||
148 | printk(KERN_ERR "Error opening lower persistent file " | ||
149 | "for lower_dentry [0x%p] and lower_mnt [0x%p]\n", | ||
150 | lower_dentry, lower_mnt); | ||
151 | rc = PTR_ERR(inode_info->lower_file); | ||
152 | inode_info->lower_file = NULL; | ||
153 | } | ||
154 | } | ||
155 | mutex_unlock(&inode_info->lower_file_mutex); | ||
156 | return rc; | ||
157 | } | ||
158 | |||
159 | /** | ||
102 | * ecryptfs_interpose | 160 | * ecryptfs_interpose |
103 | * @lower_dentry: Existing dentry in the lower filesystem | 161 | * @lower_dentry: Existing dentry in the lower filesystem |
104 | * @dentry: ecryptfs' dentry | 162 | * @dentry: ecryptfs' dentry |
@@ -155,6 +213,13 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, | |||
155 | /* This size will be overwritten for real files w/ headers and | 213 | /* This size will be overwritten for real files w/ headers and |
156 | * other metadata */ | 214 | * other metadata */ |
157 | fsstack_copy_inode_size(inode, lower_inode); | 215 | fsstack_copy_inode_size(inode, lower_inode); |
216 | rc = ecryptfs_init_persistent_file(dentry); | ||
217 | if (rc) { | ||
218 | printk(KERN_ERR "%s: Error attempting to initialize the " | ||
219 | "persistent file for the dentry with name [%s]; " | ||
220 | "rc = [%d]\n", __FUNCTION__, dentry->d_name.name, rc); | ||
221 | goto out; | ||
222 | } | ||
158 | out: | 223 | out: |
159 | return rc; | 224 | return rc; |
160 | } | 225 | } |
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 18d77f8aa7cd..b97e2106f670 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
28 | #include <linux/key.h> | 28 | #include <linux/key.h> |
29 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
30 | #include <linux/file.h> | ||
30 | #include <linux/crypto.h> | 31 | #include <linux/crypto.h> |
31 | #include "ecryptfs_kernel.h" | 32 | #include "ecryptfs_kernel.h" |
32 | 33 | ||
@@ -63,9 +64,10 @@ out: | |||
63 | * ecryptfs_destroy_inode | 64 | * ecryptfs_destroy_inode |
64 | * @inode: The ecryptfs inode | 65 | * @inode: The ecryptfs inode |
65 | * | 66 | * |
66 | * This is used during the final destruction of the inode. | 67 | * This is used during the final destruction of the inode. All |
67 | * All allocation of memory related to the inode, including allocated | 68 | * allocation of memory related to the inode, including allocated |
68 | * memory in the crypt_stat struct, will be released here. | 69 | * memory in the crypt_stat struct, will be released here. This |
70 | * function also fput()'s the persistent file for the lower inode. | ||
69 | * There should be no chance that this deallocation will be missed. | 71 | * There should be no chance that this deallocation will be missed. |
70 | */ | 72 | */ |
71 | static void ecryptfs_destroy_inode(struct inode *inode) | 73 | static void ecryptfs_destroy_inode(struct inode *inode) |
@@ -73,6 +75,20 @@ static void ecryptfs_destroy_inode(struct inode *inode) | |||
73 | struct ecryptfs_inode_info *inode_info; | 75 | struct ecryptfs_inode_info *inode_info; |
74 | 76 | ||
75 | inode_info = ecryptfs_inode_to_private(inode); | 77 | inode_info = ecryptfs_inode_to_private(inode); |
78 | mutex_lock(&inode_info->lower_file_mutex); | ||
79 | if (inode_info->lower_file) { | ||
80 | struct dentry *lower_dentry = | ||
81 | inode_info->lower_file->f_dentry; | ||
82 | |||
83 | BUG_ON(!lower_dentry); | ||
84 | if (lower_dentry->d_inode) { | ||
85 | fput(inode_info->lower_file); | ||
86 | inode_info->lower_file = NULL; | ||
87 | d_drop(lower_dentry); | ||
88 | d_delete(lower_dentry); | ||
89 | } | ||
90 | } | ||
91 | mutex_unlock(&inode_info->lower_file_mutex); | ||
76 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); | 92 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); |
77 | kmem_cache_free(ecryptfs_inode_info_cache, inode_info); | 93 | kmem_cache_free(ecryptfs_inode_info_cache, inode_info); |
78 | } | 94 | } |