/* Hash deletion functions */
void *lustre_hash_del(lustre_hash_t *lh, void *key, struct hlist_node *hnode);
void *lustre_hash_del_key(lustre_hash_t *lh, void *key);
+typedef int (*lh_cond_opt_cb)(void *obj, void *data);
+void lustre_hash_cond_del(lustre_hash_t *lh, lh_cond_opt_cb, void *data);
/* Hash lookup/for_each functions */
void *lustre_hash_lookup(lustre_hash_t *lh, void *key);
#define EXP_COUNTER_INCREMENT(exp, op);
#endif
+static inline int lprocfs_nid_ldlm_stats_init(struct nid_stat* tmp) {
+ int rc;
+
+ rc = lprocfs_register_stats(tmp->nid_proc, "stats",
+ tmp->nid_stats);
+ if (rc)
+ return rc;
+
+ /* Always add in ldlm_stats */
+ tmp->nid_ldlm_stats = lprocfs_alloc_stats(LDLM_LAST_OPC - LDLM_FIRST_OPC
+ ,LPROCFS_STATS_FLAG_NOPERCPU);
+ if (tmp->nid_ldlm_stats == NULL)
+ return -ENOMEM;
+
+ lprocfs_init_ldlm_stats(tmp->nid_ldlm_stats);
+
+ return lprocfs_register_stats(tmp->nid_proc, "ldlm_stats",
+ tmp->nid_ldlm_stats);
+}
+
#define OBD_CHECK_OP(obd, op, err) \
do { \
if (!OBT(obd) || !OBP((obd), op)) {\
return -ENOMEM;
lprocfs_init_ops_stats(LPROC_MDS_LAST, tmp->nid_stats);
- rc = lprocfs_register_stats(tmp->nid_proc, "stats",
- tmp->nid_stats);
- if (rc)
- return rc;
-
mds_stats_counter_init(tmp->nid_stats);
- /* Always add in ldlm_stats */
- tmp->nid_ldlm_stats =
- lprocfs_alloc_stats(LDLM_LAST_OPC - LDLM_FIRST_OPC,
- LPROCFS_STATS_FLAG_NOPERCPU);
- if (tmp->nid_ldlm_stats == NULL)
- return -ENOMEM;
-
- lprocfs_init_ldlm_stats(tmp->nid_ldlm_stats);
-
- rc = lprocfs_register_stats(tmp->nid_proc, "ldlm_stats",
- tmp->nid_ldlm_stats);
+ rc = lprocfs_nid_ldlm_stats_init(tmp);
if (rc)
return rc;
}
lprocfs_init_ops_stats(LPROC_MGS_LAST, tmp->nid_stats);
mgs_stats_counter_init(tmp->nid_stats);
- rc = lprocfs_register_stats(tmp->nid_proc, "stats",
- tmp->nid_stats);
- if (rc)
- return rc;
-
- /* Always add in ldlm_stats */
- tmp->nid_ldlm_stats =
- lprocfs_alloc_stats(LDLM_LAST_OPC - LDLM_FIRST_OPC,
- LPROCFS_STATS_FLAG_NOPERCPU);
- if (tmp->nid_ldlm_stats == NULL)
- return -ENOMEM;
-
- lprocfs_init_ldlm_stats(tmp->nid_ldlm_stats);
- rc = lprocfs_register_stats(tmp->nid_proc, "ldlm_stats",
- tmp->nid_ldlm_stats);
+ rc = lprocfs_nid_ldlm_stats_init(tmp);
if (rc)
return rc;
}
EXPORT_SYMBOL(lustre_hash_del);
/**
+ * Delete item from the lustre hash @lh when @func return true.
+ * The write lock being hold during loop for each bucket to avoid
+ * any object be reference.
+ */
+void
+lustre_hash_cond_del(lustre_hash_t *lh, lh_cond_opt_cb func, void *data)
+{
+ lustre_hash_bucket_t *lhb;
+ struct hlist_node *hnode;
+ struct hlist_node *pos;
+ int i;
+ ENTRY;
+
+ LASSERT(lh != NULL);
+
+ lh_write_lock(lh);
+ lh_for_each_bucket(lh, lhb, i) {
+ if (lhb == NULL)
+ continue;
+
+ write_lock(&lhb->lhb_rwlock);
+ hlist_for_each_safe(hnode, pos, &(lhb->lhb_head)) {
+ __lustre_hash_bucket_validate(lh, lhb, hnode);
+ if (func(lh_get(lh, hnode), data))
+ __lustre_hash_bucket_del(lh, lhb, hnode);
+ (void)lh_put(lh, hnode);
+ }
+ write_unlock(&lhb->lhb_rwlock);
+ }
+ lh_write_unlock(lh);
+
+ EXIT;
+}
+EXPORT_SYMBOL(lustre_hash_cond_del);
+
+/**
* Delete item given @key in lustre hash @lh. The first @key found in
* the hash will be removed, if the key exists multiple times in the hash
* @lh this function must be called once per key. The removed object
}
EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
-void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
+int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
{
struct nid_stat *stat = obj;
int i;
* add/delete blocked by hash bucket lock */
CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
if (atomic_read(&stat->nid_exp_ref_count) == 2) {
- hlist_del_init(&stat->nid_hash);
- nidstat_putref(stat);
spin_lock(&stat->nid_obd->obd_nid_lock);
list_move(&stat->nid_list, data);
spin_unlock(&stat->nid_obd->obd_nid_lock);
- EXIT;
- return;
+ RETURN(1);
}
/* we has reference to object - only clear data*/
if (stat->nid_stats)
for (i = 0; i < BRW_LAST; i++)
lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
}
- EXIT;
- return;
+ RETURN(0);
}
int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
struct nid_stat *client_stat;
CFS_LIST_HEAD(free_list);
- lustre_hash_for_each(obd->obd_nid_stats_hash,
+ lustre_hash_cond_del(obd->obd_nid_stats_hash,
lprocfs_nid_stats_clear_write_cb, &free_list);
while (!list_empty(&free_list)) {
if (rc)
RETURN(rc);
- rc = lprocfs_register_stats(tmp->nid_proc, "stats",
- tmp->nid_stats);
+ rc = lprocfs_nid_ldlm_stats_init(tmp);
if (rc)
RETURN(rc);
-
- /* Always add in ldlm_stats */
- tmp->nid_ldlm_stats =
- lprocfs_alloc_stats(LDLM_LAST_OPC - LDLM_FIRST_OPC,
- LPROCFS_STATS_FLAG_NOPERCPU);
- if (tmp->nid_ldlm_stats == NULL)
- return -ENOMEM;
-
- lprocfs_init_ldlm_stats(tmp->nid_ldlm_stats);
-
- rc = lprocfs_register_stats(tmp->nid_proc, "ldlm_stats",
- tmp->nid_ldlm_stats);
}
RETURN(0);