]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: make scrubstack queue CInode instead of CDentry
authorYan, Zheng <zyan@redhat.com>
Tue, 15 Dec 2015 14:28:44 +0000 (22:28 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 7 Mar 2016 07:59:13 +0000 (15:59 +0800)
There are two problems that enqueue CDentry in scrub stack. First,
the scrub stack code can't handle base inodes; second, the linkage
of a CDentry can change in the middle of scrubbing, this can confuse
the scrub stack code.

Signed-off-by: Yan, Zheng <zyan@redhat.com>
src/mds/CDentry.cc
src/mds/CDentry.h
src/mds/CInode.cc
src/mds/CInode.h
src/mds/MDCache.cc
src/mds/ScrubHeader.h
src/mds/ScrubStack.cc
src/mds/ScrubStack.h

index b7ccea9d09992a897544edaf8b5bb5e131ff419e..83470dca68fb173edf501b72656150eca34d9c3e 100644 (file)
@@ -621,57 +621,3 @@ std::string CDentry::linkage_t::get_remote_d_type_string() const
     default: assert(0); return "";
   }
 }
-
-void CDentry::scrub_initialize(CDir *parent, bool recurse, bool children,
-                              const ScrubHeaderRefConst& header,
-                               Context *f)
-{
-  if (!scrub_infop)
-    scrub_info_create();
-  else
-    assert(!scrub_infop->dentry_scrubbing);
-
-  scrub_infop->scrub_parent = parent;
-  scrub_infop->scrub_recursive = recurse;
-  scrub_infop->scrub_children = children;
-  scrub_infop->dentry_scrubbing = true;
-  scrub_infop->on_finish = f;
-  scrub_infop->header = header;
-
-  auth_pin(this);
-}
-
-void CDentry::scrub_finished(Context **c)
-{
-  dout(10) << __func__ << dendl;
-  assert(scrub_info()->dentry_scrubbing);
-
-  if (scrub_infop->scrub_parent) {
-    scrub_infop->scrub_parent->scrub_dentry_finished(this);
-  }
-
-  *c = scrub_infop->on_finish;
-
-  if (scrub_infop->header && scrub_infop->header->origin == this) {
-    // We are at the point that a tagging scrub was initiated
-    LogChannelRef clog = dir->cache->mds->clog;
-    clog->info() << "scrub complete with tag '"
-      << scrub_infop->header->tag << "'";
-  }
-
-  delete scrub_infop;
-  scrub_infop = NULL;
-
-  auth_unpin(this);
-}
-
-void CDentry::scrub_info_create() const
-{
-  assert(!scrub_infop);
-
-  // break out of const-land to set up implicit initial state
-  CDentry *me = const_cast<CDentry*>(this);
-
-  // we don't need to change or set up any default parameters; assign directly
-  me->scrub_infop = new scrub_info_t();
-}
index 4fc0ba0340efcd43881a2aba4171f941d179f8ab..7861b4d97242df8c623686603ae7fe7c36f7f1b3 100644 (file)
@@ -81,14 +81,14 @@ public:
   static const int PIN_INODEPIN =     1;  // linked inode is pinned
   static const int PIN_FRAGMENTING = -2;  // containing dir is refragmenting
   static const int PIN_PURGING =      3;
-  static const int PIN_SCRUBQUEUE =   4; // TODO: negative value?
+  static const int PIN_SCRUBPARENT =  4;
 
   const char *pin_name(int p) const {
     switch (p) {
     case PIN_INODEPIN: return "inodepin";
     case PIN_FRAGMENTING: return "fragmenting";
     case PIN_PURGING: return "purging";
-    case PIN_SCRUBQUEUE: return "scrub_enqueued";
+    case PIN_SCRUBPARENT: return "scrubparent";
     default: return generic_pin_name(p);
     }
   }
@@ -140,25 +140,6 @@ public:
     }
     void link_remote(CInode *in);
   };
-  
-  class scrub_info_t {
-  public:
-    CDir *scrub_parent; /// This either matches get_parent_dir() or NULL
-    bool scrub_recursive; /// true if we are scrubbing everything under this
-    bool scrub_children; /// true if we have to scrub all direct children
-    bool dentry_scrubbing; /// safety check
-    bool dentry_children_done; /// safety check
-    bool inode_validated;  /// Has our inode's validate_disk_state run?
-    Context *on_finish; /// called when we finish scrubbing
-    ScrubHeaderRefConst header;
-
-    scrub_info_t() :
-      scrub_parent(NULL), scrub_recursive(false),
-      scrub_children(false), dentry_scrubbing(false),
-      dentry_children_done(false), inode_validated(false),
-      on_finish(NULL)
-    {}
-  };
 
 protected:
   CDir *dir;     // containing dirfrag
