From: Xiubo Li Date: Thu, 18 Aug 2022 04:56:05 +0000 (+0800) Subject: [DO NOT MERGE] ceph: BUG if MDS changed truncate_seq with client caps still outstanding X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=20effa34c72a81b37476d7d1000c7bc3983dd460;p=ceph-client.git [DO NOT MERGE] ceph: BUG if MDS changed truncate_seq with client caps still outstanding 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 --- diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index d5fc9b1be7c35..c615e7b6d5c70 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -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; } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index cfa0b550eef2f..2029953a1f1a7 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -15,6 +15,7 @@ #include #include #include +#include #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)) { diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 5ea0ac6450dde..b15b455f7d1c5 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -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,