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 <philipp.reisner@linbit.com>.
9 Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
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
24struct proc_dir_entry *drbd_proc;
25
26static 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(m: seq, fmt: "%ld,", v / 1000000);
32 v %= 1000000;
33 seq_printf(m: seq, fmt: "%03ld,%03ld", v/1000, v % 1000);
34 } else if (likely(v >= 1000))
35 seq_printf(m: seq, fmt: "%ld,%03ld", v/1000, v % 1000);
36 else
37 seq_printf(m: seq, fmt: "%ld", v);
38}
39
40static 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 */
90static 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_total, bits_left: &rs_left, per_mil_done: &res);
99
100 x = res/50;
101 y = 20-x;
102 seq_puts(m: seq, s: "\t[");
103 for (i = 1; i < x; i++)
104 seq_putc(m: seq, c: '=');
105 seq_putc(m: seq, c: '>');
106 for (i = 0; i < y; i++)
107 seq_putc(m: seq, c: '.');
108 seq_puts(m: seq, s: "] ");
109
110 if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
111 seq_puts(m: seq, s: "verified:");
112 else
113 seq_puts(m: seq, s: "sync'ed:");
114 seq_printf(m: seq, fmt: "%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(m: seq, fmt: "(%lu/%lu)M",
119 (unsigned long) Bit2KB(rs_left >> 10),
120 (unsigned long) Bit2KB(rs_total >> 10));
121 else
122 seq_printf(m: seq, fmt: "(%lu/%lu)K",
123 (unsigned long) Bit2KB(rs_left),
124 (unsigned long) Bit2KB(rs_total));
125
126 seq_puts(m: seq, s: "\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(m: seq, fmt: "finish: %lu:%02lu:%02lu",
152 rt / 3600, (rt % 3600) / 60, rt % 60);
153
154 dbdt = Bit2KB(db/dt);
155 seq_puts(m: seq, s: " speed: ");
156 seq_printf_with_thousands_grouping(seq, v: dbdt);
157 seq_puts(m: seq, s: " (");
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, v: dbdt);
168 seq_puts(m: seq, s: " -- ");
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, v: dbdt);
180 seq_putc(m: seq, c: ')');
181
182 if (state.conn == C_SYNC_TARGET ||
183 state.conn == C_VERIFY_S) {
184 seq_puts(m: seq, s: " want: ");
185 seq_printf_with_thousands_grouping(seq, v: device->c_sync_rate);
186 }
187 seq_printf(m: seq, fmt: " 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(m: seq,
205 fmt: "\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(m: seq, fmt: " stop sector: %llu", stop_sector);
211 seq_putc(m: seq, c: '\n');
212 }
213}
214
215int 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(m: seq, fmt: "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(m: seq, c: '\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(m: seq, fmt: "%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(m: seq,
272 fmt: "%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(v: &device->local_cnt),
294 atomic_read(v: &device->ap_pending_cnt) +
295 atomic_read(v: &device->rs_pending_cnt),
296 atomic_read(v: &device->unacked_cnt),
297 atomic_read(v: &device->ap_bio_cnt),
298 first_peer_device(device)->connection->epochs,
299 write_ordering_chars[device->resource->write_ordering]
300 );
301 seq_printf(m: seq, fmt: " 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, lc: device->resync);
313 lc_seq_printf_stats(seq, lc: device->act_log);
314 put_ldev(device);
315 }
316
317 if (drbd_proc_details >= 2)
318 seq_printf(m: seq, fmt: "\tblocked on activity log: %d\n", atomic_read(v: &device->ap_actlog_cnt));
319 }
320 rcu_read_unlock();
321
322 return 0;
323}
324

source code of linux/drivers/block/drbd/drbd_proc.c