@@ -167,34 +148,10 @@ protected:
   
   version_t version;  // dir version when last touched.
   version_t projected_version;  // what it will be when i unlock/commit.
-  scrub_info_t* scrub_infop;
 
 public:
   elist<CDentry*>::item item_dirty;
   elist<CDentry*>::item item_stray;
-  elist<CDentry*>::item item_scrub;
-
-  const scrub_info_t *scrub_info() const {
-    if(!scrub_infop)
-      scrub_info_create();
-    return scrub_infop;
-  }
-  void scrub_initialize(CDir *parent, bool recurse, bool children,
-                        const ScrubHeaderRefConst& header,
-                        Context *f);
-  void scrub_finished(Context **c);
-  void scrub_children_finished() {
-    scrub_infop->dentry_children_done = true;
-  }
-  void scrub_set_finisher(Context *c) {
-    scrub_infop->on_finish = c;
-  }
-
-private:
-  /**
-   * Create a scrub_info_t struct for the scrub_infop pointer.
-   */
-  void scrub_info_create() const;
 
 protected:
   friend class Migrator;
@@ -221,7 +178,6 @@ public:
     first(f), last(l),
     dir(0),
     version(0), projected_version(0),
-    scrub_infop(NULL),
     item_dirty(this),
     lock(this, &lock_type),
     versionlock(this, &versionlock_type) {
@@ -234,7 +190,6 @@ public:
     first(f), last(l),
     dir(0),
     version(0), projected_version(0),
-    scrub_infop(NULL),
     item_dirty(this),
     lock(this, &lock_type),
     versionlock(this, &versionlock_type) {
@@ -244,8 +199,6 @@ public:
     linkage.remote_d_type = dt;
   }
   ~CDentry() {
-    assert(!scrub_infop);
-    assert(!item_scrub.is_on_list());
     g_num_dn--;
     g_num_dns++;
   }
index ad4ee4529ead11794c923d7915d711c5d86717e2..c4b06dd71b89b4729d6218e22b9071abb393b837 100644 (file)
@@ -4146,7 +4146,8 @@ void CInode::scrub_maybe_delete_info()
   }
 }
 
-void CInode::scrub_initialize(const ScrubHeaderRefConst& header)
+void CInode::scrub_initialize(CDentry *scrub_parent,
+                             const ScrubHeaderRefConst& header, Context *f)
 {
   dout(20) << __func__ << " with scrub_version " << get_version() << dendl;
   assert(!scrub_infop || !scrub_infop->scrub_in_progress);
@@ -4166,10 +4167,17 @@ void CInode::scrub_initialize(const ScrubHeaderRefConst& header)
       scrub_infop->dirfrag_stamps[*i];
     }
   }
+
+  if (scrub_parent)
+    scrub_parent->get(CDentry::PIN_SCRUBPARENT);
+  scrub_infop->scrub_parent = scrub_parent;
+  scrub_infop->on_finish = f;
   scrub_infop->scrub_in_progress = true;
+  scrub_infop->children_scrubbed = false;
+  scrub_infop->header = header;
+
   scrub_infop->scrub_start_version = get_version();
   scrub_infop->scrub_start_stamp = ceph_clock_now(g_ceph_context);
-  scrub_infop->header = header;
   // right now we don't handle remote inodes
 }
 
@@ -4248,9 +4256,24 @@ void CInode::scrub_finished(Context **c) {
     }
     assert(i->second.last_scrub_version == i->second.scrub_start_version);
   }
+
   scrub_infop->last_scrub_version = scrub_infop->scrub_start_version;
   scrub_infop->last_scrub_stamp = scrub_infop->scrub_start_stamp;
   scrub_infop->last_scrub_dirty = true;
   scrub_infop->scrub_in_progress = false;
-  parent->scrub_finished(c);
+
+  if (scrub_infop->scrub_parent) {
+    CDentry *dn = scrub_infop->scrub_parent;
+    scrub_infop->scrub_parent = NULL;
+    dn->dir->scrub_dentry_finished(dn);
+    dn->put(CDentry::PIN_SCRUBPARENT);
+  }
+
+  *c = scrub_infop->on_finish;
+
+  if (scrub_infop->header && scrub_infop->header->origin == this) {
+    // We are at the point that a tagging scrub was initiated
+    LogChannelRef clog = mdcache->mds->clog;
+    clog->info() << "scrub complete with tag '" << scrub_infop->header->tag << "'";
+  }
 }
