Description: Add st_block checking to multistat.c.
Details : Add st_block checking to multistat.c.
+Severity : minor
+Bugzilla : 16450
+Description: Add lu_ref support to struct obd_device.
+Details : Add lu_ref tracking to obd_device.
+
--------------------------------------------------------------------------------
2007-08-10 Cluster File Systems, Inc. <info@clusterfs.com>
#include <lustre/lustre_idl.h>
#include <lu_object.h>
+#include <lu_ref.h>
#include <lustre_lib.h>
#include <lustre_export.h>
#include <lustre_quota.h>
rwlock_t obd_pool_lock;
int obd_pool_limit;
__u64 obd_pool_slv;
+
+ /**
+ * A list of outstanding class_incref()'s against this obd. For
+ * debugging.
+ */
+ struct lu_ref obd_reference;
};
#define OBD_OPT_FORCE 0x0001
int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg);
int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg);
int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg);
-struct obd_device *class_incref(struct obd_device *obd);
-void class_decref(struct obd_device *obd);
+struct obd_device *class_incref(struct obd_device *obd,
+ const char *scope, const void *source);
+void class_decref(struct obd_device *obd,
+ const char *scope, const void *source);
/*obdecho*/
#ifdef LPROCFS
})
/* genops.c */
-#define class_export_get(exp) \
-({ \
- struct obd_export *exp_ = exp; \
- atomic_inc(&exp_->exp_refcount); \
- CDEBUG(D_INFO, "GETting export %p : new refcount %d\n", exp_, \
- atomic_read(&exp_->exp_refcount)); \
- exp_; \
-})
-
-#define class_export_put(exp) \
-do { \
- LASSERT((exp) != NULL); \
- CDEBUG(D_INFO, "PUTting export %p : new refcount %d\n", (exp), \
- atomic_read(&(exp)->exp_refcount) - 1); \
- LASSERT(atomic_read(&(exp)->exp_refcount) > 0); \
- LASSERT(atomic_read(&(exp)->exp_refcount) < 0x5a5a5a); \
- __class_export_put(exp); \
-} while (0)
-
-void __class_export_put(struct obd_export *);
+struct obd_export *class_export_get(struct obd_export *exp);
+void class_export_put(struct obd_export *exp);
struct obd_export *class_new_export(struct obd_device *obddev,
struct obd_uuid *cluuid);
void class_unlink_export(struct obd_export *exp);
#ifdef __KERNEL__
ldt = obd->obd_type->typ_lu;
d = obd->obd_lu_dev;
- if (ldt != NULL) {
- LASSERT(d != NULL);
+ if (ldt != NULL && d != NULL) {
if (cleanup_stage == OBD_CLEANUP_EXPORTS) {
struct lu_env env;
#ifdef __KERNEL__
ldt = obd->obd_type->typ_lu;
d = obd->obd_lu_dev;
- if (ldt != NULL) {
+ if (ldt != NULL && d != NULL) {
struct lu_env env;
- LASSERT(d != NULL);
rc = lu_env_init(&env, NULL, ldt->ldt_ctx_tags);
if (rc == 0) {
/* Make sure the target isn't cleaned up while we're here. Yes,
there's still a race between the above check and our incref here.
Really, class_uuid2obd should take the ref. */
- targref = class_incref(target);
+ targref = class_incref(target, __FUNCTION__, cfs_current());
str = req_capsule_client_get(&req->rq_pill, &RMF_CLUUID);
spin_unlock(&export->exp_lock);
}
if (targref)
- class_decref(targref);
+ class_decref(targref, __FUNCTION__, cfs_current());
if (rc)
req->rq_status = rc;
RETURN(rc);
copy_req->rq_reqmsg = copy_reqmsg;
copy_req->rq_user_desc = udesc;
- class_export_get(copy_req->rq_export);
+ class_export_rpc_get(copy_req->rq_export);
CFS_INIT_LIST_HEAD(©_req->rq_list);
CFS_INIT_LIST_HEAD(©_req->rq_replay_list);
sptlrpc_svc_ctx_addref(copy_req);
ptlrpc_req_drop_rs(req);
sptlrpc_svc_ctx_decref(req);
- class_export_put(req->rq_export);
+ class_export_rpc_put(req->rq_export);
list_del(&req->rq_list);
if (req->rq_user_desc) {
/* See the comments in function lprocfs_wr_evict_client()
* in ptlrpc/lproc_ptlrpc.c for details. - jay */
- class_incref(obd);
+ class_incref(obd, __FUNCTION__, cfs_current());
LPROCFS_EXIT();
obd_export_evict_by_nid(obd, tmpbuf+4);
rc);
LPROCFS_ENTRY();
- class_decref(obd);
+ class_decref(obd, __FUNCTION__, cfs_current());
ptlrpc_set_destroy(set);
return count;
OBD_NOTIFY_INACTIVE, NULL);
}
- class_decref(obd);
+ class_decref(obd, "mds_lov_synchronize", obd);
return rc;
}
still disconnected. Taking an obd reference insures that we don't
disconnect the LOV. This of course means a cleanup won't
finish for as long as the sync is blocking. */
- class_incref(obd);
+ class_incref(obd, "mds_lov_synchronize", obd);
if (nonblock) {
/* Synchronize in the background */
if (rc < 0) {
CERROR("%s: error starting mds_lov_synchronize: %d\n",
obd->obd_name, rc);
- class_decref(obd);
+ class_decref(obd, "mds_lov_synchronize", obd);
} else {
CDEBUG(D_HA, "%s: mds_lov_synchronize idx=%d "
"thread=%d\n", obd->obd_name,
GOTO(out_alloc, rc);
}
lu_device_get(d);
+ lu_ref_add(&d->ld_reference, "lu-stack", &lu_site_init);
RETURN(d);
/* We take an obd ref to insure that we can't get to mgc_cleanup
without calling mgc_fs_cleanup first. */
- class_incref(obd);
+ class_incref(obd, "mgc_fs", obd);
label = fsfilt_get_label(obd, mnt->mnt_sb);
if (label)
l_dput(cli->cl_mgc_configs_dir);
cli->cl_mgc_configs_dir = NULL;
pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- class_decref(obd);
+ class_decref(obd, "mgc_fs", obd);
}
cli->cl_mgc_vfsmnt = NULL;
obd, obd->obd_namespace, obd->obd_force);
LBUG();
}
+ lu_ref_fini(&obd->obd_reference);
OBD_SLAB_FREE_PTR(obd, obd_device_cachep);
}
-EXPORT_SYMBOL(obd_device_free);
struct obd_type *class_search_type(const char *name)
{
class_export_get(export);
}
-void __class_export_put(struct obd_export *exp)
+struct obd_export *class_export_get(struct obd_export *exp)
{
+ atomic_inc(&exp->exp_refcount);
+ CDEBUG(D_INFO, "GETting export %p : new refcount %d\n", exp,
+ atomic_read(&exp->exp_refcount));
+ return exp;
+}
+EXPORT_SYMBOL(class_export_get);
+
+void class_export_put(struct obd_export *exp)
+{
+ LASSERT(exp != NULL);
+ CDEBUG(D_INFO, "PUTting export %p : new refcount %d\n", exp,
+ atomic_read(&exp->exp_refcount) - 1);
+ LASSERT(atomic_read(&exp->exp_refcount) > 0);
+ LASSERT(atomic_read(&exp->exp_refcount) < 0x5a5a5a);
+
if (atomic_dec_and_test(&exp->exp_refcount)) {
LASSERT (list_empty(&exp->exp_obd_chain));
obd_zombie_impexp_notify();
}
}
-EXPORT_SYMBOL(__class_export_put);
+EXPORT_SYMBOL(class_export_put);
-void class_export_destroy(struct obd_export *exp)
+static void class_export_destroy(struct obd_export *exp)
{
struct obd_device *obd = exp->exp_obd;
ENTRY;
LASSERT(list_empty(&exp->exp_outstanding_replies));
LASSERT(list_empty(&exp->exp_req_replay_queue));
obd_destroy_export(exp);
+ class_decref(obd, "export", exp);
OBD_FREE_RCU(exp, sizeof(*exp), &exp->exp_handle);
- class_decref(obd);
EXIT;
}
}
LASSERT(!obd->obd_stopping); /* shouldn't happen, but might race */
- class_incref(obd);
+ class_incref(obd, "export", export);
list_add(&export->exp_obd_chain, &export->exp_obd->obd_exports);
list_add_tail(&export->exp_obd_chain_timed,
&export->exp_obd->obd_exports_timed);
}
LASSERT(import->imp_sec == NULL);
- class_decref(import->imp_obd);
+ class_decref(import->imp_obd, "import", import);
OBD_FREE_RCU(import, sizeof(*import), &import->imp_handle);
EXIT;
}
spin_lock_init(&imp->imp_lock);
imp->imp_last_success_conn = 0;
imp->imp_state = LUSTRE_IMP_NEW;
- imp->imp_obd = class_incref(obd);
+ imp->imp_obd = class_incref(obd, "import", imp);
sema_init(&imp->imp_sec_mutex, 1);
cfs_waitq_init(&imp->imp_recovery_waitq);
if (obd->obd_stopping)
continue;
- class_incref(obd);
+ class_incref(obd, __FUNCTION__, cfs_current());
spin_unlock(&obd_dev_lock);
if (obd_health_check(obd)) {
"device %s reported unhealthy\n",
obd->obd_name);
}
- class_decref(obd);
+ class_decref(obd, __FUNCTION__, cfs_current());
spin_lock(&obd_dev_lock);
}
spin_unlock(&obd_dev_lock);
spin_lock(&obd->obd_dev_lock);
atomic_set(&obd->obd_refcount, 1);
spin_unlock(&obd->obd_dev_lock);
+ lu_ref_init(&obd->obd_reference);
+ lu_ref_add(&obd->obd_reference, "attach", obd);
obd->obd_attached = 1;
CDEBUG(D_IOCTL, "OBD: dev %d attached type %s with refcount %d\n",
spin_lock(&obd->obd_dev_lock);
/* cleanup drops this */
- class_incref(obd);
+ class_incref(obd, "setup", obd);
spin_unlock(&obd->obd_dev_lock);
CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
CDEBUG(D_IOCTL, "detach on obd %s (uuid %s)\n",
obd->obd_name, obd->obd_uuid.uuid);
- class_decref(obd);
+ class_decref(obd, "attach", obd);
/* not strictly necessary, but cleans up eagerly */
obd_zombie_impexp_cull();
if (err)
CERROR("Precleanup %s returned %d\n",
obd->obd_name, err);
- class_decref(obd);
+ class_decref(obd, "setup", obd);
obd->obd_set_up = 0;
RETURN(0);
}
-struct obd_device *class_incref(struct obd_device *obd)
+struct obd_device *class_incref(struct obd_device *obd,
+ const char *scope, const void *source)
{
+ lu_ref_add_atomic(&obd->obd_reference, scope, source);
atomic_inc(&obd->obd_refcount);
CDEBUG(D_INFO, "incref %s (%p) now %d\n", obd->obd_name, obd,
atomic_read(&obd->obd_refcount));
return obd;
}
-void class_decref(struct obd_device *obd)
+void class_decref(struct obd_device *obd, const char *scope, const void *source)
{
int err;
int refs;
atomic_dec(&obd->obd_refcount);
refs = atomic_read(&obd->obd_refcount);
spin_unlock(&obd->obd_dev_lock);
+ lu_ref_del(&obd->obd_reference, scope, source);
CDEBUG(D_INFO, "Decref %s (%p) now %d\n", obd->obd_name, obd, refs);
* the proc entries under the being destroyed export{}, so I have
* to drop the lock at first here.
* - jay, jxiong@clusterfs.com */
- class_incref(obd);
+ class_incref(obd, __FUNCTION__, cfs_current());
LPROCFS_EXIT();
sscanf(buffer, "%40s", tmpbuf);
obd_export_evict_by_uuid(obd, tmpbuf);
LPROCFS_ENTRY();
- class_decref(obd);
+ class_decref(obd, __FUNCTION__, cfs_current());
return count;
}