From: Simon Gao Date: Wed, 3 Jun 2020 03:04:25 +0000 (+0800) Subject: mds: rdlock file/nest lock when accumulating stats of subtree dirfrags X-Git-Tag: v17.0.0~609^2~11 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=c8c3ba439abab26736f0caa9919362c0b447dbac;p=ceph.git mds: rdlock file/nest lock when accumulating stats of subtree dirfrags Signed-off-by: Simon Gao Signed-off-by: "Yan, Zheng" --- diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h index fe98eef892428..f0cac9e1a0db2 100644 --- a/src/include/ceph_fs.h +++ b/src/include/ceph_fs.h @@ -415,6 +415,7 @@ enum { CEPH_MDS_OP_ENQUEUE_SCRUB = 0x01503, CEPH_MDS_OP_REPAIR_FRAGSTATS = 0x01504, CEPH_MDS_OP_REPAIR_INODESTATS = 0x01505, + CEPH_MDS_OP_RDLOCK_FRAGSSTATS = 0x01507 }; extern const char *ceph_mds_op_name(int op); diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 3e771e30429a0..601a144e8c563 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -4811,7 +4811,12 @@ next: } bool check_dirfrag_rstats() { - return immediate(DIRFRAGS, 0); + if (in->has_subtree_root_dirfrag()) { + in->mdcache->rdlock_dirfrags_stats(in, get_internal_callback(DIRFRAGS)); + return false; + } else { + return immediate(DIRFRAGS, 0); + } } bool _dirfrags(int rval) { diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 234c630bef3cc..ade41bcb8f8a1 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -9650,6 +9650,9 @@ void MDCache::dispatch_request(MDRequestRef& mdr) case CEPH_MDS_OP_REPAIR_INODESTATS: repair_inode_stats_work(mdr); break; + case CEPH_MDS_OP_RDLOCK_FRAGSSTATS: + rdlock_dirfrags_stats_work(mdr); + break; default: ceph_abort(); } @@ -13056,6 +13059,40 @@ do_rdlocks: mds->server->respond_to_request(mdr, 0); } +void MDCache::rdlock_dirfrags_stats(CInode *diri, MDSInternalContext* fin) +{ + MDRequestRef mdr = request_start_internal(CEPH_MDS_OP_RDLOCK_FRAGSSTATS); + mdr->pin(diri); + mdr->internal_op_private = diri; + mdr->internal_op_finish = fin; + return rdlock_dirfrags_stats_work(mdr); +} + +void MDCache::rdlock_dirfrags_stats_work(MDRequestRef& mdr) +{ + CInode *diri = static_cast(mdr->internal_op_private); + dout(10) << __func__ << " " << *diri << dendl; + if (!diri->is_auth()) { + mds->server->respond_to_request(mdr, -ESTALE); + return; + } + if (!diri->is_dir()) { + mds->server->respond_to_request(mdr, -ENOTDIR); + return; + } + + MutationImpl::LockOpVec lov; + lov.add_rdlock(&diri->dirfragtreelock); + lov.add_rdlock(&diri->nestlock); + lov.add_rdlock(&diri->filelock); + if (!mds->locker->acquire_locks(mdr, lov)) + return; + dout(10) << __func__ << " start dirfrags : " << *diri << dendl; + + mds->server->respond_to_request(mdr, 0); + return; +} + void MDCache::flush_dentry(std::string_view path, Context *fin) { if (is_readonly()) { diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 8c0957646ad4e..2db916d70a73c 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -940,6 +940,7 @@ class MDCache { Formatter *f, Context *fin); void repair_inode_stats(CInode *diri); void repair_dirfrag_stats(CDir *dir); + void rdlock_dirfrags_stats(CInode *diri, MDSInternalContext *fin); // my leader MDSRank *mds; @@ -1125,6 +1126,7 @@ class MDCache { void enqueue_scrub_work(MDRequestRef& mdr); void repair_inode_stats_work(MDRequestRef& mdr); void repair_dirfrag_stats_work(MDRequestRef& mdr); + void rdlock_dirfrags_stats_work(MDRequestRef& mdr); ceph::unordered_map inode_map; // map of head inodes by ino map snap_inode_map; // map of snap inodes by ino diff --git a/src/mds/MDSContinuation.h b/src/mds/MDSContinuation.h index 97bae912a2a4b..e01522522556d 100644 --- a/src/mds/MDSContinuation.h +++ b/src/mds/MDSContinuation.h @@ -21,7 +21,7 @@ class MDSContinuation : public Continuation { protected: Server *server; - MDSContext *get_internal_callback(int stage) { + MDSInternalContext *get_internal_callback(int stage) { return new MDSInternalContextWrapper(server->mds, get_callback(stage)); } MDSIOContextBase *get_io_callback(int stage) {