mount.c 5.7 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
static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
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
{
	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);

104 105 106 107 108 109 110 111
		} else if (!strcmp(x, "nodir")) {
			if (!y) {
				log_error("need argument to nodir");
				error = -EINVAL;
				break;
			}
			sscanf(y, "%u", nodir);

112 113 114 115 116 117 118 119 120 121
		} else {
			log_error("unkonwn option: %s", x);
			error = -EINVAL;
			break;
		}
	}

	return error;
}

122 123 124
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,
125 126
			struct lm_lockstruct *lockstruct,
			struct kobject *fskobj)
127 128
{
	struct gdlm_ls *ls;
129
	int error = -ENOMEM, nodir = 0;
130 131 132 133 134 135 136 137

	if (min_lvb_size > GDLM_LVB_SIZE)
		goto out;

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

138 139 140 141
	error = make_args(ls, host_data, &nodir);
	if (error)
		goto out;

142 143 144 145 146
	error = gdlm_init_threads(ls);
	if (error)
		goto out_free;

	error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
147 148 149
				  &ls->dlm_lockspace,
				  nodir ? DLM_LSFL_NODIR : 0,
				  GDLM_LVB_SIZE);
150
	if (error) {
151
		log_error("dlm_new_lockspace error %d", error);
152 153 154
		goto out_thread;
	}

155
	error = gdlm_kobject_setup(ls, fskobj);
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
	if (error)
		goto out_dlm;

	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_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);

184 185 186
	/* FIXME: serialize unmount and withdraw in case they
	   happen at once.  Also, if unmount follows withdraw,
	   wait for withdraw to finish. */
187

188 189
	if (test_bit(DFL_WITHDRAW, &ls->flags))
		goto out;
190 191 192 193 194 195

	gdlm_kobject_release(ls);
	dlm_release_lockspace(ls->dlm_lockspace, 2);
	gdlm_release_threads(ls);
	rv = gdlm_release_all_locks(ls);
	if (rv)
196
		log_info("gdlm_unmount: %d stray locks freed", rv);
197 198 199 200 201 202 203 204
 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;
205
	ls->recover_jid_done = jid;
206
	kobject_uevent(&ls->kobj, KOBJ_CHANGE);
207 208 209 210 211 212
}

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

216 217 218 219
/* 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. */

220 221 222 223
static void gdlm_withdraw(lm_lockspace_t *lockspace)
{
	struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;

224
	kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
225 226 227 228 229 230 231

	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);
232
	gdlm_kobject_release(ls);
233 234 235
}

struct lm_lockops gdlm_ops = {
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
	.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,
254 255
};