}
}
+void CDentry::scrub_initialize(CDir *parent, bool recurse, bool children,
+ 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;
+
+ 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;
+
+ 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();
+}
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?
+
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";
default: return generic_pin_name(p);
}
}
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
+ Context *on_finish; /// called when we finish scrubbing
+ scrub_info_t() :
+ scrub_parent(NULL), scrub_recursive(false),
+ scrub_children(false), dentry_scrubbing(false), on_finish(NULL)
+ {}
+ };
+
protected:
CDir *dir; // containing dirfrag
linkage_t linkage;
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;
+ 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,
+ Context *f);
+ void scrub_finished(Context **c);
+
+private:
+ /**
+ * Create a scrub_info_t struct for the scrub_infop pointer.
+ */
+ void scrub_info_create() const;
+
protected:
friend class Migrator;
friend class Locker;
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) {
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) {
linkage.remote_d_type = dt;
}
~CDentry() {
+ assert(!scrub_infop);
g_num_dn--;
g_num_dns++;
}