From: Xiubo Li Date: Fri, 3 Feb 2023 01:58:29 +0000 (+0800) Subject: [DO NOT MERGE] ceph: BUG if MDS changed truncate_seq with client caps still outstanding X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=355f85036f610a08803406ba678363a5926bb4d5;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 d26edff6dd75..1a4ce8ffcf1c 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -3653,7 +3653,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)) { @@ -4048,7 +4048,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; } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 23057c3fd31e..3030136b0a61 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" @@ -755,7 +756,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); @@ -779,13 +781,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 @@ -1126,7 +1137,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)) { diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 7eedf4d8a6db..b0b368ed3018 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -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,