From ee2c628f6783954e9b25fab8ac9b572a58666a91 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 26 Apr 2018 15:12:48 +0800 Subject: [PATCH] mds: include nfiles/nsubdirs of directory inode in MClientCaps Directory inode's dirstat gets updated by request reply, but not by cap message. This causes problem for following case. 1. MDS modifies a directory 2. MDS issues CEPH_CAP_ANY_SHARED to client 3. The client satifies stat(2) by its cached metadata. Signed-off-by: "Yan, Zheng" Fixes: http://tracker.ceph.com/issues/23855 --- src/client/Client.cc | 6 ++++ src/mds/CInode.cc | 2 ++ src/messages/MClientCaps.h | 72 ++++++++++++++------------------------ 3 files changed, 35 insertions(+), 45 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 131b65e61af92..f71a39956d610 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -5056,6 +5056,12 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient decode(in->xattrs, p); in->xattr_version = m->head.xattr_version; } + + if ((new_caps & CEPH_CAP_FILE_SHARED) && m->dirstat_is_valid()) { + in->dirstat.nfiles = m->get_nfiles(); + in->dirstat.nsubdirs = m->get_nsubdirs(); + } + update_inode_file_bits(in, m->get_truncate_seq(), m->get_truncate_size(), m->get_size(), m->get_change_attr(), m->get_time_warp_seq(), m->get_ctime(), m->get_mtime(), m->get_atime(), diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index ac4af11bd38e0..d46fdf16f6a06 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -3635,6 +3635,8 @@ void CInode::encode_cap_message(MClientCaps *m, Capability *cap) m->ctime = i->ctime; m->change_attr = i->change_attr; m->time_warp_seq = i->time_warp_seq; + m->nfiles = i->dirstat.nfiles; + m->nsubdirs = i->dirstat.nsubdirs; if (cap->client_inline_version < i->inline_data.version) { m->inline_version = cap->client_inline_version = i->inline_data.version; diff --git a/src/messages/MClientCaps.h b/src/messages/MClientCaps.h index 8df0679ca36b3..33218f740f74a 100644 --- a/src/messages/MClientCaps.h +++ b/src/messages/MClientCaps.h @@ -19,7 +19,7 @@ #include "include/ceph_features.h" class MClientCaps : public Message { - static const int HEAD_VERSION = 10; + static const int HEAD_VERSION = 11; static const int COMPAT_VERSION = 1; public: @@ -29,27 +29,32 @@ class MClientCaps : public Message { struct ceph_mds_caps_head head; - uint64_t size, max_size, truncate_size, change_attr; - uint32_t truncate_seq; + uint64_t size = 0; + uint64_t max_size = 0; + uint64_t truncate_size = 0; + uint64_t change_attr = 0; + uint32_t truncate_seq = 0; utime_t mtime, atime, ctime, btime; - uint32_t time_warp_seq; + uint32_t time_warp_seq = 0; + int64_t nfiles = -1; // files in dir + int64_t nsubdirs = -1; // subdirs in dir struct ceph_mds_cap_peer peer; bufferlist snapbl; bufferlist xattrbl; bufferlist flockbl; - version_t inline_version; + version_t inline_version = 0; bufferlist inline_data; // Receivers may not use their new caps until they have this OSD map - epoch_t osd_epoch_barrier; - ceph_tid_t oldest_flush_tid; - uint32_t caller_uid; - uint32_t caller_gid; + epoch_t osd_epoch_barrier = 0; + ceph_tid_t oldest_flush_tid = 0; + uint32_t caller_uid = 0; + uint32_t caller_gid = 0; /* advisory CLIENT_CAPS_* flags to send to mds */ - unsigned flags; + unsigned flags = 0; int get_caps() { return head.caps; } int get_wanted() { return head.wanted; } @@ -72,6 +77,9 @@ class MClientCaps : public Message { utime_t get_atime() { return atime; } __u64 get_change_attr() { return change_attr; } __u32 get_time_warp_seq() { return time_warp_seq; } + uint64_t get_nfiles() { return nfiles; } + uint64_t get_nsubdirs() { return nsubdirs; } + bool dirstat_is_valid() const { return nfiles != -1 || nsubdirs != -1; } const file_layout_t& get_layout() { return layout; @@ -117,19 +125,7 @@ class MClientCaps : public Message { void clear_dirty() { head.dirty = 0; } MClientCaps() - : Message(CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION), - size(0), - max_size(0), - truncate_size(0), - change_attr(0), - truncate_seq(0), - time_warp_seq(0), - osd_epoch_barrier(0), - oldest_flush_tid(0), - caller_uid(0), caller_gid(0), - flags(0) { - inline_version = 0; - } + : Message(CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION) {} MClientCaps(int op, inodeno_t ino, inodeno_t realm, @@ -141,16 +137,7 @@ class MClientCaps : public Message { int mseq, epoch_t oeb) : Message(CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION), - size(0), - max_size(0), - truncate_size(0), - change_attr(0), - truncate_seq(0), - time_warp_seq(0), - osd_epoch_barrier(oeb), - oldest_flush_tid(0), - caller_uid(0), caller_gid(0), - flags(0) { + osd_epoch_barrier(oeb) { memset(&head, 0, sizeof(head)); head.op = op; head.ino = ino; @@ -162,22 +149,12 @@ class MClientCaps : public Message { head.dirty = dirty; head.migrate_seq = mseq; memset(&peer, 0, sizeof(peer)); - inline_version = 0; } MClientCaps(int op, inodeno_t ino, inodeno_t realm, uint64_t id, int mseq, epoch_t oeb) : Message(CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION), - size(0), - max_size(0), - truncate_size(0), - change_attr(0), - truncate_seq(0), - time_warp_seq(0), - osd_epoch_barrier(oeb), - oldest_flush_tid(0), - caller_uid(0), caller_gid(0), - flags(0) { + osd_epoch_barrier(oeb) { memset(&head, 0, sizeof(head)); head.op = op; head.ino = ino; @@ -185,7 +162,6 @@ class MClientCaps : public Message { head.cap_id = id; head.migrate_seq = mseq; memset(&peer, 0, sizeof(peer)); - inline_version = 0; } private: file_layout_t layout; @@ -281,6 +257,10 @@ public: if (header.version >= 10) { decode(flags, p); } + if (header.version >= 11) { + decode(nfiles, p); + decode(nsubdirs, p); + } } void encode_payload(uint64_t features) override { using ceph::encode; @@ -342,6 +322,8 @@ public: encode(btime, payload); encode(change_attr, payload); encode(flags, payload); + encode(nfiles, payload); + encode(nsubdirs, payload); } }; -- 2.39.5