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>

+93 -60
+4 -1
fs/ecryptfs/ecryptfs_kernel.h
··· 295 295 struct ecryptfs_inode_info { 296 296 struct inode vfs_inode; 297 297 struct inode *wii_inode; 298 + struct mutex lower_file_mutex; 299 + atomic_t lower_file_count; 298 300 struct file *lower_file; 299 301 struct ecryptfs_crypt_stat crypt_stat; 300 302 }; ··· 759 757 struct dentry *lower_dentry, 760 758 struct vfsmount *lower_mnt, 761 759 const struct cred *cred); 762 - int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry); 760 + int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry); 761 + void ecryptfs_put_lower_file(struct inode *inode); 763 762 int 764 763 ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, 765 764 size_t *packet_size,
+10 -12
fs/ecryptfs/file.c
··· 191 191 | ECRYPTFS_ENCRYPTED); 192 192 } 193 193 mutex_unlock(&crypt_stat->cs_mutex); 194 - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); 194 + rc = ecryptfs_get_lower_file(ecryptfs_dentry); 195 195 if (rc) { 196 196 printk(KERN_ERR "%s: Error attempting to initialize " 197 - "the persistent file for the dentry with name " 197 + "the lower file for the dentry with name " 198 198 "[%s]; rc = [%d]\n", __func__, 199 199 ecryptfs_dentry->d_name.name, rc); 200 200 goto out_free; ··· 202 202 if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) 203 203 == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { 204 204 rc = -EPERM; 205 - printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " 205 + printk(KERN_WARNING "%s: Lower file is RO; eCryptfs " 206 206 "file must hence be opened RO\n", __func__); 207 - goto out_free; 207 + goto out_put; 208 208 } 209 209 ecryptfs_set_file_lower( 210 210 file, ecryptfs_inode_to_private(inode)->lower_file); ··· 232 232 "Plaintext passthrough mode is not " 233 233 "enabled; returning -EIO\n"); 234 234 mutex_unlock(&crypt_stat->cs_mutex); 235 - goto out_free; 235 + goto out_put; 236 236 } 237 237 rc = 0; 238 238 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); ··· 245 245 "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, 246 246 (unsigned long long)i_size_read(inode)); 247 247 goto out; 248 + out_put: 249 + ecryptfs_put_lower_file(inode); 248 250 out_free: 249 251 kmem_cache_free(ecryptfs_file_info_cache, 250 252 ecryptfs_file_to_private(file)); ··· 256 254 257 255 static int ecryptfs_flush(struct file *file, fl_owner_t td) 258 256 { 259 - int rc = 0; 260 - struct file *lower_file = NULL; 261 - 262 - lower_file = ecryptfs_file_to_lower(file); 263 - if (lower_file->f_op && lower_file->f_op->flush) 264 - rc = lower_file->f_op->flush(lower_file, td); 265 - return rc; 257 + return file->f_mode & FMODE_WRITE 258 + ? filemap_write_and_wait(file->f_mapping) : 0; 266 259 } 267 260 268 261 static int ecryptfs_release(struct inode *inode, struct file *file) 269 262 { 263 + ecryptfs_put_lower_file(inode); 270 264 kmem_cache_free(ecryptfs_file_info_cache, 271 265 ecryptfs_file_to_private(file)); 272 266 return 0;
+21 -9
fs/ecryptfs/inode.c
··· 168 168 "context; rc = [%d]\n", rc); 169 169 goto out; 170 170 } 171 - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); 171 + rc = ecryptfs_get_lower_file(ecryptfs_dentry); 172 172 if (rc) { 173 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 175 "[%s]; rc = [%d]\n", __func__, 176 176 ecryptfs_dentry->d_name.name, rc); 177 177 goto out; 178 178 } 179 179 rc = ecryptfs_write_metadata(ecryptfs_dentry); 180 - if (rc) { 180 + if (rc) 181 181 printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); 182 - goto out; 183 - } 182 + ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); 184 183 out: 185 184 return rc; 186 185 } ··· 229 230 struct ecryptfs_crypt_stat *crypt_stat; 230 231 char *page_virt = NULL; 231 232 u64 file_size; 232 - int rc = 0; 233 + int put_lower = 0, rc = 0; 233 234 234 235 lower_dir_dentry = lower_dentry->d_parent; 235 236 lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( ··· 276 277 rc = -ENOMEM; 277 278 goto out; 278 279 } 279 - rc = ecryptfs_init_persistent_file(ecryptfs_dentry); 280 + rc = ecryptfs_get_lower_file(ecryptfs_dentry); 280 281 if (rc) { 281 282 printk(KERN_ERR "%s: Error attempting to initialize " 282 - "the persistent file for the dentry with name " 283 + "the lower file for the dentry with name " 283 284 "[%s]; rc = [%d]\n", __func__, 284 285 ecryptfs_dentry->d_name.name, rc); 285 286 goto out_free_kmem; 286 287 } 288 + put_lower = 1; 287 289 crypt_stat = &ecryptfs_inode_to_private( 288 290 ecryptfs_dentry->d_inode)->crypt_stat; 289 291 /* TODO: lock for crypt_stat comparison */ ··· 322 322 mntput(lower_mnt); 323 323 d_drop(ecryptfs_dentry); 324 324 out: 325 + if (put_lower) 326 + ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); 325 327 return rc; 326 328 } 327 329 ··· 759 757 760 758 if (unlikely((ia->ia_size == i_size))) { 761 759 lower_ia->ia_valid &= ~ATTR_SIZE; 762 - goto out; 760 + return 0; 763 761 } 762 + rc = ecryptfs_get_lower_file(dentry); 763 + if (rc) 764 + return rc; 764 765 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; 765 766 /* Switch on growing or shrinking file */ 766 767 if (ia->ia_size > i_size) { ··· 841 836 lower_ia->ia_valid &= ~ATTR_SIZE; 842 837 } 843 838 out: 839 + ecryptfs_put_lower_file(inode); 844 840 return rc; 845 841 } 846 842 ··· 917 911 918 912 mount_crypt_stat = &ecryptfs_superblock_to_private( 919 913 dentry->d_sb)->mount_crypt_stat; 914 + rc = ecryptfs_get_lower_file(dentry); 915 + if (rc) { 916 + mutex_unlock(&crypt_stat->cs_mutex); 917 + goto out; 918 + } 920 919 rc = ecryptfs_read_metadata(dentry); 920 + ecryptfs_put_lower_file(inode); 921 921 if (rc) { 922 922 if (!(mount_crypt_stat->flags 923 923 & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
+3 -3
fs/ecryptfs/kthread.c
··· 44 44 * @ignored: ignored 45 45 * 46 46 * The eCryptfs kernel thread that has the responsibility of getting 47 - * the lower persistent file with RW permissions. 47 + * the lower file with RW permissions. 48 48 * 49 49 * Returns zero on success; non-zero otherwise 50 50 */ ··· 141 141 int rc = 0; 142 142 143 143 /* Corresponding dput() and mntput() are done when the 144 - * persistent file is fput() when the eCryptfs inode is 145 - * destroyed. */ 144 + * lower file is fput() when all eCryptfs files for the inode are 145 + * released. */ 146 146 dget(lower_dentry); 147 147 mntget(lower_mnt); 148 148 flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
+51 -23
fs/ecryptfs/main.c
··· 96 96 } 97 97 98 98 /** 99 - * ecryptfs_init_persistent_file 99 + * ecryptfs_init_lower_file 100 100 * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with 101 101 * the lower dentry and the lower mount set 102 102 * ··· 104 104 * inode. All I/O operations to the lower inode occur through that 105 105 * file. When the first eCryptfs dentry that interposes with the first 106 106 * lower dentry for that inode is created, this function creates the 107 - * persistent file struct and associates it with the eCryptfs 108 - * inode. When the eCryptfs inode is destroyed, the file is closed. 107 + * lower file struct and associates it with the eCryptfs 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 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 115 * associated with the eCryptfs inode. 115 116 * 116 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 122 const struct cred *cred = current_cred(); 121 - struct ecryptfs_inode_info *inode_info = 122 - ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); 123 - int rc = 0; 123 + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 124 + struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); 125 + int rc; 124 126 125 - if (!inode_info->lower_file) { 126 - struct dentry *lower_dentry; 127 - struct vfsmount *lower_mnt = 128 - ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); 129 - 130 - lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 131 - rc = ecryptfs_privileged_open(&inode_info->lower_file, 132 - lower_dentry, lower_mnt, cred); 133 - if (rc) { 134 - printk(KERN_ERR "Error opening lower persistent file " 135 - "for lower_dentry [0x%p] and lower_mnt [0x%p]; " 136 - "rc = [%d]\n", lower_dentry, lower_mnt, rc); 137 - inode_info->lower_file = NULL; 138 - } 127 + rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt, 128 + cred); 129 + if (rc) { 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; 139 134 } 140 135 return rc; 136 + } 137 + 138 + int ecryptfs_get_lower_file(struct dentry *dentry) 139 + { 140 + struct ecryptfs_inode_info *inode_info = 141 + ecryptfs_inode_to_private(dentry->d_inode); 142 + int count, rc = 0; 143 + 144 + mutex_lock(&inode_info->lower_file_mutex); 145 + count = atomic_inc_return(&inode_info->lower_file_count); 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); 153 + } 154 + mutex_unlock(&inode_info->lower_file_mutex); 155 + return rc; 156 + } 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 + } 141 169 } 142 170 143 171 static struct inode *ecryptfs_get_inode(struct inode *lower_inode,
+4 -12
fs/ecryptfs/super.c
··· 55 55 if (unlikely(!inode_info)) 56 56 goto out; 57 57 ecryptfs_init_crypt_stat(&inode_info->crypt_stat); 58 + mutex_init(&inode_info->lower_file_mutex); 59 + atomic_set(&inode_info->lower_file_count, 0); 58 60 inode_info->lower_file = NULL; 59 61 inode = &inode_info->vfs_inode; 60 62 out: ··· 79 77 * 80 78 * This is used during the final destruction of the inode. All 81 79 * allocation of memory related to the inode, including allocated 82 - * memory in the crypt_stat struct, will be released here. This 83 - * function also fput()'s the persistent file for the lower inode. 80 + * memory in the crypt_stat struct, will be released here. 84 81 * There should be no chance that this deallocation will be missed. 85 82 */ 86 83 static void ecryptfs_destroy_inode(struct inode *inode) ··· 87 86 struct ecryptfs_inode_info *inode_info; 88 87 89 88 inode_info = ecryptfs_inode_to_private(inode); 90 - if (inode_info->lower_file) { 91 - struct dentry *lower_dentry = 92 - inode_info->lower_file->f_dentry; 93 - 94 - BUG_ON(!lower_dentry); 95 - if (lower_dentry->d_inode) { 96 - fput(inode_info->lower_file); 97 - inode_info->lower_file = NULL; 98 - } 99 - } 89 + BUG_ON(inode_info->lower_file); 100 90 ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); 101 91 call_rcu(&inode->i_rcu, ecryptfs_i_callback); 102 92 }