[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ogfs-dev]Deadman toy based on OpenDLM



On Fri, 2003-09-05 at 16:12, Stanley Wang wrote:
> Hi folks,
> Following patch is a little toy that implement deadman lock based on
> OpenDLM. I use it to hunter bugs :)
> If you are interested in it, build it with OpenDLM and have a try :)
> BE CAREFUL: there is a bug in it. At lease on of your machine will die
> when playing this toy! I'm now try to root cause it. And if you get it,
> please do notify me :)
If you call "dlmunlock" in the "blocking ast", the system will hang.
I've reported this bug to OpenDLM develop mailing list.
And I've resolved this problem by using timer. Following patch could
work properly. Just have a try :)

Enjoys,
Stan (Happy hacking...... :)
-- 
Opinions expressed are those of the author and do not represent Intel
Corporation
"gpg --recv-keys --keyserver wwwkeys.pgp.net E1390A7F"
{E1390A7F:3AD1 1B0C 2019 E183 0CFF  55E8 369A 8B75 E139 0A7F}

/* -*- linux-c -*- */

#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/timer.h>

#include <dlm.h>

#define DEADMAN_SUCCESS	0
#define DEADMAN_FAILED		1
#define DEADMAN_NONFIRST	2

#define NODES_COUNT	2

int node_id = 0;
MODULE_PARM(node_id, "i");

struct deadman_lock {
	struct lockstatus	lksb;
	int			node_id;
	int			done;
};

struct timer_list refresh_timer;

struct deadman_lock deadman[NODES_COUNT];

void deadman_block_others(void *bastargs, int mode);

void lock_ast(void *astarg)
{
        struct deadman_lock *lock = (struct deadman_lock *)astarg;
	lock->done = 1;
}

void ignore_bast(void *bastargs, int mode)
{
	return;
}

void ignore_ast(void *bastargs)
{
	return;
}

void ignore_unlockast(void *unlockastargs, int lstat, void* extrap)
{
	return;
}

void other_node_die(void* astargs)
{
	struct deadman_lock *lock = (struct deadman_lock *)astargs;
	printk("DEADMAN TOY: node %d died!\n", lock->node_id);
}

void refresh_deadman_lock(unsigned long arg)
{
	struct deadman_lock *lock = (struct deadman_lock *)arg;
	char lock_name[5];

	sprintf(lock_name, "%d", lock->node_id);

	printk("DEADMAN TOY: begin to refresh deadman lock!\n");

	dlmunlock(lock->lksb.lockid, NULL, LKM_FORCE, ignore_unlockast, NULL, NULL);

	dlmlock(LKM_CRMODE, &lock->lksb, 0, (void *)lock_name,
			 strlen(lock_name), other_node_die,
			 (void *)lock, deadman_block_others);

	printk("DEADMAN TOY: complete refreshing deadman lock!\n");

	return;
}

void deadman_block_others(void *bastargs, int mode)
{
	struct deadman_lock *lock = (struct deadman_lock *)bastargs;

	printk("DEADMAN TOY: node %d try to join us!\n", lock->node_id);

	init_timer(&refresh_timer);

	refresh_timer.expires = 1*HZ;
	refresh_timer.data = bastargs;
	refresh_timer.function = refresh_deadman_lock;

	add_timer(&refresh_timer);	

	return;
}

dlm_stats_t my_dlmlock_sync(int mode, struct lockstatus *lksb, int flags,
                            char *lock_name, struct deadman_lock *deadman, 
				dlm_bastlockfunc_t * bast)
{
        dlm_stats_t status;
	status = dlmlock(mode, lksb, flags, (void *)lock_name,
			 strlen(lock_name), lock_ast, (void *)deadman, bast);

        if(status != DLM_NORMAL)
                goto out;

 sleep:
        if(!deadman->done) {
                current->policy |= SCHED_YIELD;
                schedule();
                goto sleep;
        }
 out:
        return status;
}

void cleanup_deadman(void)
{
	int tmp;

	for( tmp = 0;tmp < NODES_COUNT; tmp++){
		dlmunlock(deadman[tmp].lksb.lockid, NULL, LKM_FORCE,
			  ignore_unlockast, NULL, NULL);
	}
}


int init_deadman(int first)
{
	unsigned int lock_num;
	dlm_stats_t status;


	for(lock_num = 0; lock_num < NODES_COUNT; lock_num++){
		char lock_name[5];
		sprintf(lock_name, "%d", lock_num);
		
		deadman[lock_num].node_id = lock_num;
		deadman[lock_num].done = 0;

		if(lock_num != node_id){
			if(first){
				printk("DEADMAN TOY: first&others!\n");
				status = my_dlmlock_sync(LKM_EXMODE, &deadman[lock_num].lksb, LKM_NOQUEUE, lock_name,
							&deadman[lock_num], deadman_block_others);
			} else {
				printk("DEADMAN TOY: non-first&others!\n");
				status = dlmlock(LKM_CRMODE, &deadman[lock_num].lksb, 0, (void *)lock_name,
							strlen(lock_name), other_node_die,
							(void *)&deadman[lock_num], deadman_block_others);
			}
		} else {
			printk("DEADMAN TOY: myself!\n");
			status = my_dlmlock_sync(LKM_EXMODE, &deadman[lock_num].lksb, 0, lock_name,
							&deadman[lock_num], ignore_bast);
		}

		if(status != DLM_NORMAL){
			return DEADMAN_FAILED; 
		}

		if(first && deadman[lock_num].lksb.status != DLM_NORMAL){
			return DEADMAN_NONFIRST;
		}
		printk("DEADMAN TOY: lockid %d\n", deadman[lock_num].lksb.lockid);
	}

	return DEADMAN_SUCCESS;
}

int start_deadman_lock(void)
{
	int error;
	
	error = init_deadman(1);

	switch (error) {

	case DEADMAN_FAILED:
		cleanup_deadman();
		return 0;

	case DEADMAN_NONFIRST:
		cleanup_deadman();
		break;
	case DEADMAN_SUCCESS:
		return 0;
	}

	error = init_deadman(0);

	if(error == DEADMAN_FAILED){
		cleanup_deadman();
		return 0;
	}

	return 0;
}

void stop_deadman_lock(void)
{
	cleanup_deadman();
	return;
}


module_init(start_deadman_lock);
module_exit(stop_deadman_lock);
MODULE_AUTHOR("Stanley Wang");
MODULE_DESCRIPTION("Deadman toy based on OpenDLM.");
MODULE_LICENSE("GPL");














-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Opengfs-devel mailing list
Opengfs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opengfs-devel

[Kernel]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Clusters]     [Linux RAID]     [Yosemite Hiking]     [Linux Resources]

Powered by Linux