xref: /linux/drivers/block/drbd/drbd_proc.c (revision 200323768787a0ee02e01c35c1aff13dc9d77dde)
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 
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