mount.c 5.5 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
 * Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License v.2.
 */
9 10 11 12 13 14 15 16 17 18 19 20 21 22

#include "lock_dlm.h"

int gdlm_drop_count;
int gdlm_drop_period;
struct lm_lockops gdlm_ops;


static struct gdlm_ls *init_gdlm(lm_callback_t cb, lm_fsdata_t *fsdata,
				 int flags, char *table_name)
{
	struct gdlm_ls *ls;
	char buf[256], *p;

23
	ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL);
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
	if (!ls)
		return NULL;

	ls->drop_locks_count = gdlm_drop_count;
	ls->drop_locks_period = gdlm_drop_period;
	ls->fscb = cb;
	ls->fsdata = fsdata;
	ls->fsflags = flags;
	spin_lock_init(&ls->async_lock);
	INIT_LIST_HEAD(&ls->complete);
	INIT_LIST_HEAD(&ls->blocking);
	INIT_LIST_HEAD(&ls->delayed);
	INIT_LIST_HEAD(&ls->submit);
	INIT_LIST_HEAD(&ls->all_locks);
	init_waitqueue_head(&ls->thread_wait);
	init_waitqueue_head(&ls->wait_control);
	ls->thread1 = NULL;
	ls->thread2 = NULL;
	ls->drop_time = jiffies;
	ls->jid = -1;

	strncpy(buf, table_name, 256);
	buf[255] = '\0';

	p = strstr(buf, ":");
	if (!p) {
50
		log_info("invalid table_name \"%s\"", table_name);
51 52 53 54 55 56
		kfree(ls);
		return NULL;
	}
	*p = '\0';
	p++;

57 58
	strncpy(ls->clustername, buf, GDLM_NAME_LEN);
	strncpy(ls->fsname, p, GDLM_NAME_LEN);
59 60 61 62

	return ls;
}

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
static int make_args(struct gdlm_ls *ls, char *data_arg)
{
	char data[256];
	char *options, *x, *y;
	int error = 0;

	memset(data, 0, 256);
	strncpy(data, data_arg, 255);

	for (options = data; (x = strsep(&options, ":")); ) {
		if (!*x)
			continue;

		y = strchr(x, '=');
		if (y)
			*y++ = 0;

		if (!strcmp(x, "jid")) {
			if (!y) {
				log_error("need argument to jid");
				error = -EINVAL;
				break;
			}
			sscanf(y, "%u", &ls->jid);

		} else if (!strcmp(x, "first")) {
			if (!y) {
				log_error("need argument to first");
				error = -EINVAL;
				break;
			}
			sscanf(y, "%u", &ls->first);

		} else if (!strcmp(x, "id")) {
			if (!y) {
				log_error("need argument to id");
				error = -EINVAL;
				break;
			}
			sscanf(y, "%u", &ls->id);

		} else {
			log_error("unkonwn option: %s", x);
			error = -EINVAL;
			break;
		}
	}

	return error;
}

114 115 116
static int gdlm_mount(char *table_name, char *host_data,
			lm_callback_t cb, lm_fsdata_t *fsdata,
			unsigned int min_lvb_size, int flags,
117 118
			struct lm_lockstruct *lockstruct,
			struct kobject *fskobj)
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
{
	struct gdlm_ls *ls;
	int error = -ENOMEM;

	if (min_lvb_size > GDLM_LVB_SIZE)
		goto out;

	ls = init_gdlm(cb, fsdata, flags, table_name);
	if (!ls)
		goto out;

	error = gdlm_init_threads(ls);
	if (error)
		goto out_free;

	error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
				  &ls->dlm_lockspace, 0, GDLM_LVB_SIZE);
	if (error) {
137
		log_error("dlm_new_lockspace error %d", error);
138 139 140
		goto out_thread;
	}

141
	error = gdlm_kobject_setup(ls, fskobj);
142 143 144
	if (error)
		goto out_dlm;

145
	error = make_args(ls, host_data);
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
	if (error)
		goto out_sysfs;

	lockstruct->ls_jid = ls->jid;
	lockstruct->ls_first = ls->first;
	lockstruct->ls_lockspace = ls;
	lockstruct->ls_ops = &gdlm_ops;
	lockstruct->ls_flags = 0;
	lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
	return 0;

 out_sysfs:
	gdlm_kobject_release(ls);
 out_dlm:
	dlm_release_lockspace(ls->dlm_lockspace, 2);
 out_thread:
	gdlm_release_threads(ls);
 out_free:
	kfree(ls);
 out:
	return error;
}

static void gdlm_unmount(lm_lockspace_t *lockspace)
{
	struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
	int rv;

	log_debug("unmount flags %lx", ls->flags);

176 177 178
	/* FIXME: serialize unmount and withdraw in case they
	   happen at once.  Also, if unmount follows withdraw,
	   wait for withdraw to finish. */
179

180 181
	if (test_bit(DFL_WITHDRAW, &ls->flags))
		goto out;
182 183 184 185 186 187

	gdlm_kobject_release(ls);
	dlm_release_lockspace(ls->dlm_lockspace, 2);
	gdlm_release_threads(ls);
	rv = gdlm_release_all_locks(ls);
	if (rv)
188
		log_info("gdlm_unmount: %d stray locks freed", rv);
189 190 191 192 193 194 195 196
 out:
	kfree(ls);
}

static void gdlm_recovery_done(lm_lockspace_t *lockspace, unsigned int jid,
                               unsigned int message)
{
	struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
197
	ls->recover_jid_done = jid;
198
	kobject_uevent(&ls->kobj, KOBJ_CHANGE);
199 200 201 202 203 204
}

static void gdlm_others_may_mount(lm_lockspace_t *lockspace)
{
	struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
	ls->first_done = 1;
205
	kobject_uevent(&ls->kobj, KOBJ_CHANGE);
206 207
}

208 209 210 211
/* Userspace gets the offline uevent, blocks new gfs locks on
   other mounters, and lets us know (sets WITHDRAW flag).  Then,
   userspace leaves the mount group while we leave the lockspace. */

212 213 214 215
static void gdlm_withdraw(lm_lockspace_t *lockspace)
{
	struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;

216
	kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
217 218 219 220 221 222 223

	wait_event_interruptible(ls->wait_control,
				 test_bit(DFL_WITHDRAW, &ls->flags));

	dlm_release_lockspace(ls->dlm_lockspace, 2);
	gdlm_release_threads(ls);
	gdlm_release_all_locks(ls);
224
	gdlm_kobject_release(ls);
225 226 227
}

struct lm_lockops gdlm_ops = {
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
	.lm_proto_name = "lock_dlm",
	.lm_mount = gdlm_mount,
	.lm_others_may_mount = gdlm_others_may_mount,
	.lm_unmount = gdlm_unmount,
	.lm_withdraw = gdlm_withdraw,
	.lm_get_lock = gdlm_get_lock,
	.lm_put_lock = gdlm_put_lock,
	.lm_lock = gdlm_lock,
	.lm_unlock = gdlm_unlock,
	.lm_plock = gdlm_plock,
	.lm_punlock = gdlm_punlock,
	.lm_plock_get = gdlm_plock_get,
	.lm_cancel = gdlm_cancel,
	.lm_hold_lvb = gdlm_hold_lvb,
	.lm_unhold_lvb = gdlm_unhold_lvb,
	.lm_sync_lvb = gdlm_sync_lvb,
	.lm_recovery_done = gdlm_recovery_done,
	.lm_owner = THIS_MODULE,
246 247
};