Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f8e0d9a authored by David Teigland's avatar David Teigland
Browse files

dlm: allow multiple lockspace creates



Add a count for lockspace create and release so that create can
be called multiple times to use the lockspace from different places.
Also add the new flag DLM_LSFL_NEWEXCL to create a lockspace with
the previous behavior of returning -EEXIST if the lockspace already
exists.

Signed-off-by: default avatarDavid Teigland <teigland@redhat.com>
parent 4c246edd
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@
*******************************************************************************
*******************************************************************************
**
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
**
**
**  This copyrighted material is made available to anyone wishing to use,
**  This copyrighted material is made available to anyone wishing to use,
**  modify, copy, or redistribute it subject to the terms and conditions
**  modify, copy, or redistribute it subject to the terms and conditions
@@ -441,7 +441,9 @@ struct dlm_ls {
	uint32_t		ls_global_id;	/* global unique lockspace ID */
	uint32_t		ls_global_id;	/* global unique lockspace ID */
	uint32_t		ls_exflags;
	uint32_t		ls_exflags;
	int			ls_lvblen;
	int			ls_lvblen;
	int			ls_count;	/* reference count */
	int			ls_count;	/* refcount of processes in
						   the dlm using this ls */
	int			ls_create_count; /* create/release refcount */
	unsigned long		ls_flags;	/* LSFL_ */
	unsigned long		ls_flags;	/* LSFL_ */
	struct kobject		ls_kobj;
	struct kobject		ls_kobj;


+70 −37
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@
*******************************************************************************
*******************************************************************************
**
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
**
**
**  This copyrighted material is made available to anyone wishing to use,
**  This copyrighted material is made available to anyone wishing to use,
**  modify, copy, or redistribute it subject to the terms and conditions
**  modify, copy, or redistribute it subject to the terms and conditions
@@ -23,6 +23,7 @@
#include "lock.h"
#include "lock.h"
#include "recover.h"
#include "recover.h"
#include "requestqueue.h"
#include "requestqueue.h"
#include "user.h"


static int			ls_count;
static int			ls_count;
static struct mutex		ls_lock;
static struct mutex		ls_lock;
@@ -246,23 +247,6 @@ static void dlm_scand_stop(void)
	kthread_stop(scand_task);
	kthread_stop(scand_task);
}
}


static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen)
{
	struct dlm_ls *ls;

	spin_lock(&lslist_lock);

	list_for_each_entry(ls, &lslist, ls_list) {
		if (ls->ls_namelen == namelen &&
		    memcmp(ls->ls_name, name, namelen) == 0)
			goto out;
	}
	ls = NULL;
 out:
	spin_unlock(&lslist_lock);
	return ls;
}

struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
{
{
	struct dlm_ls *ls;
	struct dlm_ls *ls;
@@ -327,6 +311,7 @@ static void remove_lockspace(struct dlm_ls *ls)
	for (;;) {
	for (;;) {
		spin_lock(&lslist_lock);
		spin_lock(&lslist_lock);
		if (ls->ls_count == 0) {
		if (ls->ls_count == 0) {
			WARN_ON(ls->ls_create_count != 0);
			list_del(&ls->ls_list);
			list_del(&ls->ls_list);
			spin_unlock(&lslist_lock);
			spin_unlock(&lslist_lock);
			return;
			return;
@@ -381,7 +366,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
			 uint32_t flags, int lvblen)
			 uint32_t flags, int lvblen)
{
{
	struct dlm_ls *ls;
	struct dlm_ls *ls;
	int i, size, error = -ENOMEM;
	int i, size, error;
	int do_unreg = 0;
	int do_unreg = 0;


	if (namelen > DLM_LOCKSPACE_LEN)
	if (namelen > DLM_LOCKSPACE_LEN)
@@ -393,12 +378,32 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
	if (!try_module_get(THIS_MODULE))
	if (!try_module_get(THIS_MODULE))
		return -EINVAL;
		return -EINVAL;


	ls = dlm_find_lockspace_name(name, namelen);
	error = 0;
	if (ls) {

		*lockspace = ls;
	spin_lock(&lslist_lock);
	list_for_each_entry(ls, &lslist, ls_list) {
		WARN_ON(ls->ls_create_count <= 0);
		if (ls->ls_namelen != namelen)
			continue;
		if (memcmp(ls->ls_name, name, namelen))
			continue;
		if (flags & DLM_LSFL_NEWEXCL) {
			error = -EEXIST;
			break;
		}
		ls->ls_create_count++;
		module_put(THIS_MODULE);
		module_put(THIS_MODULE);
		return -EEXIST;
		error = 1; /* not an error, return 0 */
		break;
	}
	}
	spin_unlock(&lslist_lock);

	if (error < 0)
		goto out;
	if (error)
		goto ret_zero;

	error = -ENOMEM;


	ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
	ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
	if (!ls)
	if (!ls)
@@ -418,8 +423,9 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
		ls->ls_allocation = GFP_KERNEL;
		ls->ls_allocation = GFP_KERNEL;


	/* ls_exflags are forced to match among nodes, and we don't
	/* ls_exflags are forced to match among nodes, and we don't
	   need to require all nodes to have TIMEWARN or FS set */
	   need to require all nodes to have some flags set */
	ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
	ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
				    DLM_LSFL_NEWEXCL));


	size = dlm_config.ci_rsbtbl_size;
	size = dlm_config.ci_rsbtbl_size;
	ls->ls_rsbtbl_size = size;
	ls->ls_rsbtbl_size = size;
@@ -510,6 +516,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
	down_write(&ls->ls_in_recovery);
	down_write(&ls->ls_in_recovery);


	spin_lock(&lslist_lock);
	spin_lock(&lslist_lock);
	ls->ls_create_count = 1;
	list_add(&ls->ls_list, &lslist);
	list_add(&ls->ls_list, &lslist);
	spin_unlock(&lslist_lock);
	spin_unlock(&lslist_lock);


@@ -548,7 +555,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
	dlm_create_debug_file(ls);
	dlm_create_debug_file(ls);


	log_debug(ls, "join complete");
	log_debug(ls, "join complete");

 ret_zero:
	*lockspace = ls;
	*lockspace = ls;
	return 0;
	return 0;


@@ -635,11 +642,32 @@ static int release_lockspace(struct dlm_ls *ls, int force)
	struct dlm_lkb *lkb;
	struct dlm_lkb *lkb;
	struct dlm_rsb *rsb;
	struct dlm_rsb *rsb;
	struct list_head *head;
	struct list_head *head;
	int i;
	int i, busy, rv;
	int busy = lockspace_busy(ls);

	busy = lockspace_busy(ls);


	spin_lock(&lslist_lock);
	if (ls->ls_create_count == 1) {
		if (busy > force)
		if (busy > force)
		return -EBUSY;
			rv = -EBUSY;
		else {
			/* remove_lockspace takes ls off lslist */
			ls->ls_create_count = 0;
			rv = 0;
		}
	} else if (ls->ls_create_count > 1) {
		rv = --ls->ls_create_count;
	} else {
		rv = -EINVAL;
	}
	spin_unlock(&lslist_lock);

	if (rv) {
		log_debug(ls, "release_lockspace no remove %d", rv);
		return rv;
	}

	dlm_device_deregister(ls);


	if (force < 3)
	if (force < 3)
		do_uevent(ls, 0);
		do_uevent(ls, 0);
@@ -720,15 +748,10 @@ static int release_lockspace(struct dlm_ls *ls, int force)
	dlm_clear_members(ls);
	dlm_clear_members(ls);
	dlm_clear_members_gone(ls);
	dlm_clear_members_gone(ls);
	kfree(ls->ls_node_array);
	kfree(ls->ls_node_array);
	log_debug(ls, "release_lockspace final free");
	kobject_put(&ls->ls_kobj);
	kobject_put(&ls->ls_kobj);
	/* The ls structure will be freed when the kobject is done with */
	/* The ls structure will be freed when the kobject is done with */


	mutex_lock(&ls_lock);
	ls_count--;
	if (!ls_count)
		threads_stop();
	mutex_unlock(&ls_lock);

	module_put(THIS_MODULE);
	module_put(THIS_MODULE);
	return 0;
	return 0;
}
}
@@ -750,11 +773,21 @@ static int release_lockspace(struct dlm_ls *ls, int force)
int dlm_release_lockspace(void *lockspace, int force)
int dlm_release_lockspace(void *lockspace, int force)
{
{
	struct dlm_ls *ls;
	struct dlm_ls *ls;
	int error;


	ls = dlm_find_lockspace_local(lockspace);
	ls = dlm_find_lockspace_local(lockspace);
	if (!ls)
	if (!ls)
		return -EINVAL;
		return -EINVAL;
	dlm_put_lockspace(ls);
	dlm_put_lockspace(ls);
	return release_lockspace(ls, force);

	mutex_lock(&ls_lock);
	error = release_lockspace(ls, force);
	if (!error)
		ls_count--;
	else if (!ls_count)
		threads_stop();
	mutex_unlock(&ls_lock);

	return error;
}
}
+33 −21
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (C) 2006-2007 Red Hat, Inc.  All rights reserved.
 * Copyright (C) 2006-2008 Red Hat, Inc.  All rights reserved.
 *
 *
 * This copyrighted material is made available to anyone wishing to use,
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * modify, copy, or redistribute it subject to the terms and conditions
@@ -340,10 +340,15 @@ static int device_user_deadlock(struct dlm_user_proc *proc,
	return error;
	return error;
}
}


static int create_misc_device(struct dlm_ls *ls, char *name)
static int dlm_device_register(struct dlm_ls *ls, char *name)
{
{
	int error, len;
	int error, len;


	/* The device is already registered.  This happens when the
	   lockspace is created multiple times from userspace. */
	if (ls->ls_device.name)
		return 0;

	error = -ENOMEM;
	error = -ENOMEM;
	len = strlen(name) + strlen(name_prefix) + 2;
	len = strlen(name) + strlen(name_prefix) + 2;
	ls->ls_device.name = kzalloc(len, GFP_KERNEL);
	ls->ls_device.name = kzalloc(len, GFP_KERNEL);
@@ -363,6 +368,22 @@ static int create_misc_device(struct dlm_ls *ls, char *name)
	return error;
	return error;
}
}


int dlm_device_deregister(struct dlm_ls *ls)
{
	int error;

	/* The device is not registered.  This happens when the lockspace
	   was never used from userspace, or when device_create_lockspace()
	   calls dlm_release_lockspace() after the register fails. */
	if (!ls->ls_device.name)
		return 0;

	error = misc_deregister(&ls->ls_device);
	if (!error)
		kfree(ls->ls_device.name);
	return error;
}

static int device_user_purge(struct dlm_user_proc *proc,
static int device_user_purge(struct dlm_user_proc *proc,
			     struct dlm_purge_params *params)
			     struct dlm_purge_params *params)
{
{
@@ -397,7 +418,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params)
	if (!ls)
	if (!ls)
		return -ENOENT;
		return -ENOENT;


	error = create_misc_device(ls, params->name);
	error = dlm_device_register(ls, params->name);
	dlm_put_lockspace(ls);
	dlm_put_lockspace(ls);


	if (error)
	if (error)
@@ -421,31 +442,22 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
	if (!ls)
	if (!ls)
		return -ENOENT;
		return -ENOENT;


	/* Deregister the misc device first, so we don't have
	 * a device that's not attached to a lockspace. If
	 * dlm_release_lockspace fails then we can recreate it
	 */
	error = misc_deregister(&ls->ls_device);
	if (error) {
		dlm_put_lockspace(ls);
		goto out;
	}
	kfree(ls->ls_device.name);

	if (params->flags & DLM_USER_LSFLG_FORCEFREE)
	if (params->flags & DLM_USER_LSFLG_FORCEFREE)
		force = 2;
		force = 2;


	lockspace = ls->ls_local_handle;
	lockspace = ls->ls_local_handle;
	dlm_put_lockspace(ls);


	/* dlm_release_lockspace waits for references to go to zero,
	/* The final dlm_release_lockspace waits for references to go to
	   so all processes will need to close their device for the ls
	   zero, so all processes will need to close their device for the
	   before the release will procede */
	   ls before the release will proceed.  release also calls the
	   device_deregister above.  Converting a positive return value
	   from release to zero means that userspace won't know when its
	   release was the final one, but it shouldn't need to know. */


	dlm_put_lockspace(ls);
	error = dlm_release_lockspace(lockspace, force);
	error = dlm_release_lockspace(lockspace, force);
	if (error)
	if (error > 0)
		create_misc_device(ls, ls->ls_name);
		error = 0;
 out:
	return error;
	return error;
}
}


