Commit 49d41bae authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm:
  dlm: add recovery callbacks
  dlm: add node slots and generation
  dlm: move recovery barrier calls
  dlm: convert rsb list to rb_tree
parents 7b3480f8 60f98d18
Loading
Loading
Loading
Loading
+73 −57
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
**  Copyright (C) 2004-2011 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
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/dlmconstants.h>
#include <net/ipv6.h>
#include <net/sock.h>

@@ -36,6 +37,7 @@
static struct config_group *space_list;
static struct config_group *comm_list;
static struct dlm_comm *local_comm;
static uint32_t dlm_comm_count;

struct dlm_clusters;
struct dlm_cluster;
@@ -103,6 +105,8 @@ struct dlm_cluster {
	unsigned int cl_timewarn_cs;
	unsigned int cl_waitwarn_us;
	unsigned int cl_new_rsb_count;
	unsigned int cl_recover_callbacks;
	char cl_cluster_name[DLM_LOCKSPACE_LEN];
};

enum {
@@ -118,6 +122,8 @@ enum {
	CLUSTER_ATTR_TIMEWARN_CS,
	CLUSTER_ATTR_WAITWARN_US,
	CLUSTER_ATTR_NEW_RSB_COUNT,
	CLUSTER_ATTR_RECOVER_CALLBACKS,
	CLUSTER_ATTR_CLUSTER_NAME,
};

struct cluster_attribute {
@@ -126,6 +132,27 @@ struct cluster_attribute {
	ssize_t (*store)(struct dlm_cluster *, const char *, size_t);
};

static ssize_t cluster_cluster_name_read(struct dlm_cluster *cl, char *buf)
{
	return sprintf(buf, "%s\n", cl->cl_cluster_name);
}

static ssize_t cluster_cluster_name_write(struct dlm_cluster *cl,
					  const char *buf, size_t len)
{
	strncpy(dlm_config.ci_cluster_name, buf, DLM_LOCKSPACE_LEN);
	strncpy(cl->cl_cluster_name, buf, DLM_LOCKSPACE_LEN);
	return len;
}

static struct cluster_attribute cluster_attr_cluster_name = {
	.attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "cluster_name",
                    .ca_mode = S_IRUGO | S_IWUSR },
	.show   = cluster_cluster_name_read,
	.store  = cluster_cluster_name_write,
};

static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
			   int *info_field, int check_zero,
			   const char *buf, size_t len)
@@ -171,6 +198,7 @@ CLUSTER_ATTR(protocol, 0);
CLUSTER_ATTR(timewarn_cs, 1);
CLUSTER_ATTR(waitwarn_us, 0);
CLUSTER_ATTR(new_rsb_count, 0);
CLUSTER_ATTR(recover_callbacks, 0);

