#define LINVRNT_SPIN_LOCKED(lock) do { (void)sizeof(lock); } while (0)
#define LASSERT_SEM_LOCKED(sem) do { (void)sizeof(sem); } while (0)
#define LASSERT_MUTEX_LOCKED(x) do { (void)sizeof(x); } while (0)
+#define __SPIN_LOCK_UNLOCKED(x) ((spinlock_t) {})
void spin_lock_init(spinlock_t *lock);
void spin_lock(spinlock_t *lock);
struct cl_req *cp_req;
/** List of references to this page, for debugging. */
struct lu_ref cp_reference;
- /** Link to an object, for debugging. */
- struct lu_ref_link *cp_obj_ref;
- /** Link to a queue, for debugging. */
- struct lu_ref_link *cp_queue_ref;
- /** Per-page flags from enum cl_page_flags. Protected by a VM lock. */
- unsigned cp_flags;
- /** Assigned if doing a sync_io */
- struct cl_sync_io *cp_sync_io;
+ /** Link to an object, for debugging. */
+ struct lu_ref_link cp_obj_ref;
+ /** Link to a queue, for debugging. */
+ struct lu_ref_link cp_queue_ref;
+ /** Per-page flags from enum cl_page_flags. Protected by a VM lock. */
+ unsigned cp_flags;
+ /** Assigned if doing a sync_io */
+ struct cl_sync_io *cp_sync_io;
};
/**
* A list of holds on this lock, for debugging.
*/
struct lu_ref cll_holders;
- /**
- * A reference for cl_lock::cll_descr::cld_obj. For debugging.
- */
- struct lu_ref_link *cll_obj_ref;
+ /**
+ * A reference for cl_lock::cll_descr::cld_obj. For debugging.
+ */
+ struct lu_ref_link cll_obj_ref;
#ifdef CONFIG_LOCKDEP
- /* "dep_map" name is assumed by lockdep.h macros. */
- struct lockdep_map dep_map;
+ /* "dep_map" name is assumed by lockdep.h macros. */
+ struct lockdep_map dep_map;
#endif
};
* A per-object state that (potentially multi-object) transfer request keeps.
*/
struct cl_req_obj {
- /** object itself */
- struct cl_object *ro_obj;
- /** reference to cl_req_obj::ro_obj. For debugging. */
- struct lu_ref_link *ro_obj_ref;
- /* something else? Number of pages for a given object? */
+ /** object itself */
+ struct cl_object *ro_obj;
+ /** reference to cl_req_obj::ro_obj. For debugging. */
+ struct lu_ref_link ro_obj_ref;
+ /* something else? Number of pages for a given object? */
};
/**
* Flags from enum lu_object_flags.
*/
__u32 lo_flags;
- /**
- * Link to the device, for debugging.
- */
- struct lu_ref_link *lo_dev_ref;
+ /**
+ * Link to the device, for debugging.
+ */
+ struct lu_ref_link lo_dev_ref;
};
enum lu_object_header_flags {
return o->lo_header->loh_attr;
}
-static inline struct lu_ref_link *lu_object_ref_add(struct lu_object *o,
- const char *scope,
- const void *source)
+static inline void lu_object_ref_add(struct lu_object *o,
+ const char *scope,
+ const void *source)
+{
+ lu_ref_add(&o->lo_header->loh_reference, scope, source);
+}
+
+static inline void lu_object_ref_add_at(struct lu_object *o,
+ struct lu_ref_link *link,
+ const char *scope,
+ const void *source)
{
- return lu_ref_add(&o->lo_header->loh_reference, scope, source);
+ lu_ref_add_at(&o->lo_header->loh_reference, link, scope, source);
}
static inline void lu_object_ref_del(struct lu_object *o,
#ifdef USE_LU_REF
-/* An incomplete type (defined locally in lu_ref.c) */
-struct lu_ref_link;
-
/**
* Data-structure to keep track of references to a given object. This is used
* for debugging.
cfs_list_t lf_linkage;
};
+struct lu_ref_link {
+ struct lu_ref *ll_ref;
+ cfs_list_t ll_linkage;
+ const char *ll_scope;
+ const void *ll_source;
+};
+
void lu_ref_init_loc(struct lu_ref *ref, const char *func, const int line);
void lu_ref_fini (struct lu_ref *ref);
#define lu_ref_init(ref) lu_ref_init_loc(ref, __FUNCTION__, __LINE__)
-struct lu_ref_link *lu_ref_add (struct lu_ref *ref, const char *scope,
- const void *source);
-struct lu_ref_link *lu_ref_add_atomic(struct lu_ref *ref, const char *scope,
- const void *source);
-void lu_ref_del (struct lu_ref *ref, const char *scope,
- const void *source);
-void lu_ref_set_at (struct lu_ref *ref,
- struct lu_ref_link *link,
- const char *scope, const void *source0,
- const void *source1);
-void lu_ref_del_at (struct lu_ref *ref,
- struct lu_ref_link *link,
- const char *scope, const void *source);
-void lu_ref_print (const struct lu_ref *ref);
-void lu_ref_print_all (void);
+void lu_ref_add(struct lu_ref *ref, const char *scope, const void *source);
+
+void lu_ref_add_atomic(struct lu_ref *ref, const char *scope,
+ const void *source);
+
+void lu_ref_add_at(struct lu_ref *ref, struct lu_ref_link *link,
+ const char *scope, const void *source);
+
+void lu_ref_del(struct lu_ref *ref, const char *scope, const void *source);
+
+void lu_ref_set_at(struct lu_ref *ref, struct lu_ref_link *link,
+ const char *scope, const void *source0, const void *source1);
+
+void lu_ref_del_at(struct lu_ref *ref, struct lu_ref_link *link,
+ const char *scope, const void *source);
+
+void lu_ref_print(const struct lu_ref *ref);
+
+void lu_ref_print_all(void);
+
+int lu_ref_global_init(void);
+
+void lu_ref_global_fini(void);
#else /* !USE_LU_REF */
-struct lu_ref {};
+struct lu_ref {
+};
+
+struct lu_ref_link {
+};
static inline void lu_ref_init(struct lu_ref *ref)
{
{
}
-static inline struct lu_ref_link *lu_ref_add(struct lu_ref *ref,
- const char *scope,
- const void *source)
+static inline void lu_ref_add(struct lu_ref *ref,
+ const char *scope,
+ const void *source)
+{
+}
+
+static inline void lu_ref_add_atomic(struct lu_ref *ref,
+ const char *scope,
+ const void *source)
{
- return NULL;
}
-static inline struct lu_ref_link *lu_ref_add_atomic(struct lu_ref *ref,
- const char *scope,
- const void *source)
+static inline void lu_ref_add_at(struct lu_ref *ref,
+ struct lu_ref_link *link,
+ const char *scope,
+ const void *source)
{
- return NULL;
}
static inline void lu_ref_del(struct lu_ref *ref, const char *scope,
LASSERT(cfs_list_empty(&page->cp_batch));
cfs_list_add_tail(&page->cp_batch, &plist->pl_pages);
++plist->pl_nr;
- page->cp_queue_ref = lu_ref_add(&page->cp_reference, "queue", plist);
- cl_page_get(page);
- EXIT;
+ lu_ref_add_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist);
+ cl_page_get(page);
+ EXIT;
}
EXPORT_SYMBOL(cl_page_list_add);
mutex_unlock(&page->cp_mutex);
lockdep_on();
--plist->pl_nr;
- lu_ref_del_at(&page->cp_reference, page->cp_queue_ref, "queue", plist);
- cl_page_put(env, page);
- EXIT;
+ lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist);
+ cl_page_put(env, page);
+ EXIT;
}
EXPORT_SYMBOL(cl_page_list_del);
cfs_list_move_tail(&page->cp_batch, &dst->pl_pages);
--src->pl_nr;
++dst->pl_nr;
- lu_ref_set_at(&page->cp_reference,
- page->cp_queue_ref, "queue", src, dst);
- EXIT;
+ lu_ref_set_at(&page->cp_reference, &page->cp_queue_ref, "queue",
+ src, dst);
+ EXIT;
}
EXPORT_SYMBOL(cl_page_list_move);
* XXX cl_page_disown0() will fail if page is not locked.
*/
cl_page_disown0(env, io, page);
- lu_ref_del(&page->cp_reference, "queue", plist);
+ lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue",
+ plist);
cl_page_put(env, page);
}
EXIT;
if (req->crq_o != NULL) {
for (i = 0; i < req->crq_nrobjs; ++i) {
struct cl_object *obj = req->crq_o[i].ro_obj;
- if (obj != NULL) {
- lu_object_ref_del_at(&obj->co_lu,
- req->crq_o[i].ro_obj_ref,
- "cl_req", req);
- cl_object_put(env, obj);
- }
+ if (obj != NULL) {
+ lu_object_ref_del_at(&obj->co_lu,
+ &req->crq_o[i].ro_obj_ref,
+ "cl_req", req);
+ cl_object_put(env, obj);
+ }
}
OBD_FREE(req->crq_o, req->crq_nrobjs * sizeof req->crq_o[0]);
}
if (rqo->ro_obj == NULL) {
rqo->ro_obj = obj;
cl_object_get(obj);
- rqo->ro_obj_ref = lu_object_ref_add(&obj->co_lu,
- "cl_req", req);
+ lu_object_ref_add_at(&obj->co_lu, &rqo->ro_obj_ref,
+ "cl_req", req);
break;
}
}
}
CS_LOCK_DEC(obj, total);
CS_LOCKSTATE_DEC(obj, lock->cll_state);
- lu_object_ref_del_at(&obj->co_lu, lock->cll_obj_ref, "cl_lock", lock);
+ lu_object_ref_del_at(&obj->co_lu, &lock->cll_obj_ref, "cl_lock", lock);
cl_object_put(env, obj);
lu_ref_fini(&lock->cll_reference);
lu_ref_fini(&lock->cll_holders);
lock->cll_descr = *descr;
lock->cll_state = CLS_NEW;
cl_object_get(obj);
- lock->cll_obj_ref = lu_object_ref_add(&obj->co_lu,
- "cl_lock", lock);
+ lu_object_ref_add_at(&obj->co_lu, &lock->cll_obj_ref, "cl_lock",
+ lock);
CFS_INIT_LIST_HEAD(&lock->cll_layers);
CFS_INIT_LIST_HEAD(&lock->cll_linkage);
CFS_INIT_LIST_HEAD(&lock->cll_inclosure);
}
CS_PAGE_DEC(obj, total);
CS_PAGESTATE_DEC(obj, page->cp_state);
- lu_object_ref_del_at(&obj->co_lu, page->cp_obj_ref, "cl_page", page);
+ lu_object_ref_del_at(&obj->co_lu, &page->cp_obj_ref, "cl_page", page);
cl_object_put(env, obj);
lu_ref_fini(&page->cp_reference);
OBD_FREE(page, pagesize);
cfs_atomic_inc(&page->cp_ref);
page->cp_obj = o;
cl_object_get(o);
- page->cp_obj_ref = lu_object_ref_add(&o->co_lu, "cl_page",page);
+ lu_object_ref_add_at(&o->co_lu, &page->cp_obj_ref, "cl_page",
+ page);
page->cp_index = ind;
cl_page_state_set_trust(page, CPS_CACHED);
page->cp_type = type;
* Initialize object \a o that is part of compound object \a h and was created
* by device \a d.
*/
-int lu_object_init(struct lu_object *o,
- struct lu_object_header *h, struct lu_device *d)
-{
- memset(o, 0, sizeof *o);
- o->lo_header = h;
- o->lo_dev = d;
- lu_device_get(d);
- o->lo_dev_ref = lu_ref_add(&d->ld_reference, "lu_object", o);
- CFS_INIT_LIST_HEAD(&o->lo_linkage);
- return 0;
+int lu_object_init(struct lu_object *o, struct lu_object_header *h,
+ struct lu_device *d)
+{
+ memset(o, 0, sizeof(*o));
+ o->lo_header = h;
+ o->lo_dev = d;
+ lu_device_get(d);
+ lu_ref_add_at(&d->ld_reference, &o->lo_dev_ref, "lu_object", o);
+ CFS_INIT_LIST_HEAD(&o->lo_linkage);
+
+ return 0;
}
EXPORT_SYMBOL(lu_object_init);
*/
void lu_object_fini(struct lu_object *o)
{
- struct lu_device *dev = o->lo_dev;
+ struct lu_device *dev = o->lo_dev;
- LASSERT(cfs_list_empty(&o->lo_linkage));
+ LASSERT(cfs_list_empty(&o->lo_linkage));
- if (dev != NULL) {
- lu_ref_del_at(&dev->ld_reference,
- o->lo_dev_ref , "lu_object", o);
- lu_device_put(dev);
- o->lo_dev = NULL;
- }
+ if (dev != NULL) {
+ lu_ref_del_at(&dev->ld_reference, &o->lo_dev_ref,
+ "lu_object", o);
+ lu_device_put(dev);
+ o->lo_dev = NULL;
+ }
}
EXPORT_SYMBOL(lu_object_fini);
} \
} while (0)
-struct lu_ref_link {
- struct lu_ref *ll_ref;
- cfs_list_t ll_linkage;
- const char *ll_scope;
- const void *ll_source;
-};
-
static cfs_mem_cache_t *lu_ref_link_kmem;
static struct lu_kmem_descr lu_ref_caches[] = {
static CFS_LIST_HEAD(lu_ref_refs);
static spinlock_t lu_ref_refs_guard;
static struct lu_ref lu_ref_marker = {
- .lf_guard = DEFINE_SPINLOCK(lu_ref_marker.lf_guard),
- .lf_list = CFS_LIST_HEAD_INIT(lu_ref_marker.lf_list),
- .lf_linkage = CFS_LIST_HEAD_INIT(lu_ref_marker.lf_linkage)
+ .lf_guard = __SPIN_LOCK_UNLOCKED(lu_ref_marker.lf_guard),
+ .lf_list = CFS_LIST_HEAD_INIT(lu_ref_marker.lf_list),
+ .lf_linkage = CFS_LIST_HEAD_INIT(lu_ref_marker.lf_linkage)
};
void lu_ref_print(const struct lu_ref *ref)
return link;
}
-struct lu_ref_link *lu_ref_add(struct lu_ref *ref, const char *scope,
- const void *source)
+void lu_ref_add(struct lu_ref *ref, const char *scope, const void *source)
{
- cfs_might_sleep();
- return lu_ref_add_context(ref, CFS_ALLOC_STD, scope, source);
+ cfs_might_sleep();
+ lu_ref_add_context(ref, CFS_ALLOC_STD, scope, source);
}
EXPORT_SYMBOL(lu_ref_add);
+void lu_ref_add_at(struct lu_ref *ref, struct lu_ref_link *link,
+ const char *scope, const void *source)
+{
+ link->ll_ref = ref;
+ link->ll_scope = scope;
+ link->ll_source = source;
+ spin_lock(&ref->lf_guard);
+ cfs_list_add_tail(&link->ll_linkage, &ref->lf_list);
+ ref->lf_refs++;
+ spin_unlock(&ref->lf_guard);
+}
+EXPORT_SYMBOL(lu_ref_add_at);
+
/**
* Version of lu_ref_add() to be used in non-blockable contexts.
*/
-struct lu_ref_link *lu_ref_add_atomic(struct lu_ref *ref, const char *scope,
- const void *source)
+void lu_ref_add_atomic(struct lu_ref *ref, const char *scope,
+ const void *source)
{
- return lu_ref_add_context(ref, CFS_ALLOC_ATOMIC, scope, source);
+ lu_ref_add_context(ref, CFS_ALLOC_ATOMIC, scope, source);
}
EXPORT_SYMBOL(lu_ref_add_atomic);
const char *scope,
const void *source0, const void *source1)
{
+ REFASSERT(ref, link != NULL && !IS_ERR(link));
+
spin_lock(&ref->lf_guard);
- if (link != ERR_PTR(-ENOMEM)) {
- REFASSERT(ref, link->ll_ref == ref);
- REFASSERT(ref, lu_ref_link_eq(link, scope, source0));
- link->ll_source = source1;
- } else {
- REFASSERT(ref, ref->lf_failed > 0);
- }
+ REFASSERT(ref, link->ll_ref == ref);
+ REFASSERT(ref, lu_ref_link_eq(link, scope, source0));
+ link->ll_source = source1;
spin_unlock(&ref->lf_guard);
}
EXPORT_SYMBOL(lu_ref_set_at);
void lu_ref_del_at(struct lu_ref *ref, struct lu_ref_link *link,
const char *scope, const void *source)
{
- if (link != ERR_PTR(-ENOMEM)) {
- spin_lock(&ref->lf_guard);
- REFASSERT(ref, link->ll_ref == ref);
- REFASSERT(ref, lu_ref_link_eq(link, scope, source));
- cfs_list_del(&link->ll_linkage);
- ref->lf_refs--;
- spin_unlock(&ref->lf_guard);
- OBD_SLAB_FREE(link, lu_ref_link_kmem, sizeof(*link));
- } else {
- spin_lock(&ref->lf_guard);
- REFASSERT(ref, ref->lf_failed > 0);
- ref->lf_failed--;
- spin_unlock(&ref->lf_guard);
- }
+ REFASSERT(ref, link != NULL && !IS_ERR(link));
+ spin_lock(&ref->lf_guard);
+ REFASSERT(ref, link->ll_ref == ref);
+ REFASSERT(ref, lu_ref_link_eq(link, scope, source));
+ cfs_list_del(&link->ll_linkage);
+ ref->lf_refs--;
+ spin_unlock(&ref->lf_guard);
}
EXPORT_SYMBOL(lu_ref_del_at);
while ((osc = osc_next_obj(cli)) != NULL) {
struct cl_object *obj = osc2cl(osc);
- struct lu_ref_link *link;
+ struct lu_ref_link link;
OSC_IO_DEBUG(osc, "%lu in flight\n", rpcs_in_flight(cli));
cl_object_get(obj);
client_obd_list_unlock(&cli->cl_loi_list_lock);
- link = lu_object_ref_add(&obj->co_lu, "check", cfs_current());
+ lu_object_ref_add_at(&obj->co_lu, &link, "check",
+ cfs_current());
/* attempt some read/write balancing by alternating between
* reads and writes in an object. The makes_rpc checks here
osc_object_unlock(osc);
osc_list_maint(cli, osc);
- lu_object_ref_del_at(&obj->co_lu, link, "check", cfs_current());
+ lu_object_ref_del_at(&obj->co_lu, &link, "check",
+ cfs_current());
cl_object_put(env, obj);
client_obd_list_lock(&cli->cl_loi_list_lock);
dcb->dcb_func(NULL, th, dcb, error);
}
- lu_ref_del_at(&lud->ld_reference, oh->ot_dev_link, "osd-tx", th);
+ lu_ref_del_at(&lud->ld_reference, &oh->ot_dev_link, "osd-tx", th);
lu_device_put(lud);
th->th_dev = NULL;
lu_context_enter(&th->th_ctx);
lu_device_get(&d->dd_lu_dev);
- oh->ot_dev_link = lu_ref_add(&d->dd_lu_dev.ld_reference,
- "osd-tx", th);
+ lu_ref_add_at(&d->dd_lu_dev.ld_reference, &oh->ot_dev_link,
+ "osd-tx", th);
oti->oti_txns++;
rc = 0;
} else {
handle_t *ot_handle;
struct ldiskfs_journal_cb_entry ot_jcb;
cfs_list_t ot_dcb_list;
- /* Link to the device, for debugging. */
- struct lu_ref_link *ot_dev_link;
+ /* Link to the device, for debugging. */
+ struct lu_ref_link ot_dev_link;
unsigned short ot_credits;
unsigned short ot_id_cnt;
unsigned short ot_id_type;
case IT_QUOTA_CONN:
/* grab reference on qqi for new lock */
#ifdef USE_LU_REF
+ {
struct ldlm_lock *lock;
lock = ldlm_handle2lock(&qti->qti_lockh);
}
lu_ref_add(&qqi->qqi_reference, "glb_lock", lock);
LDLM_LOCK_PUT(lock);
+ }
#endif
qqi_getref(qqi);
break;