Fixed Yang Sheng's patch as per Robert's comment.
i=rread
void cfs_hash_for_each_empty(cfs_hash_t *hs, cfs_hash_for_each_cb_t, void *data);
void cfs_hash_for_each_key(cfs_hash_t *hs, void *key,
cfs_hash_for_each_cb_t, void *data);
+typedef int (*cfs_hash_cond_opt_cb_t)(void *obj, void *data);
+void cfs_hash_cond_del(cfs_hash_t *hs, cfs_hash_cond_opt_cb_t, void *data);
/*
* Rehash - Theta is calculated to be the average chained
CFS_EXPORT_SYMBOL(cfs_hash_del);
/**
+ * Delete item from the libcfs hash @hs when @func return true.
+ * The write lock being hold during loop for each bucket to avoid
+ * any object be reference.
+ */
+void
+cfs_hash_cond_del(cfs_hash_t *hs, cfs_hash_cond_opt_cb_t func, void *data)
+{
+ cfs_hlist_node_t *hnode;
+ cfs_hlist_node_t *pos;
+ cfs_hash_bucket_t *hsb;
+ int i;
+ ENTRY;
+
+ cfs_hash_wlock(hs);
+ cfs_hash_for_each_bucket(hs, hsb, i) {
+ cfs_write_lock(&hsb->hsb_rwlock);
+ cfs_hlist_for_each_safe(hnode, pos, &(hsb->hsb_head)) {
+ __cfs_hash_bucket_validate(hs, hsb, hnode);
+ if (func(cfs_hash_get(hs, hnode), data))
+ __cfs_hash_bucket_del(hs, hsb, hnode);
+ (void)cfs_hash_put(hs, hnode);
+ }
+ cfs_write_unlock(&hsb->hsb_rwlock);
+ }
+ cfs_hash_wunlock(hs);
+
+ EXIT;
+}
+CFS_EXPORT_SYMBOL(cfs_hash_cond_del);
+
+/**
* Delete item given @key in libcfs hash @hs. The first @key found in
* the hash will be removed, if the key exists multiple times in the hash
* @hs this function must be called once per key. The removed object
cfs_write_lock(&new_hsb->hsb_rwlock);
cfs_write_lock(&old_hsb->hsb_rwlock);
} else { /* do nothing */
- cfs_read_unlock(&hs->hs_rwlock);
+ cfs_hash_runlock(hs);
EXIT;
return;
}
#define EXP_MD_COUNTER_INCREMENT(exp, op)
#endif
+static inline int lprocfs_nid_ldlm_stats_init(struct nid_stat* tmp) {
+ /* 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_MD_OP(obd, op, err) \
do { \
if (!OBT(obd) || !MDP((obd), op)) { \
RETURN(rc);
}
if (newnid) {
- /* Always add in ldlm_stats */
- exp->exp_nid_stats->nid_ldlm_stats =
- lprocfs_alloc_stats(LDLM_LAST_OPC - LDLM_FIRST_OPC,
- LPROCFS_STATS_FLAG_NOPERCPU);
- if (exp->exp_nid_stats->nid_ldlm_stats == NULL)
- GOTO(clean, rc = -ENOMEM);
- lprocfs_init_ldlm_stats(exp->exp_nid_stats->nid_ldlm_stats);
- rc = lprocfs_register_stats(exp->exp_nid_stats->nid_proc,
- "ldlm_stats",
- exp->exp_nid_stats->nid_ldlm_stats);
+ rc = lprocfs_nid_ldlm_stats_init(exp->exp_nid_stats);
if (rc)
GOTO(clean, rc);
}
}
if (newnid) {
- /* Always add in ldlm_stats */
- exp->exp_nid_stats->nid_ldlm_stats =
- lprocfs_alloc_stats(LDLM_LAST_OPC - LDLM_FIRST_OPC,
- LPROCFS_STATS_FLAG_NOPERCPU);
- if (exp->exp_nid_stats->nid_ldlm_stats == NULL)
- GOTO(clean, rc = -ENOMEM);
- lprocfs_init_ldlm_stats(exp->exp_nid_stats->nid_ldlm_stats);
- rc = lprocfs_register_stats(exp->exp_nid_stats->nid_proc,
- "ldlm_stats",
- exp->exp_nid_stats->nid_ldlm_stats);
+ rc = lprocfs_nid_ldlm_stats_init(exp->exp_nid_stats);
if (rc)
GOTO(clean, rc);
}
}
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", cfs_atomic_read(&stat->nid_exp_ref_count));
if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
- cfs_hlist_del_init(&stat->nid_hash);
- nidstat_putref(stat);
cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
cfs_list_move(&stat->nid_list, data);
cfs_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);
- cfs_hash_for_each(obd->obd_nid_stats_hash,
+ cfs_hash_cond_del(obd->obd_nid_stats_hash,
lprocfs_nid_stats_clear_write_cb, &free_list);
while (!cfs_list_empty(&free_list)) {
tmp->nid_stats);
if (rc)
GOTO(clean, 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)
- GOTO(clean, rc = -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)
GOTO(clean, rc);
}
}
run_test 85 "ensure there is no reply on bulk write if obd is in rdonly mode"
+test_86() {
+ umount $MOUNT
+ do_facet $SINGLEMDS lctl set_param mdt.${FSNAME}-MDT*.exports.clear=0
+ remount_facet $SINGLEMDS
+}
+run_test 86 "umount server after clear nid_stats should not hit LBUG"
+
equals_msg `basename $0`: test complete, cleaning up
check_and_cleanup_lustre
[ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG && grep -q FAIL $TESTSUITELOG && exit 1 || true
fi
}
+remount_facet() {
+ local facet=$1
+
+ stop $facet
+ mount_facet $facet
+}
+
reboot_facet() {
facet=$1
if [ "$FAILURE_MODE" = HARD ]; then