]> 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>
Wed, 11 Feb 2026 18:19:15 +0000 (19:19 +0100)
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 71b784a9d97e3979f276bac94f0a65a427689ede..5f5e763dad2e50c840f3e213a4c8ec536a8175a3 100644 (file)
@@ -3657,7 +3657,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)) {
@@ -4057,7 +4057,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 4af3866a886885456d1c2ccbbce347311c0bbd60..5f56c5d242454a189ccd932d3ee56275363b28cc 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"
@@ -803,7 +804,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);
@@ -827,13 +829,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
@@ -1163,7 +1174,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 df2cecccf413fc0b825e01c539b7a389eed4f959..18f8e5d35143fa177cfc0e1ced923d478c32463b 100644 (file)
@@ -1070,7 +1070,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,