diff options
Diffstat (limited to 'fs/dlm')
-rw-r--r-- | fs/dlm/Makefile | 1 | ||||
-rw-r--r-- | fs/dlm/config.c | 8 | ||||
-rw-r--r-- | fs/dlm/config.h | 1 | ||||
-rw-r--r-- | fs/dlm/dlm_internal.h | 10 | ||||
-rw-r--r-- | fs/dlm/lock.c | 146 | ||||
-rw-r--r-- | fs/dlm/lock.h | 4 | ||||
-rw-r--r-- | fs/dlm/lockspace.c | 10 | ||||
-rw-r--r-- | fs/dlm/main.c | 11 | ||||
-rw-r--r-- | fs/dlm/member.c | 5 | ||||
-rw-r--r-- | fs/dlm/netlink.c | 155 | ||||
-rw-r--r-- | fs/dlm/recoverd.c | 4 | ||||
-rw-r--r-- | fs/dlm/user.c | 2 |
12 files changed, 348 insertions, 9 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 | ||
95 | enum { | 96 | enum { |
@@ -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 | ||
108 | struct cluster_attribute { | 110 | struct cluster_attribute { |
@@ -162,6 +164,7 @@ CLUSTER_ATTR(toss_secs, 1); | |||
162 | CLUSTER_ATTR(scan_secs, 1); | 164 | CLUSTER_ATTR(scan_secs, 1); |
163 | CLUSTER_ATTR(log_debug, 0); | 165 | CLUSTER_ATTR(log_debug, 0); |
164 | CLUSTER_ATTR(protocol, 0); | 166 | CLUSTER_ATTR(protocol, 0); |
167 | CLUSTER_ATTR(timewarn_cs, 1); | ||
165 | 168 | ||
166 | static struct configfs_attribute *cluster_attrs[] = { | 169 | static 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 | ||
920 | struct dlm_config_info dlm_config = { | 925 | struct 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 | ||
32 | extern struct dlm_config_info dlm_config; | 33 | extern 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 | ||
219 | struct dlm_lkb { | 221 | struct 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); | |||
82 | static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb); | 82 | static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb); |
83 | static int send_remove(struct dlm_rsb *r); | 83 | static int send_remove(struct dlm_rsb *r); |
84 | static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); | 84 | static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); |
85 | static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); | ||
85 | static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | 86 | static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, |
86 | struct dlm_message *ms); | 87 | struct dlm_message *ms); |
87 | static int receive_extralen(struct dlm_message *ms); | 88 | static int receive_extralen(struct dlm_message *ms); |
88 | static void do_purge(struct dlm_ls *ls, int nodeid, int pid); | 89 | static void do_purge(struct dlm_ls *ls, int nodeid, int pid); |
90 | static void del_timeout(struct dlm_lkb *lkb); | ||
91 | void 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 | ||
1009 | static 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 | |||
1035 | static 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 | |||
1053 | void 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 | |||
1116 | void 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 | ||
998 | static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) | 1130 | static 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); | |||
26 | void dlm_scan_rsbs(struct dlm_ls *ls); | 26 | void dlm_scan_rsbs(struct dlm_ls *ls); |
27 | int dlm_lock_recovery_try(struct dlm_ls *ls); | 27 | int dlm_lock_recovery_try(struct dlm_ls *ls); |
28 | void dlm_unlock_recovery(struct dlm_ls *ls); | 28 | void dlm_unlock_recovery(struct dlm_ls *ls); |
29 | void dlm_scan_timeout(struct dlm_ls *ls); | ||
30 | void dlm_adjust_timeouts(struct dlm_ls *ls); | ||
29 | 31 | ||
30 | int dlm_purge_locks(struct dlm_ls *ls); | 32 | int dlm_purge_locks(struct dlm_ls *ls); |
31 | void dlm_purge_mstcpy_locks(struct dlm_rsb *r); | 33 | void 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); | |||
25 | static inline int dlm_register_debugfs(void) { return 0; } | 25 | static inline int dlm_register_debugfs(void) { return 0; } |
26 | static inline void dlm_unregister_debugfs(void) { } | 26 | static inline void dlm_unregister_debugfs(void) { } |
27 | #endif | 27 | #endif |
28 | int dlm_netlink_init(void); | ||
29 | void dlm_netlink_exit(void); | ||
28 | 30 | ||
29 | static int __init init_dlm(void) | 31 | static 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 | ||
69 | static void __exit exit_dlm(void) | 77 | static 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 | |||
15 | static uint32_t dlm_nl_seqnum; | ||
16 | static uint32_t listener_nlpid; | ||
17 | |||
18 | static struct genl_family family = { | ||
19 | .id = GENL_ID_GENERATE, | ||
20 | .name = DLM_GENL_NAME, | ||
21 | .version = DLM_GENL_VERSION, | ||
22 | }; | ||
23 | |||
24 | static 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 | |||
44 | static 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 | |||
54 | static 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 | |||
69 | static 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 | |||
76 | static struct genl_ops dlm_nl_ops = { | ||
77 | .cmd = DLM_CMD_HELLO, | ||
78 | .doit = user_cmd, | ||
79 | }; | ||
80 | |||
81 | int 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 | |||
98 | void dlm_netlink_exit(void) | ||
99 | { | ||
100 | genl_unregister_ops(&family, &dlm_nl_ops); | ||
101 | genl_unregister_family(&family); | ||
102 | } | ||
103 | |||
104 | static 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 | |||
129 | void 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 | ||