xref: /openbmc/linux/drivers/block/drbd/drbd_proc.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
193c68cc4SChristoph Böhmwalder // SPDX-License-Identifier: GPL-2.0-only
2b411b363SPhilipp Reisner /*
3b411b363SPhilipp Reisner    drbd_proc.c
4b411b363SPhilipp Reisner 
5b411b363SPhilipp Reisner    This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
6b411b363SPhilipp Reisner 
7b411b363SPhilipp Reisner    Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
8b411b363SPhilipp Reisner    Copyright (C) 1999-2008, Philipp Reisner <philipp.reisner@linbit.com>.
9b411b363SPhilipp Reisner    Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
10b411b363SPhilipp Reisner 
11b411b363SPhilipp Reisner 
12b411b363SPhilipp Reisner  */
13b411b363SPhilipp Reisner 
14b411b363SPhilipp Reisner #include <linux/module.h>
15b411b363SPhilipp Reisner 
167e5fec31SFabian Frederick #include <linux/uaccess.h>
17b411b363SPhilipp Reisner #include <linux/fs.h>
18b411b363SPhilipp Reisner #include <linux/file.h>
19b411b363SPhilipp Reisner #include <linux/proc_fs.h>
20b411b363SPhilipp Reisner #include <linux/seq_file.h>
21b411b363SPhilipp Reisner #include <linux/drbd.h>
22b411b363SPhilipp Reisner #include "drbd_int.h"
23b411b363SPhilipp Reisner 
24b411b363SPhilipp Reisner struct proc_dir_entry *drbd_proc;
25b411b363SPhilipp Reisner 
seq_printf_with_thousands_grouping(struct seq_file * seq,long v)26fbe0d91cSRashika Kheria static void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
27439d5953SLars Ellenberg {
28439d5953SLars Ellenberg 	/* v is in kB/sec. We don't expect TiByte/sec yet. */
29439d5953SLars Ellenberg 	if (unlikely(v >= 1000000)) {
30439d5953SLars Ellenberg 		/* cool: > GiByte/s */
31439d5953SLars Ellenberg 		seq_printf(seq, "%ld,", v / 1000000);
32fc251d5cSLars Ellenberg 		v %= 1000000;
33439d5953SLars Ellenberg 		seq_printf(seq, "%03ld,%03ld", v/1000, v % 1000);
34439d5953SLars Ellenberg 	} else if (likely(v >= 1000))
35439d5953SLars Ellenberg 		seq_printf(seq, "%ld,%03ld", v/1000, v % 1000);
36439d5953SLars Ellenberg 	else
37439d5953SLars Ellenberg 		seq_printf(seq, "%ld", v);
38439d5953SLars Ellenberg }
39b411b363SPhilipp Reisner 
drbd_get_syncer_progress(struct drbd_device * device,union drbd_dev_state state,unsigned long * rs_total,unsigned long * bits_left,unsigned int * per_mil_done)40a5655dacSLars Ellenberg static void drbd_get_syncer_progress(struct drbd_device *device,
41a5655dacSLars Ellenberg 		union drbd_dev_state state, unsigned long *rs_total,
42a5655dacSLars Ellenberg 		unsigned long *bits_left, unsigned int *per_mil_done)
43a5655dacSLars Ellenberg {
44a5655dacSLars Ellenberg 	/* this is to break it at compile time when we change that, in case we
45a5655dacSLars Ellenberg 	 * want to support more than (1<<32) bits on a 32bit arch. */
46a5655dacSLars Ellenberg 	typecheck(unsigned long, device->rs_total);
47a5655dacSLars Ellenberg 	*rs_total = device->rs_total;
48a5655dacSLars Ellenberg 
49a5655dacSLars Ellenberg 	/* note: both rs_total and rs_left are in bits, i.e. in
50a5655dacSLars Ellenberg 	 * units of BM_BLOCK_SIZE.
51a5655dacSLars Ellenberg 	 * for the percentage, we don't care. */
52a5655dacSLars Ellenberg 
53a5655dacSLars Ellenberg 	if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
54a5655dacSLars Ellenberg 		*bits_left = device->ov_left;
55a5655dacSLars Ellenberg 	else
56a5655dacSLars Ellenberg 		*bits_left = drbd_bm_total_weight(device) - device->rs_failed;
57a5655dacSLars Ellenberg 	/* >> 10 to prevent overflow,
58a5655dacSLars Ellenberg 	 * +1 to prevent division by zero */
59a5655dacSLars Ellenberg 	if (*bits_left > *rs_total) {
60a5655dacSLars Ellenberg 		/* D'oh. Maybe a logic bug somewhere.  More likely just a race
61a5655dacSLars Ellenberg 		 * between state change and reset of rs_total.
62a5655dacSLars Ellenberg 		 */
63a5655dacSLars Ellenberg 		*bits_left = *rs_total;
64a5655dacSLars Ellenberg 		*per_mil_done = *rs_total ? 0 : 1000;
65a5655dacSLars Ellenberg 	} else {
66a5655dacSLars Ellenberg 		/* Make sure the division happens in long context.
67a5655dacSLars Ellenberg 		 * We allow up to one petabyte storage right now,
68a5655dacSLars Ellenberg 		 * at a granularity of 4k per bit that is 2**38 bits.
69a5655dacSLars Ellenberg 		 * After shift right and multiplication by 1000,
70a5655dacSLars Ellenberg 		 * this should still fit easily into a 32bit long,
71a5655dacSLars Ellenberg 		 * so we don't need a 64bit division on 32bit arch.
72a5655dacSLars Ellenberg 		 * Note: currently we don't support such large bitmaps on 32bit
73a5655dacSLars Ellenberg 		 * arch anyways, but no harm done to be prepared for it here.
74a5655dacSLars Ellenberg 		 */
75a5655dacSLars Ellenberg 		unsigned int shift = *rs_total > UINT_MAX ? 16 : 10;
76a5655dacSLars Ellenberg 		unsigned long left = *bits_left >> shift;
77a5655dacSLars Ellenberg 		unsigned long total = 1UL + (*rs_total >> shift);
78a5655dacSLars Ellenberg 		unsigned long tmp = 1000UL - left * 1000UL/total;
79a5655dacSLars Ellenberg 		*per_mil_done = tmp;
80a5655dacSLars Ellenberg 	}
81a5655dacSLars Ellenberg }
82a5655dacSLars Ellenberg 
83a5655dacSLars Ellenberg 
84b411b363SPhilipp Reisner /*lge
85b411b363SPhilipp Reisner  * progress bars shamelessly adapted from driver/md/md.c
86b411b363SPhilipp Reisner  * output looks like
87b411b363SPhilipp Reisner  *	[=====>..............] 33.5% (23456/123456)
88b411b363SPhilipp Reisner  *	finish: 2:20:20 speed: 6,345 (6,456) K/sec
89b411b363SPhilipp Reisner  */
drbd_syncer_progress(struct drbd_device * device,struct seq_file * seq,union drbd_dev_state state)90a5655dacSLars Ellenberg static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq,
91a5655dacSLars Ellenberg 		union drbd_dev_state state)
92b411b363SPhilipp Reisner {
93a5655dacSLars Ellenberg 	unsigned long db, dt, dbdt, rt, rs_total, rs_left;
94b411b363SPhilipp Reisner 	unsigned int res;
95b411b363SPhilipp Reisner 	int i, x, y;
961d7734a0SLars Ellenberg 	int stalled = 0;
97b411b363SPhilipp Reisner 
98a5655dacSLars Ellenberg 	drbd_get_syncer_progress(device, state, &rs_total, &rs_left, &res);
99b411b363SPhilipp Reisner 
100b411b363SPhilipp Reisner 	x = res/50;
101b411b363SPhilipp Reisner 	y = 20-x;
1027e5fec31SFabian Frederick 	seq_puts(seq, "\t[");
103b411b363SPhilipp Reisner 	for (i = 1; i < x; i++)
1047e5fec31SFabian Frederick 		seq_putc(seq, '=');
1057e5fec31SFabian Frederick 	seq_putc(seq, '>');
106b411b363SPhilipp Reisner 	for (i = 0; i < y; i++)
107427fd2beSMarkus Elfring 		seq_putc(seq, '.');
1087e5fec31SFabian Frederick 	seq_puts(seq, "] ");
109b411b363SPhilipp Reisner 
110a5655dacSLars Ellenberg 	if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
1117e5fec31SFabian Frederick 		seq_puts(seq, "verified:");
1125f9915bbSLars Ellenberg 	else
1137e5fec31SFabian Frederick 		seq_puts(seq, "sync'ed:");
1145f9915bbSLars Ellenberg 	seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
1155f9915bbSLars Ellenberg 
1164b0715f0SLars Ellenberg 	/* if more than a few GB, display in MB */
117a5655dacSLars Ellenberg 	if (rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
1184b0715f0SLars Ellenberg 		seq_printf(seq, "(%lu/%lu)M",
119b411b363SPhilipp Reisner 			    (unsigned long) Bit2KB(rs_left >> 10),
120a5655dacSLars Ellenberg 			    (unsigned long) Bit2KB(rs_total >> 10));
121b411b363SPhilipp Reisner 	else
122590001c2SPhilipp Reisner 		seq_printf(seq, "(%lu/%lu)K",
123b411b363SPhilipp Reisner 			    (unsigned long) Bit2KB(rs_left),
124a5655dacSLars Ellenberg 			    (unsigned long) Bit2KB(rs_total));
125b411b363SPhilipp Reisner 
1267e5fec31SFabian Frederick 	seq_puts(seq, "\n\t");
127590001c2SPhilipp Reisner 
128b411b363SPhilipp Reisner 	/* see drivers/md/md.c
129b411b363SPhilipp Reisner 	 * We do not want to overflow, so the order of operands and
130b411b363SPhilipp Reisner 	 * the * 100 / 100 trick are important. We do a +1 to be
131b411b363SPhilipp Reisner 	 * safe against division by zero. We only estimate anyway.
132b411b363SPhilipp Reisner 	 *
133b411b363SPhilipp Reisner 	 * dt: time from mark until now
134b411b363SPhilipp Reisner 	 * db: blocks written from mark until now
135b411b363SPhilipp Reisner 	 * rt: remaining time
136b411b363SPhilipp Reisner 	 */
1371d7734a0SLars Ellenberg 	/* Rolling marks. last_mark+1 may just now be modified.  last_mark+2 is
1381d7734a0SLars Ellenberg 	 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
1391d7734a0SLars Ellenberg 	 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
140439d5953SLars Ellenberg 	/* ------------------------ ~18s average ------------------------ */
141b30ab791SAndreas Gruenbacher 	i = (device->rs_last_mark + 2) % DRBD_SYNC_MARKS;
142b30ab791SAndreas Gruenbacher 	dt = (jiffies - device->rs_mark_time[i]) / HZ;
1439ae47260SLars Ellenberg 	if (dt > 180)
1441d7734a0SLars Ellenberg 		stalled = 1;
145b411b363SPhilipp Reisner 
146b411b363SPhilipp Reisner 	if (!dt)
147b411b363SPhilipp Reisner 		dt++;
148b30ab791SAndreas Gruenbacher 	db = device->rs_mark_left[i] - rs_left;
149b411b363SPhilipp Reisner 	rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
150b411b363SPhilipp Reisner 
151b411b363SPhilipp Reisner 	seq_printf(seq, "finish: %lu:%02lu:%02lu",
152b411b363SPhilipp Reisner 		rt / 3600, (rt % 3600) / 60, rt % 60);
153b411b363SPhilipp Reisner 
154b411b363SPhilipp Reisner 	dbdt = Bit2KB(db/dt);
1557e5fec31SFabian Frederick 	seq_puts(seq, " speed: ");
156439d5953SLars Ellenberg 	seq_printf_with_thousands_grouping(seq, dbdt);
1577e5fec31SFabian Frederick 	seq_puts(seq, " (");
158439d5953SLars Ellenberg 	/* ------------------------- ~3s average ------------------------ */
159183ece30SRoland Kammerer 	if (drbd_proc_details >= 1) {
160439d5953SLars Ellenberg 		/* this is what drbd_rs_should_slow_down() uses */
161b30ab791SAndreas Gruenbacher 		i = (device->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
162b30ab791SAndreas Gruenbacher 		dt = (jiffies - device->rs_mark_time[i]) / HZ;
163439d5953SLars Ellenberg 		if (!dt)
164439d5953SLars Ellenberg 			dt++;
165b30ab791SAndreas Gruenbacher 		db = device->rs_mark_left[i] - rs_left;
166439d5953SLars Ellenberg 		dbdt = Bit2KB(db/dt);
167439d5953SLars Ellenberg 		seq_printf_with_thousands_grouping(seq, dbdt);
1687e5fec31SFabian Frederick 		seq_puts(seq, " -- ");
169439d5953SLars Ellenberg 	}
170439d5953SLars Ellenberg 
171439d5953SLars Ellenberg 	/* --------------------- long term average ---------------------- */
172b411b363SPhilipp Reisner 	/* mean speed since syncer started
173b411b363SPhilipp Reisner 	 * we do account for PausedSync periods */
174b30ab791SAndreas Gruenbacher 	dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
17522657695SDan Carpenter 	if (dt == 0)
176b411b363SPhilipp Reisner 		dt = 1;
177a5655dacSLars Ellenberg 	db = rs_total - rs_left;
178b411b363SPhilipp Reisner 	dbdt = Bit2KB(db/dt);
179439d5953SLars Ellenberg 	seq_printf_with_thousands_grouping(seq, dbdt);
1807e5fec31SFabian Frederick 	seq_putc(seq, ')');
181b411b363SPhilipp Reisner 
182a5655dacSLars Ellenberg 	if (state.conn == C_SYNC_TARGET ||
183a5655dacSLars Ellenberg 	    state.conn == C_VERIFY_S) {
1847e5fec31SFabian Frederick 		seq_puts(seq, " want: ");
185b30ab791SAndreas Gruenbacher 		seq_printf_with_thousands_grouping(seq, device->c_sync_rate);
1861d7734a0SLars Ellenberg 	}
1871d7734a0SLars Ellenberg 	seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
1885f9915bbSLars Ellenberg 
189183ece30SRoland Kammerer 	if (drbd_proc_details >= 1) {
1905f9915bbSLars Ellenberg 		/* 64 bit:
1915f9915bbSLars Ellenberg 		 * we convert to sectors in the display below. */
192b30ab791SAndreas Gruenbacher 		unsigned long bm_bits = drbd_bm_bits(device);
1934896e8c1SLars Ellenberg 		unsigned long bit_pos;
19458ffa580SLars Ellenberg 		unsigned long long stop_sector = 0;
195a5655dacSLars Ellenberg 		if (state.conn == C_VERIFY_S ||
196a5655dacSLars Ellenberg 		    state.conn == C_VERIFY_T) {
197b30ab791SAndreas Gruenbacher 			bit_pos = bm_bits - device->ov_left;
198b30ab791SAndreas Gruenbacher 			if (verify_can_do_stop_sector(device))
199b30ab791SAndreas Gruenbacher 				stop_sector = device->ov_stop_sector;
20058ffa580SLars Ellenberg 		} else
201b30ab791SAndreas Gruenbacher 			bit_pos = device->bm_resync_fo;
2025f9915bbSLars Ellenberg 		/* Total sectors may be slightly off for oddly
2035f9915bbSLars Ellenberg 		 * sized devices. So what. */
2045f9915bbSLars Ellenberg 		seq_printf(seq,
20558ffa580SLars Ellenberg 			"\t%3d%% sector pos: %llu/%llu",
2065f9915bbSLars Ellenberg 			(int)(bit_pos / (bm_bits/100+1)),
2074896e8c1SLars Ellenberg 			(unsigned long long)bit_pos * BM_SECT_PER_BIT,
2084896e8c1SLars Ellenberg 			(unsigned long long)bm_bits * BM_SECT_PER_BIT);
20958ffa580SLars Ellenberg 		if (stop_sector != 0 && stop_sector != ULLONG_MAX)
21058ffa580SLars Ellenberg 			seq_printf(seq, " stop sector: %llu", stop_sector);
2117e5fec31SFabian Frederick 		seq_putc(seq, '\n');
2125f9915bbSLars Ellenberg 	}
213b411b363SPhilipp Reisner }
214b411b363SPhilipp Reisner 
drbd_seq_show(struct seq_file * seq,void * v)215004fd11dSChristoph Hellwig int drbd_seq_show(struct seq_file *seq, void *v)
216b411b363SPhilipp Reisner {
21781a5d60eSPhilipp Reisner 	int i, prev_i = -1;
218b411b363SPhilipp Reisner 	const char *sn;
219b30ab791SAndreas Gruenbacher 	struct drbd_device *device;
22044ed167dSPhilipp Reisner 	struct net_conf *nc;
221a5655dacSLars Ellenberg 	union drbd_dev_state state;
22244ed167dSPhilipp Reisner 	char wp;
223b411b363SPhilipp Reisner 
224b411b363SPhilipp Reisner 	static char write_ordering_chars[] = {
225f6ba8636SAndreas Gruenbacher 		[WO_NONE] = 'n',
226f6ba8636SAndreas Gruenbacher 		[WO_DRAIN_IO] = 'd',
227f6ba8636SAndreas Gruenbacher 		[WO_BDEV_FLUSH] = 'f',
228b411b363SPhilipp Reisner 	};
229b411b363SPhilipp Reisner 
230b411b363SPhilipp Reisner 	seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
231*4e2da933SChristoph Böhmwalder 		   GENL_MAGIC_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
232b411b363SPhilipp Reisner 
233b411b363SPhilipp Reisner 	/*
234b411b363SPhilipp Reisner 	  cs .. connection state
235b411b363SPhilipp Reisner 	  ro .. node role (local/remote)
236b411b363SPhilipp Reisner 	  ds .. disk state (local/remote)
237b411b363SPhilipp Reisner 	     protocol
238b411b363SPhilipp Reisner 	     various flags
239b411b363SPhilipp Reisner 	  ns .. network send
240b411b363SPhilipp Reisner 	  nr .. network receive
241b411b363SPhilipp Reisner 	  dw .. disk write
242b411b363SPhilipp Reisner 	  dr .. disk read
243b411b363SPhilipp Reisner 	  al .. activity log write count
244b411b363SPhilipp Reisner 	  bm .. bitmap update write count
245b411b363SPhilipp Reisner 	  pe .. pending (waiting for ack or data reply)
246b411b363SPhilipp Reisner 	  ua .. unack'd (still need to send ack or data reply)
247b411b363SPhilipp Reisner 	  ap .. application requests accepted, but not yet completed
248b411b363SPhilipp Reisner 	  ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
249b411b363SPhilipp Reisner 	  wo .. write ordering mode currently in use
250b411b363SPhilipp Reisner 	 oos .. known out-of-sync kB
251b411b363SPhilipp Reisner 	*/
252b411b363SPhilipp Reisner 
253c141ebdaSPhilipp Reisner 	rcu_read_lock();
25405a10ec7SAndreas Gruenbacher 	idr_for_each_entry(&drbd_devices, device, i) {
25581a5d60eSPhilipp Reisner 		if (prev_i != i - 1)
2567e5fec31SFabian Frederick 			seq_putc(seq, '\n');
25781a5d60eSPhilipp Reisner 		prev_i = i;
258b411b363SPhilipp Reisner 
259a5655dacSLars Ellenberg 		state = device->state;
260a5655dacSLars Ellenberg 		sn = drbd_conn_str(state.conn);
261b411b363SPhilipp Reisner 
262a5655dacSLars Ellenberg 		if (state.conn == C_STANDALONE &&
263a5655dacSLars Ellenberg 		    state.disk == D_DISKLESS &&
264a5655dacSLars Ellenberg 		    state.role == R_SECONDARY) {
265b411b363SPhilipp Reisner 			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
266b411b363SPhilipp Reisner 		} else {
267b30ab791SAndreas Gruenbacher 			/* reset device->congestion_reason */
2688a943170SLars Ellenberg 
269a6b32bc3SAndreas Gruenbacher 			nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
27044ed167dSPhilipp Reisner 			wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
271b411b363SPhilipp Reisner 			seq_printf(seq,
2720778286aSPhilipp Reisner 			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
273b411b363SPhilipp Reisner 			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
274b411b363SPhilipp Reisner 			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
275b411b363SPhilipp Reisner 			   i, sn,
276a5655dacSLars Ellenberg 			   drbd_role_str(state.role),
277a5655dacSLars Ellenberg 			   drbd_role_str(state.peer),
278a5655dacSLars Ellenberg 			   drbd_disk_str(state.disk),
279a5655dacSLars Ellenberg 			   drbd_disk_str(state.pdsk),
28044ed167dSPhilipp Reisner 			   wp,
281b30ab791SAndreas Gruenbacher 			   drbd_suspended(device) ? 's' : 'r',
282a5655dacSLars Ellenberg 			   state.aftr_isp ? 'a' : '-',
283a5655dacSLars Ellenberg 			   state.peer_isp ? 'p' : '-',
284a5655dacSLars Ellenberg 			   state.user_isp ? 'u' : '-',
285b30ab791SAndreas Gruenbacher 			   device->congestion_reason ?: '-',
286b30ab791SAndreas Gruenbacher 			   test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-',
287b30ab791SAndreas Gruenbacher 			   device->send_cnt/2,
288b30ab791SAndreas Gruenbacher 			   device->recv_cnt/2,
289b30ab791SAndreas Gruenbacher 			   device->writ_cnt/2,
290b30ab791SAndreas Gruenbacher 			   device->read_cnt/2,
291b30ab791SAndreas Gruenbacher 			   device->al_writ_cnt,
292b30ab791SAndreas Gruenbacher 			   device->bm_writ_cnt,
293b30ab791SAndreas Gruenbacher 			   atomic_read(&device->local_cnt),
294b30ab791SAndreas Gruenbacher 			   atomic_read(&device->ap_pending_cnt) +
295b30ab791SAndreas Gruenbacher 			   atomic_read(&device->rs_pending_cnt),
296b30ab791SAndreas Gruenbacher 			   atomic_read(&device->unacked_cnt),
297b30ab791SAndreas Gruenbacher 			   atomic_read(&device->ap_bio_cnt),
298a6b32bc3SAndreas Gruenbacher 			   first_peer_device(device)->connection->epochs,
299e9526580SPhilipp Reisner 			   write_ordering_chars[device->resource->write_ordering]
300b411b363SPhilipp Reisner 			);
30118edc0b9SLars Ellenberg 			seq_printf(seq, " oos:%llu\n",
30218edc0b9SLars Ellenberg 				   Bit2KB((unsigned long long)
303b30ab791SAndreas Gruenbacher 					   drbd_bm_total_weight(device)));
304b411b363SPhilipp Reisner 		}
305a5655dacSLars Ellenberg 		if (state.conn == C_SYNC_SOURCE ||
306a5655dacSLars Ellenberg 		    state.conn == C_SYNC_TARGET ||
307a5655dacSLars Ellenberg 		    state.conn == C_VERIFY_S ||
308a5655dacSLars Ellenberg 		    state.conn == C_VERIFY_T)
309a5655dacSLars Ellenberg 			drbd_syncer_progress(device, seq, state);
310b411b363SPhilipp Reisner 
311183ece30SRoland Kammerer 		if (drbd_proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) {
312b30ab791SAndreas Gruenbacher 			lc_seq_printf_stats(seq, device->resync);
313b30ab791SAndreas Gruenbacher 			lc_seq_printf_stats(seq, device->act_log);
314b30ab791SAndreas Gruenbacher 			put_ldev(device);
315b411b363SPhilipp Reisner 		}
316ad3fee79SLars Ellenberg 
317183ece30SRoland Kammerer 		if (drbd_proc_details >= 2)
318ad3fee79SLars Ellenberg 			seq_printf(seq, "\tblocked on activity log: %d\n", atomic_read(&device->ap_actlog_cnt));
319b411b363SPhilipp Reisner 	}
320c141ebdaSPhilipp Reisner 	rcu_read_unlock();
321b411b363SPhilipp Reisner 
322b411b363SPhilipp Reisner 	return 0;
323b411b363SPhilipp Reisner }
324