aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/main.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/main.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/main.c')
-rw-r--r--fs/ecryptfs/main.c72
1 files changed, 50 insertions, 22 deletions
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index fdb2eb0ad09e..89b93389af8e 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...)
96} 96}
97 97
98/** 98/**
99 * ecryptfs_init_persistent_file 99 * ecryptfs_init_lower_file
100 * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with 100 * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with
101 * the lower dentry and the lower mount set 101 * the lower dentry and the lower mount set
102 * 102 *
@@ -104,42 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...)
104 * inode. All I/O operations to the lower inode occur through that 104 * inode. All I/O operations to the lower inode occur through that
105 * file. When the first eCryptfs dentry that interposes with the first 105 * file. When the first eCryptfs dentry that interposes with the first
106 * lower dentry for that inode is created, this function creates the 106 * lower dentry for that inode is created, this function creates the
107 * persistent file struct and associates it with the eCryptfs 107 * lower file struct and associates it with the eCryptfs
108 * inode. When the eCryptfs inode is destroyed, the file is closed. 108 * inode. When all eCryptfs files associated with the inode are released, the
109 * file is closed.
109 * 110 *
110 * The persistent file will be opened with read/write permissions, if 111 * The lower file will be opened with read/write permissions, if
111 * possible. Otherwise, it is opened read-only. 112 * possible. Otherwise, it is opened read-only.
112 * 113 *
113 * This function does nothing if a lower persistent file is already 114 * This function does nothing if a lower file is already
114 * associated with the eCryptfs inode. 115 * associated with the eCryptfs inode.
115 * 116 *
116 * Returns zero on success; non-zero otherwise 117 * Returns zero on success; non-zero otherwise
117 */ 118 */
118int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) 119static int ecryptfs_init_lower_file(struct dentry *dentry,
120 struct file **lower_file)
119{ 121{
120 const struct cred *cred = current_cred(); 122 const struct cred *cred = current_cred();
121 struct ecryptfs_inode_info *inode_info = 123 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
122 ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); 124 struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
123 int rc = 0; 125 int rc;
124 126
125 if (!inode_info->lower_file) { 127 rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt,
126 struct dentry *lower_dentry; 128 cred);
127 struct vfsmount *lower_mnt = 129 if (rc) {
128 ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); 130 printk(KERN_ERR "Error opening lower file "
131 "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
132 "rc = [%d]\n", lower_dentry, lower_mnt, rc);
133 (*lower_file) = NULL;
134 }
135 return rc;
136}
129 137
130 lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 138int ecryptfs_get_lower_file(struct dentry *dentry)
131 rc = ecryptfs_privileged_open(&inode_info->lower_file, 139{
132 lower_dentry, lower_mnt, cred); 140 struct ecryptfs_inode_info *inode_info =
133 if (rc) { 141 ecryptfs_inode_to_private(dentry->d_inode);
134 printk(KERN_ERR "Error opening lower persistent file " 142 int count, rc = 0;
135 "for lower_dentry [0x%p] and lower_mnt [0x%p]; " 143
136 "rc = [%d]\n", lower_dentry, lower_mnt, rc); 144 mutex_lock(&inode_info->lower_file_mutex);
137 inode_info->lower_file = NULL; 145 count = atomic_inc_return(&inode_info->lower_file_count);
138 } 146 if (WARN_ON_ONCE(count < 1))
147 rc = -EINVAL;
148 else if (count == 1) {
149 rc = ecryptfs_init_lower_file(dentry,
150 &inode_info->lower_file);
151 if (rc)
152 atomic_set(&inode_info->lower_file_count, 0);
139 } 153 }
154 mutex_unlock(&inode_info->lower_file_mutex);
140 return rc; 155 return rc;
141} 156}
142 157
158void ecryptfs_put_lower_file(struct inode *inode)
159{
160 struct ecryptfs_inode_info *inode_info;
161
162 inode_info = ecryptfs_inode_to_private(inode);
163 if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
164 &inode_info->lower_file_mutex)) {
165 fput(inode_info->lower_file);
166 inode_info->lower_file = NULL;
167 mutex_unlock(&inode_info->lower_file_mutex);
168 }
169}
170
143static struct inode *ecryptfs_get_inode(struct inode *lower_inode, 171static struct inode *ecryptfs_get_inode(struct inode *lower_inode,
144 struct super_block *sb) 172 struct super_block *sb)
145{ 173{