162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci*******************************************************************************
462306a36Sopenharmony_ci**
562306a36Sopenharmony_ci**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
662306a36Sopenharmony_ci**  Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
762306a36Sopenharmony_ci**
862306a36Sopenharmony_ci**
962306a36Sopenharmony_ci*******************************************************************************
1062306a36Sopenharmony_ci******************************************************************************/
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "dlm_internal.h"
1562306a36Sopenharmony_ci#include "lockspace.h"
1662306a36Sopenharmony_ci#include "member.h"
1762306a36Sopenharmony_ci#include "recoverd.h"
1862306a36Sopenharmony_ci#include "dir.h"
1962306a36Sopenharmony_ci#include "midcomms.h"
2062306a36Sopenharmony_ci#include "config.h"
2162306a36Sopenharmony_ci#include "memory.h"
2262306a36Sopenharmony_ci#include "lock.h"
2362306a36Sopenharmony_ci#include "recover.h"
2462306a36Sopenharmony_ci#include "requestqueue.h"
2562306a36Sopenharmony_ci#include "user.h"
2662306a36Sopenharmony_ci#include "ast.h"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic int			ls_count;
2962306a36Sopenharmony_cistatic struct mutex		ls_lock;
3062306a36Sopenharmony_cistatic struct list_head		lslist;
3162306a36Sopenharmony_cistatic spinlock_t		lslist_lock;
3262306a36Sopenharmony_cistatic struct task_struct *	scand_task;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	ssize_t ret = len;
3862306a36Sopenharmony_ci	int n;
3962306a36Sopenharmony_ci	int rc = kstrtoint(buf, 0, &n);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (rc)
4262306a36Sopenharmony_ci		return rc;
4362306a36Sopenharmony_ci	ls = dlm_find_lockspace_local(ls->ls_local_handle);
4462306a36Sopenharmony_ci	if (!ls)
4562306a36Sopenharmony_ci		return -EINVAL;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	switch (n) {
4862306a36Sopenharmony_ci	case 0:
4962306a36Sopenharmony_ci		dlm_ls_stop(ls);
5062306a36Sopenharmony_ci		break;
5162306a36Sopenharmony_ci	case 1:
5262306a36Sopenharmony_ci		dlm_ls_start(ls);
5362306a36Sopenharmony_ci		break;
5462306a36Sopenharmony_ci	default:
5562306a36Sopenharmony_ci		ret = -EINVAL;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci	dlm_put_lockspace(ls);
5862306a36Sopenharmony_ci	return ret;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	int rc = kstrtoint(buf, 0, &ls->ls_uevent_result);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (rc)
6662306a36Sopenharmony_ci		return rc;
6762306a36Sopenharmony_ci	set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags);
6862306a36Sopenharmony_ci	wake_up(&ls->ls_uevent_wait);
6962306a36Sopenharmony_ci	return len;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic ssize_t dlm_id_show(struct dlm_ls *ls, char *buf)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", ls->ls_global_id);
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	int rc = kstrtouint(buf, 0, &ls->ls_global_id);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	if (rc)
8262306a36Sopenharmony_ci		return rc;
8362306a36Sopenharmony_ci	return len;
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic ssize_t dlm_nodir_show(struct dlm_ls *ls, char *buf)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", dlm_no_directory(ls));
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistatic ssize_t dlm_nodir_store(struct dlm_ls *ls, const char *buf, size_t len)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	int val;
9462306a36Sopenharmony_ci	int rc = kstrtoint(buf, 0, &val);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	if (rc)
9762306a36Sopenharmony_ci		return rc;
9862306a36Sopenharmony_ci	if (val == 1)
9962306a36Sopenharmony_ci		set_bit(LSFL_NODIR, &ls->ls_flags);
10062306a36Sopenharmony_ci	return len;
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic ssize_t dlm_recover_status_show(struct dlm_ls *ls, char *buf)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	uint32_t status = dlm_recover_status(ls);
10662306a36Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%x\n", status);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic ssize_t dlm_recover_nodeid_show(struct dlm_ls *ls, char *buf)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", ls->ls_recover_nodeid);
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistruct dlm_attr {
11562306a36Sopenharmony_ci	struct attribute attr;
11662306a36Sopenharmony_ci	ssize_t (*show)(struct dlm_ls *, char *);
11762306a36Sopenharmony_ci	ssize_t (*store)(struct dlm_ls *, const char *, size_t);
11862306a36Sopenharmony_ci};
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic struct dlm_attr dlm_attr_control = {
12162306a36Sopenharmony_ci	.attr  = {.name = "control", .mode = S_IWUSR},
12262306a36Sopenharmony_ci	.store = dlm_control_store
12362306a36Sopenharmony_ci};
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic struct dlm_attr dlm_attr_event = {
12662306a36Sopenharmony_ci	.attr  = {.name = "event_done", .mode = S_IWUSR},
12762306a36Sopenharmony_ci	.store = dlm_event_store
12862306a36Sopenharmony_ci};
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic struct dlm_attr dlm_attr_id = {
13162306a36Sopenharmony_ci	.attr  = {.name = "id", .mode = S_IRUGO | S_IWUSR},
13262306a36Sopenharmony_ci	.show  = dlm_id_show,
13362306a36Sopenharmony_ci	.store = dlm_id_store
13462306a36Sopenharmony_ci};
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic struct dlm_attr dlm_attr_nodir = {
13762306a36Sopenharmony_ci	.attr  = {.name = "nodir", .mode = S_IRUGO | S_IWUSR},
13862306a36Sopenharmony_ci	.show  = dlm_nodir_show,
13962306a36Sopenharmony_ci	.store = dlm_nodir_store
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic struct dlm_attr dlm_attr_recover_status = {
14362306a36Sopenharmony_ci	.attr  = {.name = "recover_status", .mode = S_IRUGO},
14462306a36Sopenharmony_ci	.show  = dlm_recover_status_show
14562306a36Sopenharmony_ci};
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic struct dlm_attr dlm_attr_recover_nodeid = {
14862306a36Sopenharmony_ci	.attr  = {.name = "recover_nodeid", .mode = S_IRUGO},
14962306a36Sopenharmony_ci	.show  = dlm_recover_nodeid_show
15062306a36Sopenharmony_ci};
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic struct attribute *dlm_attrs[] = {
15362306a36Sopenharmony_ci	&dlm_attr_control.attr,
15462306a36Sopenharmony_ci	&dlm_attr_event.attr,
15562306a36Sopenharmony_ci	&dlm_attr_id.attr,
15662306a36Sopenharmony_ci	&dlm_attr_nodir.attr,
15762306a36Sopenharmony_ci	&dlm_attr_recover_status.attr,
15862306a36Sopenharmony_ci	&dlm_attr_recover_nodeid.attr,
15962306a36Sopenharmony_ci	NULL,
16062306a36Sopenharmony_ci};
16162306a36Sopenharmony_ciATTRIBUTE_GROUPS(dlm);
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistatic ssize_t dlm_attr_show(struct kobject *kobj, struct attribute *attr,
16462306a36Sopenharmony_ci			     char *buf)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct dlm_ls *ls  = container_of(kobj, struct dlm_ls, ls_kobj);
16762306a36Sopenharmony_ci	struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
16862306a36Sopenharmony_ci	return a->show ? a->show(ls, buf) : 0;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr,
17262306a36Sopenharmony_ci			      const char *buf, size_t len)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	struct dlm_ls *ls  = container_of(kobj, struct dlm_ls, ls_kobj);
17562306a36Sopenharmony_ci	struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
17662306a36Sopenharmony_ci	return a->store ? a->store(ls, buf, len) : len;
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cistatic void lockspace_kobj_release(struct kobject *k)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	struct dlm_ls *ls  = container_of(k, struct dlm_ls, ls_kobj);
18262306a36Sopenharmony_ci	kfree(ls);
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic const struct sysfs_ops dlm_attr_ops = {
18662306a36Sopenharmony_ci	.show  = dlm_attr_show,
18762306a36Sopenharmony_ci	.store = dlm_attr_store,
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic struct kobj_type dlm_ktype = {
19162306a36Sopenharmony_ci	.default_groups = dlm_groups,
19262306a36Sopenharmony_ci	.sysfs_ops     = &dlm_attr_ops,
19362306a36Sopenharmony_ci	.release       = lockspace_kobj_release,
19462306a36Sopenharmony_ci};
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic struct kset *dlm_kset;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic int do_uevent(struct dlm_ls *ls, int in)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	if (in)
20162306a36Sopenharmony_ci		kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE);
20262306a36Sopenharmony_ci	else
20362306a36Sopenharmony_ci		kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	log_rinfo(ls, "%s the lockspace group...", in ? "joining" : "leaving");
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	/* dlm_controld will see the uevent, do the necessary group management
20862306a36Sopenharmony_ci	   and then write to sysfs to wake us */
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	wait_event(ls->ls_uevent_wait,
21162306a36Sopenharmony_ci		   test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	log_rinfo(ls, "group event done %d", ls->ls_uevent_result);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	return ls->ls_uevent_result;
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cistatic int dlm_uevent(const struct kobject *kobj, struct kobj_uevent_env *env)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	const struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	add_uevent_var(env, "LOCKSPACE=%s", ls->ls_name);
22362306a36Sopenharmony_ci	return 0;
22462306a36Sopenharmony_ci}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic const struct kset_uevent_ops dlm_uevent_ops = {
22762306a36Sopenharmony_ci	.uevent = dlm_uevent,
22862306a36Sopenharmony_ci};
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ciint __init dlm_lockspace_init(void)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	ls_count = 0;
23362306a36Sopenharmony_ci	mutex_init(&ls_lock);
23462306a36Sopenharmony_ci	INIT_LIST_HEAD(&lslist);
23562306a36Sopenharmony_ci	spin_lock_init(&lslist_lock);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	dlm_kset = kset_create_and_add("dlm", &dlm_uevent_ops, kernel_kobj);
23862306a36Sopenharmony_ci	if (!dlm_kset) {
23962306a36Sopenharmony_ci		printk(KERN_WARNING "%s: can not create kset\n", __func__);
24062306a36Sopenharmony_ci		return -ENOMEM;
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci	return 0;
24362306a36Sopenharmony_ci}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_civoid dlm_lockspace_exit(void)
24662306a36Sopenharmony_ci{
24762306a36Sopenharmony_ci	kset_unregister(dlm_kset);
24862306a36Sopenharmony_ci}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cistatic struct dlm_ls *find_ls_to_scan(void)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	struct dlm_ls *ls;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	spin_lock(&lslist_lock);
25562306a36Sopenharmony_ci	list_for_each_entry(ls, &lslist, ls_list) {
25662306a36Sopenharmony_ci		if (time_after_eq(jiffies, ls->ls_scan_time +
25762306a36Sopenharmony_ci					    dlm_config.ci_scan_secs * HZ)) {
25862306a36Sopenharmony_ci			spin_unlock(&lslist_lock);
25962306a36Sopenharmony_ci			return ls;
26062306a36Sopenharmony_ci		}
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
26362306a36Sopenharmony_ci	return NULL;
26462306a36Sopenharmony_ci}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic int dlm_scand(void *data)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	struct dlm_ls *ls;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	while (!kthread_should_stop()) {
27162306a36Sopenharmony_ci		ls = find_ls_to_scan();
27262306a36Sopenharmony_ci		if (ls) {
27362306a36Sopenharmony_ci			if (dlm_lock_recovery_try(ls)) {
27462306a36Sopenharmony_ci				ls->ls_scan_time = jiffies;
27562306a36Sopenharmony_ci				dlm_scan_rsbs(ls);
27662306a36Sopenharmony_ci				dlm_unlock_recovery(ls);
27762306a36Sopenharmony_ci			} else {
27862306a36Sopenharmony_ci				ls->ls_scan_time += HZ;
27962306a36Sopenharmony_ci			}
28062306a36Sopenharmony_ci			continue;
28162306a36Sopenharmony_ci		}
28262306a36Sopenharmony_ci		schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
28362306a36Sopenharmony_ci	}
28462306a36Sopenharmony_ci	return 0;
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cistatic int dlm_scand_start(void)
28862306a36Sopenharmony_ci{
28962306a36Sopenharmony_ci	struct task_struct *p;
29062306a36Sopenharmony_ci	int error = 0;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	p = kthread_run(dlm_scand, NULL, "dlm_scand");
29362306a36Sopenharmony_ci	if (IS_ERR(p))
29462306a36Sopenharmony_ci		error = PTR_ERR(p);
29562306a36Sopenharmony_ci	else
29662306a36Sopenharmony_ci		scand_task = p;
29762306a36Sopenharmony_ci	return error;
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic void dlm_scand_stop(void)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	kthread_stop(scand_task);
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistruct dlm_ls *dlm_find_lockspace_global(uint32_t id)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	struct dlm_ls *ls;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	spin_lock(&lslist_lock);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	list_for_each_entry(ls, &lslist, ls_list) {
31262306a36Sopenharmony_ci		if (ls->ls_global_id == id) {
31362306a36Sopenharmony_ci			atomic_inc(&ls->ls_count);
31462306a36Sopenharmony_ci			goto out;
31562306a36Sopenharmony_ci		}
31662306a36Sopenharmony_ci	}
31762306a36Sopenharmony_ci	ls = NULL;
31862306a36Sopenharmony_ci out:
31962306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
32062306a36Sopenharmony_ci	return ls;
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_cistruct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
32462306a36Sopenharmony_ci{
32562306a36Sopenharmony_ci	struct dlm_ls *ls;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	spin_lock(&lslist_lock);
32862306a36Sopenharmony_ci	list_for_each_entry(ls, &lslist, ls_list) {
32962306a36Sopenharmony_ci		if (ls->ls_local_handle == lockspace) {
33062306a36Sopenharmony_ci			atomic_inc(&ls->ls_count);
33162306a36Sopenharmony_ci			goto out;
33262306a36Sopenharmony_ci		}
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci	ls = NULL;
33562306a36Sopenharmony_ci out:
33662306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
33762306a36Sopenharmony_ci	return ls;
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cistruct dlm_ls *dlm_find_lockspace_device(int minor)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	struct dlm_ls *ls;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	spin_lock(&lslist_lock);
34562306a36Sopenharmony_ci	list_for_each_entry(ls, &lslist, ls_list) {
34662306a36Sopenharmony_ci		if (ls->ls_device.minor == minor) {
34762306a36Sopenharmony_ci			atomic_inc(&ls->ls_count);
34862306a36Sopenharmony_ci			goto out;
34962306a36Sopenharmony_ci		}
35062306a36Sopenharmony_ci	}
35162306a36Sopenharmony_ci	ls = NULL;
35262306a36Sopenharmony_ci out:
35362306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
35462306a36Sopenharmony_ci	return ls;
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_civoid dlm_put_lockspace(struct dlm_ls *ls)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	if (atomic_dec_and_test(&ls->ls_count))
36062306a36Sopenharmony_ci		wake_up(&ls->ls_count_wait);
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic void remove_lockspace(struct dlm_ls *ls)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ciretry:
36662306a36Sopenharmony_ci	wait_event(ls->ls_count_wait, atomic_read(&ls->ls_count) == 0);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	spin_lock(&lslist_lock);
36962306a36Sopenharmony_ci	if (atomic_read(&ls->ls_count) != 0) {
37062306a36Sopenharmony_ci		spin_unlock(&lslist_lock);
37162306a36Sopenharmony_ci		goto retry;
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	WARN_ON(ls->ls_create_count != 0);
37562306a36Sopenharmony_ci	list_del(&ls->ls_list);
37662306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
37762306a36Sopenharmony_ci}
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cistatic int threads_start(void)
38062306a36Sopenharmony_ci{
38162306a36Sopenharmony_ci	int error;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	/* Thread for sending/receiving messages for all lockspace's */
38462306a36Sopenharmony_ci	error = dlm_midcomms_start();
38562306a36Sopenharmony_ci	if (error) {
38662306a36Sopenharmony_ci		log_print("cannot start dlm midcomms %d", error);
38762306a36Sopenharmony_ci		goto fail;
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	error = dlm_scand_start();
39162306a36Sopenharmony_ci	if (error) {
39262306a36Sopenharmony_ci		log_print("cannot start dlm_scand thread %d", error);
39362306a36Sopenharmony_ci		goto midcomms_fail;
39462306a36Sopenharmony_ci	}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	return 0;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci midcomms_fail:
39962306a36Sopenharmony_ci	dlm_midcomms_stop();
40062306a36Sopenharmony_ci fail:
40162306a36Sopenharmony_ci	return error;
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic int new_lockspace(const char *name, const char *cluster,
40562306a36Sopenharmony_ci			 uint32_t flags, int lvblen,
40662306a36Sopenharmony_ci			 const struct dlm_lockspace_ops *ops, void *ops_arg,
40762306a36Sopenharmony_ci			 int *ops_result, dlm_lockspace_t **lockspace)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	struct dlm_ls *ls;
41062306a36Sopenharmony_ci	int i, size, error;
41162306a36Sopenharmony_ci	int do_unreg = 0;
41262306a36Sopenharmony_ci	int namelen = strlen(name);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	if (namelen > DLM_LOCKSPACE_LEN || namelen == 0)
41562306a36Sopenharmony_ci		return -EINVAL;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	if (lvblen % 8)
41862306a36Sopenharmony_ci		return -EINVAL;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	if (!try_module_get(THIS_MODULE))
42162306a36Sopenharmony_ci		return -EINVAL;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	if (!dlm_user_daemon_available()) {
42462306a36Sopenharmony_ci		log_print("dlm user daemon not available");
42562306a36Sopenharmony_ci		error = -EUNATCH;
42662306a36Sopenharmony_ci		goto out;
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	if (ops && ops_result) {
43062306a36Sopenharmony_ci	       	if (!dlm_config.ci_recover_callbacks)
43162306a36Sopenharmony_ci			*ops_result = -EOPNOTSUPP;
43262306a36Sopenharmony_ci		else
43362306a36Sopenharmony_ci			*ops_result = 0;
43462306a36Sopenharmony_ci	}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	if (!cluster)
43762306a36Sopenharmony_ci		log_print("dlm cluster name '%s' is being used without an application provided cluster name",
43862306a36Sopenharmony_ci			  dlm_config.ci_cluster_name);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	if (dlm_config.ci_recover_callbacks && cluster &&
44162306a36Sopenharmony_ci	    strncmp(cluster, dlm_config.ci_cluster_name, DLM_LOCKSPACE_LEN)) {
44262306a36Sopenharmony_ci		log_print("dlm cluster name '%s' does not match "
44362306a36Sopenharmony_ci			  "the application cluster name '%s'",
44462306a36Sopenharmony_ci			  dlm_config.ci_cluster_name, cluster);
44562306a36Sopenharmony_ci		error = -EBADR;
44662306a36Sopenharmony_ci		goto out;
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	error = 0;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	spin_lock(&lslist_lock);
45262306a36Sopenharmony_ci	list_for_each_entry(ls, &lslist, ls_list) {
45362306a36Sopenharmony_ci		WARN_ON(ls->ls_create_count <= 0);
45462306a36Sopenharmony_ci		if (ls->ls_namelen != namelen)
45562306a36Sopenharmony_ci			continue;
45662306a36Sopenharmony_ci		if (memcmp(ls->ls_name, name, namelen))
45762306a36Sopenharmony_ci			continue;
45862306a36Sopenharmony_ci		if (flags & DLM_LSFL_NEWEXCL) {
45962306a36Sopenharmony_ci			error = -EEXIST;
46062306a36Sopenharmony_ci			break;
46162306a36Sopenharmony_ci		}
46262306a36Sopenharmony_ci		ls->ls_create_count++;
46362306a36Sopenharmony_ci		*lockspace = ls;
46462306a36Sopenharmony_ci		error = 1;
46562306a36Sopenharmony_ci		break;
46662306a36Sopenharmony_ci	}
46762306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	if (error)
47062306a36Sopenharmony_ci		goto out;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	error = -ENOMEM;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	ls = kzalloc(sizeof(*ls), GFP_NOFS);
47562306a36Sopenharmony_ci	if (!ls)
47662306a36Sopenharmony_ci		goto out;
47762306a36Sopenharmony_ci	memcpy(ls->ls_name, name, namelen);
47862306a36Sopenharmony_ci	ls->ls_namelen = namelen;
47962306a36Sopenharmony_ci	ls->ls_lvblen = lvblen;
48062306a36Sopenharmony_ci	atomic_set(&ls->ls_count, 0);
48162306a36Sopenharmony_ci	init_waitqueue_head(&ls->ls_count_wait);
48262306a36Sopenharmony_ci	ls->ls_flags = 0;
48362306a36Sopenharmony_ci	ls->ls_scan_time = jiffies;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	if (ops && dlm_config.ci_recover_callbacks) {
48662306a36Sopenharmony_ci		ls->ls_ops = ops;
48762306a36Sopenharmony_ci		ls->ls_ops_arg = ops_arg;
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	/* ls_exflags are forced to match among nodes, and we don't
49162306a36Sopenharmony_ci	 * need to require all nodes to have some flags set
49262306a36Sopenharmony_ci	 */
49362306a36Sopenharmony_ci	ls->ls_exflags = (flags & ~(DLM_LSFL_FS | DLM_LSFL_NEWEXCL));
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	size = READ_ONCE(dlm_config.ci_rsbtbl_size);
49662306a36Sopenharmony_ci	ls->ls_rsbtbl_size = size;
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	ls->ls_rsbtbl = vmalloc(array_size(size, sizeof(struct dlm_rsbtable)));
49962306a36Sopenharmony_ci	if (!ls->ls_rsbtbl)
50062306a36Sopenharmony_ci		goto out_lsfree;
50162306a36Sopenharmony_ci	for (i = 0; i < size; i++) {
50262306a36Sopenharmony_ci		ls->ls_rsbtbl[i].keep.rb_node = NULL;
50362306a36Sopenharmony_ci		ls->ls_rsbtbl[i].toss.rb_node = NULL;
50462306a36Sopenharmony_ci		spin_lock_init(&ls->ls_rsbtbl[i].lock);
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) {
50862306a36Sopenharmony_ci		ls->ls_remove_names[i] = kzalloc(DLM_RESNAME_MAXLEN+1,
50962306a36Sopenharmony_ci						 GFP_KERNEL);
51062306a36Sopenharmony_ci		if (!ls->ls_remove_names[i])
51162306a36Sopenharmony_ci			goto out_rsbtbl;
51262306a36Sopenharmony_ci	}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	idr_init(&ls->ls_lkbidr);
51562306a36Sopenharmony_ci	spin_lock_init(&ls->ls_lkbidr_spin);
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_waiters);
51862306a36Sopenharmony_ci	mutex_init(&ls->ls_waiters_mutex);
51962306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_orphans);
52062306a36Sopenharmony_ci	mutex_init(&ls->ls_orphans_mutex);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_new_rsb);
52362306a36Sopenharmony_ci	spin_lock_init(&ls->ls_new_rsb_spin);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_nodes);
52662306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_nodes_gone);
52762306a36Sopenharmony_ci	ls->ls_num_nodes = 0;
52862306a36Sopenharmony_ci	ls->ls_low_nodeid = 0;
52962306a36Sopenharmony_ci	ls->ls_total_weight = 0;
53062306a36Sopenharmony_ci	ls->ls_node_array = NULL;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	memset(&ls->ls_local_rsb, 0, sizeof(struct dlm_rsb));
53362306a36Sopenharmony_ci	ls->ls_local_rsb.res_ls = ls;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	ls->ls_debug_rsb_dentry = NULL;
53662306a36Sopenharmony_ci	ls->ls_debug_waiters_dentry = NULL;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	init_waitqueue_head(&ls->ls_uevent_wait);
53962306a36Sopenharmony_ci	ls->ls_uevent_result = 0;
54062306a36Sopenharmony_ci	init_completion(&ls->ls_recovery_done);
54162306a36Sopenharmony_ci	ls->ls_recovery_result = -1;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	spin_lock_init(&ls->ls_cb_lock);
54462306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_cb_delay);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	ls->ls_recoverd_task = NULL;
54762306a36Sopenharmony_ci	mutex_init(&ls->ls_recoverd_active);
54862306a36Sopenharmony_ci	spin_lock_init(&ls->ls_recover_lock);
54962306a36Sopenharmony_ci	spin_lock_init(&ls->ls_rcom_spin);
55062306a36Sopenharmony_ci	get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
55162306a36Sopenharmony_ci	ls->ls_recover_status = 0;
55262306a36Sopenharmony_ci	ls->ls_recover_seq = get_random_u64();
55362306a36Sopenharmony_ci	ls->ls_recover_args = NULL;
55462306a36Sopenharmony_ci	init_rwsem(&ls->ls_in_recovery);
55562306a36Sopenharmony_ci	init_rwsem(&ls->ls_recv_active);
55662306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_requestqueue);
55762306a36Sopenharmony_ci	atomic_set(&ls->ls_requestqueue_cnt, 0);
55862306a36Sopenharmony_ci	init_waitqueue_head(&ls->ls_requestqueue_wait);
55962306a36Sopenharmony_ci	mutex_init(&ls->ls_requestqueue_mutex);
56062306a36Sopenharmony_ci	spin_lock_init(&ls->ls_clear_proc_locks);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	/* Due backwards compatibility with 3.1 we need to use maximum
56362306a36Sopenharmony_ci	 * possible dlm message size to be sure the message will fit and
56462306a36Sopenharmony_ci	 * not having out of bounds issues. However on sending side 3.2
56562306a36Sopenharmony_ci	 * might send less.
56662306a36Sopenharmony_ci	 */
56762306a36Sopenharmony_ci	ls->ls_recover_buf = kmalloc(DLM_MAX_SOCKET_BUFSIZE, GFP_NOFS);
56862306a36Sopenharmony_ci	if (!ls->ls_recover_buf)
56962306a36Sopenharmony_ci		goto out_lkbidr;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	ls->ls_slot = 0;
57262306a36Sopenharmony_ci	ls->ls_num_slots = 0;
57362306a36Sopenharmony_ci	ls->ls_slots_size = 0;
57462306a36Sopenharmony_ci	ls->ls_slots = NULL;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_recover_list);
57762306a36Sopenharmony_ci	spin_lock_init(&ls->ls_recover_list_lock);
57862306a36Sopenharmony_ci	idr_init(&ls->ls_recover_idr);
57962306a36Sopenharmony_ci	spin_lock_init(&ls->ls_recover_idr_lock);
58062306a36Sopenharmony_ci	ls->ls_recover_list_count = 0;
58162306a36Sopenharmony_ci	ls->ls_local_handle = ls;
58262306a36Sopenharmony_ci	init_waitqueue_head(&ls->ls_wait_general);
58362306a36Sopenharmony_ci	INIT_LIST_HEAD(&ls->ls_root_list);
58462306a36Sopenharmony_ci	init_rwsem(&ls->ls_root_sem);
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	spin_lock(&lslist_lock);
58762306a36Sopenharmony_ci	ls->ls_create_count = 1;
58862306a36Sopenharmony_ci	list_add(&ls->ls_list, &lslist);
58962306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	if (flags & DLM_LSFL_FS) {
59262306a36Sopenharmony_ci		error = dlm_callback_start(ls);
59362306a36Sopenharmony_ci		if (error) {
59462306a36Sopenharmony_ci			log_error(ls, "can't start dlm_callback %d", error);
59562306a36Sopenharmony_ci			goto out_delist;
59662306a36Sopenharmony_ci		}
59762306a36Sopenharmony_ci	}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	init_waitqueue_head(&ls->ls_recover_lock_wait);
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	/*
60262306a36Sopenharmony_ci	 * Once started, dlm_recoverd first looks for ls in lslist, then
60362306a36Sopenharmony_ci	 * initializes ls_in_recovery as locked in "down" mode.  We need
60462306a36Sopenharmony_ci	 * to wait for the wakeup from dlm_recoverd because in_recovery
60562306a36Sopenharmony_ci	 * has to start out in down mode.
60662306a36Sopenharmony_ci	 */
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	error = dlm_recoverd_start(ls);
60962306a36Sopenharmony_ci	if (error) {
61062306a36Sopenharmony_ci		log_error(ls, "can't start dlm_recoverd %d", error);
61162306a36Sopenharmony_ci		goto out_callback;
61262306a36Sopenharmony_ci	}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	wait_event(ls->ls_recover_lock_wait,
61562306a36Sopenharmony_ci		   test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags));
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	/* let kobject handle freeing of ls if there's an error */
61862306a36Sopenharmony_ci	do_unreg = 1;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	ls->ls_kobj.kset = dlm_kset;
62162306a36Sopenharmony_ci	error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
62262306a36Sopenharmony_ci				     "%s", ls->ls_name);
62362306a36Sopenharmony_ci	if (error)
62462306a36Sopenharmony_ci		goto out_recoverd;
62562306a36Sopenharmony_ci	kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	/* This uevent triggers dlm_controld in userspace to add us to the
62862306a36Sopenharmony_ci	   group of nodes that are members of this lockspace (managed by the
62962306a36Sopenharmony_ci	   cluster infrastructure.)  Once it's done that, it tells us who the
63062306a36Sopenharmony_ci	   current lockspace members are (via configfs) and then tells the
63162306a36Sopenharmony_ci	   lockspace to start running (via sysfs) in dlm_ls_start(). */
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	error = do_uevent(ls, 1);
63462306a36Sopenharmony_ci	if (error)
63562306a36Sopenharmony_ci		goto out_recoverd;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	/* wait until recovery is successful or failed */
63862306a36Sopenharmony_ci	wait_for_completion(&ls->ls_recovery_done);
63962306a36Sopenharmony_ci	error = ls->ls_recovery_result;
64062306a36Sopenharmony_ci	if (error)
64162306a36Sopenharmony_ci		goto out_members;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	dlm_create_debug_file(ls);
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	log_rinfo(ls, "join complete");
64662306a36Sopenharmony_ci	*lockspace = ls;
64762306a36Sopenharmony_ci	return 0;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci out_members:
65062306a36Sopenharmony_ci	do_uevent(ls, 0);
65162306a36Sopenharmony_ci	dlm_clear_members(ls);
65262306a36Sopenharmony_ci	kfree(ls->ls_node_array);
65362306a36Sopenharmony_ci out_recoverd:
65462306a36Sopenharmony_ci	dlm_recoverd_stop(ls);
65562306a36Sopenharmony_ci out_callback:
65662306a36Sopenharmony_ci	dlm_callback_stop(ls);
65762306a36Sopenharmony_ci out_delist:
65862306a36Sopenharmony_ci	spin_lock(&lslist_lock);
65962306a36Sopenharmony_ci	list_del(&ls->ls_list);
66062306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
66162306a36Sopenharmony_ci	idr_destroy(&ls->ls_recover_idr);
66262306a36Sopenharmony_ci	kfree(ls->ls_recover_buf);
66362306a36Sopenharmony_ci out_lkbidr:
66462306a36Sopenharmony_ci	idr_destroy(&ls->ls_lkbidr);
66562306a36Sopenharmony_ci out_rsbtbl:
66662306a36Sopenharmony_ci	for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++)
66762306a36Sopenharmony_ci		kfree(ls->ls_remove_names[i]);
66862306a36Sopenharmony_ci	vfree(ls->ls_rsbtbl);
66962306a36Sopenharmony_ci out_lsfree:
67062306a36Sopenharmony_ci	if (do_unreg)
67162306a36Sopenharmony_ci		kobject_put(&ls->ls_kobj);
67262306a36Sopenharmony_ci	else
67362306a36Sopenharmony_ci		kfree(ls);
67462306a36Sopenharmony_ci out:
67562306a36Sopenharmony_ci	module_put(THIS_MODULE);
67662306a36Sopenharmony_ci	return error;
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_cistatic int __dlm_new_lockspace(const char *name, const char *cluster,
68062306a36Sopenharmony_ci			       uint32_t flags, int lvblen,
68162306a36Sopenharmony_ci			       const struct dlm_lockspace_ops *ops,
68262306a36Sopenharmony_ci			       void *ops_arg, int *ops_result,
68362306a36Sopenharmony_ci			       dlm_lockspace_t **lockspace)
68462306a36Sopenharmony_ci{
68562306a36Sopenharmony_ci	int error = 0;
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	mutex_lock(&ls_lock);
68862306a36Sopenharmony_ci	if (!ls_count)
68962306a36Sopenharmony_ci		error = threads_start();
69062306a36Sopenharmony_ci	if (error)
69162306a36Sopenharmony_ci		goto out;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	error = new_lockspace(name, cluster, flags, lvblen, ops, ops_arg,
69462306a36Sopenharmony_ci			      ops_result, lockspace);
69562306a36Sopenharmony_ci	if (!error)
69662306a36Sopenharmony_ci		ls_count++;
69762306a36Sopenharmony_ci	if (error > 0)
69862306a36Sopenharmony_ci		error = 0;
69962306a36Sopenharmony_ci	if (!ls_count) {
70062306a36Sopenharmony_ci		dlm_scand_stop();
70162306a36Sopenharmony_ci		dlm_midcomms_shutdown();
70262306a36Sopenharmony_ci		dlm_midcomms_stop();
70362306a36Sopenharmony_ci	}
70462306a36Sopenharmony_ci out:
70562306a36Sopenharmony_ci	mutex_unlock(&ls_lock);
70662306a36Sopenharmony_ci	return error;
70762306a36Sopenharmony_ci}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ciint dlm_new_lockspace(const char *name, const char *cluster, uint32_t flags,
71062306a36Sopenharmony_ci		      int lvblen, const struct dlm_lockspace_ops *ops,
71162306a36Sopenharmony_ci		      void *ops_arg, int *ops_result,
71262306a36Sopenharmony_ci		      dlm_lockspace_t **lockspace)
71362306a36Sopenharmony_ci{
71462306a36Sopenharmony_ci	return __dlm_new_lockspace(name, cluster, flags | DLM_LSFL_FS, lvblen,
71562306a36Sopenharmony_ci				   ops, ops_arg, ops_result, lockspace);
71662306a36Sopenharmony_ci}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ciint dlm_new_user_lockspace(const char *name, const char *cluster,
71962306a36Sopenharmony_ci			   uint32_t flags, int lvblen,
72062306a36Sopenharmony_ci			   const struct dlm_lockspace_ops *ops,
72162306a36Sopenharmony_ci			   void *ops_arg, int *ops_result,
72262306a36Sopenharmony_ci			   dlm_lockspace_t **lockspace)
72362306a36Sopenharmony_ci{
72462306a36Sopenharmony_ci	return __dlm_new_lockspace(name, cluster, flags, lvblen, ops,
72562306a36Sopenharmony_ci				   ops_arg, ops_result, lockspace);
72662306a36Sopenharmony_ci}
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_cistatic int lkb_idr_is_local(int id, void *p, void *data)
72962306a36Sopenharmony_ci{
73062306a36Sopenharmony_ci	struct dlm_lkb *lkb = p;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	return lkb->lkb_nodeid == 0 && lkb->lkb_grmode != DLM_LOCK_IV;
73362306a36Sopenharmony_ci}
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_cistatic int lkb_idr_is_any(int id, void *p, void *data)
73662306a36Sopenharmony_ci{
73762306a36Sopenharmony_ci	return 1;
73862306a36Sopenharmony_ci}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_cistatic int lkb_idr_free(int id, void *p, void *data)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	struct dlm_lkb *lkb = p;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	if (lkb->lkb_lvbptr && test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags))
74562306a36Sopenharmony_ci		dlm_free_lvb(lkb->lkb_lvbptr);
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	dlm_free_lkb(lkb);
74862306a36Sopenharmony_ci	return 0;
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci/* NOTE: We check the lkbidr here rather than the resource table.
75262306a36Sopenharmony_ci   This is because there may be LKBs queued as ASTs that have been unlinked
75362306a36Sopenharmony_ci   from their RSBs and are pending deletion once the AST has been delivered */
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_cistatic int lockspace_busy(struct dlm_ls *ls, int force)
75662306a36Sopenharmony_ci{
75762306a36Sopenharmony_ci	int rv;
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	spin_lock(&ls->ls_lkbidr_spin);
76062306a36Sopenharmony_ci	if (force == 0) {
76162306a36Sopenharmony_ci		rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_any, ls);
76262306a36Sopenharmony_ci	} else if (force == 1) {
76362306a36Sopenharmony_ci		rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_local, ls);
76462306a36Sopenharmony_ci	} else {
76562306a36Sopenharmony_ci		rv = 0;
76662306a36Sopenharmony_ci	}
76762306a36Sopenharmony_ci	spin_unlock(&ls->ls_lkbidr_spin);
76862306a36Sopenharmony_ci	return rv;
76962306a36Sopenharmony_ci}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cistatic int release_lockspace(struct dlm_ls *ls, int force)
77262306a36Sopenharmony_ci{
77362306a36Sopenharmony_ci	struct dlm_rsb *rsb;
77462306a36Sopenharmony_ci	struct rb_node *n;
77562306a36Sopenharmony_ci	int i, busy, rv;
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	busy = lockspace_busy(ls, force);
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	spin_lock(&lslist_lock);
78062306a36Sopenharmony_ci	if (ls->ls_create_count == 1) {
78162306a36Sopenharmony_ci		if (busy) {
78262306a36Sopenharmony_ci			rv = -EBUSY;
78362306a36Sopenharmony_ci		} else {
78462306a36Sopenharmony_ci			/* remove_lockspace takes ls off lslist */
78562306a36Sopenharmony_ci			ls->ls_create_count = 0;
78662306a36Sopenharmony_ci			rv = 0;
78762306a36Sopenharmony_ci		}
78862306a36Sopenharmony_ci	} else if (ls->ls_create_count > 1) {
78962306a36Sopenharmony_ci		rv = --ls->ls_create_count;
79062306a36Sopenharmony_ci	} else {
79162306a36Sopenharmony_ci		rv = -EINVAL;
79262306a36Sopenharmony_ci	}
79362306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	if (rv) {
79662306a36Sopenharmony_ci		log_debug(ls, "release_lockspace no remove %d", rv);
79762306a36Sopenharmony_ci		return rv;
79862306a36Sopenharmony_ci	}
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	if (ls_count == 1)
80162306a36Sopenharmony_ci		dlm_midcomms_version_wait();
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	dlm_device_deregister(ls);
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	if (force < 3 && dlm_user_daemon_available())
80662306a36Sopenharmony_ci		do_uevent(ls, 0);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	dlm_recoverd_stop(ls);
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	if (ls_count == 1) {
81162306a36Sopenharmony_ci		dlm_scand_stop();
81262306a36Sopenharmony_ci		dlm_clear_members(ls);
81362306a36Sopenharmony_ci		dlm_midcomms_shutdown();
81462306a36Sopenharmony_ci	}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	dlm_callback_stop(ls);
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	remove_lockspace(ls);
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	dlm_delete_debug_file(ls);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	idr_destroy(&ls->ls_recover_idr);
82362306a36Sopenharmony_ci	kfree(ls->ls_recover_buf);
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	/*
82662306a36Sopenharmony_ci	 * Free all lkb's in idr
82762306a36Sopenharmony_ci	 */
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	idr_for_each(&ls->ls_lkbidr, lkb_idr_free, ls);
83062306a36Sopenharmony_ci	idr_destroy(&ls->ls_lkbidr);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	/*
83362306a36Sopenharmony_ci	 * Free all rsb's on rsbtbl[] lists
83462306a36Sopenharmony_ci	 */
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	for (i = 0; i < ls->ls_rsbtbl_size; i++) {
83762306a36Sopenharmony_ci		while ((n = rb_first(&ls->ls_rsbtbl[i].keep))) {
83862306a36Sopenharmony_ci			rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
83962306a36Sopenharmony_ci			rb_erase(n, &ls->ls_rsbtbl[i].keep);
84062306a36Sopenharmony_ci			dlm_free_rsb(rsb);
84162306a36Sopenharmony_ci		}
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci		while ((n = rb_first(&ls->ls_rsbtbl[i].toss))) {
84462306a36Sopenharmony_ci			rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
84562306a36Sopenharmony_ci			rb_erase(n, &ls->ls_rsbtbl[i].toss);
84662306a36Sopenharmony_ci			dlm_free_rsb(rsb);
84762306a36Sopenharmony_ci		}
84862306a36Sopenharmony_ci	}
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	vfree(ls->ls_rsbtbl);
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++)
85362306a36Sopenharmony_ci		kfree(ls->ls_remove_names[i]);
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	while (!list_empty(&ls->ls_new_rsb)) {
85662306a36Sopenharmony_ci		rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb,
85762306a36Sopenharmony_ci				       res_hashchain);
85862306a36Sopenharmony_ci		list_del(&rsb->res_hashchain);
85962306a36Sopenharmony_ci		dlm_free_rsb(rsb);
86062306a36Sopenharmony_ci	}
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	/*
86362306a36Sopenharmony_ci	 * Free structures on any other lists
86462306a36Sopenharmony_ci	 */
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	dlm_purge_requestqueue(ls);
86762306a36Sopenharmony_ci	kfree(ls->ls_recover_args);
86862306a36Sopenharmony_ci	dlm_clear_members(ls);
86962306a36Sopenharmony_ci	dlm_clear_members_gone(ls);
87062306a36Sopenharmony_ci	kfree(ls->ls_node_array);
87162306a36Sopenharmony_ci	log_rinfo(ls, "release_lockspace final free");
87262306a36Sopenharmony_ci	kobject_put(&ls->ls_kobj);
87362306a36Sopenharmony_ci	/* The ls structure will be freed when the kobject is done with */
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	module_put(THIS_MODULE);
87662306a36Sopenharmony_ci	return 0;
87762306a36Sopenharmony_ci}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci/*
88062306a36Sopenharmony_ci * Called when a system has released all its locks and is not going to use the
88162306a36Sopenharmony_ci * lockspace any longer.  We free everything we're managing for this lockspace.
88262306a36Sopenharmony_ci * Remaining nodes will go through the recovery process as if we'd died.  The
88362306a36Sopenharmony_ci * lockspace must continue to function as usual, participating in recoveries,
88462306a36Sopenharmony_ci * until this returns.
88562306a36Sopenharmony_ci *
88662306a36Sopenharmony_ci * Force has 4 possible values:
88762306a36Sopenharmony_ci * 0 - don't destroy lockspace if it has any LKBs
88862306a36Sopenharmony_ci * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
88962306a36Sopenharmony_ci * 2 - destroy lockspace regardless of LKBs
89062306a36Sopenharmony_ci * 3 - destroy lockspace as part of a forced shutdown
89162306a36Sopenharmony_ci */
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ciint dlm_release_lockspace(void *lockspace, int force)
89462306a36Sopenharmony_ci{
89562306a36Sopenharmony_ci	struct dlm_ls *ls;
89662306a36Sopenharmony_ci	int error;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	ls = dlm_find_lockspace_local(lockspace);
89962306a36Sopenharmony_ci	if (!ls)
90062306a36Sopenharmony_ci		return -EINVAL;
90162306a36Sopenharmony_ci	dlm_put_lockspace(ls);
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	mutex_lock(&ls_lock);
90462306a36Sopenharmony_ci	error = release_lockspace(ls, force);
90562306a36Sopenharmony_ci	if (!error)
90662306a36Sopenharmony_ci		ls_count--;
90762306a36Sopenharmony_ci	if (!ls_count)
90862306a36Sopenharmony_ci		dlm_midcomms_stop();
90962306a36Sopenharmony_ci	mutex_unlock(&ls_lock);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	return error;
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_civoid dlm_stop_lockspaces(void)
91562306a36Sopenharmony_ci{
91662306a36Sopenharmony_ci	struct dlm_ls *ls;
91762306a36Sopenharmony_ci	int count;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci restart:
92062306a36Sopenharmony_ci	count = 0;
92162306a36Sopenharmony_ci	spin_lock(&lslist_lock);
92262306a36Sopenharmony_ci	list_for_each_entry(ls, &lslist, ls_list) {
92362306a36Sopenharmony_ci		if (!test_bit(LSFL_RUNNING, &ls->ls_flags)) {
92462306a36Sopenharmony_ci			count++;
92562306a36Sopenharmony_ci			continue;
92662306a36Sopenharmony_ci		}
92762306a36Sopenharmony_ci		spin_unlock(&lslist_lock);
92862306a36Sopenharmony_ci		log_error(ls, "no userland control daemon, stopping lockspace");
92962306a36Sopenharmony_ci		dlm_ls_stop(ls);
93062306a36Sopenharmony_ci		goto restart;
93162306a36Sopenharmony_ci	}
93262306a36Sopenharmony_ci	spin_unlock(&lslist_lock);
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	if (count)
93562306a36Sopenharmony_ci		log_print("dlm user daemon left %d lockspaces", count);
93662306a36Sopenharmony_ci}
93762306a36Sopenharmony_ci
938