]> git.apps.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>
Thu, 18 Aug 2022 04:56:05 +0000 (12:56 +0800)
committerXiubo Li <xiubli@redhat.com>
Fri, 26 Aug 2022 23:51:58 +0000 (07:51 +0800)
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 d5fc9b1be7c3525afd00c576b1ba1f374ca980c5..c615e7b6d5c700ef151c880a4d44da65bbf94ea3 100644 (file)
@@ -3547,7 +3547,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)) {
@@ -3917,7 +3917,8 @@ static bool handle_cap_trunc(struct inode *inode,
        dout("handle_cap_trunc inode %p mds%d seq %d to %lld seq %d\n",
             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 cfa0b550eef2fbab0d53e4a6f7dfacde32768315..2029953a1f1a7e15adf47c7653857b973fa1d2a4 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"
@@ -714,7 +715,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_inode_info *ci = ceph_inode(inode);
        int queue_trunc = 0;
@@ -742,10 +744,20 @@ int ceph_fill_file_size(struct inode *inode, int issued,
                        ci->i_truncate_seq = truncate_seq;
 
                        /* the MDS should have revoked these caps */
-                       WARN_ON_ONCE(issued & (CEPH_CAP_FILE_EXCL |
-                                              CEPH_CAP_FILE_RD |
-                                              CEPH_CAP_FILE_WR |
-                                              CEPH_CAP_FILE_LAZYIO));
+                       if (issued & (CEPH_CAP_FILE_EXCL |
+                                     CEPH_CAP_FILE_RD |
+                                     CEPH_CAP_FILE_WR |
+                                     CEPH_CAP_FILE_LAZYIO)) {
+                               pr_err("%s %p ino %llx.%llx already issued %s, newcaps %s\n",
+                                      __func__, inode, ceph_vinop(inode),
+                                      ceph_cap_string(issued),
+                                      ceph_cap_string(newcaps));
+                               pr_err(" truncate_seq %u -> %u\n",
+                                      ci->i_truncate_seq, truncate_seq);
+                               pr_err("  size %lld -> %llu\n", isize, size);
+                               msleep(1000);
+                               BUG();
+                       }
                        /*
                         * If we hold relevant caps, or in the case where we're
                         * not the only client referencing this file and we
@@ -1040,7 +1052,8 @@ 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),
-                                       le64_to_cpu(info->size));
+                                       le64_to_cpu(info->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 5ea0ac6450dde83420c48dd0d6121e4884bb5072..b15b455f7d1c5a7a108279717e47f4c5fbad2c93 100644 (file)
@@ -1003,7 +1003,8 @@ extern struct inode *ceph_get_inode(struct super_block *sb,
                                    struct ceph_vino vino, 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,