.ldo_object_alloc = ls_object_alloc
};
-static struct ls_device *__ls_find_dev(struct dt_device *dev)
-{
- struct ls_device *ls, *ret = NULL;
-
- list_for_each_entry(ls, &ls_list_head, ls_linkage) {
- if (ls->ls_osd == dev) {
- atomic_inc(&ls->ls_refcount);
- ret = ls;
- break;
- }
- }
- return ret;
-}
-
static const struct lu_device_type_operations ls_device_type_ops = {
.ldto_start = NULL,
.ldto_stop = NULL,
.ldt_ops = &ls_device_type_ops,
};
-struct ls_device *ls_device_get(struct dt_device *dev)
+static
+struct ls_device *ls_device_init(struct dt_device *dev)
{
struct ls_device *ls;
ENTRY;
- mutex_lock(&ls_list_mutex);
- ls = __ls_find_dev(dev);
- if (ls)
- GOTO(out_ls, ls);
-
- /* not found, then create */
OBD_ALLOC_PTR(ls);
if (ls == NULL)
GOTO(out_ls, ls = ERR_PTR(-ENOMEM));
- atomic_set(&ls->ls_refcount, 1);
+ kref_init(&ls->ls_refcount);
INIT_LIST_HEAD(&ls->ls_los_list);
mutex_init(&ls->ls_los_mutex);
/* finally add ls to the list */
list_add(&ls->ls_linkage, &ls_list_head);
out_ls:
+ RETURN(ls);
+}
+
+struct ls_device *ls_device_find_or_init(struct dt_device *dev)
+{
+ struct ls_device *ls, *ret = NULL;
+
+ ENTRY;
+
+ mutex_lock(&ls_list_mutex);
+ /* find */
+ list_for_each_entry(ls, &ls_list_head, ls_linkage) {
+ if (ls->ls_osd == dev) {
+ kref_get(&ls->ls_refcount);
+ ret = ls;
+ break;
+ }
+ }
+ /* found */
+ if (ret)
+ GOTO(out_ls, ret);
+
+ /* not found, then create */
+ ls = ls_device_init(dev);
+out_ls:
mutex_unlock(&ls_list_mutex);
RETURN(ls);
}
+static void ls_device_put_free(struct kref *kref)
+{
+ struct ls_device *ls = container_of(kref, struct ls_device,
+ ls_refcount);
+
+ LASSERT(list_empty(&ls->ls_los_list));
+ list_del(&ls->ls_linkage);
+ mutex_unlock(&ls_list_mutex);
+}
+
void ls_device_put(const struct lu_env *env, struct ls_device *ls)
{
LASSERT(env);
- if (!atomic_dec_and_test(&ls->ls_refcount))
- return;
-
- mutex_lock(&ls_list_mutex);
- if (atomic_read(&ls->ls_refcount) == 0) {
- LASSERT(list_empty(&ls->ls_los_list));
- list_del(&ls->ls_linkage);
+ if (kref_put_mutex(&ls->ls_refcount, ls_device_put_free,
+ &ls_list_mutex)) {
lu_site_purge(env, ls->ls_top_dev.dd_lu_dev.ld_site, ~0);
lu_device_fini(&ls->ls_top_dev.dd_lu_dev);
OBD_FREE_PTR(ls);
}
- mutex_unlock(&ls_list_mutex);
}
/**
} else {
struct ls_device *ls;
- ls = ls_device_get(dt);
+ ls = ls_device_find_or_init(dt);
if (IS_ERR(ls)) {
dto = ERR_CAST(ls);
} else {
} else {
struct ls_device *ls;
- ls = ls_device_get(dt);
+ ls = ls_device_find_or_init(dt);
if (IS_ERR(ls)) {
dto = ERR_CAST(ls);
} else {
return rc;
}
+
/**
* Initialize local OID storage for required sequence.
* That may be needed for services that uses local files and requires
ENTRY;
- ls = ls_device_get(dev);
+ ls = ls_device_find_or_init(dev);
if (IS_ERR(ls))
RETURN(PTR_ERR(ls));
atomic_set(&(*los)->los_refcount, 1);
mutex_init(&(*los)->los_id_lock);
(*los)->los_dev = &ls->ls_top_dev;
- atomic_inc(&ls->ls_refcount);
+ kref_get(&ls->ls_refcount);
list_add(&(*los)->los_list, &ls->ls_los_list);
/* Use {seq, 0, 0} to create the LAST_ID file for every
out_los:
if (rc != 0) {
list_del(&(*los)->los_list);
- atomic_dec(&ls->ls_refcount);
+ ls_device_put(env, ls);
OBD_FREE_PTR(*los);
*los = NULL;
if (o != NULL && !IS_ERR(o))
/* all initialized ls_devices on this node linked by this */
struct list_head ls_linkage;
/* how many handle's reference this local storage */
- atomic_t ls_refcount;
+ struct kref ls_refcount;
/* underlaying OSD device */
struct dt_device *ls_osd;
/* list of all local OID storages */
&ls->ls_top_dev.dd_lu_dev, conf);
}
-struct ls_device *ls_device_get(struct dt_device *dev);
+struct ls_device *ls_device_find_or_init(struct dt_device *dev);
void ls_device_put(const struct lu_env *env, struct ls_device *ls);
struct local_oid_storage *dt_los_find(struct ls_device *ls, __u64 seq);
void dt_los_put(struct local_oid_storage *los);