]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
ceph: size handling for encrypted inodes in cap updates
authorJeff Layton <jlayton@kernel.org>
Fri, 5 Nov 2021 14:22:08 +0000 (22:22 +0800)
committerJeff Layton <jlayton@kernel.org>
Tue, 31 May 2022 15:50:00 +0000 (11:50 -0400)
Transmit the rounded-up size as the normal size, and fill out the
fscrypt_file field with the real file size.

Reviewed-by: Xiubo Li <xiubli@redhat.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
fs/ceph/caps.c
fs/ceph/crypto.h

index 3ac38f74fcfcda3411ae304413bd42fed9eb0fc7..bf2575d5ebbff8c1e5889a8ca9138e823e1a5fc6 100644 (file)
@@ -1215,10 +1215,9 @@ struct cap_msg_args {
        umode_t                 mode;
        bool                    inline_data;
        bool                    wake;
+       bool                    encrypted;
        u32                     fscrypt_auth_len;
-       u32                     fscrypt_file_len;
        u8                      fscrypt_auth[sizeof(struct ceph_fscrypt_auth)]; // for context
-       u8                      fscrypt_file[sizeof(u64)]; // for size
 };
 
 /* Marshal up the cap msg to the MDS */
@@ -1253,7 +1252,12 @@ static void encode_cap_msg(struct ceph_msg *msg, struct cap_msg_args *arg)
        fc->ino = cpu_to_le64(arg->ino);
        fc->snap_follows = cpu_to_le64(arg->follows);
 
-       fc->size = cpu_to_le64(arg->size);
+#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
+       if (arg->encrypted)
+               fc->size = cpu_to_le64(round_up(arg->size, CEPH_FSCRYPT_BLOCK_SIZE));
+       else
+#endif
+               fc->size = cpu_to_le64(arg->size);
        fc->max_size = cpu_to_le64(arg->max_size);
        ceph_encode_timespec64(&fc->mtime, &arg->mtime);
        ceph_encode_timespec64(&fc->atime, &arg->atime);
@@ -1313,11 +1317,17 @@ static void encode_cap_msg(struct ceph_msg *msg, struct cap_msg_args *arg)
        ceph_encode_64(&p, 0);
 
 #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
-       /* fscrypt_auth and fscrypt_file (version 12) */
+       /*
+        * fscrypt_auth and fscrypt_file (version 12)
+        *
+        * fscrypt_auth holds the crypto context (if any). fscrypt_file
+        * tracks the real i_size as an __le64 field (and we use a rounded-up
+        * i_size in * the traditional size field).
+        */
        ceph_encode_32(&p, arg->fscrypt_auth_len);
        ceph_encode_copy(&p, arg->fscrypt_auth, arg->fscrypt_auth_len);
-       ceph_encode_32(&p, arg->fscrypt_file_len);
-       ceph_encode_copy(&p, arg->fscrypt_file, arg->fscrypt_file_len);
+       ceph_encode_32(&p, sizeof(__le64));
+       ceph_encode_64(&p, arg->size);
 #else /* CONFIG_FS_ENCRYPTION */
        ceph_encode_32(&p, 0);
        ceph_encode_32(&p, 0);
@@ -1389,7 +1399,6 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
        arg->follows = flushing ? ci->i_head_snapc->seq : 0;
        arg->flush_tid = flush_tid;
        arg->oldest_flush_tid = oldest_flush_tid;
-
        arg->size = i_size_read(inode);
        ci->i_reported_size = arg->size;
        arg->max_size = ci->i_wanted_max_size;
@@ -1443,6 +1452,7 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
                }
        }
        arg->flags = flags;
+       arg->encrypted = IS_ENCRYPTED(inode);
 #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
        if (ci->fscrypt_auth_len &&
            WARN_ON_ONCE(ci->fscrypt_auth_len > sizeof(struct ceph_fscrypt_auth))) {
@@ -1453,21 +1463,21 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
                memcpy(arg->fscrypt_auth, ci->fscrypt_auth,
                        min_t(size_t, ci->fscrypt_auth_len, sizeof(arg->fscrypt_auth)));
        }
-       /* FIXME: use this to track "real" size */
-       arg->fscrypt_file_len = 0;
 #endif /* CONFIG_FS_ENCRYPTION */
 }
 
+#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
 #define CAP_MSG_FIXED_FIELDS (sizeof(struct ceph_mds_caps) + \
-                     4 + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + 8 + 4 + 4)
+                     4 + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + 8 + 4 + 4 + 8)
 
-#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
 static inline int cap_msg_size(struct cap_msg_args *arg)
 {
-       return CAP_MSG_FIXED_FIELDS + arg->fscrypt_auth_len +
-                       arg->fscrypt_file_len;
+       return CAP_MSG_FIXED_FIELDS + arg->fscrypt_auth_len;
 }
 #else
+#define CAP_MSG_FIXED_FIELDS (sizeof(struct ceph_mds_caps) + \
+                     4 + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 8 + 8 + 4 + 8 + 8 + 4 + 4)
+
 static inline int cap_msg_size(struct cap_msg_args *arg)
 {
        return CAP_MSG_FIXED_FIELDS;
@@ -1546,13 +1556,10 @@ static inline int __send_flush_snap(struct inode *inode,
        arg.inline_data = capsnap->inline_data;
        arg.flags = 0;
        arg.wake = false;
+       arg.encrypted = IS_ENCRYPTED(inode);
 
-       /*
-        * No fscrypt_auth changes from a capsnap. It will need
-        * to update fscrypt_file on size changes (TODO).
-        */
+       /* No fscrypt_auth changes from a capsnap.*/
        arg.fscrypt_auth_len = 0;
-       arg.fscrypt_file_len = 0;
 
        msg = ceph_msg_new(CEPH_MSG_CLIENT_CAPS, cap_msg_size(&arg),
                           GFP_NOFS, false);
index 05db33f1a421595c015e1125611457b3d3ea6d75..918da2be41655d7d37b953ac0ba16280b387f631 100644 (file)
@@ -9,6 +9,10 @@
 #include <crypto/sha2.h>
 #include <linux/fscrypt.h>
 
+#define CEPH_FSCRYPT_BLOCK_SHIFT   12
+#define CEPH_FSCRYPT_BLOCK_SIZE    (_AC(1, UL) << CEPH_FSCRYPT_BLOCK_SHIFT)
+#define CEPH_FSCRYPT_BLOCK_MASK           (~(CEPH_FSCRYPT_BLOCK_SIZE-1))
+
 struct ceph_fs_client;
 struct ceph_acl_sec_ctx;
 struct ceph_mds_request;