]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
[DO NOT MERGE] ceph: BUG if MDS changed truncate_seq with client caps still outstanding
authorXiubo Li <xiubli@redhat.com>
Fri, 3 Feb 2023 01:58:29 +0000 (09:58 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Fri, 6 Jun 2025 09:12:28 +0000 (11:12 +0200)
We need to trigger to crash the kernel and fail the qa tests to
get more infomation about the bug.

URL: https://tracker.ceph.com/issues/56693
Signed-off-by: Xiubo Li <xiubli@redhat.com>
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/super.h

index 5e7c9bd4dfa2c023099056c9aedaad4ef05eafef..8d49df60f442d9ca32b72b5b3bafee7597976942 100644 (file)
@@ -3656,7 +3656,7 @@ static void handle_cap_grant(struct inode *inode,
                queue_trunc = ceph_fill_file_size(inode, extra_info->issued,
                                        le32_to_cpu(grant->truncate_seq),
                                        le64_to_cpu(grant->truncate_size),
-                                       size);
+                                       size, newcaps);
        }
 
        if (ci->i_auth_cap == cap && (newcaps & CEPH_CAP_ANY_FILE_WR)) {
@@ -4056,7 +4056,8 @@ static bool handle_cap_trunc(struct inode *inode,
        doutc(cl, "%p %llx.%llx mds%d seq %d to %lld truncate seq %d\n",
              inode, ceph_vinop(inode), mds, seq, truncate_size, truncate_seq);
        queue_trunc = ceph_fill_file_size(inode, issued,
-                                         truncate_seq, truncate_size, size);
+                                         truncate_seq, truncate_size,
+                                         size, 0);
        return queue_trunc;
 }
 
index c46fa6ed11c19c5a24ba4bceb8ae00649458c4cd..130bb3d66be666b543dd2362fabe10097aa98387 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sort.h>
 #include <linux/iversion.h>
 #include <linux/fscrypt.h>
+#include <linux/delay.h>
 
 #include "super.h"
 #include "mds_client.h"
@@ -756,7 +757,8 @@ static inline blkcnt_t calc_inode_blocks(u64 size)
  * truncate() increments the corresponding _seq values.)
  */
 int ceph_fill_file_size(struct inode *inode, int issued,
-                       u32 truncate_seq, u64 truncate_size, u64 size)
+                       u32 truncate_seq, u64 truncate_size,
+                       u64 size, int newcaps)
 {
        struct ceph_client *cl = ceph_inode_to_client(inode);
        struct ceph_inode_info *ci = ceph_inode(inode);
@@ -780,13 +782,22 @@ int ceph_fill_file_size(struct inode *inode, int issued,
                        ceph_fscache_update(inode);
                ci->i_reported_size = size;
                if (truncate_seq != ci->i_truncate_seq) {
+                       /* the MDS should have revoked these caps */
+                       if (issued & (CEPH_CAP_FILE_RD |
+                                     CEPH_CAP_FILE_LAZYIO)) {
+                               pr_err_client(cl, "%p ino %llx.%llx already issued %s, newcaps %s\n",
+                                             inode, ceph_vinop(inode),
+                                             ceph_cap_string(issued),
+                                             ceph_cap_string(newcaps));
+                               pr_err_client(cl, " truncate_seq %u -> %u\n",
+                                             ci->i_truncate_seq, truncate_seq);
+                               pr_err_client(cl, "  size %lld -> %llu\n", isize, size);
+                               WARN_ON(1);
+                       }
                        doutc(cl, "truncate_seq %u -> %u\n",
                              ci->i_truncate_seq, truncate_seq);
                        ci->i_truncate_seq = truncate_seq;
 
-                       /* the MDS should have revoked these caps */
-                       WARN_ON_ONCE(issued & (CEPH_CAP_FILE_RD |
-                                              CEPH_CAP_FILE_LAZYIO));
                        /*
                         * If we hold relevant caps, or in the case where we're
                         * not the only client referencing this file and we
@@ -1127,7 +1138,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
                queue_trunc = ceph_fill_file_size(inode, issued,
                                        le32_to_cpu(info->truncate_seq),
                                        le64_to_cpu(info->truncate_size),
-                                       size);
+                                       size, info_caps);
                /* only update max_size on auth cap */
                if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) &&
                    ci->i_max_size != le64_to_cpu(info->max_size)) {
index 4a54fc273ec1d51d14747f08dfce610aad66b0a3..0dfe5557de91a8dffc93aa91bfb0129373036ee7 100644 (file)
@@ -1042,7 +1042,8 @@ extern struct inode *ceph_get_inode(struct super_block *sb,
                                    struct inode *newino);
 extern struct inode *ceph_get_snapdir(struct inode *parent);
 extern int ceph_fill_file_size(struct inode *inode, int issued,
-                              u32 truncate_seq, u64 truncate_size, u64 size);
+                              u32 truncate_seq, u64 truncate_size,
+                              u64 size, int newcaps);
 extern void ceph_fill_file_time(struct inode *inode, int issued,
                                u64 time_warp_seq, struct timespec64 *ctime,
                                struct timespec64 *mtime,