ceph: switch ceph_lookup/atomic_open() to use new fscrypt helper
authorLuís Henriques <lhenriques@suse.de>
Thu, 16 Mar 2023 18:14:12 +0000 (18:14 +0000)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 24 Aug 2023 09:24:37 +0000 (11:24 +0200)
Instead of setting the no-key dentry, use the new
fscrypt_prepare_lookup_partial() helper.  We still need to mark the
directory as incomplete if the directory was just unlocked.

In ceph_atomic_open() this fixes a bug where a dentry is incorrectly
set with DCACHE_NOKEY_NAME when 'dir' has been evicted but the key is
still available (for example, where there's a drop_caches).

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>
fs/ceph/dir.c
fs/ceph/file.c

index 0e4f8e0..854cbdd 100644 (file)
@@ -785,14 +785,15 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
                return ERR_PTR(-ENAMETOOLONG);
 
        if (IS_ENCRYPTED(dir)) {
-               err = ceph_fscrypt_prepare_readdir(dir);
+               bool had_key = fscrypt_has_encryption_key(dir);
+
+               err = fscrypt_prepare_lookup_partial(dir, dentry);
                if (err < 0)
                        return ERR_PTR(err);
-               if (!fscrypt_has_encryption_key(dir)) {
-                       spin_lock(&dentry->d_lock);
-                       dentry->d_flags |= DCACHE_NOKEY_NAME;
-                       spin_unlock(&dentry->d_lock);
-               }
+
+               /* mark directory as incomplete if it has been unlocked */
+               if (!had_key && fscrypt_has_encryption_key(dir))
+                       ceph_dir_clear_complete(dir);
        }
 
        /* can we conclude ENOENT locally? */
index e587872..b1da02f 100644 (file)
@@ -791,11 +791,9 @@ retry:
        ihold(dir);
        if (IS_ENCRYPTED(dir)) {
                set_bit(CEPH_MDS_R_FSCRYPT_FILE, &req->r_req_flags);
-               if (!fscrypt_has_encryption_key(dir)) {
-                       spin_lock(&dentry->d_lock);
-                       dentry->d_flags |= DCACHE_NOKEY_NAME;
-                       spin_unlock(&dentry->d_lock);
-               }
+               err = fscrypt_prepare_lookup_partial(dir, dentry);
+               if (err < 0)
+                       goto out_req;
        }
 
        if (flags & O_CREAT) {