}
};
-/**
- * Purge a dentry from a stray directory. This function
- * is called once eval_stray is satisfied and StrayManager
- * throttling is also satisfied. There is no going back
- * at this stage!
- */
void StrayManager::purge(CDentry *dn, uint32_t op_allowance)
{
CDentry::linkage_t *dnl = dn->get_projected_linkage();
}
};
-/**
- * Completion handler for a Filer::purge on a stray inode.
- *
- *
- */
void StrayManager::_purge_stray_purged(
CDentry *dn, uint32_t ops_allowance, bool only_head)
{
}
}
-
-/**
- * Enqueue a purge operation on a dentry that has passed the tests
- * in eval_stray. This may start the operation inline if the throttle
- * allowances are already available.
- *
- * @param trunc false to purge dentry (normal), true to just truncate
- * inode (snapshots)
- */
void StrayManager::enqueue(CDentry *dn, bool trunc)
{
CDentry::linkage_t *dnl = dn->get_projected_linkage();
}
}
-
-/**
- * Iteratively call _consume on items from the ready_for_purge
- * list until it returns false (throttle limit reached)
- */
void StrayManager::_advance()
{
std::list<QueuedStray>::iterator i;
ready_for_purge.erase(ready_for_purge.begin(), i);
}
-/**
- * Attempt to purge an inode, if throttling permits
- * it. Note that there are compromises to how
- * the throttling works, in interests of simplicity:
+/*
+ * Note that there are compromises to how throttling
+ * is implemented here, in the interests of simplicity:
* * If insufficient ops are available to execute
* the next item on the queue, we block even if
* there are items further down the queue requiring
* required by a single inode is greater than the
* limit, for example directories with very many
* fragments.
- *
- * Return true if we successfully consumed resource,
- * false if insufficient resource was available.
*/
bool StrayManager::_consume(CDentry *dn, bool trunc, uint32_t ops_required)
{
return true;
}
-
-/**
- * Return the maximum number of concurrent RADOS ops that
- * may be executed while purging this inode.
- *
- * @param trunc true if it's a truncate, false if it's a purge
- */
uint32_t StrayManager::_calculate_ops_required(CInode *in, bool trunc)
{
uint32_t ops_required = 0;
}
};
-/**
- * Evaluate a stray dentry for purging or reintegration.
- *
- * If the inode has no linkage, and no more references, then
- * we may decide to purge it.
- *
- * If the inode still has linkage, then it means someone else
- * (a hard link) is still referring to it, and we should
- * think about reintegrating that inode into the remote dentry.
- *
- * @returns true if the dentry will be purged (caller should never
- * take more refs after this happens), else false.
- */
bool StrayManager::eval_stray(CDentry *dn, bool delay)
{
dout(10) << "eval_stray " << *dn << dendl;
}
}
-
-
-/**
- * When hard links exist to an inode whose primary dentry
- * is unlinked, the inode gets a stray primary dentry.
- *
- * We may later "reintegrate" the inode into a remaining
- * non-stray dentry (one of what was previously a remote
- * dentry) by issuing a rename from the stray to the other
- * dentry.
- */
void StrayManager::reintegrate_stray(CDentry *straydn, CDentry *rdn)
{
dout(10) << __func__ << " " << *straydn << " into " << *rdn << dendl;
mds->send_message_mds(req, rdn->authority().first);
}
-
-/**
- * Given a dentry within one of my stray directories,
- * send it off to a stray directory in another MDS.
- *
- * This is for use:
- * * Case A: when shutting down a rank, we migrate strays
- * away from ourselves rather than waiting for purge
- * * Case B: when a client request has a trace that refers to
- * a stray inode on another MDS, we migrate that inode from
- * there to here, in order that we can later re-integrate it
- * here.
- *
- * In case B, the receiver should be calling into eval_stray
- * on completion of mv (i.e. inode put), resulting in a subsequent
- * reintegration.
- */
void StrayManager::migrate_stray(CDentry *dn, mds_rank_t to)
{
CInode *in = dn->get_linkage()->get_inode();
update_op_limit();
}
-
-/**
- * For any strays that are enqueued for purge, but
- * currently blocked on throttling, clear their
- * purging status. Used during MDS rank shutdown
- * so that it can migrate these strays instead
- * of waiting for them to trickle through the
- * queue.
- */
void StrayManager::abort_queue()
{
for (std::list<QueuedStray>::iterator i = ready_for_purge.begin();
gather.activate();
}
-
-/**
- * Callback: we have logged the update to an inode's metadata
- * reflecting it's newly-zeroed length.
- */
void StrayManager::_truncate_stray_logged(CDentry *dn, LogSegment *ls)
{
CInode *in = dn->get_projected_linkage()->get_inode();
return KEYS;
}
-
-// Subscribe to the per-PG ops throttle config event, and do a cool calculation
-// of (throttle * pg_num / (mds_num))
void StrayManager::handle_conf_change(const struct md_config_t *conf,
const std::set <std::string> &changed)
{
uint64_t num_strays_delayed;
void truncate(CDentry *dn, uint32_t op_allowance);
+
+ /**
+ * Purge a dentry from a stray directory. This function
+ * is called once eval_stray is satisfied and StrayManager
+ * throttling is also satisfied. There is no going back
+ * at this stage!
+ */
void purge(CDentry *dn, uint32_t op_allowance);
+
+ /**
+ * Completion handler for a Filer::purge on a stray inode.
+ */
void _purge_stray_purged(CDentry *dn, uint32_t ops, bool only_head);
+
void _purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls);
+
+ /**
+ * Callback: we have logged the update to an inode's metadata
+ * reflecting it's newly-zeroed length.
+ */
void _truncate_stray_logged(CDentry *dn, LogSegment *ls);
friend class StrayManagerIOContext;
friend class C_TruncateStrayLogged;
friend class C_IO_PurgeStrayPurged;
+ /**
+ * Enqueue a purge operation on a dentry that has passed the tests
+ * in eval_stray. This may start the operation inline if the throttle
+ * allowances are already available.
+ *
+ * @param trunc false to purge dentry (normal), true to just truncate
+ * inode (snapshots)
+ */
+ void enqueue(CDentry *dn, bool trunc);
+
+ /**
+ * Iteratively call _consume on items from the ready_for_purge
+ * list until it returns false (throttle limit reached)
+ */
void _advance();
+
+ /**
+ * Attempt to purge an inode, if throttling permits
+ * its.
+ *
+ * Return true if we successfully consumed resource,
+ * false if insufficient resource was available.
+ */
bool _consume(CDentry *dn, bool trunc, uint32_t ops_required);
+
+ /**
+ * Return the maximum number of concurrent RADOS ops that
+ * may be executed while purging this inode.
+ *
+ * @param trunc true if it's a truncate, false if it's a purge
+ */
uint32_t _calculate_ops_required(CInode *in, bool trunc);
+ /**
+ * When hard links exist to an inode whose primary dentry
+ * is unlinked, the inode gets a stray primary dentry.
+ *
+ * We may later "reintegrate" the inode into a remaining
+ * non-stray dentry (one of what was previously a remote
+ * dentry) by issuing a rename from the stray to the other
+ * dentry.
+ */
void reintegrate_stray(CDentry *dn, CDentry *rlink);
-
// My public interface is for consumption by MDCache
public:
+ StrayManager(MDS *mds);
+ void set_logger(PerfCounters *l) {logger = l;}
- void enqueue(CDentry *dn, bool trunc);
+ /**
+ * Where eval_stray was previously invoked with delay=true, call
+ * eval_stray again for any dentries that were put on the
+ * delayed_eval_stray list as a result of the original call.
+ *
+ * Used so that various places can call eval_stray(delay=true) during
+ * an operation to identify dentries of interest, and then call
+ * this function later during trim in order to do the final
+ * evaluation (and resulting actions) while not in the middle of another
+ * metadata operation.
+ */
void advance_delayed();
+
+ /**
+ * Evaluate a stray dentry for purging or reintegration.
+ *
+ * purging: If the inode has no linkage, and no more references, then
+ * we may decide to purge it.
+ *
+ * reintegration: If the inode still has linkage, then it means someone else
+ * (a hard link) is still referring to it, and we should
+ * think about reintegrating that inode into the remote dentry.
+ *
+ * @returns true if the dentry will be purged (caller should never
+ * take more refs after this happens), else false.
+ */
bool eval_stray(CDentry *dn, bool delay=false);
+
+ /**
+ * When a metadata op touches a remote dentry that points to
+ * a stray, call in here to evaluate it for migration (move
+ * a stray residing on another MDS to this MDS) or reintegration
+ * (move a stray dentry's inode into a non-stray hardlink dentry and
+ * clean up the stray).
+ *
+ * @param stray_dn a stray dentry whose inode has been referenced
+ * by a remote dentry
+ * @param remote_dn (optional) which remote dentry was touched
+ * in an operation that led us here: this is used
+ * as a hint for which remote to reintegrate into
+ * if there are multiple remotes.
+ */
void eval_remote_stray(CDentry *stray_dn, CDentry *remote_dn=NULL);
+
+ /**
+ * Given a dentry within one of my stray directories,
+ * send it off to a stray directory in another MDS.
+ *
+ * This is for use:
+ * * Case A: when shutting down a rank, we migrate strays
+ * away from ourselves rather than waiting for purge
+ * * Case B: when a client request has a trace that refers to
+ * a stray inode on another MDS, we migrate that inode from
+ * there to here, in order that we can later re-integrate it
+ * here.
+ *
+ * In case B, the receiver should be calling into eval_stray
+ * on completion of mv (i.e. inode put), resulting in a subsequent
+ * reintegration.
+ */
void migrate_stray(CDentry *dn, mds_rank_t dest);
- StrayManager(MDS *mds);
- void set_logger(PerfCounters *l) {logger = l;}
+ /**
+ * Update stats to reflect a newly created stray dentry. Needed
+ * because stats on strays live here, but creation happens
+ * in Server or MDCache. For our purposes "creation" includes
+ * loading a stray from a dirfrag and migrating a stray from
+ * another MDS, in addition to creations per-se.
+ */
void notify_stray_created();
+
+ /**
+ * Update stats to reflect a removed stray dentry. Needed because
+ * stats on strays live here, but removal happens in Server or
+ * MDCache. Also includes migration (rename) of strays from
+ * this MDS to another MDS.
+ */
void notify_stray_removed();
+
+ /**
+ * For any strays that are enqueued for purge, but
+ * currently blocked on throttling, clear their
+ * purging status. Used during MDS rank shutdown
+ * so that it can migrate these strays instead
+ * of waiting for them to trickle through the
+ * queue.
+ */
void abort_queue();
+ /*
+ * Calculate our local RADOS op throttle limit based on
+ * (mds_max_purge_ops_per_pg / number_of_mds) * number_of_pg
+ *
+ * Call this whenever one of those operands changes.
+ */
void update_op_limit();
+
+ /**
+ * Subscribe to changes on mds_max_purge_ops
+ */
virtual const char** get_tracked_conf_keys() const;
+
+ /**
+ * Call update_op_limit if mds_max_purge_ops changes
+ */
virtual void handle_conf_change(const struct md_config_t *conf,
const std::set <std::string> &changed);
};