From 14dd8a9a8a653ef0142ce795454ae3e0e920d386 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 3 May 2010 15:04:16 -0700 Subject: [PATCH] mds: acquire anchor_create locks in caller We're not allowed to call acquire_locks again once we've completed locking. Do it in the caller. Add a helper that will also take an rdlock to ensure the anchor doesn't go away due to a racing operation. --- src/mds/MDCache.cc | 37 +++++++++++++++++++++---------------- src/mds/MDCache.h | 2 ++ src/mds/Server.cc | 18 ++++++++++++++++++ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 1f1bc11216754..1655a79651859 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -6542,6 +6542,27 @@ public: } }; +void MDCache::anchor_create_prep_locks(MDRequest *mdr, CInode *in, + set& rdlocks, set& xlocks) +{ + dout(10) << "anchor_create_prep_locks " << *in << dendl; + + if (in->is_anchored()) { + // caller may have already xlocked it.. if so, that will suffice! + if (xlocks.count(&in->linklock) == 0) + rdlocks.insert(&in->linklock); + } else { + xlocks.insert(&in->linklock); + + // path components too! + CDentry *dn = in->get_projected_parent_dn(); + while (dn) { + rdlocks.insert(&dn->lock); + dn = dn->get_dir()->get_inode()->get_parent_dn(); + } + } +} + void MDCache::anchor_create(MDRequest *mdr, CInode *in, Context *onfinish) { assert(in->is_auth()); @@ -6555,22 +6576,6 @@ void MDCache::anchor_create(MDRequest *mdr, CInode *in, Context *onfinish) return; } - // rdlock path - set rdlocks = mdr->rdlocks; - set wrlocks = mdr->wrlocks; - set xlocks = mdr->xlocks; - xlocks.insert(&in->linklock); - - CDentry *dn = in->get_parent_dn(); - while (dn) { - rdlocks.insert(&dn->lock); - dn = dn->get_dir()->get_inode()->get_parent_dn(); - } - if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) { - dout(7) << "anchor_create waiting for locks " << *in << dendl; - return; - } - // wait in->add_waiter(CInode::WAIT_ANCHORED, onfinish); diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index ae4d7f39d9cc7..9c1c0af7b80dd 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -971,6 +971,8 @@ public: // -- anchors -- public: + void anchor_create_prep_locks(MDRequest *mdr, CInode *in, set& rdlocks, + set& xlocks); void anchor_create(MDRequest *mdr, CInode *in, Context *onfinish); void anchor_destroy(CInode *in, Context *onfinish); protected: diff --git a/src/mds/Server.cc b/src/mds/Server.cc index bde9d236e12a3..b0195bb970c6f 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -3106,6 +3106,10 @@ void Server::handle_client_link(MDRequest *mdr) } xlocks.insert(&targeti->linklock); + + // take any locks needed for anchor creation/verification + mds->mdcache->anchor_create_prep_locks(mdr, targeti, rdlocks, xlocks); + if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) return; @@ -3375,6 +3379,17 @@ void Server::handle_slave_link_prep(MDRequest *mdr) // anchor? if (mdr->slave_request->get_op() == MMDSSlaveRequest::OP_LINKPREP) { + + set rdlocks = mdr->rdlocks; + set wrlocks = mdr->wrlocks; + set xlocks = mdr->xlocks; + + // take any locks needed for anchor creation/verification + mds->mdcache->anchor_create_prep_locks(mdr, targeti, rdlocks, xlocks); + + if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) + return; + if (targeti->is_anchored()) { dout(7) << "target anchored already (nlink=" << targeti->inode.nlink << "), sweet" << dendl; } @@ -4144,6 +4159,9 @@ void Server::handle_client_rename(MDRequest *mdr) else rdlocks.insert(&srci->snaplock); + // take any locks needed for anchor creation/verification + mds->mdcache->anchor_create_prep_locks(mdr, srci, rdlocks, xlocks); + if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) return; -- 2.39.5