Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/block/drbd/drbd_proc.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
drbd_proc.c
4
5
This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
6
7
Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
8
Copyright (C) 1999-2008, Philipp Reisner <[email protected]>.
9
Copyright (C) 2002-2008, Lars Ellenberg <[email protected]>.
10
11
12
*/
13
14
#include <linux/module.h>
15
16
#include <linux/uaccess.h>
17
#include <linux/fs.h>
18
#include <linux/file.h>
19
#include <linux/proc_fs.h>
20
#include <linux/seq_file.h>
21
#include <linux/drbd.h>
22
#include "drbd_int.h"
23
24
struct proc_dir_entry *drbd_proc;
25
26
static void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
27
{
28
/* v is in kB/sec. We don't expect TiByte/sec yet. */
29
if (unlikely(v >= 1000000)) {
30
/* cool: > GiByte/s */
31
seq_printf(seq, "%ld,", v / 1000000);
32
v %= 1000000;
33
seq_printf(seq, "%03ld,%03ld", v/1000, v % 1000);
34
} else if (likely(v >= 1000))
35
seq_printf(seq, "%ld,%03ld", v/1000, v % 1000);
36
else
37
seq_printf(seq, "%ld", v);
38
}
39
40
static void drbd_get_syncer_progress(struct drbd_device *device,
41
union drbd_dev_state state, unsigned long *rs_total,
42
unsigned long *bits_left, unsigned int *per_mil_done)
43
{
44
/* this is to break it at compile time when we change that, in case we
45
* want to support more than (1<<32) bits on a 32bit arch. */
46
typecheck(unsigned long, device->rs_total);
47
*rs_total = device->rs_total;
48
49
/* note: both rs_total and rs_left are in bits, i.e. in
50
* units of BM_BLOCK_SIZE.
51
* for the percentage, we don't care. */
52
53
if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
54
*bits_left = device->ov_left;
55
else
56
*bits_left = drbd_bm_total_weight(device) - device->rs_failed;
57
/* >> 10 to prevent overflow,
58
* +1 to prevent division by zero */
59
if (*bits_left > *rs_total) {
60
/* D'oh. Maybe a logic bug somewhere. More likely just a race
61
* between state change and reset of rs_total.
62
*/
63
*bits_left = *rs_total;
64
*per_mil_done = *rs_total ? 0 : 1000;
65
} else {
66
/* Make sure the division happens in long context.
67
* We allow up to one petabyte storage right now,
68
* at a granularity of 4k per bit that is 2**38 bits.
69
* After shift right and multiplication by 1000,
70
* this should still fit easily into a 32bit long,
71
* so we don't need a 64bit division on 32bit arch.
72
* Note: currently we don't support such large bitmaps on 32bit
73
* arch anyways, but no harm done to be prepared for it here.
74
*/
75
unsigned int shift = *rs_total > UINT_MAX ? 16 : 10;
76
unsigned long left = *bits_left >> shift;
77
unsigned long total = 1UL + (*rs_total >> shift);
78
unsigned long tmp = 1000UL - left * 1000UL/total;
79
*per_mil_done = tmp;
80
}
81
}
82
83
84
/*lge
85
* progress bars shamelessly adapted from driver/md/md.c
86
* output looks like
87
* [=====>..............] 33.5% (23456/123456)
88
* finish: 2:20:20 speed: 6,345 (6,456) K/sec
89
*/
90
static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq,
91
union drbd_dev_state state)
92
{
93
unsigned long db, dt, dbdt, rt, rs_total, rs_left;
94
unsigned int res;
95
int i, x, y;
96
int stalled = 0;
97
98
drbd_get_syncer_progress(device, state, &rs_total, &rs_left, &res);
99
100
x = res/50;
101
y = 20-x;
102
seq_puts(seq, "\t[");
103
for (i = 1; i < x; i++)
104
seq_putc(seq, '=');
105
seq_putc(seq, '>');
106
for (i = 0; i < y; i++)
107
seq_putc(seq, '.');
108
seq_puts(seq, "] ");
109
110
if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
111
seq_puts(seq, "verified:");
112
else
113
seq_puts(seq, "sync'ed:");
114
seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
115
116
/* if more than a few GB, display in MB */
117
if (rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
118
seq_printf(seq, "(%lu/%lu)M",
119
(unsigned long) Bit2KB(rs_left >> 10),
120
(unsigned long) Bit2KB(rs_total >> 10));
121
else
122
seq_printf(seq, "(%lu/%lu)K",
123
(unsigned long) Bit2KB(rs_left),
124
(unsigned long) Bit2KB(rs_total));
125
126
seq_puts(seq, "\n\t");
127
128
/* see drivers/md/md.c
129
* We do not want to overflow, so the order of operands and
130
* the * 100 / 100 trick are important. We do a +1 to be
131
* safe against division by zero. We only estimate anyway.
132
*
133
* dt: time from mark until now
134
* db: blocks written from mark until now
135
* rt: remaining time
136
*/
137
/* Rolling marks. last_mark+1 may just now be modified. last_mark+2 is
138
* at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
139
* least DRBD_SYNC_MARK_STEP time before it will be modified. */
140
/* ------------------------ ~18s average ------------------------ */
141
i = (device->rs_last_mark + 2) % DRBD_SYNC_MARKS;
142
dt = (jiffies - device->rs_mark_time[i]) / HZ;
143
if (dt > 180)
144
stalled = 1;
145
146
if (!dt)
147
dt++;
148
db = device->rs_mark_left[i] - rs_left;
149
rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
150
151
seq_printf(seq, "finish: %lu:%02lu:%02lu",
152
rt / 3600, (rt % 3600) / 60, rt % 60);
153
154
dbdt = Bit2KB(db/dt);
155
seq_puts(seq, " speed: ");
156
seq_printf_with_thousands_grouping(seq, dbdt);
157
seq_puts(seq, " (");
158
/* ------------------------- ~3s average ------------------------ */
159
if (drbd_proc_details >= 1) {
160
/* this is what drbd_rs_should_slow_down() uses */
161
i = (device->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
162
dt = (jiffies - device->rs_mark_time[i]) / HZ;
163
if (!dt)
164
dt++;
165
db = device->rs_mark_left[i] - rs_left;
166
dbdt = Bit2KB(db/dt);
167
seq_printf_with_thousands_grouping(seq, dbdt);
168
seq_puts(seq, " -- ");
169
}
170
171
/* --------------------- long term average ---------------------- */
172
/* mean speed since syncer started
173
* we do account for PausedSync periods */
174
dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
175
if (dt == 0)
176
dt = 1;
177
db = rs_total - rs_left;
178
dbdt = Bit2KB(db/dt);
179
seq_printf_with_thousands_grouping(seq, dbdt);
180
seq_putc(seq, ')');
181
182
if (state.conn == C_SYNC_TARGET ||
183
state.conn == C_VERIFY_S) {
184
seq_puts(seq, " want: ");
185
seq_printf_with_thousands_grouping(seq, device->c_sync_rate);
186
}
187
seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
188
189
if (drbd_proc_details >= 1) {
190
/* 64 bit:
191
* we convert to sectors in the display below. */
192
unsigned long bm_bits = drbd_bm_bits(device);
193
unsigned long bit_pos;
194
unsigned long long stop_sector = 0;
195
if (state.conn == C_VERIFY_S ||
196
state.conn == C_VERIFY_T) {
197
bit_pos = bm_bits - device->ov_left;
198
if (verify_can_do_stop_sector(device))
199
stop_sector = device->ov_stop_sector;
200
} else
201
bit_pos = device->bm_resync_fo;
202
/* Total sectors may be slightly off for oddly
203
* sized devices. So what. */
204
seq_printf(seq,
205
"\t%3d%% sector pos: %llu/%llu",
206
(int)(bit_pos / (bm_bits/100+1)),
207
(unsigned long long)bit_pos * BM_SECT_PER_BIT,
208
(unsigned long long)bm_bits * BM_SECT_PER_BIT);
209
if (stop_sector != 0 && stop_sector != ULLONG_MAX)
210
seq_printf(seq, " stop sector: %llu", stop_sector);
211
seq_putc(seq, '\n');
212
}
213
}
214
215
int drbd_seq_show(struct seq_file *seq, void *v)
216
{
217
int i, prev_i = -1;
218
const char *sn;
219
struct drbd_device *device;
220
struct net_conf *nc;
221
union drbd_dev_state state;
222
char wp;
223
224
static char write_ordering_chars[] = {
225
[WO_NONE] = 'n',
226
[WO_DRAIN_IO] = 'd',
227
[WO_BDEV_FLUSH] = 'f',
228
};
229
230
seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
231
GENL_MAGIC_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
232
233
/*
234
cs .. connection state
235
ro .. node role (local/remote)
236
ds .. disk state (local/remote)
237
protocol
238
various flags
239
ns .. network send
240
nr .. network receive
241
dw .. disk write
242
dr .. disk read
243
al .. activity log write count
244
bm .. bitmap update write count
245
pe .. pending (waiting for ack or data reply)
246
ua .. unack'd (still need to send ack or data reply)
247
ap .. application requests accepted, but not yet completed
248
ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
249
wo .. write ordering mode currently in use
250
oos .. known out-of-sync kB
251
*/
252
253
rcu_read_lock();
254
idr_for_each_entry(&drbd_devices, device, i) {
255
if (prev_i != i - 1)
256
seq_putc(seq, '\n');
257
prev_i = i;
258
259
state = device->state;
260
sn = drbd_conn_str(state.conn);
261
262
if (state.conn == C_STANDALONE &&
263
state.disk == D_DISKLESS &&
264
state.role == R_SECONDARY) {
265
seq_printf(seq, "%2d: cs:Unconfigured\n", i);
266
} else {
267
/* reset device->congestion_reason */
268
269
nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
270
wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
271
seq_printf(seq,
272
"%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
273
" ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
274
"lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
275
i, sn,
276
drbd_role_str(state.role),
277
drbd_role_str(state.peer),
278
drbd_disk_str(state.disk),
279
drbd_disk_str(state.pdsk),
280
wp,
281
drbd_suspended(device) ? 's' : 'r',
282
state.aftr_isp ? 'a' : '-',
283
state.peer_isp ? 'p' : '-',
284
state.user_isp ? 'u' : '-',
285
device->congestion_reason ?: '-',
286
test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-',
287
device->send_cnt/2,
288
device->recv_cnt/2,
289
device->writ_cnt/2,
290
device->read_cnt/2,
291
device->al_writ_cnt,
292
device->bm_writ_cnt,
293
atomic_read(&device->local_cnt),
294
atomic_read(&device->ap_pending_cnt) +
295
atomic_read(&device->rs_pending_cnt),
296
atomic_read(&device->unacked_cnt),
297
atomic_read(&device->ap_bio_cnt),
298
first_peer_device(device)->connection->epochs,
299
write_ordering_chars[device->resource->write_ordering]
300
);
301
seq_printf(seq, " oos:%llu\n",
302
Bit2KB((unsigned long long)
303
drbd_bm_total_weight(device)));
304
}
305
if (state.conn == C_SYNC_SOURCE ||
306
state.conn == C_SYNC_TARGET ||
307
state.conn == C_VERIFY_S ||
308
state.conn == C_VERIFY_T)
309
drbd_syncer_progress(device, seq, state);
310
311
if (drbd_proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) {
312
lc_seq_printf_stats(seq, device->resync);
313
lc_seq_printf_stats(seq, device->act_log);
314
put_ldev(device);
315
}
316
317
if (drbd_proc_details >= 2)
318
seq_printf(seq, "\tblocked on activity log: %d\n", atomic_read(&device->ap_actlog_cnt));
319
}
320
rcu_read_unlock();
321
322
return 0;
323
}
324
325