aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/main.c
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2011-05-19 04:51:57 -0400
committerJames Morris <jmorris@namei.org>2011-05-19 04:51:57 -0400
commit12a5a2621b1ee14d32beca35304d7c6076a58815 (patch)
tree213e13f99de690b3c4a510f504393b63ada626bd /fs/ecryptfs/main.c
parente77dc3460fa59be5759e9327ad882868eee9d61b (diff)
parent61c4f2c81c61f73549928dfd9f3e8f26aa36a8cf (diff)
Merge branch 'master' into next
Conflicts: include/linux/capability.h Manually resolve merge conflict w/ thanks to Stephen Rothwell. Signed-off-by: James Morris <jmorris@namei.org>
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{