+2 −1
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
 * Copyright (C) 2006-2008 Red Hat, Inc.  All rights reserved.
 *
 *
 * This copyrighted material is made available to anyone wishing to use,
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * modify, copy, or redistribute it subject to the terms and conditions
@@ -12,5 +12,6 @@
void dlm_user_add_ast(struct dlm_lkb *lkb, int type);
void dlm_user_add_ast(struct dlm_lkb *lkb, int type);
int dlm_user_init(void);
int dlm_user_init(void);
void dlm_user_exit(void);
void dlm_user_exit(void);
int dlm_device_deregister(struct dlm_ls *ls);


#endif
#endif
+2 −1
Original line number Original line Diff line number Diff line
@@ -144,7 +144,8 @@ static int gdlm_mount(char *table_name, char *host_data,


	error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
	error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
				  &ls->dlm_lockspace,
				  &ls->dlm_lockspace,
				  DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
				  DLM_LSFL_FS | DLM_LSFL_NEWEXCL |
				  (nodir ? DLM_LSFL_NODIR : 0),
				  GDLM_LVB_SIZE);
				  GDLM_LVB_SIZE);
	if (error) {
	if (error) {
		log_error("dlm_new_lockspace error %d", error);
		log_error("dlm_new_lockspace error %d", error);
Loading