aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dlm/Makefile1
-rw-r--r--fs/dlm/config.c8
-rw-r--r--fs/dlm/config.h1
-rw-r--r--fs/dlm/dlm_internal.h10
-rw-r--r--fs/dlm/lock.c146
-rw-r--r--fs/dlm/lock.h4
-rw-r--r--fs/dlm/lockspace.c10
-rw-r--r--fs/dlm/main.c11
-rw-r--r--fs/dlm/member.c5
-rw-r--r--fs/dlm/netlink.c155
-rw-r--r--fs/dlm/recoverd.c4
-rw-r--r--fs/dlm/user.c2
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/dlm.h7
-rw-r--r--include/linux/dlm_netlink.h56
15 files changed, 409 insertions, 12 deletions
diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile
index 604cf7dc5f39..d248e60951ba 100644
--- a/fs/dlm/Makefile
+++ b/fs/dlm/Makefile
@@ -8,6 +8,7 @@ dlm-y := ast.o \
8 member.o \ 8 member.o \
9 memory.o \ 9 memory.o \
10 midcomms.o \ 10 midcomms.o \
11 netlink.o \
11 lowcomms.o \ 12 lowcomms.o \
12 rcom.o \ 13 rcom.o \
13 recover.o \ 14 recover.o \
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 5a3d390cc826..2909abf1bbc3 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -90,6 +90,7 @@ struct cluster {
90 unsigned int cl_scan_secs; 90 unsigned int cl_scan_secs;
91 unsigned int cl_log_debug; 91 unsigned int cl_log_debug;
92 unsigned int cl_protocol; 92 unsigned int cl_protocol;
93 unsigned int cl_timewarn_cs;
93}; 94};
94 95
95enum { 96enum {
@@ -103,6 +104,7 @@ enum {
103 CLUSTER_ATTR_SCAN_SECS, 104 CLUSTER_ATTR_SCAN_SECS,
104 CLUSTER_ATTR_LOG_DEBUG, 105 CLUSTER_ATTR_LOG_DEBUG,
105 CLUSTER_ATTR_PROTOCOL, 106 CLUSTER_ATTR_PROTOCOL,
107 CLUSTER_ATTR_TIMEWARN_CS,
106}; 108};
107 109
108struct cluster_attribute { 110struct cluster_attribute {
@@ -162,6 +164,7 @@ CLUSTER_ATTR(toss_secs, 1);
162CLUSTER_ATTR(scan_secs, 1); 164CLUSTER_ATTR(scan_secs, 1);
163CLUSTER_ATTR(log_debug, 0); 165CLUSTER_ATTR(log_debug, 0);
164CLUSTER_ATTR(protocol, 0); 166CLUSTER_ATTR(protocol, 0);
167CLUSTER_ATTR(timewarn_cs, 1);
165 168
166static struct configfs_attribute *cluster_attrs[] = { 169static struct configfs_attribute *cluster_attrs[] = {
167 [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, 170 [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
@@ -174,6 +177,7 @@ static struct configfs_attribute *cluster_attrs[] = {
174 [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr, 177 [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
175 [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr, 178 [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
176 [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr, 179 [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
180 [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
177 NULL, 181 NULL,
178}; 182};
179 183
@@ -916,6 +920,7 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
916#define DEFAULT_SCAN_SECS 5 920#define DEFAULT_SCAN_SECS 5
917#define DEFAULT_LOG_DEBUG 0 921#define DEFAULT_LOG_DEBUG 0
918#define DEFAULT_PROTOCOL 0 922#define DEFAULT_PROTOCOL 0
923#define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */
919 924
920struct dlm_config_info dlm_config = { 925struct dlm_config_info dlm_config = {
921 .ci_tcp_port = DEFAULT_TCP_PORT, 926 .ci_tcp_port = DEFAULT_TCP_PORT,
@@ -927,6 +932,7 @@ struct dlm_config_info dlm_config = {
927 .ci_toss_secs = DEFAULT_TOSS_SECS, 932 .ci_toss_secs = DEFAULT_TOSS_SECS,
928 .ci_scan_secs = DEFAULT_SCAN_SECS, 933 .ci_scan_secs = DEFAULT_SCAN_SECS,
929 .ci_log_debug = DEFAULT_LOG_DEBUG, 934 .ci_log_debug = DEFAULT_LOG_DEBUG,
930 .ci_protocol = DEFAULT_PROTOCOL 935 .ci_protocol = DEFAULT_PROTOCOL,
936 .ci_timewarn_cs = DEFAULT_TIMEWARN_CS
931}; 937};
932 938
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index 967cc3d72e5e..a3170fe22090 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -27,6 +27,7 @@ struct dlm_config_info {
27 int ci_scan_secs; 27 int ci_scan_secs;
28 int ci_log_debug; 28 int ci_log_debug;
29 int ci_protocol; 29 int ci_protocol;
30 int ci_timewarn_cs;
30}; 31};
31 32
32extern struct dlm_config_info dlm_config; 33extern struct dlm_config_info dlm_config;
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 30994d68f6a0..65a5fc076b8a 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -213,8 +213,10 @@ struct dlm_args {
213#define DLM_IFL_OVERLAP_UNLOCK 0x00080000 213#define DLM_IFL_OVERLAP_UNLOCK 0x00080000
214#define DLM_IFL_OVERLAP_CANCEL 0x00100000 214#define DLM_IFL_OVERLAP_CANCEL 0x00100000
215#define DLM_IFL_ENDOFLIFE 0x00200000 215#define DLM_IFL_ENDOFLIFE 0x00200000
216#define DLM_IFL_WATCH_TIMEWARN 0x00400000
216#define DLM_IFL_USER 0x00000001 217#define DLM_IFL_USER 0x00000001
217#define DLM_IFL_ORPHAN 0x00000002 218#define DLM_IFL_ORPHAN 0x00000002
219#define DLM_IFL_TIMEOUT_CANCEL 0x00000004
218 220
219struct dlm_lkb { 221struct dlm_lkb {
220 struct dlm_rsb *lkb_resource; /* the rsb */ 222 struct dlm_rsb *lkb_resource; /* the rsb */
@@ -243,6 +245,9 @@ struct dlm_lkb {
243 struct list_head lkb_wait_reply; /* waiting for remote reply */ 245 struct list_head lkb_wait_reply; /* waiting for remote reply */
244 struct list_head lkb_astqueue; /* need ast to be sent */ 246 struct list_head lkb_astqueue; /* need ast to be sent */
245 struct list_head lkb_ownqueue; /* list of locks for a process */ 247 struct list_head lkb_ownqueue; /* list of locks for a process */
248 struct list_head lkb_time_list;
249 unsigned long lkb_timestamp;
250 unsigned long lkb_timeout_cs;
246 251
247 char *lkb_lvbptr; 252 char *lkb_lvbptr;
248 struct dlm_lksb *lkb_lksb; /* caller's status block */ 253 struct dlm_lksb *lkb_lksb; /* caller's status block */
@@ -447,6 +452,9 @@ struct dlm_ls {
447 struct mutex ls_orphans_mutex; 452 struct mutex ls_orphans_mutex;
448 struct list_head ls_orphans; 453 struct list_head ls_orphans;
449 454
455 struct mutex ls_timeout_mutex;
456 struct list_head ls_timeout;
457
450 struct list_head ls_nodes; /* current nodes in ls */ 458 struct list_head ls_nodes; /* current nodes in ls */
451 struct list_head ls_nodes_gone; /* dead node list, recovery */ 459 struct list_head ls_nodes_gone; /* dead node list, recovery */
452 int ls_num_nodes; /* number of nodes in ls */ 460 int ls_num_nodes; /* number of nodes in ls */
@@ -472,6 +480,7 @@ struct dlm_ls {
472 struct task_struct *ls_recoverd_task; 480 struct task_struct *ls_recoverd_task;
473 struct mutex ls_recoverd_active; 481 struct mutex ls_recoverd_active;
474 spinlock_t ls_recover_lock; 482 spinlock_t ls_recover_lock;
483 unsigned long ls_recover_begin; /* jiffies timestamp */
475 uint32_t ls_recover_status; /* DLM_RS_ */ 484 uint32_t ls_recover_status; /* DLM_RS_ */
476 uint64_t ls_recover_seq; 485 uint64_t ls_recover_seq;
477 struct dlm_recover *ls_recover_args; 486 struct dlm_recover *ls_recover_args;
@@ -501,6 +510,7 @@ struct dlm_ls {
501#define LSFL_RCOM_READY 3 510#define LSFL_RCOM_READY 3
502#define LSFL_RCOM_WAIT 4 511#define LSFL_RCOM_WAIT 4
503#define LSFL_UEVENT_WAIT 5 512#define LSFL_UEVENT_WAIT 5
513#define LSFL_TIMEWARN 6
504 514
505/* much of this is just saving user space pointers associated with the 515/* much of this is just saving user space pointers associated with the
506 lock that we pass back to the user lib with an ast */ 516 lock that we pass back to the user lib with an ast */
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 09668ec2e279..ab986dfbe6d3 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -82,10 +82,13 @@ static int send_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int mode);
82static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb); 82static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb);
83static int send_remove(struct dlm_rsb *r); 83static int send_remove(struct dlm_rsb *r);
84static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); 84static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
85static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
85static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, 86static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
86 struct dlm_message *ms); 87 struct dlm_message *ms);
87static int receive_extralen(struct dlm_message *ms); 88static int receive_extralen(struct dlm_message *ms);
88static void do_purge(struct dlm_ls *ls, int nodeid, int pid); 89static void do_purge(struct dlm_ls *ls, int nodeid, int pid);
90static void del_timeout(struct dlm_lkb *lkb);
91void dlm_timeout_warn(struct dlm_lkb *lkb);
89 92
90/* 93/*
91 * Lock compatibilty matrix - thanks Steve 94 * Lock compatibilty matrix - thanks Steve
@@ -286,8 +289,17 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
286 if (is_master_copy(lkb)) 289 if (is_master_copy(lkb))
287 return; 290 return;
288 291
292 del_timeout(lkb);
293
289 DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb);); 294 DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb););
290 295
296 /* if the operation was a cancel, then return -DLM_ECANCEL, if a
297 timeout caused the cancel then return -ETIMEDOUT */
298 if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_TIMEOUT_CANCEL)) {
299 lkb->lkb_flags &= ~DLM_IFL_TIMEOUT_CANCEL;
300 rv = -ETIMEDOUT;
301 }
302
291 lkb->lkb_lksb->sb_status = rv; 303 lkb->lkb_lksb->sb_status = rv;
292 lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags; 304 lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
293 305
@@ -581,6 +593,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
581 kref_init(&lkb->lkb_ref); 593 kref_init(&lkb->lkb_ref);
582 INIT_LIST_HEAD(&lkb->lkb_ownqueue); 594 INIT_LIST_HEAD(&lkb->lkb_ownqueue);
583 INIT_LIST_HEAD(&lkb->lkb_rsb_lookup); 595 INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
596 INIT_LIST_HEAD(&lkb->lkb_time_list);
584 597
585 get_random_bytes(&bucket, sizeof(bucket)); 598 get_random_bytes(&bucket, sizeof(bucket));
586 bucket &= (ls->ls_lkbtbl_size - 1); 599 bucket &= (ls->ls_lkbtbl_size - 1);
@@ -993,6 +1006,125 @@ void dlm_scan_rsbs(struct dlm_ls *ls)
993 } 1006 }
994} 1007}
995 1008
1009static void add_timeout(struct dlm_lkb *lkb)
1010{
1011 struct dlm_ls *ls = lkb->lkb_resource->res_ls;
1012
1013 if (is_master_copy(lkb))
1014 return;
1015
1016 if (lkb->lkb_exflags & DLM_LKF_TIMEOUT)
1017 goto add_it;
1018
1019 if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) &&
1020 !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
1021 lkb->lkb_flags |= DLM_IFL_WATCH_TIMEWARN;
1022 goto add_it;
1023 }
1024 return;
1025
1026 add_it:
1027 DLM_ASSERT(list_empty(&lkb->lkb_time_list), dlm_print_lkb(lkb););
1028 mutex_lock(&ls->ls_timeout_mutex);
1029 hold_lkb(lkb);
1030 lkb->lkb_timestamp = jiffies;
1031 list_add_tail(&lkb->lkb_time_list, &ls->ls_timeout);
1032 mutex_unlock(&ls->ls_timeout_mutex);
1033}
1034
1035static void del_timeout(struct dlm_lkb *lkb)
1036{
1037 struct dlm_ls *ls = lkb->lkb_resource->res_ls;
1038
1039 mutex_lock(&ls->ls_timeout_mutex);
1040 if (!list_empty(&lkb->lkb_time_list)) {
1041 list_del_init(&lkb->lkb_time_list);
1042 unhold_lkb(lkb);
1043 }
1044 mutex_unlock(&ls->ls_timeout_mutex);
1045}
1046
1047/* FIXME: is it safe to look at lkb_exflags, lkb_flags, lkb_timestamp, and
1048 lkb_lksb_timeout without lock_rsb? Note: we can't lock timeout_mutex
1049 and then lock rsb because of lock ordering in add_timeout. We may need
1050 to specify some special timeout-related bits in the lkb that are just to
1051 be accessed under the timeout_mutex. */
1052
1053void dlm_scan_timeout(struct dlm_ls *ls)
1054{
1055 struct dlm_rsb *r;
1056 struct dlm_lkb *lkb;
1057 int do_cancel, do_warn;
1058
1059 for (;;) {
1060 if (dlm_locking_stopped(ls))
1061 break;
1062
1063 do_cancel = 0;
1064 do_warn = 0;
1065 mutex_lock(&ls->ls_timeout_mutex);
1066 list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) {
1067
1068 if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) &&
1069 time_after_eq(jiffies, lkb->lkb_timestamp +
1070 lkb->lkb_timeout_cs * HZ/100))
1071 do_cancel = 1;
1072
1073 if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
1074 time_after_eq(jiffies, lkb->lkb_timestamp +
1075 dlm_config.ci_timewarn_cs * HZ/100))
1076 do_warn = 1;
1077
1078 if (!do_cancel && !do_warn)
1079 continue;
1080 hold_lkb(lkb);
1081 break;
1082 }
1083 mutex_unlock(&ls->ls_timeout_mutex);
1084
1085 if (!do_cancel && !do_warn)
1086 break;
1087
1088 r = lkb->lkb_resource;
1089 hold_rsb(r);
1090 lock_rsb(r);
1091
1092 if (do_warn) {
1093 /* clear flag so we only warn once */
1094 lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
1095 if (!(lkb->lkb_exflags & DLM_LKF_TIMEOUT))
1096 del_timeout(lkb);
1097 dlm_timeout_warn(lkb);
1098 }
1099
1100 if (do_cancel) {
1101 lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
1102 lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
1103 del_timeout(lkb);
1104 _cancel_lock(r, lkb);
1105 }
1106
1107 unlock_rsb(r);
1108 unhold_rsb(r);
1109 dlm_put_lkb(lkb);
1110 }
1111}
1112
1113/* This is only called by dlm_recoverd, and we rely on dlm_ls_stop() stopping
1114 dlm_recoverd before checking/setting ls_recover_begin. */
1115
1116void dlm_adjust_timeouts(struct dlm_ls *ls)
1117{
1118 struct dlm_lkb *lkb;
1119 long adj = jiffies - ls->ls_recover_begin;
1120
1121 ls->ls_recover_begin = 0;
1122 mutex_lock(&ls->ls_timeout_mutex);
1123 list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list)
1124 lkb->lkb_timestamp += adj;
1125 mutex_unlock(&ls->ls_timeout_mutex);
1126}
1127
996/* lkb is master or local copy */ 1128/* lkb is master or local copy */
997 1129
998static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 1130static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -1902,6 +2034,9 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
1902 if (is_overlap(lkb)) 2034 if (is_overlap(lkb))
1903 goto out; 2035 goto out;
1904 2036
2037 /* don't let scand try to do a cancel */
2038 del_timeout(lkb);
2039
1905 if (lkb->lkb_flags & DLM_IFL_RESEND) { 2040 if (lkb->lkb_flags & DLM_IFL_RESEND) {
1906 lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL; 2041 lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
1907 rv = -EBUSY; 2042 rv = -EBUSY;
@@ -1933,6 +2068,9 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
1933 if (is_overlap_unlock(lkb)) 2068 if (is_overlap_unlock(lkb))
1934 goto out; 2069 goto out;
1935 2070
2071 /* don't let scand try to do a cancel */
2072 del_timeout(lkb);
2073
1936 if (lkb->lkb_flags & DLM_IFL_RESEND) { 2074 if (lkb->lkb_flags & DLM_IFL_RESEND) {
1937 lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK; 2075 lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
1938 rv = -EBUSY; 2076 rv = -EBUSY;
@@ -1993,6 +2131,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
1993 error = -EINPROGRESS; 2131 error = -EINPROGRESS;
1994 add_lkb(r, lkb, DLM_LKSTS_WAITING); 2132 add_lkb(r, lkb, DLM_LKSTS_WAITING);
1995 send_blocking_asts(r, lkb); 2133 send_blocking_asts(r, lkb);
2134 add_timeout(lkb);
1996 goto out; 2135 goto out;
1997 } 2136 }
1998 2137
@@ -2040,6 +2179,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
2040 del_lkb(r, lkb); 2179 del_lkb(r, lkb);
2041 add_lkb(r, lkb, DLM_LKSTS_CONVERT); 2180 add_lkb(r, lkb, DLM_LKSTS_CONVERT);
2042 send_blocking_asts(r, lkb); 2181 send_blocking_asts(r, lkb);
2182 add_timeout(lkb);
2043 goto out; 2183 goto out;
2044 } 2184 }
2045 2185
@@ -3110,9 +3250,10 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
3110 lkb->lkb_remid = ms->m_lkid; 3250 lkb->lkb_remid = ms->m_lkid;
3111 if (is_altmode(lkb)) 3251 if (is_altmode(lkb))
3112 munge_altmode(lkb, ms); 3252 munge_altmode(lkb, ms);
3113 if (result) 3253 if (result) {
3114 add_lkb(r, lkb, DLM_LKSTS_WAITING); 3254 add_lkb(r, lkb, DLM_LKSTS_WAITING);
3115 else { 3255 add_timeout(lkb);
3256 } else {
3116 grant_lock_pc(r, lkb, ms); 3257 grant_lock_pc(r, lkb, ms);
3117 queue_cast(r, lkb, 0); 3258 queue_cast(r, lkb, 0);
3118 } 3259 }
@@ -3178,6 +3319,7 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
3178 munge_demoted(lkb, ms); 3319 munge_demoted(lkb, ms);
3179 del_lkb(r, lkb); 3320 del_lkb(r, lkb);
3180 add_lkb(r, lkb, DLM_LKSTS_CONVERT); 3321 add_lkb(r, lkb, DLM_LKSTS_CONVERT);
3322 add_timeout(lkb);
3181 break; 3323 break;
3182 3324
3183 case 0: 3325 case 0:
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
index 19403aa08739..6b5b71f0e9dd 100644
--- a/fs/dlm/lock.h
+++ b/fs/dlm/lock.h
@@ -1,7 +1,7 @@
1/****************************************************************************** 1/******************************************************************************
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) 2005 Red Hat, Inc. All rights reserved. 4** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
5** 5**
6** This copyrighted material is made available to anyone wishing to use, 6** This copyrighted material is made available to anyone wishing to use,
7** modify, copy, or redistribute it subject to the terms and conditions 7** modify, copy, or redistribute it subject to the terms and conditions
@@ -26,6 +26,8 @@ int dlm_put_lkb(struct dlm_lkb *lkb);
26void dlm_scan_rsbs(struct dlm_ls *ls); 26void dlm_scan_rsbs(struct dlm_ls *ls);
27int dlm_lock_recovery_try(struct dlm_ls *ls); 27int dlm_lock_recovery_try(struct dlm_ls *ls);
28void dlm_unlock_recovery(struct dlm_ls *ls); 28void dlm_unlock_recovery(struct dlm_ls *ls);
29void dlm_scan_timeout(struct dlm_ls *ls);
30void dlm_adjust_timeouts(struct dlm_ls *ls);
29 31
30int dlm_purge_locks(struct dlm_ls *ls); 32int dlm_purge_locks(struct dlm_ls *ls);
31void dlm_purge_mstcpy_locks(struct dlm_rsb *r); 33void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 414a108df934..339a204d7479 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -237,6 +237,7 @@ static int dlm_scand(void *data)
237 list_for_each_entry(ls, &lslist, ls_list) { 237 list_for_each_entry(ls, &lslist, ls_list) {
238 if (dlm_lock_recovery_try(ls)) { 238 if (dlm_lock_recovery_try(ls)) {
239 dlm_scan_rsbs(ls); 239 dlm_scan_rsbs(ls);
240 dlm_scan_timeout(ls);
240 dlm_unlock_recovery(ls); 241 dlm_unlock_recovery(ls);
241 } 242 }
242 } 243 }
@@ -421,11 +422,16 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
421 goto out; 422 goto out;
422 memcpy(ls->ls_name, name, namelen); 423 memcpy(ls->ls_name, name, namelen);
423 ls->ls_namelen = namelen; 424 ls->ls_namelen = namelen;
424 ls->ls_exflags = flags;
425 ls->ls_lvblen = lvblen; 425 ls->ls_lvblen = lvblen;
426 ls->ls_count = 0; 426 ls->ls_count = 0;
427 ls->ls_flags = 0; 427 ls->ls_flags = 0;
428 428
429 /* ls_exflags are forced to match among nodes, and we don't
430 need to require all nodes to have TIMEWARN active */
431 if (flags & DLM_LSFL_TIMEWARN)
432 set_bit(LSFL_TIMEWARN, &ls->ls_flags);
433 ls->ls_exflags = (flags & ~DLM_LSFL_TIMEWARN);
434
429 size = dlm_config.ci_rsbtbl_size; 435 size = dlm_config.ci_rsbtbl_size;
430 ls->ls_rsbtbl_size = size; 436 ls->ls_rsbtbl_size = size;
431 437
@@ -465,6 +471,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
465 mutex_init(&ls->ls_waiters_mutex); 471 mutex_init(&ls->ls_waiters_mutex);
466 INIT_LIST_HEAD(&ls->ls_orphans); 472 INIT_LIST_HEAD(&ls->ls_orphans);
467 mutex_init(&ls->ls_orphans_mutex); 473 mutex_init(&ls->ls_orphans_mutex);
474 INIT_LIST_HEAD(&ls->ls_timeout);
475 mutex_init(&ls->ls_timeout_mutex);
468 476
469 INIT_LIST_HEAD(&ls->ls_nodes); 477 INIT_LIST_HEAD(&ls->ls_nodes);
470 INIT_LIST_HEAD(&ls->ls_nodes_gone); 478 INIT_LIST_HEAD(&ls->ls_nodes_gone);
diff --git a/fs/dlm/main.c b/fs/dlm/main.c
index 162fbae58fe5..eca2907f2386 100644
--- a/fs/dlm/main.c
+++ b/fs/dlm/main.c
@@ -2,7 +2,7 @@
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
5** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. 5** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
6** 6**
7** This copyrighted material is made available to anyone wishing to use, 7** This copyrighted material is made available to anyone wishing to use,
8** modify, copy, or redistribute it subject to the terms and conditions 8** modify, copy, or redistribute it subject to the terms and conditions
@@ -25,6 +25,8 @@ void dlm_unregister_debugfs(void);
25static inline int dlm_register_debugfs(void) { return 0; } 25static inline int dlm_register_debugfs(void) { return 0; }
26static inline void dlm_unregister_debugfs(void) { } 26static inline void dlm_unregister_debugfs(void) { }
27#endif 27#endif
28int dlm_netlink_init(void);
29void dlm_netlink_exit(void);
28 30
29static int __init init_dlm(void) 31static int __init init_dlm(void)
30{ 32{
@@ -50,10 +52,16 @@ static int __init init_dlm(void)
50 if (error) 52 if (error)
51 goto out_debug; 53 goto out_debug;
52 54
55 error = dlm_netlink_init();
56 if (error)
57 goto out_user;
58
53 printk("DLM (built %s %s) installed\n", __DATE__, __TIME__); 59 printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
54 60
55 return 0; 61 return 0;
56 62
63 out_user:
64 dlm_user_exit();
57 out_debug: 65 out_debug:
58 dlm_unregister_debugfs(); 66 dlm_unregister_debugfs();
59 out_config: 67 out_config:
@@ -68,6 +76,7 @@ static int __init init_dlm(void)
68 76
69static void __exit exit_dlm(void) 77static void __exit exit_dlm(void)
70{ 78{
79 dlm_netlink_exit();
71 dlm_user_exit(); 80 dlm_user_exit();
72 dlm_config_exit(); 81 dlm_config_exit();
73 dlm_memory_exit(); 82 dlm_memory_exit();
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 85e2897bd740..f08faec3d854 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -1,7 +1,7 @@
1/****************************************************************************** 1/******************************************************************************
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) 2005 Red Hat, Inc. All rights reserved. 4** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
5** 5**
6** This copyrighted material is made available to anyone wishing to use, 6** This copyrighted material is made available to anyone wishing to use,
7** modify, copy, or redistribute it subject to the terms and conditions 7** modify, copy, or redistribute it subject to the terms and conditions
@@ -284,6 +284,9 @@ int dlm_ls_stop(struct dlm_ls *ls)
284 dlm_recoverd_suspend(ls); 284 dlm_recoverd_suspend(ls);
285 ls->ls_recover_status = 0; 285 ls->ls_recover_status = 0;
286 dlm_recoverd_resume(ls); 286 dlm_recoverd_resume(ls);
287
288 if (!ls->ls_recover_begin)
289 ls->ls_recover_begin = jiffies;
287 return 0; 290 return 0;
288} 291}
289 292
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
new file mode 100644
index 000000000000..804b32cd22c1
--- /dev/null
+++ b/fs/dlm/netlink.c
@@ -0,0 +1,155 @@
1/*
2 * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
3 *
4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions
6 * of the GNU General Public License v.2.
7 */
8
9#include <net/genetlink.h>
10#include <linux/dlm.h>
11#include <linux/dlm_netlink.h>
12
13#include "dlm_internal.h"
14
15static uint32_t dlm_nl_seqnum;
16static uint32_t listener_nlpid;
17
18static struct genl_family family = {
19 .id = GENL_ID_GENERATE,
20 .name = DLM_GENL_NAME,
21 .version = DLM_GENL_VERSION,
22};
23
24static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
25{
26 struct sk_buff *skb;
27 void *data;
28
29 skb = genlmsg_new(size, GFP_KERNEL);
30 if (!skb)
31 return -ENOMEM;
32
33 /* add the message headers */
34 data = genlmsg_put(skb, 0, dlm_nl_seqnum++, &family, 0, cmd);
35 if (!data) {
36 nlmsg_free(skb);
37 return -EINVAL;
38 }
39
40 *skbp = skb;
41 return 0;
42}
43
44static struct dlm_lock_data *mk_data(struct sk_buff *skb)
45{
46 struct nlattr *ret;
47
48 ret = nla_reserve(skb, DLM_TYPE_LOCK, sizeof(struct dlm_lock_data));
49 if (!ret)
50 return NULL;
51 return nla_data(ret);
52}
53
54static int send_data(struct sk_buff *skb)
55{
56 struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
57 void *data = genlmsg_data(genlhdr);
58 int rv;
59
60 rv = genlmsg_end(skb, data);
61 if (rv < 0) {
62 nlmsg_free(skb);
63 return rv;
64 }
65
66 return genlmsg_unicast(skb, listener_nlpid);
67}
68
69static int user_cmd(struct sk_buff *skb, struct genl_info *info)
70{
71 listener_nlpid = info->snd_pid;
72 printk("user_cmd nlpid %u\n", listener_nlpid);
73 return 0;
74}
75
76static struct genl_ops dlm_nl_ops = {
77 .cmd = DLM_CMD_HELLO,
78 .doit = user_cmd,
79};
80
81int dlm_netlink_init(void)
82{
83 int rv;
84
85 rv = genl_register_family(&family);
86 if (rv)
87 return rv;
88
89 rv = genl_register_ops(&family, &dlm_nl_ops);
90 if (rv < 0)
91 goto err;
92 return 0;
93 err:
94 genl_unregister_family(&family);
95 return rv;
96}
97
98void dlm_netlink_exit(void)
99{
100 genl_unregister_ops(&family, &dlm_nl_ops);
101 genl_unregister_family(&family);
102}
103
104static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
105{
106 struct dlm_rsb *r = lkb->lkb_resource;
107 struct dlm_user_args *ua = (struct dlm_user_args *) lkb->lkb_astparam;
108
109 memset(data, 0, sizeof(struct dlm_lock_data));
110
111 data->version = DLM_LOCK_DATA_VERSION;
112 data->nodeid = lkb->lkb_nodeid;
113 data->ownpid = lkb->lkb_ownpid;
114 data->id = lkb->lkb_id;
115 data->remid = lkb->lkb_remid;
116 data->status = lkb->lkb_status;
117 data->grmode = lkb->lkb_grmode;
118 data->rqmode = lkb->lkb_rqmode;
119 data->timestamp = lkb->lkb_timestamp;
120 if (ua)
121 data->xid = ua->xid;
122 if (r) {
123 data->lockspace_id = r->res_ls->ls_global_id;
124 data->resource_namelen = r->res_length;
125 memcpy(data->resource_name, r->res_name, r->res_length);
126 }
127}
128
129void dlm_timeout_warn(struct dlm_lkb *lkb)
130{
131 struct dlm_lock_data *data;
132 struct sk_buff *send_skb;
133 size_t size;
134 int rv;
135
136 log_debug(lkb->lkb_resource->res_ls, "timeout_warn %x", lkb->lkb_id);
137
138 size = nla_total_size(sizeof(struct dlm_lock_data)) +
139 nla_total_size(0); /* why this? */
140
141 rv = prepare_data(DLM_CMD_TIMEOUT, &send_skb, size);
142 if (rv < 0)
143 return;
144
145 data = mk_data(send_skb);
146 if (!data) {
147 nlmsg_free(send_skb);
148 return;
149 }
150
151 fill_data(data, lkb);
152
153 send_data(send_skb);
154}
155
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 3cb636d60249..66575997861c 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -2,7 +2,7 @@
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
5** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. 5** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
6** 6**
7** This copyrighted material is made available to anyone wishing to use, 7** This copyrighted material is made available to anyone wishing to use,
8** modify, copy, or redistribute it subject to the terms and conditions 8** modify, copy, or redistribute it subject to the terms and conditions
@@ -190,6 +190,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
190 190
191 dlm_clear_members_gone(ls); 191 dlm_clear_members_gone(ls);
192 192
193 dlm_adjust_timeouts(ls);
194
193 error = enable_locking(ls, rv->seq); 195 error = enable_locking(ls, rv->seq);
194 if (error) { 196 if (error) {
195 log_debug(ls, "enable_locking failed %d", error); 197 log_debug(ls, "enable_locking failed %d", error);
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index b0201ec325a7..c7612da5b617 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -348,7 +348,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params)
348 return -EPERM; 348 return -EPERM;
349 349
350 error = dlm_new_lockspace(params->name, strlen(params->name), 350 error = dlm_new_lockspace(params->name, strlen(params->name),
351 &lockspace, 0, DLM_USER_LVB_LEN); 351 &lockspace, params->flags, DLM_USER_LVB_LEN);
352 if (error) 352 if (error)
353 return error; 353 return error;
354 354
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index f317c270d4bf..afae306b177c 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -49,6 +49,7 @@ header-y += consolemap.h
49header-y += const.h 49header-y += const.h
50header-y += cycx_cfm.h 50header-y += cycx_cfm.h
51header-y += dlm_device.h 51header-y += dlm_device.h
52header-y += dlm_netlink.h
52header-y += dm-ioctl.h 53header-y += dm-ioctl.h
53header-y += dn.h 54header-y += dn.h
54header-y += dqblk_v1.h 55header-y += dqblk_v1.h
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 1b1dcb9a40bb..975f17d8aa53 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -2,7 +2,7 @@
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
5** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. 5** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
6** 6**
7** This copyrighted material is made available to anyone wishing to use, 7** This copyrighted material is made available to anyone wishing to use,
8** modify, copy, or redistribute it subject to the terms and conditions 8** modify, copy, or redistribute it subject to the terms and conditions
@@ -149,6 +149,7 @@
149#define DLM_LKF_ALTPR 0x00008000 149#define DLM_LKF_ALTPR 0x00008000
150#define DLM_LKF_ALTCW 0x00010000 150#define DLM_LKF_ALTCW 0x00010000
151#define DLM_LKF_FORCEUNLOCK 0x00020000 151#define DLM_LKF_FORCEUNLOCK 0x00020000
152#define DLM_LKF_TIMEOUT 0x00040000
152 153
153/* 154/*
154 * Some return codes that are not in errno.h 155 * Some return codes that are not in errno.h
@@ -199,11 +200,11 @@ struct dlm_lksb {
199 char * sb_lvbptr; 200 char * sb_lvbptr;
200}; 201};
201 202
203#define DLM_LSFL_NODIR 0x00000001
204#define DLM_LSFL_TIMEWARN 0x00000002
202 205
203#ifdef __KERNEL__ 206#ifdef __KERNEL__
204 207
205#define DLM_LSFL_NODIR 0x00000001
206
207/* 208/*
208 * dlm_new_lockspace 209 * dlm_new_lockspace
209 * 210 *
diff --git a/include/linux/dlm_netlink.h b/include/linux/dlm_netlink.h
new file mode 100644
index 000000000000..19276332707a
--- /dev/null
+++ b/include/linux/dlm_netlink.h
@@ -0,0 +1,56 @@
1/*
2 * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
3 *
4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions
6 * of the GNU General Public License v.2.
7 */
8
9#ifndef _DLM_NETLINK_H
10#define _DLM_NETLINK_H
11
12enum {
13 DLM_STATUS_WAITING = 1,
14 DLM_STATUS_GRANTED = 2,
15 DLM_STATUS_CONVERT = 3,
16};
17
18#define DLM_LOCK_DATA_VERSION 1
19
20struct dlm_lock_data {
21 uint16_t version;
22 uint32_t lockspace_id;
23 int nodeid;
24 int ownpid;
25 uint32_t id;
26 uint32_t remid;
27 uint64_t xid;
28 int8_t status;
29 int8_t grmode;
30 int8_t rqmode;
31 unsigned long timestamp;
32 int resource_namelen;
33 char resource_name[DLM_RESNAME_MAXLEN];
34};
35
36enum {
37 DLM_CMD_UNSPEC = 0,
38 DLM_CMD_HELLO, /* user->kernel */
39 DLM_CMD_TIMEOUT, /* kernel->user */
40 __DLM_CMD_MAX,
41};
42
43#define DLM_CMD_MAX (__DLM_CMD_MAX - 1)
44
45enum {
46 DLM_TYPE_UNSPEC = 0,
47 DLM_TYPE_LOCK,
48 __DLM_TYPE_MAX,
49};
50
51#define DLM_TYPE_MAX (__DLM_TYPE_MAX - 1)
52
53#define DLM_GENL_VERSION 0x1
54#define DLM_GENL_NAME "DLM"
55
56#endif /* _DLM_NETLINK_H */