From: Yan, Zheng Date: Tue, 12 Mar 2013 08:27:22 +0000 (+0800) Subject: mds: share inode max size after MDS recovers X-Git-Tag: v0.62~120^2~16 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=10b1a5663f51ddc05f287aead9a0078d96ae296a;p=ceph.git mds: share inode max size after MDS recovers 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 Reviewed-by: Greg Farnum --- diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index d0dbd4ce9d8..3ce5420e1d7 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -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::iterator it = in->client_caps.begin(); - it != in->client_caps.end(); - ++it) { + map::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); + } } } diff --git a/src/mds/Locker.h b/src/mds/Locker.h index 3f79996cb92..d98104fc435 100644 --- a/src/mds/Locker.h +++ b/src/mds/Locker.h @@ -276,7 +276,7 @@ public: void calc_new_client_ranges(CInode *in, uint64_t size, map& 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; diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index b0fe2b73042..10254a4f7df 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -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(),