aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/inode.c
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>2011-04-14 16:35:11 -0400
committerTyler Hicks <tyhicks@linux.vnet.ibm.com>2011-04-25 19:32:37 -0400
commit332ab16f830f59e7621ae8eb2c353dc135a316f6 (patch)
treec5b249f34dcacf2aa5ee24de8d332d8171398203 /fs/ecryptfs/inode.c
parentdd55c89852481a0708c3fd4b48f3081f4280d9d3 (diff)
eCryptfs: Add reference counting to lower files
For any given lower inode, eCryptfs keeps only one lower file open and multiplexes all eCryptfs file operations through that lower file. The lower file was considered "persistent" and stayed open from the first lookup through the lifetime of the inode. This patch keeps the notion of a single, per-inode lower file, but adds reference counting around the lower file so that it is closed when not currently in use. If the reference count is at 0 when an operation (such as open, create, etc.) needs to use the lower file, a new lower file is opened. Since the file is no longer persistent, all references to the term persistent file are changed to lower file. Locking is added around the sections of code that opens the lower file and assign the pointer in the inode info, as well as the code the fputs the lower file when all eCryptfs users are done with it. This patch is needed to fix issues, when mounted on top of the NFSv3 client, where the lower file is left silly renamed until the eCryptfs inode is destroyed. Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r--fs/ecryptfs/inode.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 72d357649599..f6b388638c3d 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
168 "context; rc = [%d]\n", rc); 168 "context; rc = [%d]\n", rc);
169 goto out; 169 goto out;
170 } 170 }
171 rc = ecryptfs_init_persistent_file(ecryptfs_dentry); 171 rc = ecryptfs_get_lower_file(ecryptfs_dentry);
172 if (rc) { 172 if (rc) {
173 printk(KERN_ERR "%s: Error attempting to initialize " 173 printk(KERN_ERR "%s: Error attempting to initialize "
174 "the persistent file for the dentry with name " 174 "the lower file for the dentry with name "
175 "[%s]; rc = [%d]\n", __func__, 175 "[%s]; rc = [%d]\n", __func__,
176 ecryptfs_dentry->d_name.name, rc); 176 ecryptfs_dentry->d_name.name, rc);
177 goto out; 177 goto out;
178 } 178 }
179 rc = ecryptfs_write_metadata(ecryptfs_dentry); 179 rc = ecryptfs_write_metadata(ecryptfs_dentry);
180 if (rc) { 180 if (rc)
181 printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); 181 printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
182 goto out; 182 ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
183 }
184out: 183out:
185 return rc; 184 return rc;
186} 185}
@@ -230,7 +229,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
230 struct ecryptfs_crypt_stat *crypt_stat; 229 struct ecryptfs_crypt_stat *crypt_stat;
231 char *page_virt = NULL; 230 char *page_virt = NULL;
232 u64 file_size; 231 u64 file_size;
233 int rc = 0; 232 int put_lower = 0, rc = 0;
234 233
235 lower_dir_dentry = lower_dentry->d_parent; 234 lower_dir_dentry = lower_dentry->d_parent;
236 lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( 235 lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(
@@ -277,14 +276,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
277 rc = -ENOMEM; 276 rc = -ENOMEM;
278 goto out; 277 goto out;
279 } 278 }
280 rc = ecryptfs_init_persistent_file(ecryptfs_dentry); 279 rc = ecryptfs_get_lower_file(ecryptfs_dentry);
281 if (rc) { 280 if (rc) {
282 printk(KERN_ERR "%s: Error attempting to initialize " 281 printk(KERN_ERR "%s: Error attempting to initialize "
283 "the persistent file for the dentry with name " 282 "the lower file for the dentry with name "
284 "[%s]; rc = [%d]\n", __func__, 283 "[%s]; rc = [%d]\n", __func__,
285 ecryptfs_dentry->d_name.name, rc); 284 ecryptfs_dentry->d_name.name, rc);
286 goto out_free_kmem; 285 goto out_free_kmem;
287 } 286 }
287 put_lower = 1;
288 crypt_stat = &ecryptfs_inode_to_private( 288 crypt_stat = &ecryptfs_inode_to_private(
289 ecryptfs_dentry->d_inode)->crypt_stat; 289 ecryptfs_dentry->d_inode)->crypt_stat;
290 /* TODO: lock for crypt_stat comparison */ 290 /* TODO: lock for crypt_stat comparison */
@@ -322,6 +322,8 @@ out_put:
322 mntput(lower_mnt); 322 mntput(lower_mnt);
323 d_drop(ecryptfs_dentry); 323 d_drop(ecryptfs_dentry);
324out: 324out:
325 if (put_lower)
326 ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
325 return rc; 327 return rc;
326} 328}
327 329
@@ -757,8 +759,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
757 759
758 if (unlikely((ia->ia_size == i_size))) { 760 if (unlikely((ia->ia_size == i_size))) {
759 lower_ia->ia_valid &= ~ATTR_SIZE; 761 lower_ia->ia_valid &= ~ATTR_SIZE;
760 goto out; 762 return 0;
761 } 763 }
764 rc = ecryptfs_get_lower_file(dentry);
765 if (rc)
766 return rc;
762 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; 767 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
763 /* Switch on growing or shrinking file */ 768 /* Switch on growing or shrinking file */
764 if (ia->ia_size > i_size) { 769 if (ia->ia_size > i_size) {
@@ -836,6 +841,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
836 lower_ia->ia_valid &= ~ATTR_SIZE; 841 lower_ia->ia_valid &= ~ATTR_SIZE;
837 } 842 }
838out: 843out:
844 ecryptfs_put_lower_file(inode);
839 return rc; 845 return rc;
840} 846}
841 847
@@ -911,7 +917,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
911 917
912 mount_crypt_stat = &ecryptfs_superblock_to_private( 918 mount_crypt_stat = &ecryptfs_superblock_to_private(
913 dentry->d_sb)->mount_crypt_stat; 919 dentry->d_sb)->mount_crypt_stat;
920 rc = ecryptfs_get_lower_file(dentry);
921 if (rc) {
922 mutex_unlock(&crypt_stat->cs_mutex);
923 goto out;
924 }
914 rc = ecryptfs_read_metadata(dentry); 925 rc = ecryptfs_read_metadata(dentry);
926 ecryptfs_put_lower_file(inode);
915 if (rc) { 927 if (rc) {
916 if (!(mount_crypt_stat->flags 928 if (!(mount_crypt_stat->flags
917 & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { 929 & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {