xref: /openbmc/linux/drivers/block/drbd/drbd_proc.c (revision 95e9fd10)
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 <philipp.reisner@linbit.com>.
8    Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
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 			/* reset mdev->congestion_reason */
249 			bdi_rw_congested(&mdev->rq_queue->backing_dev_info);
250 
251 			seq_printf(seq,
252 			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
253 			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
254 			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
255 			   i, sn,
256 			   drbd_role_str(mdev->state.role),
257 			   drbd_role_str(mdev->state.peer),
258 			   drbd_disk_str(mdev->state.disk),
259 			   drbd_disk_str(mdev->state.pdsk),
260 			   (mdev->net_conf == NULL ? ' ' :
261 			    (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
262 			   is_susp(mdev->state) ? 's' : 'r',
263 			   mdev->state.aftr_isp ? 'a' : '-',
264 			   mdev->state.peer_isp ? 'p' : '-',
265 			   mdev->state.user_isp ? 'u' : '-',
266 			   mdev->congestion_reason ?: '-',
267 			   test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
268 			   mdev->send_cnt/2,
269 			   mdev->recv_cnt/2,
270 			   mdev->writ_cnt/2,
271 			   mdev->read_cnt/2,
272 			   mdev->al_writ_cnt,
273 			   mdev->bm_writ_cnt,
274 			   atomic_read(&mdev->local_cnt),
275 			   atomic_read(&mdev->ap_pending_cnt) +
276 			   atomic_read(&mdev->rs_pending_cnt),
277 			   atomic_read(&mdev->unacked_cnt),
278 			   atomic_read(&mdev->ap_bio_cnt),
279 			   mdev->epochs,
280 			   write_ordering_chars[mdev->write_ordering]
281 			);
282 			seq_printf(seq, " oos:%llu\n",
283 				   Bit2KB((unsigned long long)
284 					   drbd_bm_total_weight(mdev)));
285 		}
286 		if (mdev->state.conn == C_SYNC_SOURCE ||
287 		    mdev->state.conn == C_SYNC_TARGET ||
288 		    mdev->state.conn == C_VERIFY_S ||
289 		    mdev->state.conn == C_VERIFY_T)
290 			drbd_syncer_progress(mdev, seq);
291 
292 		if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
293 			lc_seq_printf_stats(seq, mdev->resync);
294 			lc_seq_printf_stats(seq, mdev->act_log);
295 			put_ldev(mdev);
296 		}
297 
298 		if (proc_details >= 2) {
299 			if (mdev->resync) {
300 				lc_seq_dump_details(seq, mdev->resync, "rs_left",
301 					resync_dump_detail);
302 			}
303 		}
304 	}
305 
306 	return 0;
307 }
308 
309 static int drbd_proc_open(struct inode *inode, struct file *file)
310 {
311 	if (try_module_get(THIS_MODULE))
312 		return single_open(file, drbd_seq_show, PDE(inode)->data);
313 	return -ENODEV;
314 }
315 
316 static int drbd_proc_release(struct inode *inode, struct file *file)
317 {
318 	module_put(THIS_MODULE);
319 	return single_release(inode, file);
320 }
321 
322 /* PROC FS stuff end */
323