Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ceph: mark directory as non-complete after loading key

When setting a directory's crypt context, ceph_dir_clear_complete()
needs to be called otherwise if it was complete before, any existing
(old) dentry will still be valid.

This patch adds a wrapper around __fscrypt_prepare_readdir() which will
ensure a directory is marked as non-complete if key status changes.

[ xiubli: revise commit title per Milind ]

Signed-off-by: Luís Henriques <lhenriques@suse.de>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Milind Changire <mchangir@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

authored by

Luís Henriques and committed by
Ilya Dryomov
14e034a6 e127e030

+46 -9
+33 -2
fs/ceph/crypto.c
··· 287 287 if (fname->name_len > NAME_MAX || fname->ctext_len > NAME_MAX) 288 288 return -EIO; 289 289 290 - ret = __fscrypt_prepare_readdir(fname->dir); 291 - if (ret) 290 + ret = ceph_fscrypt_prepare_readdir(fname->dir); 291 + if (ret < 0) 292 292 return ret; 293 293 294 294 /* ··· 333 333 out: 334 334 fscrypt_fname_free_buffer(&_tname); 335 335 return ret; 336 + } 337 + 338 + /** 339 + * ceph_fscrypt_prepare_readdir - simple __fscrypt_prepare_readdir() wrapper 340 + * @dir: directory inode for readdir prep 341 + * 342 + * Simple wrapper around __fscrypt_prepare_readdir() that will mark directory as 343 + * non-complete if this call results in having the directory unlocked. 344 + * 345 + * Returns: 346 + * 1 - if directory was locked and key is now loaded (i.e. dir is unlocked) 347 + * 0 - if directory is still locked 348 + * < 0 - if __fscrypt_prepare_readdir() fails 349 + */ 350 + int ceph_fscrypt_prepare_readdir(struct inode *dir) 351 + { 352 + bool had_key = fscrypt_has_encryption_key(dir); 353 + int err; 354 + 355 + if (!IS_ENCRYPTED(dir)) 356 + return 0; 357 + 358 + err = __fscrypt_prepare_readdir(dir); 359 + if (err) 360 + return err; 361 + if (!had_key && fscrypt_has_encryption_key(dir)) { 362 + /* directory just got unlocked, mark it as not complete */ 363 + ceph_dir_clear_complete(dir); 364 + return 1; 365 + } 366 + return 0; 336 367 }
+6
fs/ceph/crypto.h
··· 103 103 104 104 int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname, 105 105 struct fscrypt_str *oname, bool *is_nokey); 106 + int ceph_fscrypt_prepare_readdir(struct inode *dir); 106 107 107 108 #else /* CONFIG_FS_ENCRYPTION */ 108 109 ··· 159 158 { 160 159 oname->name = fname->name; 161 160 oname->len = fname->name_len; 161 + return 0; 162 + } 163 + 164 + static inline int ceph_fscrypt_prepare_readdir(struct inode *dir) 165 + { 162 166 return 0; 163 167 } 164 168 #endif /* CONFIG_FS_ENCRYPTION */
+4 -4
fs/ceph/dir.c
··· 343 343 ctx->pos = 2; 344 344 } 345 345 346 - err = fscrypt_prepare_readdir(inode); 347 - if (err) 346 + err = ceph_fscrypt_prepare_readdir(inode); 347 + if (err < 0) 348 348 return err; 349 349 350 350 spin_lock(&ci->i_ceph_lock); ··· 785 785 return ERR_PTR(-ENAMETOOLONG); 786 786 787 787 if (IS_ENCRYPTED(dir)) { 788 - err = __fscrypt_prepare_readdir(dir); 789 - if (err) 788 + err = ceph_fscrypt_prepare_readdir(dir); 789 + if (err < 0) 790 790 return ERR_PTR(err); 791 791 if (!fscrypt_has_encryption_key(dir)) { 792 792 spin_lock(&dentry->d_lock);
+3 -3
fs/ceph/mds_client.c
··· 2545 2545 if (!IS_ENCRYPTED(dir)) 2546 2546 goto success; 2547 2547 2548 - ret = __fscrypt_prepare_readdir(dir); 2549 - if (ret) 2548 + ret = ceph_fscrypt_prepare_readdir(dir); 2549 + if (ret < 0) 2550 2550 return ERR_PTR(ret); 2551 2551 2552 2552 /* No key? Just ignore it. */ ··· 2666 2666 spin_unlock(&cur->d_lock); 2667 2667 parent = dget_parent(cur); 2668 2668 2669 - ret = __fscrypt_prepare_readdir(d_inode(parent)); 2669 + ret = ceph_fscrypt_prepare_readdir(d_inode(parent)); 2670 2670 if (ret < 0) { 2671 2671 dput(parent); 2672 2672 dput(cur);