]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: share inode max size after MDS recovers
authorYan, Zheng <zheng.z.yan@intel.com>
Tue, 12 Mar 2013 08:27:22 +0000 (16:27 +0800)
committerGreg Farnum <greg@inktank.com>
Mon, 1 Apr 2013 16:26:23 +0000 (09:26 -0700)
The MDS may crash after journaling the new max size, but before sending
the new max size to the client. Later when the MDS recovers, the client
re-requests the new max size, but the MDS finds max size unchanged. So
the client waits for the new max size forever. This issue can be avoided
by checking client cap's last_sent, share inode max size if it is zero.
(reconnected cap's last_sent is zero)

Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Reviewed-by: Greg Farnum <greg@inktank.com>
src/mds/Locker.cc
src/mds/Locker.h
src/mds/MDCache.cc

index d0dbd4ce9d8453a28db75bc0d2a5eeec8e7e994c..3ce5420e1d7c15110bca4ee57542e4d0dadddeb1 100644 (file)
@@ -2089,7 +2089,7 @@ bool Locker::check_inode_max_size(CInode *in, bool force_wrlock,
 }
 
 
-void Locker::share_inode_max_size(CInode *in)
+void Locker::share_inode_max_size(CInode *in, Capability *only_cap)
 {
   /*
    * only share if currently issued a WR cap.  if client doesn't have it,
@@ -2097,9 +2097,12 @@ void Locker::share_inode_max_size(CInode *in)
    * the cap later.
    */
   dout(10) << "share_inode_max_size on " << *in << dendl;
-  for (map<client_t,Capability*>::iterator it = in->client_caps.begin();
-       it != in->client_caps.end();
-       ++it) {
+  map<client_t, Capability*>::iterator it;
+  if (only_cap)
+    it = in->client_caps.find(only_cap->get_client());
+  else
+    it = in->client_caps.begin();
+  for (; it != in->client_caps.end(); ++it) {
     const client_t client = it->first;
     Capability *cap = it->second;
     if (cap->is_suppress())
@@ -2115,6 +2118,8 @@ void Locker::share_inode_max_size(CInode *in)
       in->encode_cap_message(m, cap);
       mds->send_message_client_counted(m, client);
     }
+    if (only_cap)
+      break;
   }
 }
 
@@ -2398,6 +2403,11 @@ void Locker::handle_client_caps(MClientCaps *m)
       bool did_issue = eval(in, CEPH_CAP_LOCKS);
       if (!did_issue && (cap->wanted() & ~cap->pending()))
        issue_caps(in, cap);
+      if (cap->get_last_seq() == 0 &&
+         (cap->pending() & (CEPH_CAP_FILE_WR|CEPH_CAP_FILE_BUFFER))) {
+       cap->issue_norevoke(cap->issued());
+       share_inode_max_size(in, cap);
+      }
     }
   }
 
index 3f79996cb926d392a7b533bf178432c99d90ffb4..d98104fc4357502ca0bf1023a4ee968e117852ef 100644 (file)
@@ -276,7 +276,7 @@ public:
   void calc_new_client_ranges(CInode *in, uint64_t size, map<client_t, client_writeable_range_t>& new_ranges);
   bool check_inode_max_size(CInode *in, bool force_wrlock=false, bool update_size=false, uint64_t newsize=0,
                            utime_t mtime=utime_t());
-  void share_inode_max_size(CInode *in);
+  void share_inode_max_size(CInode *in, Capability *only_cap=0);
 
 private:
   friend class C_MDL_CheckMaxSize;
index b0fe2b730423bc87aef724c50ca4ab04887a4bb5..10254a4f7dfc3228d06e022e1698872d235002d0 100644 (file)
@@ -5066,6 +5066,8 @@ void MDCache::do_cap_import(Session *session, CInode *in, Capability *cap)
   SnapRealm *realm = in->find_snaprealm();
   if (realm->have_past_parents_open()) {
     dout(10) << "do_cap_import " << session->info.inst.name << " mseq " << cap->get_mseq() << " on " << *in << dendl;
+    if (cap->get_last_seq() == 0)
+      cap->issue_norevoke(cap->issued()); // reconnected cap
     cap->set_last_issue();
     MClientCaps *reap = new MClientCaps(CEPH_CAP_OP_IMPORT,
                                        in->ino(),