static struct configfs_attribute *cluster_attrs[] = {
	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
@@ -185,6 +213,8 @@ static struct configfs_attribute *cluster_attrs[] = {
	[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
	[CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr,
	[CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr,
	[CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks.attr,
	[CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name.attr,
	NULL,
};

@@ -293,6 +323,7 @@ struct dlm_comms {

struct dlm_comm {
	struct config_item item;
	int seq;
	int nodeid;
	int local;
	int addr_count;
@@ -309,6 +340,7 @@ struct dlm_node {
	int nodeid;
	int weight;
	int new;
	int comm_seq; /* copy of cm->seq when nd->nodeid is set */
};

static struct configfs_group_operations clusters_ops = {
@@ -455,6 +487,9 @@ static struct config_group *make_cluster(struct config_group *g,
	cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
	cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us;
	cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count;
	cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks;
	memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name,
	       DLM_LOCKSPACE_LEN);

	space_list = &sps->ss_group;
	comm_list = &cms->cs_group;
@@ -558,6 +593,11 @@ static struct config_item *make_comm(struct config_group *g, const char *name)
		return ERR_PTR(-ENOMEM);

	config_item_init_type_name(&cm->item, name, &comm_type);

	cm->seq = dlm_comm_count++;
	if (!cm->seq)
		cm->seq = dlm_comm_count++;

	cm->nodeid = -1;
	cm->local = 0;
	cm->addr_count = 0;
@@ -801,7 +841,10 @@ static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf)
static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
				 size_t len)
{
	uint32_t seq = 0;
	nd->nodeid = simple_strtol(buf, NULL, 0);
	dlm_comm_seq(nd->nodeid, &seq);
	nd->comm_seq = seq;
	return len;
}

@@ -908,13 +951,13 @@ static void put_comm(struct dlm_comm *cm)
}

/* caller must free mem */
int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
		    int **new_out, int *new_count_out)
int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
		     int *count_out)
{
	struct dlm_space *sp;
	struct dlm_node *nd;
	int i = 0, rv = 0, ids_count = 0, new_count = 0;
	int *ids, *new;
	struct dlm_config_node *nodes, *node;
	int rv, count;

	sp = get_space(lsname);
	if (!sp)
@@ -927,73 +970,42 @@ int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
		goto out;
	}

	ids_count = sp->members_count;
	count = sp->members_count;

	ids = kcalloc(ids_count, sizeof(int), GFP_NOFS);
	if (!ids) {
	nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
	if (!nodes) {
		rv = -ENOMEM;
		goto out;
	}

	node = nodes;
	list_for_each_entry(nd, &sp->members, list) {
		ids[i++] = nd->nodeid;
		if (nd->new)
			new_count++;
	}

	if (ids_count != i)
		printk(KERN_ERR "dlm: bad nodeid count %d %d\n", ids_count, i);

	if (!new_count)
		goto out_ids;
		node->nodeid = nd->nodeid;
		node->weight = nd->weight;
		node->new = nd->new;
		node->comm_seq = nd->comm_seq;
		node++;

	new = kcalloc(new_count, sizeof(int), GFP_NOFS);
	if (!new) {
		kfree(ids);
		rv = -ENOMEM;
		goto out;
	}

	i = 0;
	list_for_each_entry(nd, &sp->members, list) {
		if (nd->new) {
			new[i++] = nd->nodeid;
		nd->new = 0;
	}
	}
	*new_count_out = new_count;
	*new_out = new;

 out_ids:
	*ids_count_out = ids_count;
	*ids_out = ids;
	*count_out = count;
	*nodes_out = nodes;
	rv = 0;
 out:
	mutex_unlock(&sp->members_lock);
	put_space(sp);
	return rv;
}

int dlm_node_weight(char *lsname, int nodeid)
int dlm_comm_seq(int nodeid, uint32_t *seq)
{
	struct dlm_space *sp;
	struct dlm_node *nd;
	int w = -EEXIST;

	sp = get_space(lsname);
	if (!sp)
		goto out;

	mutex_lock(&sp->members_lock);
	list_for_each_entry(nd, &sp->members, list) {
		if (nd->nodeid != nodeid)
			continue;
		w = nd->weight;
		break;
	}
	mutex_unlock(&sp->members_lock);
	put_space(sp);
 out:
	return w;
	struct dlm_comm *cm = get_comm(nodeid, NULL);
	if (!cm)
		return -EEXIST;
	*seq = cm->seq;
	put_comm(cm);
	return 0;
}

int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr)
@@ -1047,6 +1059,8 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
#define DEFAULT_TIMEWARN_CS      500 /* 5 sec = 500 centiseconds */
#define DEFAULT_WAITWARN_US	   0
#define DEFAULT_NEW_RSB_COUNT    128
#define DEFAULT_RECOVER_CALLBACKS  0
#define DEFAULT_CLUSTER_NAME      ""

struct dlm_config_info dlm_config = {
	.ci_tcp_port = DEFAULT_TCP_PORT,
@@ -1060,6 +1074,8 @@ struct dlm_config_info dlm_config = {
	.ci_protocol = DEFAULT_PROTOCOL,
	.ci_timewarn_cs = DEFAULT_TIMEWARN_CS,
	.ci_waitwarn_us = DEFAULT_WAITWARN_US,
	.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT
	.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT,
	.ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS,
	.ci_cluster_name = DEFAULT_CLUSTER_NAME
};
+13 −4
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
**  Copyright (C) 2004-2011 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
@@ -14,6 +14,13 @@
#ifndef __CONFIG_DOT_H__
#define __CONFIG_DOT_H__

struct dlm_config_node {
	int nodeid;
	int weight;
	int new;
	uint32_t comm_seq;
};

#define DLM_MAX_ADDR_COUNT 3

struct dlm_config_info {
@@ -29,15 +36,17 @@ struct dlm_config_info {
	int ci_timewarn_cs;
	int ci_waitwarn_us;
	int ci_new_rsb_count;
	int ci_recover_callbacks;
	char ci_cluster_name[DLM_LOCKSPACE_LEN];
};

extern struct dlm_config_info dlm_config;

int dlm_config_init(void);
void dlm_config_exit(void);
int dlm_node_weight(char *lsname, int nodeid);
int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
		    int **new_out, int *new_count_out);
int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
		     int *count_out);
int dlm_comm_seq(int nodeid, uint32_t *seq);
int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
int dlm_our_nodeid(void);
+15 −13
Original line number Diff line number Diff line
@@ -393,6 +393,7 @@ static const struct seq_operations format3_seq_ops;

static void *table_seq_start(struct seq_file *seq, loff_t *pos)
{
	struct rb_node *node;
	struct dlm_ls *ls = seq->private;
	struct rsbtbl_iter *ri;
	struct dlm_rsb *r;
@@ -418,9 +419,10 @@ static void *table_seq_start(struct seq_file *seq, loff_t *pos)
		ri->format = 3;

	spin_lock(&ls->ls_rsbtbl[bucket].lock);
	if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
		list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list,
				    res_hashchain) {
	if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
		for (node = rb_first(&ls->ls_rsbtbl[bucket].keep); node;
		     node = rb_next(node)) {
			r = rb_entry(node, struct dlm_rsb, res_hashnode);
			if (!entry--) {
				dlm_hold_rsb(r);
				ri->rsb = r;
@@ -449,9 +451,9 @@ static void *table_seq_start(struct seq_file *seq, loff_t *pos)
		}

		spin_lock(&ls->ls_rsbtbl[bucket].lock);
		if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
			r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
					     struct dlm_rsb, res_hashchain);
		if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
			node = rb_first(&ls->ls_rsbtbl[bucket].keep);
			r = rb_entry(node, struct dlm_rsb, res_hashnode);
			dlm_hold_rsb(r);
			ri->rsb = r;
			ri->bucket = bucket;
@@ -467,7 +469,7 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
{
	struct dlm_ls *ls = seq->private;
	struct rsbtbl_iter *ri = iter_ptr;
	struct list_head *next;
	struct rb_node *next;
	struct dlm_rsb *r, *rp;
	loff_t n = *pos;
	unsigned bucket;
@@ -480,10 +482,10 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)

	spin_lock(&ls->ls_rsbtbl[bucket].lock);
	rp = ri->rsb;
	next = rp->res_hashchain.next;
	next = rb_next(&rp->res_hashnode);

	if (next != &ls->ls_rsbtbl[bucket].list) {
		r = list_entry(next, struct dlm_rsb, res_hashchain);
	if (next) {
		r = rb_entry(next, struct dlm_rsb, res_hashnode);
		dlm_hold_rsb(r);
		ri->rsb = r;
		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
@@ -511,9 +513,9 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
		}

		spin_lock(&ls->ls_rsbtbl[bucket].lock);
		if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
			r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
					     struct dlm_rsb, res_hashchain);
		if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
			next = rb_first(&ls->ls_rsbtbl[bucket].keep);
			r = rb_entry(next, struct dlm_rsb, res_hashnode);
			dlm_hold_rsb(r);
			ri->rsb = r;
			ri->bucket = bucket;
+0 −1
Original line number Diff line number Diff line
@@ -290,7 +290,6 @@ int dlm_recover_directory(struct dlm_ls *ls)

 out_status:
	error = 0;
	dlm_set_recover_status(ls, DLM_RS_DIR);
	log_debug(ls, "dlm_recover_directory %d entries", count);
 out_free:
	kfree(last_name);
+50 −10
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004-2010 Red Hat, Inc.  All rights reserved.
**  Copyright (C) 2004-2011 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
@@ -103,8 +103,8 @@ struct dlm_dirtable {
};

struct dlm_rsbtable {
	struct list_head	list;
	struct list_head	toss;
	struct rb_root		keep;
	struct rb_root		toss;
	spinlock_t		lock;
};

@@ -117,6 +117,10 @@ struct dlm_member {
	struct list_head	list;
	int			nodeid;
	int			weight;
	int			slot;
	int			slot_prev;
	int			comm_seq;
	uint32_t		generation;
};

/*
@@ -125,10 +129,8 @@ struct dlm_member {

struct dlm_recover {
	struct list_head	list;
	int			*nodeids;   /* nodeids of all members */
	int			node_count;
	int			*new;       /* nodeids of new members */
	int			new_count;
	struct dlm_config_node	*nodes;
	int			nodes_count;
	uint64_t		seq;
};

@@ -285,7 +287,10 @@ struct dlm_rsb {
	unsigned long		res_toss_time;
	uint32_t		res_first_lkid;
	struct list_head	res_lookup;	/* lkbs waiting on first */
	struct list_head	res_hashchain;	/* rsbtbl */
	union {
		struct list_head	res_hashchain;
		struct rb_node		res_hashnode;	/* rsbtbl */
	};
	struct list_head	res_grantqueue;
	struct list_head	res_convertqueue;
	struct list_head	res_waitqueue;
@@ -334,7 +339,9 @@ static inline int rsb_flag(struct dlm_rsb *r, enum rsb_flags flag)
/* dlm_header is first element of all structs sent between nodes */

#define DLM_HEADER_MAJOR	0x00030000
#define DLM_HEADER_MINOR	0x00000000
#define DLM_HEADER_MINOR	0x00000001

#define DLM_HEADER_SLOTS	0x00000001

#define DLM_MSG			1
#define DLM_RCOM		2
@@ -422,10 +429,34 @@ union dlm_packet {
	struct dlm_rcom		rcom;
};

#define DLM_RSF_NEED_SLOTS	0x00000001

/* RCOM_STATUS data */
struct rcom_status {
	__le32			rs_flags;
	__le32			rs_unused1;
	__le64			rs_unused2;
};

/* RCOM_STATUS_REPLY data */
struct rcom_config {
	__le32			rf_lvblen;
	__le32			rf_lsflags;
	__le64			rf_unused;

	/* DLM_HEADER_SLOTS adds: */
	__le32			rf_flags;
	__le16			rf_our_slot;
	__le16			rf_num_slots;
	__le32			rf_generation;
	__le32			rf_unused1;
	__le64			rf_unused2;
};

struct rcom_slot {
	__le32			ro_nodeid;
	__le16			ro_slot;
	__le16			ro_unused1;
	__le64			ro_unused2;
};

struct rcom_lock {
@@ -452,6 +483,7 @@ struct dlm_ls {
	struct list_head	ls_list;	/* list of lockspaces */
	dlm_lockspace_t		*ls_local_handle;
	uint32_t		ls_global_id;	/* global unique lockspace ID */
	uint32_t		ls_generation;
	uint32_t		ls_exflags;
	int			ls_lvblen;
	int			ls_count;	/* refcount of processes in
@@ -490,6 +522,11 @@ struct dlm_ls {
	int			ls_total_weight;
	int			*ls_node_array;

	int			ls_slot;
	int			ls_num_slots;
	int			ls_slots_size;
	struct dlm_slot		*ls_slots;

	struct dlm_rsb		ls_stub_rsb;	/* for returning errors */
	struct dlm_lkb		ls_stub_lkb;	/* for returning errors */
	struct dlm_message	ls_stub_ms;	/* for faking a reply */
@@ -537,6 +574,9 @@ struct dlm_ls {
	struct list_head	ls_root_list;	/* root resources */
	struct rw_semaphore	ls_root_sem;	/* protect root_list */

	const struct dlm_lockspace_ops *ls_ops;
	void			*ls_ops_arg;

	int			ls_namelen;
	char			ls_name[1];
};
Loading