diff options
Diffstat (limited to 'fs/gfs2/lock_dlm.c')
-rw-r--r-- | fs/gfs2/lock_dlm.c | 123 |
1 files changed, 118 insertions, 5 deletions
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 8944d1e32ab5..f8411bd1b805 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c | |||
@@ -18,14 +18,106 @@ | |||
18 | #include "glock.h" | 18 | #include "glock.h" |
19 | #include "util.h" | 19 | #include "util.h" |
20 | #include "sys.h" | 20 | #include "sys.h" |
21 | #include "trace_gfs2.h" | ||
21 | 22 | ||
22 | extern struct workqueue_struct *gfs2_control_wq; | 23 | extern struct workqueue_struct *gfs2_control_wq; |
23 | 24 | ||
25 | /** | ||
26 | * gfs2_update_stats - Update time based stats | ||
27 | * @mv: Pointer to mean/variance structure to update | ||
28 | * @sample: New data to include | ||
29 | * | ||
30 | * @delta is the difference between the current rtt sample and the | ||
31 | * running average srtt. We add 1/8 of that to the srtt in order to | ||
32 | * update the current srtt estimate. The varience estimate is a bit | ||
33 | * more complicated. We subtract the abs value of the @delta from | ||
34 | * the current variance estimate and add 1/4 of that to the running | ||
35 | * total. | ||
36 | * | ||
37 | * Note that the index points at the array entry containing the smoothed | ||
38 | * mean value, and the variance is always in the following entry | ||
39 | * | ||
40 | * Reference: TCP/IP Illustrated, vol 2, p. 831,832 | ||
41 | * All times are in units of integer nanoseconds. Unlike the TCP/IP case, | ||
42 | * they are not scaled fixed point. | ||
43 | */ | ||
44 | |||
45 | static inline void gfs2_update_stats(struct gfs2_lkstats *s, unsigned index, | ||
46 | s64 sample) | ||
47 | { | ||
48 | s64 delta = sample - s->stats[index]; | ||
49 | s->stats[index] += (delta >> 3); | ||
50 | index++; | ||
51 | s->stats[index] += ((abs64(delta) - s->stats[index]) >> 2); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * gfs2_update_reply_times - Update locking statistics | ||
56 | * @gl: The glock to update | ||
57 | * | ||
58 | * This assumes that gl->gl_dstamp has been set earlier. | ||
59 | * | ||
60 | * The rtt (lock round trip time) is an estimate of the time | ||
61 | * taken to perform a dlm lock request. We update it on each | ||
62 | * reply from the dlm. | ||
63 | * | ||
64 | * The blocking flag is set on the glock for all dlm requests | ||
65 | * which may potentially block due to lock requests from other nodes. | ||
66 | * DLM requests where the current lock state is exclusive, the | ||
67 | * requested state is null (or unlocked) or where the TRY or | ||
68 | * TRY_1CB flags are set are classified as non-blocking. All | ||
69 | * other DLM requests are counted as (potentially) blocking. | ||
70 | */ | ||
71 | static inline void gfs2_update_reply_times(struct gfs2_glock *gl) | ||
72 | { | ||
73 | struct gfs2_pcpu_lkstats *lks; | ||
74 | const unsigned gltype = gl->gl_name.ln_type; | ||
75 | unsigned index = test_bit(GLF_BLOCKING, &gl->gl_flags) ? | ||
76 | GFS2_LKS_SRTTB : GFS2_LKS_SRTT; | ||
77 | s64 rtt; | ||
78 | |||
79 | preempt_disable(); | ||
80 | rtt = ktime_to_ns(ktime_sub(ktime_get_real(), gl->gl_dstamp)); | ||
81 | lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats); | ||
82 | gfs2_update_stats(&gl->gl_stats, index, rtt); /* Local */ | ||
83 | gfs2_update_stats(&lks->lkstats[gltype], index, rtt); /* Global */ | ||
84 | preempt_enable(); | ||
85 | |||
86 | trace_gfs2_glock_lock_time(gl, rtt); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * gfs2_update_request_times - Update locking statistics | ||
91 | * @gl: The glock to update | ||
92 | * | ||
93 | * The irt (lock inter-request times) measures the average time | ||
94 | * between requests to the dlm. It is updated immediately before | ||
95 | * each dlm call. | ||
96 | */ | ||
97 | |||
98 | static inline void gfs2_update_request_times(struct gfs2_glock *gl) | ||
99 | { | ||
100 | struct gfs2_pcpu_lkstats *lks; | ||
101 | const unsigned gltype = gl->gl_name.ln_type; | ||
102 | ktime_t dstamp; | ||
103 | s64 irt; | ||
104 | |||
105 | preempt_disable(); | ||
106 | dstamp = gl->gl_dstamp; | ||
107 | gl->gl_dstamp = ktime_get_real(); | ||
108 | irt = ktime_to_ns(ktime_sub(gl->gl_dstamp, dstamp)); | ||
109 | lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats); | ||
110 | gfs2_update_stats(&gl->gl_stats, GFS2_LKS_SIRT, irt); /* Local */ | ||
111 | gfs2_update_stats(&lks->lkstats[gltype], GFS2_LKS_SIRT, irt); /* Global */ | ||
112 | preempt_enable(); | ||
113 | } | ||
114 | |||
24 | static void gdlm_ast(void *arg) | 115 | static void gdlm_ast(void *arg) |
25 | { | 116 | { |
26 | struct gfs2_glock *gl = arg; | 117 | struct gfs2_glock *gl = arg; |
27 | unsigned ret = gl->gl_state; | 118 | unsigned ret = gl->gl_state; |
28 | 119 | ||
120 | gfs2_update_reply_times(gl); | ||
29 | BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); | 121 | BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); |
30 | 122 | ||
31 | if (gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID) | 123 | if (gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID) |
@@ -111,7 +203,7 @@ static int make_mode(const unsigned int lmstate) | |||
111 | static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, | 203 | static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, |
112 | const int req) | 204 | const int req) |
113 | { | 205 | { |
114 | u32 lkf = 0; | 206 | u32 lkf = DLM_LKF_VALBLK; |
115 | 207 | ||
116 | if (gfs_flags & LM_FLAG_TRY) | 208 | if (gfs_flags & LM_FLAG_TRY) |
117 | lkf |= DLM_LKF_NOQUEUE; | 209 | lkf |= DLM_LKF_NOQUEUE; |
@@ -138,26 +230,43 @@ static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, | |||
138 | if (lkid != 0) | 230 | if (lkid != 0) |
139 | lkf |= DLM_LKF_CONVERT; | 231 | lkf |= DLM_LKF_CONVERT; |
140 | 232 | ||
141 | lkf |= DLM_LKF_VALBLK; | ||
142 | |||
143 | return lkf; | 233 | return lkf; |
144 | } | 234 | } |
145 | 235 | ||
236 | static void gfs2_reverse_hex(char *c, u64 value) | ||
237 | { | ||
238 | while (value) { | ||
239 | *c-- = hex_asc[value & 0x0f]; | ||
240 | value >>= 4; | ||
241 | } | ||
242 | } | ||
243 | |||
146 | static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state, | 244 | static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state, |
147 | unsigned int flags) | 245 | unsigned int flags) |
148 | { | 246 | { |
149 | struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; | 247 | struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; |
150 | int req; | 248 | int req; |
151 | u32 lkf; | 249 | u32 lkf; |
250 | char strname[GDLM_STRNAME_BYTES] = ""; | ||
152 | 251 | ||
153 | req = make_mode(req_state); | 252 | req = make_mode(req_state); |
154 | lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); | 253 | lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); |
155 | 254 | gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); | |
255 | gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); | ||
256 | if (gl->gl_lksb.sb_lkid) { | ||
257 | gfs2_update_request_times(gl); | ||
258 | } else { | ||
259 | memset(strname, ' ', GDLM_STRNAME_BYTES - 1); | ||
260 | strname[GDLM_STRNAME_BYTES - 1] = '\0'; | ||
261 | gfs2_reverse_hex(strname + 7, gl->gl_name.ln_type); | ||
262 | gfs2_reverse_hex(strname + 23, gl->gl_name.ln_number); | ||
263 | gl->gl_dstamp = ktime_get_real(); | ||
264 | } | ||
156 | /* | 265 | /* |
157 | * Submit the actual lock request. | 266 | * Submit the actual lock request. |
158 | */ | 267 | */ |
159 | 268 | ||
160 | return dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname, | 269 | return dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, strname, |
161 | GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast); | 270 | GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast); |
162 | } | 271 | } |
163 | 272 | ||
@@ -172,6 +281,10 @@ static void gdlm_put_lock(struct gfs2_glock *gl) | |||
172 | return; | 281 | return; |
173 | } | 282 | } |
174 | 283 | ||
284 | clear_bit(GLF_BLOCKING, &gl->gl_flags); | ||
285 | gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); | ||
286 | gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); | ||
287 | gfs2_update_request_times(gl); | ||
175 | error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK, | 288 | error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK, |
176 | NULL, gl); | 289 | NULL, gl); |
177 | if (error) { | 290 | if (error) { |