Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/block/drbd/drbd_proc.c
15180 views
1
/*
2
drbd_proc.c
3
4
This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
5
6
Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
7
Copyright (C) 1999-2008, Philipp Reisner <[email protected]>.
8
Copyright (C) 2002-2008, Lars Ellenberg <[email protected]>.
9
10
drbd is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 2, or (at your option)
13
any later version.
14
15
drbd is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
19
20
You should have received a copy of the GNU General Public License
21
along with drbd; see the file COPYING. If not, write to
22
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
24
*/
25
26
#include <linux/module.h>
27
28
#include <asm/uaccess.h>
29
#include <linux/fs.h>
30
#include <linux/file.h>
31
#include <linux/proc_fs.h>
32
#include <linux/seq_file.h>
33
#include <linux/drbd.h>
34
#include "drbd_int.h"
35
36
static int drbd_proc_open(struct inode *inode, struct file *file);
37
static int drbd_proc_release(struct inode *inode, struct file *file);
38
39
40
struct proc_dir_entry *drbd_proc;
41
const struct file_operations drbd_proc_fops = {
42
.owner = THIS_MODULE,
43
.open = drbd_proc_open,
44
.read = seq_read,
45
.llseek = seq_lseek,
46
.release = drbd_proc_release,
47
};
48
49
void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
50
{
51
/* v is in kB/sec. We don't expect TiByte/sec yet. */
52
if (unlikely(v >= 1000000)) {
53
/* cool: > GiByte/s */
54
seq_printf(seq, "%ld,", v / 1000000);
55
v /= 1000000;
56
seq_printf(seq, "%03ld,%03ld", v/1000, v % 1000);
57
} else if (likely(v >= 1000))
58
seq_printf(seq, "%ld,%03ld", v/1000, v % 1000);
59
else
60
seq_printf(seq, "%ld", v);
61
}
62
63
/*lge
64
* progress bars shamelessly adapted from driver/md/md.c
65
* output looks like
66
* [=====>..............] 33.5% (23456/123456)
67
* finish: 2:20:20 speed: 6,345 (6,456) K/sec
68
*/
69
static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
70
{
71
unsigned long db, dt, dbdt, rt, rs_left;
72
unsigned int res;
73
int i, x, y;
74
int stalled = 0;
75
76
drbd_get_syncer_progress(mdev, &rs_left, &res);
77
78
x = res/50;
79
y = 20-x;
80
seq_printf(seq, "\t[");
81
for (i = 1; i < x; i++)
82
seq_printf(seq, "=");
83
seq_printf(seq, ">");
84
for (i = 0; i < y; i++)
85
seq_printf(seq, ".");
86
seq_printf(seq, "] ");
87
88
if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
89
seq_printf(seq, "verified:");
90
else
91
seq_printf(seq, "sync'ed:");
92
seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
93
94
/* if more than a few GB, display in MB */
95
if (mdev->rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
96
seq_printf(seq, "(%lu/%lu)M",
97
(unsigned long) Bit2KB(rs_left >> 10),
98
(unsigned long) Bit2KB(mdev->rs_total >> 10));
99
else
100
seq_printf(seq, "(%lu/%lu)K\n\t",
101
(unsigned long) Bit2KB(rs_left),
102
(unsigned long) Bit2KB(mdev->rs_total));
103
104
/* see drivers/md/md.c
105
* We do not want to overflow, so the order of operands and
106
* the * 100 / 100 trick are important. We do a +1 to be
107
* safe against division by zero. We only estimate anyway.
108
*
109
* dt: time from mark until now
110
* db: blocks written from mark until now
111
* rt: remaining time
112
*/
113
/* Rolling marks. last_mark+1 may just now be modified. last_mark+2 is
114
* at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
115
* least DRBD_SYNC_MARK_STEP time before it will be modified. */
116
/* ------------------------ ~18s average ------------------------ */
117
i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
118
dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
119
if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
120
stalled = 1;
121
122
if (!dt)
123
dt++;
124
db = mdev->rs_mark_left[i] - rs_left;
125
rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
126
127
seq_printf(seq, "finish: %lu:%02lu:%02lu",
128
rt / 3600, (rt % 3600) / 60, rt % 60);
129
130
dbdt = Bit2KB(db/dt);
131
seq_printf(seq, " speed: ");
132
seq_printf_with_thousands_grouping(seq, dbdt);
133
seq_printf(seq, " (");
134
/* ------------------------- ~3s average ------------------------ */
135
if (proc_details >= 1) {
136
/* this is what drbd_rs_should_slow_down() uses */
137
i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
138
dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
139
if (!dt)
140
dt++;
141
db = mdev->rs_mark_left[i] - rs_left;
142
dbdt = Bit2KB(db/dt);
143
seq_printf_with_thousands_grouping(seq, dbdt);
144
seq_printf(seq, " -- ");
145
}
146
147
/* --------------------- long term average ---------------------- */
148
/* mean speed since syncer started
149
* we do account for PausedSync periods */
150
dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
151
if (dt == 0)
152
dt = 1;
153
db = mdev->rs_total - rs_left;
154
dbdt = Bit2KB(db/dt);
155
seq_printf_with_thousands_grouping(seq, dbdt);
156
seq_printf(seq, ")");
157
158
if (mdev->state.conn == C_SYNC_TARGET ||
159
mdev->state.conn == C_VERIFY_S) {
160
seq_printf(seq, " want: ");
161
seq_printf_with_thousands_grouping(seq, mdev->c_sync_rate);
162
}
163
seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
164
165
if (proc_details >= 1) {
166
/* 64 bit:
167
* we convert to sectors in the display below. */
168
unsigned long bm_bits = drbd_bm_bits(mdev);
169
unsigned long bit_pos;
170
if (mdev->state.conn == C_VERIFY_S ||
171
mdev->state.conn == C_VERIFY_T)
172
bit_pos = bm_bits - mdev->ov_left;
173
else
174
bit_pos = mdev->bm_resync_fo;
175
/* Total sectors may be slightly off for oddly
176
* sized devices. So what. */
177
seq_printf(seq,
178
"\t%3d%% sector pos: %llu/%llu\n",
179
(int)(bit_pos / (bm_bits/100+1)),
180
(unsigned long long)bit_pos * BM_SECT_PER_BIT,
181
(unsigned long long)bm_bits * BM_SECT_PER_BIT);
182
}
183
}
184
185
static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
186
{
187
struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
188
189
seq_printf(seq, "%5d %s %s\n", bme->rs_left,
190
bme->flags & BME_NO_WRITES ? "NO_WRITES" : "---------",
191
bme->flags & BME_LOCKED ? "LOCKED" : "------"
192
);
193
}
194
195
static int drbd_seq_show(struct seq_file *seq, void *v)
196
{
197
int i, hole = 0;
198
const char *sn;
199
struct drbd_conf *mdev;
200
201
static char write_ordering_chars[] = {
202
[WO_none] = 'n',
203
[WO_drain_io] = 'd',
204
[WO_bdev_flush] = 'f',
205
};
206
207
seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
208
API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
209
210
/*
211
cs .. connection state
212
ro .. node role (local/remote)
213
ds .. disk state (local/remote)
214
protocol
215
various flags
216
ns .. network send
217
nr .. network receive
218
dw .. disk write
219
dr .. disk read
220
al .. activity log write count
221
bm .. bitmap update write count
222
pe .. pending (waiting for ack or data reply)
223
ua .. unack'd (still need to send ack or data reply)
224
ap .. application requests accepted, but not yet completed
225
ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
226
wo .. write ordering mode currently in use
227
oos .. known out-of-sync kB
228
*/
229
230
for (i = 0; i < minor_count; i++) {
231
mdev = minor_to_mdev(i);
232
if (!mdev) {
233
hole = 1;
234
continue;
235
}
236
if (hole) {
237
hole = 0;
238
seq_printf(seq, "\n");
239
}
240
241
sn = drbd_conn_str(mdev->state.conn);
242
243
if (mdev->state.conn == C_STANDALONE &&
244
mdev->state.disk == D_DISKLESS &&
245
mdev->state.role == R_SECONDARY) {
246
seq_printf(seq, "%2d: cs:Unconfigured\n", i);
247
} else {
248
seq_printf(seq,
249
"%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
250
" ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
251
"lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
252
i, sn,
253
drbd_role_str(mdev->state.role),
254
drbd_role_str(mdev->state.peer),
255
drbd_disk_str(mdev->state.disk),
256
drbd_disk_str(mdev->state.pdsk),
257
(mdev->net_conf == NULL ? ' ' :
258
(mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
259
is_susp(mdev->state) ? 's' : 'r',
260
mdev->state.aftr_isp ? 'a' : '-',
261
mdev->state.peer_isp ? 'p' : '-',
262
mdev->state.user_isp ? 'u' : '-',
263
mdev->congestion_reason ?: '-',
264
test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
265
mdev->send_cnt/2,
266
mdev->recv_cnt/2,
267
mdev->writ_cnt/2,
268
mdev->read_cnt/2,
269
mdev->al_writ_cnt,
270
mdev->bm_writ_cnt,
271
atomic_read(&mdev->local_cnt),
272
atomic_read(&mdev->ap_pending_cnt) +
273
atomic_read(&mdev->rs_pending_cnt),
274
atomic_read(&mdev->unacked_cnt),
275
atomic_read(&mdev->ap_bio_cnt),
276
mdev->epochs,
277
write_ordering_chars[mdev->write_ordering]
278
);
279
seq_printf(seq, " oos:%llu\n",
280
Bit2KB((unsigned long long)
281
drbd_bm_total_weight(mdev)));
282
}
283
if (mdev->state.conn == C_SYNC_SOURCE ||
284
mdev->state.conn == C_SYNC_TARGET ||
285
mdev->state.conn == C_VERIFY_S ||
286
mdev->state.conn == C_VERIFY_T)
287
drbd_syncer_progress(mdev, seq);
288
289
if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
290
lc_seq_printf_stats(seq, mdev->resync);
291
lc_seq_printf_stats(seq, mdev->act_log);
292
put_ldev(mdev);
293
}
294
295
if (proc_details >= 2) {
296
if (mdev->resync) {
297
lc_seq_dump_details(seq, mdev->resync, "rs_left",
298
resync_dump_detail);
299
}
300
}
301
}
302
303
return 0;
304
}
305
306
static int drbd_proc_open(struct inode *inode, struct file *file)
307
{
308
if (try_module_get(THIS_MODULE))
309
return single_open(file, drbd_seq_show, PDE(inode)->data);
310
return -ENODEV;
311
}
312
313
static int drbd_proc_release(struct inode *inode, struct file *file)
314
{
315
module_put(THIS_MODULE);
316
return single_release(inode, file);
317
}
318
319
/* PROC FS stuff end */
320
321