From c3ae0ee6ae2246e63fd614ac4d6ac8414bbe2e92 Mon Sep 17 00:00:00 2001 From: sageweil Date: Fri, 5 Oct 2007 15:44:21 +0000 Subject: [PATCH] bugfixes, EOpen works with logsegments * try_to_expire does teh right thing with open files * dirlock on base inodes never scattered * trim more aggressive about base inodes when max==0 git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1886 29311d96-e01e-0410-9327-a35deaab8ce9 --- branches/sage/mds/TODO | 5 ++ branches/sage/mds/mds/CInode.cc | 12 ++-- branches/sage/mds/mds/CInode.h | 6 +- branches/sage/mds/mds/Locker.cc | 5 +- branches/sage/mds/mds/LogSegment.h | 2 +- branches/sage/mds/mds/MDCache.cc | 21 ++++++- branches/sage/mds/mds/ScatterLock.h | 2 + branches/sage/mds/mds/Server.cc | 11 ++-- branches/sage/mds/mds/events/EAnchor.h | 2 - branches/sage/mds/mds/events/EAnchorClient.h | 2 - branches/sage/mds/mds/events/EOpen.h | 2 - branches/sage/mds/mds/events/EUpdate.h | 2 - branches/sage/mds/mds/journal.cc | 66 ++++++-------------- branches/sage/mds/mds/mdstypes.h | 12 ++-- 14 files changed, 75 insertions(+), 75 deletions(-) diff --git a/branches/sage/mds/TODO b/branches/sage/mds/TODO index 256a7cc134f8a..a857bd7195ad4 100644 --- a/branches/sage/mds/TODO +++ b/branches/sage/mds/TODO @@ -84,6 +84,9 @@ mds bugs - verify once-per-segment jouranl context is working... +- open file rejournaling vs capped log... + - open files vs shutdown in general! need to export any caps on replicated metadata + mds cleanup - fix freeze_* interface to pull waiters _outside_ - get rid of replicate objects for replicate_to .. encode to bufferlists directly @@ -93,6 +96,8 @@ mds - fix path_traverse - fix reconnect/rejoin open file weirdness +- export caps to auth on unlinked inodes + - stray reintegration - stray purge on shutdown - need to export stray crap to another mds.. diff --git a/branches/sage/mds/mds/CInode.cc b/branches/sage/mds/mds/CInode.cc index d447d6f0d1f36..05ad442aa83a7 100644 --- a/branches/sage/mds/mds/CInode.cc +++ b/branches/sage/mds/mds/CInode.cc @@ -64,8 +64,7 @@ ostream& operator<<(ostream& out, CInode& in) out << " v" << in.get_version(); - if (in.state_test(CInode::STATE_AMBIGUOUSAUTH)) - out << " AMBIGAUTH"; + if (in.state_test(CInode::STATE_AMBIGUOUSAUTH)) out << " AMBIGAUTH"; if (in.is_freezing_inode()) out << " FREEZING"; if (in.is_frozen_inode()) out << " FROZEN"; @@ -607,10 +606,15 @@ bool CInode::is_freezing() void CInode::add_waiter(int tag, Context *c) { + dout(10) << "add_waiter tag " << tag + << " !ambig " << !state_test(STATE_AMBIGUOUSAUTH) + << " !frozen " << !is_frozen_inode() + << " !freezing " << !is_freezing_inode() + << dendl; // wait on the directory? // make sure its not the inode that is explicitly ambiguous|freezing|frozen - if ((tag & WAIT_SINGLEAUTH) && !state_test(STATE_AMBIGUOUSAUTH) || - (tag & WAIT_UNFREEZE) && !state_test(STATE_FROZEN|STATE_FREEZING)) { + if (((tag & WAIT_SINGLEAUTH) && !state_test(STATE_AMBIGUOUSAUTH)) || + ((tag & WAIT_UNFREEZE) && !is_frozen_inode() && !is_freezing_inode())) { parent->dir->add_waiter(tag, c); return; } diff --git a/branches/sage/mds/mds/CInode.h b/branches/sage/mds/mds/CInode.h index cce2b43058f56..acb600ea04aff 100644 --- a/branches/sage/mds/mds/CInode.h +++ b/branches/sage/mds/mds/CInode.h @@ -104,7 +104,6 @@ class CInode : public MDSCacheObject { static const int WAIT_UNANCHORED = (1<<3); static const int WAIT_CAPS = (1<<4); static const int WAIT_FROZEN = (1<<5); - static const int WAIT_UNFREEZE = (1<<6); static const int WAIT_AUTHLOCK_OFFSET = 5; static const int WAIT_LINKLOCK_OFFSET = 5 + SimpleLock::WAIT_BITS; @@ -197,7 +196,7 @@ protected: // LogSegment xlists i (may) belong to xlist::item xlist_dirty; public: - xlist::item xlist_opened_files; + xlist::item xlist_open_file; xlist::item xlist_dirty_inode_mtime; xlist::item xlist_purging_inode; @@ -228,7 +227,7 @@ private: stickydir_ref(0), parent(0), force_auth(CDIR_AUTH_DEFAULT), replica_caps_wanted(0), - xlist_dirty(this), xlist_opened_files(this), + xlist_dirty(this), xlist_open_file(this), xlist_dirty_inode_mtime(this), xlist_purging_inode(this), auth_pins(0), nested_auth_pins(0), versionlock(this, LOCK_OTYPE_IVERSION, WAIT_VERSIONLOCK_OFFSET), @@ -257,6 +256,7 @@ private: bool is_root() { return inode.ino == MDS_INO_ROOT; } bool is_stray() { return MDS_INO_IS_STRAY(inode.ino); } + bool is_base() { return inode.ino < MDS_INO_BASE; } // note: this overloads MDSCacheObject bool is_ambiguous_auth() { diff --git a/branches/sage/mds/mds/Locker.cc b/branches/sage/mds/mds/Locker.cc index ad5d021b612d7..5a605fb3ecc9e 100644 --- a/branches/sage/mds/mds/Locker.cc +++ b/branches/sage/mds/mds/Locker.cc @@ -720,6 +720,8 @@ void Locker::handle_client_file_caps(MClientFileCaps *m) if (cap->is_null()) { dout(7) << " cap for client" << client << " is now null, removing from " << *in << dendl; in->remove_client_cap(client); + if (!in->is_any_caps()) + in->xlist_open_file.remove_myself(); // unpin logsegment if (!in->is_auth()) request_inode_file_caps(in); @@ -1594,7 +1596,8 @@ void Locker::scatter_eval(ScatterLock *lock) assert(lock->get_parent()->is_auth()); assert(lock->is_stable()); - if (((CInode*)lock->get_parent())->has_subtree_root_dirfrag()) { + CInode *in = (CInode*)lock->get_parent(); + if (in->has_subtree_root_dirfrag() && !in->is_base()) { // i _should_ be scattered. if (!lock->is_rdlocked() && !lock->is_xlocked()) { diff --git a/branches/sage/mds/mds/LogSegment.h b/branches/sage/mds/mds/LogSegment.h index 58511c66db904..7579add569d50 100644 --- a/branches/sage/mds/mds/LogSegment.h +++ b/branches/sage/mds/mds/LogSegment.h @@ -37,7 +37,7 @@ class LogSegment { xlist dirty_inodes; xlist dirty_dentries; - xlist opened_files; + xlist open_files; xlist dirty_inode_mtimes; //xlist purging_inodes; diff --git a/branches/sage/mds/mds/MDCache.cc b/branches/sage/mds/mds/MDCache.cc index 646f719327ba9..df5cd916df0a7 100644 --- a/branches/sage/mds/mds/MDCache.cc +++ b/branches/sage/mds/mds/MDCache.cc @@ -2895,6 +2895,22 @@ bool MDCache::trim(int max) p = n; } } + if (max == 0) { + for (set::iterator p = base_inodes.begin(); + p != base_inodes.end(); + ++p) { + CInode *in = *p; + list ls; + in->get_dirfrags(ls); + for (list::iterator p = ls.begin(); p != ls.end(); ++p) { + CDir *dir = *p; + if (dir->get_num_ref() == 0) + trim_dirfrag(dir, 0, expiremap); + } + if (in->get_num_ref() == 0) + trim_inode(0, in, 0, expiremap); + } + } // send! send_expire_messages(expiremap); @@ -6039,7 +6055,7 @@ void MDCache::show_subtrees(int dbl) return; // i won't print anything. if (subtrees.empty()) { - dout(dbl) << "no subtrees" << dendl; + dout(dbl) << "show_subtrees - no subtrees" << dendl; return; } @@ -6049,7 +6065,8 @@ void MDCache::show_subtrees(int dbl) p != base_inodes.end(); ++p) (*p)->get_dirfrags(basefrags); - dout(15) << "show_subtrees, base dirfrags " << basefrags << dendl; + //dout(15) << "show_subtrees, base dirfrags " << basefrags << dendl; + dout(15) << "show_subtrees" << dendl; // queue stuff list > q; diff --git a/branches/sage/mds/mds/ScatterLock.h b/branches/sage/mds/mds/ScatterLock.h index f93034d0b8829..0645622aee56d 100644 --- a/branches/sage/mds/mds/ScatterLock.h +++ b/branches/sage/mds/mds/ScatterLock.h @@ -166,6 +166,8 @@ public: out << " x=" << get_xlocked_by(); if (is_wrlocked()) out << " wr=" << get_num_wrlocks(); + if (updated) + out << " updated"; out << ")"; } diff --git a/branches/sage/mds/mds/Server.cc b/branches/sage/mds/mds/Server.cc index 4df9347319371..2e40d323d0173 100644 --- a/branches/sage/mds/mds/Server.cc +++ b/branches/sage/mds/mds/Server.cc @@ -3685,14 +3685,17 @@ void Server::journal_opens() EOpen *le = 0; // check queued inodes + LogSegment *ls = mdlog->get_current_segment(); for (set::iterator p = journal_open_queue.begin(); p != journal_open_queue.end(); ++p) { - (*p)->put(CInode::PIN_BATCHOPENJOURNAL); - if ((*p)->is_any_caps()) { + CInode *in = *p; + in->put(CInode::PIN_BATCHOPENJOURNAL); + if (in->is_any_caps()) { if (!le) le = new EOpen(mdlog); - le->add_inode(*p); - (*p)->last_open_journaled = mds->mdlog->get_write_pos(); + le->add_inode(in); + in->last_open_journaled = mds->mdlog->get_write_pos(); + ls->open_files.push_back(&in->xlist_open_file); } } journal_open_queue.clear(); diff --git a/branches/sage/mds/mds/events/EAnchor.h b/branches/sage/mds/mds/events/EAnchor.h index 5de43f1ba19aa..97a21a36734be 100644 --- a/branches/sage/mds/mds/events/EAnchor.h +++ b/branches/sage/mds/mds/events/EAnchor.h @@ -73,8 +73,6 @@ protected: if (reqmds >= 0) out << " by mds" << reqmds; } - bool has_expired(MDS *mds); - void expire(MDS *mds, Context *c); void update_segment(); void replay(MDS *mds); }; diff --git a/branches/sage/mds/mds/events/EAnchorClient.h b/branches/sage/mds/mds/events/EAnchorClient.h index 7cd36453e17b9..21f78369cae72 100644 --- a/branches/sage/mds/mds/events/EAnchorClient.h +++ b/branches/sage/mds/mds/events/EAnchorClient.h @@ -49,8 +49,6 @@ protected: if (atid) out << " atid " << atid; } - bool has_expired(MDS *mds); - void expire(MDS *mds, Context *c); void replay(MDS *mds); }; diff --git a/branches/sage/mds/mds/events/EOpen.h b/branches/sage/mds/mds/events/EOpen.h index b96892678023b..fccc3650707a8 100644 --- a/branches/sage/mds/mds/events/EOpen.h +++ b/branches/sage/mds/mds/events/EOpen.h @@ -46,8 +46,6 @@ public: metablob._decode(bl, off); } - bool has_expired(MDS *mds); - void expire(MDS *mds, Context *c); void update_segment(); void replay(MDS *mds); }; diff --git a/branches/sage/mds/mds/events/EUpdate.h b/branches/sage/mds/mds/events/EUpdate.h index ba0a4863f0daf..de965429f9bdd 100644 --- a/branches/sage/mds/mds/events/EUpdate.h +++ b/branches/sage/mds/mds/events/EUpdate.h @@ -43,8 +43,6 @@ public: metablob._decode(bl, off); } - bool has_expired(MDS *mds); - void expire(MDS *mds, Context *c); void update_segment(); void replay(MDS *mds); }; diff --git a/branches/sage/mds/mds/journal.cc b/branches/sage/mds/mds/journal.cc index 7d843a99a0311..243acc037f740 100644 --- a/branches/sage/mds/mds/journal.cc +++ b/branches/sage/mds/mds/journal.cc @@ -87,10 +87,10 @@ C_Gather *LogSegment::try_to_expire(MDS *mds) ++p) { CDir *dir = *p; if (dir->can_auth_pin()) { - dout(10) << " committing " << *dir << dendl; + dout(10) << "try_to_expire committing " << *dir << dendl; dir->commit(0, gather->new_sub()); } else { - dout(10) << " waiting for unfreeze on " << *dir << dendl; + dout(10) << "try_to_expire waiting for unfreeze on " << *dir << dendl; dir->add_waiter(CDir::WAIT_UNFREEZE, gather->new_sub()); } } @@ -98,21 +98,34 @@ C_Gather *LogSegment::try_to_expire(MDS *mds) // dirty non-auth mtimes for (xlist::iterator p = dirty_inode_mtimes.begin(); !p.end(); ++p) { - dout(10) << " waiting for dirlock mtime flush on " << *p << dendl; + dout(10) << "try_to_expire waiting for dirlock mtime flush on " << *p << dendl; if (!gather) gather = new C_Gather; (*p)->dirlock.add_waiter(SimpleLock::WAIT_STABLE, gather->new_sub()); } + + // open files + if (!open_files.empty()) { + assert(!mds->mdlog->is_capped()); // hmm FIXME + for (xlist::iterator p = open_files.begin(); !p.end(); ++p) { + dout(20) << "try_to_expire requeueing open file " << **p << dendl; + mds->server->queue_journal_open(*p); + } + if (!gather) gather = new C_Gather; + mds->server->add_journal_open_waiter(gather->new_sub()); + mds->server->maybe_journal_opens(); + dout(10) << "try_to_expire waiting for open files to rejournal" << dendl; + } // idalloc if (allocv > mds->idalloc->get_committed_version()) { - dout(10) << " saving idalloc table, need " << allocv << dendl; + dout(10) << "try_to_expire saving idalloc table, need " << allocv << dendl; if (!gather) gather = new C_Gather; mds->idalloc->save(gather->new_sub(), allocv); } // clientmap if (clientmapv > mds->clientmap.get_committed()) { - dout(10) << " saving clientmap, need " << clientmapv << dendl; + dout(10) << "try_to_expire saving clientmap, need " << clientmapv << dendl; if (!gather) gather = new C_Gather; mds->clientmap.save(gather->new_sub(), clientmapv); } @@ -123,21 +136,20 @@ C_Gather *LogSegment::try_to_expire(MDS *mds) ++p) { if (!gather) gather = new C_Gather; assert(!mds->anchorclient->has_committed(*p)); - dout(10) << " anchor transaction " << *p + dout(10) << "try_to_expire anchor transaction " << *p << " pending commit (not yet acked), waiting" << dendl; mds->anchorclient->wait_for_ack(*p, gather->new_sub()); } // anchortable if (anchortablev > mds->anchortable->get_committed_version()) { - dout(10) << " saving anchor table, need " << anchortablev << dendl; + dout(10) << "try_to_expire waiting for anchor table to save, need " << anchortablev << dendl; if (!gather) gather = new C_Gather; mds->anchortable->save(gather->new_sub()); } // FIXME client requests...? // audit handling of anchor transactions? - // open files? return gather; } @@ -796,44 +808,6 @@ void EUpdate::replay(MDS *mds) // ------------------------ // EOpen -bool EOpen::has_expired(MDS *mds) -{ - for (list::iterator p = inos.begin(); p != inos.end(); ++p) { - CInode *in = mds->mdcache->get_inode(*p); - if (in && - in->is_any_caps() && - !(in->last_open_journaled > get_start_off() || - in->last_open_journaled == 0)) { - dout(10) << "EOpen.has_expired still refer to caps on " << *in << dendl; - return false; - } - } - return true; -} - -void EOpen::expire(MDS *mds, Context *c) -{ - dout(10) << "EOpen.expire " << dendl; - - if (mds->mdlog->is_capped()) { - dout(0) << "uh oh, log is capped, but i have unexpired opens." << dendl; - assert(0); - } - - for (list::iterator p = inos.begin(); p != inos.end(); ++p) { - CInode *in = mds->mdcache->get_inode(*p); - if (!in) continue; - if (!in->is_any_caps()) continue; - - dout(10) << "EOpen.expire " << in->ino() - << " last_open_journaled " << in->last_open_journaled << dendl; - - mds->server->queue_journal_open(in); - } - mds->server->add_journal_open_waiter(c); - mds->server->maybe_journal_opens(); -} - void EOpen::update_segment() { // ?? diff --git a/branches/sage/mds/mds/mdstypes.h b/branches/sage/mds/mds/mdstypes.h index a3112223f1028..3992c7a61b7ac 100644 --- a/branches/sage/mds/mds/mdstypes.h +++ b/branches/sage/mds/mds/mdstypes.h @@ -433,16 +433,16 @@ class MDSCacheObject { unsigned state; // state bits public: - unsigned get_state() { return state; } + unsigned get_state() const { return state; } + unsigned state_test(unsigned mask) const { return (state & mask); } void state_clear(unsigned mask) { state &= ~mask; } void state_set(unsigned mask) { state |= mask; } - unsigned state_test(unsigned mask) { return state & mask; } void state_reset(unsigned s) { state = s; } - bool is_auth() { return state_test(STATE_AUTH); } - bool is_dirty() { return state_test(STATE_DIRTY); } - bool is_clean() { return !is_dirty(); } - bool is_rejoining() { return state_test(STATE_REJOINING); } + bool is_auth() const { return state_test(STATE_AUTH); } + bool is_dirty() const { return state_test(STATE_DIRTY); } + bool is_clean() const { return !is_dirty(); } + bool is_rejoining() const { return state_test(STATE_REJOINING); } // -------------------------------------------- // authority -- 2.39.5