diff options
Diffstat (limited to 'fs/ecryptfs/main.c')
| -rw-r--r-- | fs/ecryptfs/main.c | 72 |
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 | */ |
| 118 | int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | 119 | static 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); | 138 | int 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 | ||
| 158 | void 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 | |||
| 143 | static struct inode *ecryptfs_get_inode(struct inode *lower_inode, | 171 | static struct inode *ecryptfs_get_inode(struct inode *lower_inode, |
| 144 | struct super_block *sb) | 172 | struct super_block *sb) |
| 145 | { | 173 | { |
