extern int lprocfs_add_clear_entry(struct obd_device * obd,
cfs_proc_dir_entry_t *entry);
extern int lprocfs_exp_setup(struct obd_export *exp,
- lnet_nid_t *peer_nid, int *newnid);
+ lnet_nid_t *peer_nid, int reconnect, int *newnid);
extern int lprocfs_exp_cleanup(struct obd_export *exp);
extern cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
char *name,
struct obd_export;
static inline int lprocfs_add_clear_entry(struct obd_export *exp)
{ return 0; }
-static inline int lprocfs_exp_setup(struct obd_export *exp,
- lnet_nid_t *peer_nid, int *newnid)
+static inline int lprocfs_exp_setup(struct obd_export *exp,lnet_nid_t *peer_nid,
+ int reconnect, int *newnid)
{ return 0; }
static inline int lprocfs_exp_cleanup(struct obd_export *exp)
{ return 0; }
int mdt_export_stats_init(struct obd_device *obd,
struct obd_export *exp,
+ int reconnect,
void *localdata)
{
lnet_nid_t *client_nid = localdata;
int rc, newnid;
ENTRY;
- rc = lprocfs_exp_setup(exp, client_nid, &newnid);
+ rc = lprocfs_exp_setup(exp, client_nid, reconnect, &newnid);
if (rc) {
/* Mask error for already created
* /proc entries */
memcpy(lcd->lcd_uuid, cluuid, sizeof lcd->lcd_uuid);
rc = mdt_client_new(env, mdt);
if (rc == 0)
- mdt_export_stats_init(obd, lexp, localdata);
+ mdt_export_stats_init(obd, lexp, 0, localdata);
}
out:
rc = mdt_connect_internal(exp, mdt_dev(obd->obd_lu_dev), data);
if (rc == 0)
- mdt_export_stats_init(obd, exp, localdata);
+ mdt_export_stats_init(obd, exp, 1, localdata);
RETURN(rc);
}
int mdt_export_stats_init(struct obd_device *obd,
struct obd_export *exp,
+ int reconnect,
void *client_nid);
int mdt_pin(struct mdt_thread_info* info);
#include <libcfs/list.h>
#include "mgs_internal.h"
-static int mgs_export_stats_init(struct obd_device *obd, struct obd_export *exp,
- void *localdata)
+int mgs_export_stats_init(struct obd_device *obd, struct obd_export *exp,
+ int reconnect, void *localdata)
+
{
lnet_nid_t *client_nid = localdata;
int rc, newnid;
ENTRY;
- rc = lprocfs_exp_setup(exp, client_nid, &newnid);
+ rc = lprocfs_exp_setup(exp, client_nid, reconnect, &newnid);
if (rc) {
/* Mask error for already created
* /proc entries */
int mgs_client_add(struct obd_device *obd, struct obd_export *exp,
void *localdata)
{
- return mgs_export_stats_init(obd, exp, localdata);
+ return 0;
}
/* Remove client export data from the MGS */
data->ocd_version = LUSTRE_VERSION_CODE;
}
- rc = mgs_client_add(obd, lexp, localdata);
+ rc = mgs_export_stats_init(obd, lexp, 0, localdata);
if (rc) {
class_disconnect(lexp);
data->ocd_version = LUSTRE_VERSION_CODE;
}
- RETURN(0);
+ RETURN(mgs_export_stats_init(obd, exp, 1, localdata));
}
static int mgs_disconnect(struct obd_export *exp)
void mgs_revoke_lock(struct obd_device *obd, struct fs_db *fsdb);
/* mgs_fs.c */
-int mgs_client_add(struct obd_device *obd, struct obd_export *exp,
- void *localdata);
+int mgs_export_stats_init(struct obd_device *obd, struct obd_export *exp,
+ int reconnect, void *localdata);
int mgs_client_free(struct obd_export *exp);
int mgs_fs_setup(struct obd_device *obd, struct vfsmount *mnt);
int mgs_fs_cleanup(struct obd_device *obddev);
}
EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
-int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
+int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int reconnect,
+ int *newnid)
{
struct nid_stat *new_stat, *old_stat;
struct obd_device *obd = NULL;
new_stat->nid = *nid;
new_stat->nid_obd = exp->exp_obd;
- cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
+ /* we need set default refcount to 1 to balance obd_disconnect */
+ cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
nid, &new_stat->nid_hash);
/* Return -EALREADY here so that we know that the /proc
* entry already has been created */
if (old_stat != new_stat) {
- cfs_spin_lock(&obd->obd_nid_lock);
- if (exp->exp_nid_stats != old_stat) {
- if (exp->exp_nid_stats)
- nidstat_putref(exp->exp_nid_stats);
- exp->exp_nid_stats = old_stat;
- } else {
- /* cfs_hash_findadd_unique() has added
- * old_stat's refcount */
+ /* if this connects to the existing export of same nid,
+ * we need to release old stats for obd_disconnect won't
+ * balance the reference gotten in "cfs_hash_findadd_uinque" */
+ if (reconnect && exp->exp_nid_stats)
nidstat_putref(old_stat);
- }
-
- cfs_spin_unlock(&obd->obd_nid_lock);
+ exp->exp_nid_stats = old_stat;
GOTO(destroy_new, rc = -EALREADY);
}
/* not found - create */
GOTO(destroy_new_ns, rc);
}
- if (exp->exp_nid_stats)
- nidstat_putref(exp->exp_nid_stats);
- nidstat_getref(new_stat);
exp->exp_nid_stats = new_stat;
*newnid = 1;
/* protect competitive add to list, not need locking on destroy */
cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
destroy_new:
+ nidstat_putref(new_stat);
OBD_FREE_PTR(new_stat);
RETURN(rc);
}
plus the procfs overhead :( */
static int filter_export_stats_init(struct obd_device *obd,
struct obd_export *exp,
+ int reconnect,
void *client_nid)
{
int rc, newnid = 0;
/* Self-export gets no proc entry */
RETURN(0);
- rc = lprocfs_exp_setup(exp, client_nid, &newnid);
+ rc = lprocfs_exp_setup(exp, client_nid, reconnect, &newnid);
if (rc) {
/* Mask error for already created
* /proc entries */
fed = &exp->exp_filter_data;
*fed->fed_ted.ted_lcd = *lcd;
fed->fed_group = 0; /* will be assigned at connect */
- filter_export_stats_init(obd, exp, NULL);
+ filter_export_stats_init(obd, exp, 0, NULL);
rc = filter_client_add(obd, exp, cl_idx);
/* can't fail for existing client */
LASSERTF(rc == 0, "rc = %d\n", rc);
rc = filter_connect_internal(exp, data, 1);
if (rc == 0)
- filter_export_stats_init(obd, exp, localdata);
+ filter_export_stats_init(obd, exp, 1, localdata);
RETURN(rc);
}
if (rc)
GOTO(cleanup, rc);
- filter_export_stats_init(obd, lexp, localdata);
+ filter_export_stats_init(obd, lexp, 0, localdata);
if (obd->obd_replayable) {
struct lsd_client_data *lcd = lexp->exp_target_data.ted_lcd;
LASSERT(lcd);