index 50482964a25b9bca85ad554818c4572fc07fcbd8..98af256f3c40c467be3af9c84c05be87d5dbaa88 100644 (file)
@@ -171,6 +171,7 @@ public:
   static const int PIN_EXPORTINGCAPS =    22;
   static const int PIN_DIRTYPARENT =      23;
   static const int PIN_DIRWAITER =        24;
+  static const int PIN_SCRUBQUEUE =       25;
 
   const char *pin_name(int p) const {
     switch (p) {
@@ -195,6 +196,7 @@ public:
     case PIN_DIRTYRSTAT: return "dirtyrstat";
     case PIN_DIRTYPARENT: return "dirtyparent";
     case PIN_DIRWAITER: return "dirwaiter";
+    case PIN_SCRUBQUEUE: return "scrubqueue";
     default: return generic_pin_name(p);
     }
   }
@@ -259,15 +261,22 @@ public:
 
   class scrub_info_t : public scrub_stamp_info_t {
   public:
+    CDentry *scrub_parent;
+    Context *on_finish;
+
     bool last_scrub_dirty; /// are our stamps dirty with respect to disk state?
     bool scrub_in_progress; /// are we currently scrubbing?
+    bool children_scrubbed;
+
     /// my own (temporary) stamps and versions for each dirfrag we have
     std::map<frag_t, scrub_stamp_info_t> dirfrag_stamps;
 
     ScrubHeaderRefConst header;
 
-    scrub_info_t() : scrub_stamp_info_t(), last_scrub_dirty(false),
-        scrub_in_progress(false) {}
+    scrub_info_t() : scrub_stamp_info_t(),
+       scrub_parent(NULL), on_finish(NULL),
+       last_scrub_dirty(false), scrub_in_progress(false),
+       children_scrubbed(false) {}
   };
 
   const scrub_info_t *scrub_info() const{
@@ -283,7 +292,8 @@ public:
    * @param scrub_version What version are we scrubbing at (usually, parent
    * directory's get_projected_version())
    */
-  void scrub_initialize(const ScrubHeaderRefConst& header);
+  void scrub_initialize(CDentry *scrub_parent,
+                       const ScrubHeaderRefConst& header, Context *f);
   /**
    * Get the next dirfrag to scrub. Gives you a frag_t in output param which
    * you must convert to a CDir (and possibly load off disk).
@@ -315,6 +325,16 @@ public:
    * be complete()ed.
    */
   void scrub_finished(Context **c);
+  /**
+   * Report to the CInode that alldirfrags it owns have been scrubbed.
+   */
+  void scrub_children_finished() {
+    scrub_infop->children_scrubbed = true;
+  }
+  void scrub_set_finisher(Context *c) {
+    assert(!scrub_infop->on_finish);
+    scrub_infop->on_finish = c;
+  }
 
 private:
   /**
@@ -600,6 +620,7 @@ public:
   elist<CInode*>::item item_dirty_dirfrag_dir;
   elist<CInode*>::item item_dirty_dirfrag_nest;
   elist<CInode*>::item item_dirty_dirfrag_dirfragtree;
+  elist<CInode*>::item item_scrub;
 
 public:
   int auth_pin_freeze_allowance;
index bdadc6d1f7168f33628cc2901de6930f8d0d84bf..9eb47f8b02ccf59dbd32208247f2975e89253824 100644 (file)
@@ -11740,20 +11740,16 @@ void MDCache::enqueue_scrub_work(MDRequestRef& mdr)
   if (!locked)
     return;
 
-  CDentry *dn = in->get_parent_dn();
-  // We got to this inode by path, so it must have a parent
-  assert(dn != NULL);
-
   C_MDS_EnqueueScrub *cs = static_cast<C_MDS_EnqueueScrub*>(mdr->internal_op_finish);
   ScrubHeaderRef &header = cs->header;
 
   // Cannot scrub same dentry twice at same time
-  if (dn->scrub_info()->dentry_scrubbing) {
+  if (in->scrub_info()->scrub_in_progress) {
     mds->server->respond_to_request(mdr, -EBUSY);
     return;
   }
 
-  header->origin = dn;
+  header->origin = in;
 
   // only set completion context for non-recursive scrub, because we don't 
   // want to block asok caller on long running scrub
@@ -11761,7 +11757,7 @@ void MDCache::enqueue_scrub_work(MDRequestRef& mdr)
   if (!header->recursive)
     fin = cs->take_finisher();
 
-  mds->scrubstack->enqueue_dentry_bottom(dn, header->recursive, false, header, fin);
+  mds->scrubstack->enqueue_inode_bottom(in, header, fin);
 
   mds->server->respond_to_request(mdr, 0);
   return;
index 35d355695e31df2a4d467ffa98bc0ec3e0d18647..3b7eadea23e608709ff8feb5384563ecd722d14a 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef SCRUB_HEADER_H_
 #define SCRUB_HEADER_H_
 
-class CDentry;
+class CInode;
 
 /**
  * Externally input parameters for a scrub, associated with the root
@@ -13,7 +13,7 @@ class CDentry;
  */
 class ScrubHeader {
 public:
-  CDentry *origin;
+  CInode *origin;
   std::string tag;
 
   bool recursive;
index df55b8fa2acd3e8a95f8f6406ddffae47c524f94..f3e5ce887be3f0799a8e33781a3f8e096aa4f1cd 100644 (file)
@@ -27,56 +27,54 @@ static ostream& _prefix(std::ostream *_dout, MDSRank *mds) {
   return *_dout << "mds." << mds->get_nodeid() << ".scrubstack ";
 }
 
-void ScrubStack::push_dentry(CDentry *dentry)
+void ScrubStack::push_inode(CInode *in)
 {
-  dout(20) << "pushing " << *dentry << " on top of ScrubStack" << dendl;
-  if (!dentry->item_scrub.is_on_list()) {
-    dentry->get(CDentry::PIN_SCRUBQUEUE);
+  dout(20) << "pushing " << *in << " on top of ScrubStack" << dendl;
+  if (!in->item_scrub.is_on_list()) {
+    in->get(CInode::PIN_SCRUBQUEUE);
     stack_size++;
   }
-  dentry_stack.push_front(&dentry->item_scrub);
+  inode_stack.push_front(&in->item_scrub);
 }
 
-void ScrubStack::push_dentry_bottom(CDentry *dentry)
+void ScrubStack::push_inode_bottom(CInode *in)
 {
-  dout(20) << "pushing " << *dentry << " on bottom of ScrubStack" << dendl;
-  if (!dentry->item_scrub.is_on_list()) {
-    dentry->get(CDentry::PIN_SCRUBQUEUE);
+  dout(20) << "pushing " << *in << " on bottom of ScrubStack" << dendl;
+  if (!in->item_scrub.is_on_list()) {
+    in->get(CInode::PIN_SCRUBQUEUE);
     stack_size++;
   }
-  dentry_stack.push_back(&dentry->item_scrub);
+  inode_stack.push_back(&in->item_scrub);
 }
 
-void ScrubStack::pop_dentry(CDentry *dn)
+void ScrubStack::pop_inode(CInode *in)
 {
-  dout(20) << "popping " << *dn
+  dout(20) << "popping " << *in
           << " off of ScrubStack" << dendl;
-  assert(dn->item_scrub.is_on_list());
-  dn->put(CDentry::PIN_SCRUBQUEUE);
-  dn->item_scrub.remove_myself();
+  assert(in->item_scrub.is_on_list());
+  in->put(CInode::PIN_SCRUBQUEUE);
+  in->item_scrub.remove_myself();
   stack_size--;
 }
 
-void ScrubStack::_enqueue_dentry(CDentry *dn, CDir *parent, bool recursive,
-    bool children, const ScrubHeaderRefConst& header,
-    Context *on_finish, bool top)
+void ScrubStack::_enqueue_inode(CInode *in, CDentry *parent,
+                               const ScrubHeaderRefConst& header,
+                               Context *on_finish, bool top)
 {
-  dout(10) << __func__ << " with {" << *dn << "}"
-           << ", recursive=" << recursive << ", children=" << children
+  dout(10) << __func__ << " with {" << *in << "}"
            << ", on_finish=" << on_finish << ", top=" << top << dendl;
   assert(mdcache->mds->mds_lock.is_locked_by_me());
-  dn->scrub_initialize(parent, recursive, children, header, on_finish);
+  in->scrub_initialize(parent, header, on_finish);
   if (top)
-    push_dentry(dn);
+    push_inode(in);
   else
-    push_dentry_bottom(dn);
+    push_inode_bottom(in);
 }
 
-void ScrubStack::enqueue_dentry(CDentry *dn, bool recursive, bool children,
-                                const ScrubHeaderRefConst& header,
-                                Context *on_finish, bool top)
+void ScrubStack::enqueue_inode(CInode *in, const ScrubHeaderRefConst& header,
+                               Context *on_finish, bool top)
 {
-  _enqueue_dentry(dn, NULL, recursive, children, header, on_finish, top);
+  _enqueue_inode(in, NULL, header, on_finish, top);
   kick_off_scrubs();
 }
 
@@ -85,38 +83,36 @@ void ScrubStack::kick_off_scrubs()
   dout(20) << __func__ << " entering with " << scrubs_in_progress << " in "
               "progress and " << stack_size << " in the stack" << dendl;
   bool can_continue = true;
-  elist<CDentry*>::iterator i = dentry_stack.begin();
+  elist<CInode*>::iterator i = inode_stack.begin();
   while (g_conf->mds_max_scrub_ops_in_progress > scrubs_in_progress &&
       can_continue && !i.end()) {
-    CDentry *cur = *i;
-
-    dout(20) << __func__ << " examining dentry " << *cur << dendl;
-
-    CInode *curi = cur->get_projected_inode();
+    CInode *curi = *i;
     ++i; // we have our reference, push iterator forward
 
+    dout(20) << __func__ << " examining " << *curi << dendl;
+
     if (!curi->is_dir()) {
       // it's a regular file, symlink, or hard link
-      pop_dentry(cur); // we only touch it this once, so remove from stack
+      pop_inode(curi); // we only touch it this once, so remove from stack
 
-      if (!cur->scrub_info()->on_finish) {
+      if (!curi->scrub_info()->on_finish) {
        scrubs_in_progress++;
-       cur->scrub_set_finisher(&scrub_kick);
+       curi->scrub_set_finisher(&scrub_kick);
       }
-      scrub_file_dentry(cur);
+      scrub_file_inode(curi);
       can_continue = true;
     } else {
       bool completed; // it's done, so pop it off the stack
       bool terminal; // not done, but we can start ops on other directories
       bool progress; // it added new dentries to the top of the stack
-      scrub_dir_dentry(cur, &progress, &terminal, &completed);
+      scrub_dir_inode(curi, &progress, &terminal, &completed);
       if (completed) {
         dout(20) << __func__ << " dir completed" << dendl;
-        pop_dentry(cur);
+        pop_inode(curi);
       } else if (progress) {
         dout(20) << __func__ << " dir progressed" << dendl;
         // we added new stuff to top of stack, so reset ourselves there
-        i = dentry_stack.begin();
+        i = inode_stack.begin();
       } else {
         dout(20) << __func__ << " dir no-op" << dendl;
       }
@@ -126,34 +122,20 @@ void ScrubStack::kick_off_scrubs()
   }
 }
 
-void ScrubStack::scrub_dir_dentry(CDentry *dn,
-                                  bool *added_children,
-                                  bool *terminal,
-                                  bool *done)
+void ScrubStack::scrub_dir_inode(CInode *in,
+                                 bool *added_children,
+                                 bool *terminal,
+                                 bool *done)
 {
-  assert(dn != NULL);
-  dout(10) << __func__ << *dn << dendl;
-
-  CInode *in = dn->get_projected_inode();
-  // FIXME: greg -- is get_version the appropriate version?  (i.e. is scrub_version
-  // // meant to be an actual version that we're scrubbing, or something else?)
-  if (!in->scrub_info()->scrub_in_progress) {
-    // We may come through here more than once on our way up and down
-    // the stack... or actually is that right?  Should we perhaps
-    // only see ourselves once on the way down and once on the way
-    // back up again, and not do this?
-    in->scrub_initialize(dn->scrub_info()->header);
-  }
+  dout(10) << __func__ << *in << dendl;
 
   *added_children = false;
   bool all_frags_terminal = true;
   bool all_frags_done = true;
 
-  if (!dn->scrub_info()->scrub_children &&
-      !dn->scrub_info()->scrub_recursive) {
-    dout(20) << "!scrub_children and !scrub_recursive" << dendl;
-  } else {
+  const ScrubHeaderRefConst& header = in->scrub_info()->header;
 
+  if (header->recursive) {
     list<frag_t> scrubbing_frags;
     list<CDir*> scrubbing_cdirs;
     in->scrub_dirfrags_scrubbing(&scrubbing_frags);
@@ -200,8 +182,8 @@ void ScrubStack::scrub_dir_dentry(CDentry *dn,
       bool frag_added_children = false;
       bool frag_terminal = true;
       bool frag_done = false;
-      scrub_dirfrag(cur_dir, dn->scrub_info()->scrub_recursive,
-         &frag_added_children, &frag_terminal, &frag_done);
+      scrub_dirfrag(cur_dir, header,
+                   &frag_added_children, &frag_terminal, &frag_done);
       if (frag_done) {
        // FIXME is this right?  Can we end up hitting this more than
        // once and is that a problem?
@@ -214,14 +196,17 @@ void ScrubStack::scrub_dir_dentry(CDentry *dn,
 
     dout(20) << "finished looping; all_frags_terminal=" << all_frags_terminal
             << ", all_frags_done=" << all_frags_done << dendl;
+  } else {
+    dout(20) << "!scrub_recursive" << dendl;
   }
+
   if (all_frags_done) {
     assert (!*added_children); // can't do this if children are still pending
 
     // OK, so now I can... fire off a validate on the dir inode, and
     // when it completes, come through here again, noticing that we've
     // set a flag to indicate the the validate happened, and 
-    scrub_dir_dentry_final(dn);
+    scrub_dir_inode_final(in);
   }
 
   *terminal = all_frags_terminal;
@@ -262,9 +247,9 @@ class C_InodeValidated : public MDSInternalContext
   public:
     ScrubStack *stack;
     CInode::validated_data result;
-    CDentry *target;
+    CInode *target;
 
-    C_InodeValidated(MDSRank *mds, ScrubStack *stack_, CDentry *target_)
+    C_InodeValidated(MDSRank *mds, ScrubStack *stack_, CInode *target_)
       : MDSInternalContext(mds), stack(stack_), target(target_)
     {}
 
@@ -275,9 +260,9 @@ class C_InodeValidated : public MDSInternalContext
 };
 
 
-void ScrubStack::scrub_dir_dentry_final(CDentry *dn)
+void ScrubStack::scrub_dir_inode_final(CInode *in)
 {
-  dout(20) << __func__ << *dn << dendl;
+  dout(20) << __func__ << *in << dendl;
 
   // Two passes through this function.  First one triggers inode validation,
   // second one sets finally_done
@@ -286,24 +271,24 @@ void ScrubStack::scrub_dir_dentry_final(CDentry *dn)
   // doing our validate_disk_state on the inode
   // FIXME: the magic-constructing scrub_info() is going to leave
   // an unneeded scrub_infop lying around here
-  if (!dn->scrub_info()->dentry_children_done) {
-    if (!dn->scrub_info()->on_finish) {
+  if (!in->scrub_info()->children_scrubbed) {
+    if (!in->scrub_info()->on_finish) {
       scrubs_in_progress++;
-      dn->scrub_set_finisher(&scrub_kick);
+      in->scrub_set_finisher(&scrub_kick);
     }
 
-    dn->scrub_children_finished();
-    CInode *in = dn->get_projected_inode();
-    C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, dn);
+    in->scrub_children_finished();
+    C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, in);
     in->validate_disk_state(&fin->result, fin);
   }
 
   return;
 }
 
-void ScrubStack::scrub_dirfrag(CDir *dir, bool recursive,
-                              bool *added_children,
-                              bool *is_terminal, bool *done)
+void ScrubStack::scrub_dirfrag(CDir *dir,
+                              const ScrubHeaderRefConst& header,
+                              bool *added_children, bool *is_terminal,
+                              bool *done)
 {
   assert(dir != NULL);
 
@@ -312,7 +297,6 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool recursive,
   *is_terminal = false;
   *done = false;
 
-  const ScrubHeaderRefConst& header = dir->get_inode()->scrub_info()->header;
 
   if (!dir->scrub_info()->directory_scrubbing) {
     // Get the frag complete before calling
@@ -376,58 +360,39 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool recursive,
     // never get random IO errors here.
     assert(r == 0);
 
-
     // FIXME: Do I *really* need to construct a kick context for every
     // single dentry I'm going to scrub?
-    _enqueue_dentry(dn,
-        dir,
-       recursive,
-        false,  // We are already recursing so scrub_children not meaningful
-        header,
-       NULL,
-        true);
+    _enqueue_inode(dn->get_projected_inode(), dn, header, NULL, true);
 
     *added_children = true;
   }
 }
 
-void ScrubStack::scrub_file_dentry(CDentry *dn)
+void ScrubStack::scrub_file_inode(CInode *in)
 {
-  assert(dn->get_linkage()->get_inode() != NULL);
-
-  CInode *in = dn->get_projected_inode();
-  C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, dn);
-
+  C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, in);
   // At this stage the DN is already past scrub_initialize, so
   // it's in the cache, it has PIN_SCRUBQUEUE and it is authpinned
   in->validate_disk_state(&fin->result, fin);
 }
 
-void ScrubStack::_validate_inode_done(CDentry *dn, int r,
-    const CInode::validated_data &result)
+void ScrubStack::_validate_inode_done(CInode *in, int r,
+                                     const CInode::validated_data &result)
 {
   // FIXME: do something real with result!  DamageTable!  Spamming
   // the cluster log for debugging purposes
   LogChannelRef clog = mdcache->mds->clog;
-  clog->info() << __func__ << " " << *dn << " r=" << r;
+  clog->info() << __func__ << " " << *in << " r=" << r;
 #if 0
-  assert(dn->scrub_info_p != NULL);
-  dn->scrub_info_p->inode_validated = true;
+  assert(in->scrub_infop != NULL);
+  in->scrub_infop->inode_validated = true;
 #endif
-  const ScrubHeaderRefConst header = dn->scrub_info()->header;
+  const ScrubHeaderRefConst header = in->scrub_info()->header;
 
   Context *c = NULL;
-  CInode *in = dn->get_projected_inode();
-  if (in->is_dir()) {
-    // For directories, inodes undergo a scrub_init/scrub_finish cycle
-    in->scrub_finished(&c);
-  } else {
-    // For regular files, we never touch the scrub_info on the inode,
-    // just the dentry.
-    dn->scrub_finished(&c);
-  }
+  in->scrub_finished(&c);
 
-  if (!header->recursive && dn == header->origin) {
+  if (!header->recursive && in == header->origin) {
     if (r >= 0) { // we got into the scrubbing dump it
       result.dump(header->formatter);
     } else { // we failed the lookup or something; dump ourselves
index 87f3ca242e6ff4dedd34b4129e4611fdab701c5a..39dbddcffb2693f0594060c2358b1d024efaedf5 100644 (file)
@@ -32,7 +32,7 @@ protected:
   Finisher *finisher;
 
   /// The stack of dentries we want to scrub
-  elist<CDentry*> dentry_stack;
+  elist<CInode*> inode_stack;
   /// current number of dentries we're actually scrubbing
   int scrubs_in_progress;
   ScrubStack *scrubstack; // hack for dout
@@ -55,53 +55,44 @@ public:
   MDCache *mdcache;
   ScrubStack(MDCache *mdc, Finisher *finisher_) :
     finisher(finisher_),
-    dentry_stack(member_offset(CDentry, item_scrub)),
+    inode_stack(member_offset(CInode, item_scrub)),
     scrubs_in_progress(0),
     scrubstack(this),
     stack_size(0),
     scrub_kick(mdc, this),
     mdcache(mdc) {}
   ~ScrubStack() {
-    assert(dentry_stack.empty());
+    assert(inode_stack.empty());
     assert(!scrubs_in_progress);
   }
   /**
-   * Put a dentry on the top of the scrub stack, so it is the highest priority.
+   * Put a inode on the top of the scrub stack, so it is the highest priority.
    * If there are other scrubs in progress, they will not continue scrubbing new
    * entries until this one is completed.
-   * @param dn The dentry to scrub
-   * @param recursive True if we want to recursively scrub the
-   * entire hierarchy under dn.
-   * @param children True if we want to scrub the direct children of
-   * dn but aren't doing a recursive scrub. (Otherwise, all checks are
-   * local to dn's disk state.)
+   * @param in The inodey to scrub
    * @param header The ScrubHeader propagated from whereever this scrub
    *               was initiated
    */
-  void enqueue_dentry_top(CDentry *dn, bool recursive, bool children,
-                          const ScrubHeaderRefConst& header,
-                          Context *on_finish) {
-    enqueue_dentry(dn, recursive, children, header, on_finish, true);
+  void enqueue_inode_top(CInode *in, const ScrubHeaderRefConst& header,
+                        Context *on_finish) {
+    enqueue_inode(in, header, on_finish, true);
   }
-  /** Like enqueue_dentry_top, but we wait for all pending scrubs before
+  /** Like enqueue_inode_top, but we wait for all pending scrubs before
    * starting this one.
    */
-  void enqueue_dentry_bottom(CDentry *dn, bool recursive, bool children,
-                             const ScrubHeaderRefConst& header,
-                             Context *on_finish) {
-    enqueue_dentry(dn, recursive, children, header, on_finish, false);
+  void enqueue_inode_bottom(CInode *in, const ScrubHeaderRefConst& header,
+                           Context *on_finish) {
+    enqueue_inode(in, header, on_finish, false);
   }
 
 private:
   /**
-   * Put the dentry at either the top or bottom of the stack, with
+   * Put the inode at either the top or bottom of the stack, with
    * the given scrub params, and then try and kick off more scrubbing.
    */
-  void enqueue_dentry(CDentry *dn, bool recursive, bool children,
-                      const ScrubHeaderRefConst& header,
+  void enqueue_inode(CInode *in, const ScrubHeaderRefConst& header,
                       Context *on_finish, bool top);
-  void _enqueue_dentry(CDentry *dn, CDir *parent, bool recursive, bool children,
-                      const ScrubHeaderRefConst& header,
+  void _enqueue_inode(CInode *in, CDentry *parent, const ScrubHeaderRefConst& header,
                       Context *on_finish, bool top);
   /**
    * Kick off as many scrubs as are appropriate, based on the current
@@ -109,34 +100,32 @@ private:
    */
   void kick_off_scrubs();
   /**
-   * Push a dentry on top of the stack.
+   * Push a indoe on top of the stack.
    */
-  inline void push_dentry(CDentry *dentry);
+  inline void push_inode(CInode *in);
   /**
-   * Push a dentry to the bottom of the stack.
+   * Push a inode to the bottom of the stack.
    */
-  inline void push_dentry_bottom(CDentry *dentry);
+  inline void push_inode_bottom(CInode *in);
   /**
-   * Pop the given dentry off the stack.
+   * Pop the given inode off the stack.
    */
-  inline void pop_dentry(CDentry *dn);
+  inline void pop_inode(CInode *in);
 
   /**
-   * Scrub a file-representing dentry.
-   * @param dn The dentry to scrub
-   * @param progress Out pointer to a bool, which will be set to true.
-   * @pre dn->get_projected_inode()->is_file()==true;
+   * Scrub a file inode.
+   * @param in The indoe to scrub
    */
-  void scrub_file_dentry(CDentry *dn);
+  void scrub_file_inode(CInode *in);
 
   /**
    * Callback from completion of CInode::validate_disk_state
-   * @param dn The dentry owning the inode we were validating
+   * @param in The inode we were validating
    * @param r The return status from validate_disk_state
    * @param result Populated results from validate_disk_state
    */
-  void _validate_inode_done(CDentry *dn, int r,
-    const CInode::validated_data &result);
+  void _validate_inode_done(CInode *in, int r,
+                           const CInode::validated_data &result);
   friend class C_InodeValidated;
 
   /**
@@ -152,15 +141,15 @@ private:
    *
    * 4) If all dirfrags have been scrubbed, scrub my inode.
    *
-   * @param dn The CDentry to scrub as a directory
+   * @param in The CInode to scrub as a directory
    * @param added_dentries set to true if we pushed some of our children
    * onto the ScrubStack
    * @param is_terminal set to true if there are no descendant dentries
    * remaining to start scrubbing.
    * @param done set to true if we and all our children have finished scrubbing
    */
-  void scrub_dir_dentry(CDentry *dn, bool *added_children, bool *is_terminal,
-                        bool *done);
+  void scrub_dir_inode(CInode *in, bool *added_children, bool *is_terminal,
+                       bool *done);
   /**
    * Make progress on scrubbing a dirfrag. It may return after each of the
    * following steps, but will report making progress on each one.
@@ -175,14 +164,14 @@ private:
    * progress. Try again later.
    *
    */
-  void scrub_dirfrag(CDir *dir, bool recursive,
+  void scrub_dirfrag(CDir *dir, const ScrubHeaderRefConst& header,
                     bool *added_children, bool *is_terminal, bool *done);
   /**
    * Scrub a directory-representing dentry.
    *
-   * @param dn The CDentry of the directory we're doing final scrub on.
+   * @param in The directory inode we're doing final scrub on.
    */
-  void scrub_dir_dentry_final(CDentry *dn);
+  void scrub_dir_inode_final(CInode *in);
 
   /**
    * Get a CDir into memory, and return it if it's already complete.