]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: include nfiles/nsubdirs of directory inode in MClientCaps 22118/head
authorYan, Zheng <zyan@redhat.com>
Thu, 26 Apr 2018 07:12:48 +0000 (15:12 +0800)
committerPrashant D <pdhange@redhat.com>
Mon, 21 May 2018 11:30:34 +0000 (07:30 -0400)
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" <zyan@redhat.com>
Fixes: http://tracker.ceph.com/issues/23855
(cherry picked from commit ee2c628f6783954e9b25fab8ac9b572a58666a91)

Conflicts:
src/messages/MClientCaps.h: Resolved in encode_payload

src/client/Client.cc
src/mds/CInode.cc
src/messages/MClientCaps.h

index 044c29f3a08156818acfde4bd481b4a68903d109..2f13ac9271f18c0a09eb0748c97393d467216a47 100644 (file)
@@ -5069,6 +5069,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(),
index 929e3252e48a1722110d46b558d3e07cc900f581..a825d118d7ca2d2cd84e9b1f231b25d7e2b63f38 100644 (file)
@@ -3442,6 +3442,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;
index e973b63413818eadcf5e0f55557841a077a43f8c..01f5746c4394e841e9ec152705fc665a91b8b462 100644 (file)
 #define        CLIENT_CAPS_SYNC                (0x1)
 
 class MClientCaps : public Message {
-  static const int HEAD_VERSION = 10;
+  static const int HEAD_VERSION = 11;
   static const int COMPAT_VERSION = 1;
 
  public:
   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; }
@@ -70,6 +75,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;
@@ -115,19 +123,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,
@@ -139,16 +135,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;
@@ -160,22 +147,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;
@@ -183,7 +160,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;
@@ -279,6 +255,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 {
     header.version = HEAD_VERSION;
@@ -339,6 +319,8 @@ public:
     ::encode(btime, payload);
     ::encode(change_attr, payload);
     ::encode(flags, payload);
+    ::encode(nfiles, payload);
+    ::encode(nsubdirs, payload);
   }
 };