xref: /openbmc/linux/drivers/block/drbd/drbd_proc.c (revision d0b73b48)
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 		unsigned long long stop_sector = 0;
171 		if (mdev->state.conn == C_VERIFY_S ||
172 		    mdev->state.conn == C_VERIFY_T) {
173 			bit_pos = bm_bits - mdev->ov_left;
174 			if (verify_can_do_stop_sector(mdev))
175 				stop_sector = mdev->ov_stop_sector;
176 		} else
177 			bit_pos = mdev->bm_resync_fo;
178 		/* Total sectors may be slightly off for oddly
179 		 * sized devices. So what. */
180 		seq_printf(seq,
181 			"\t%3d%% sector pos: %llu/%llu",
182 			(int)(bit_pos / (bm_bits/100+1)),
183 			(unsigned long long)bit_pos * BM_SECT_PER_BIT,
184 			(unsigned long long)bm_bits * BM_SECT_PER_BIT);
185 		if (stop_sector != 0 && stop_sector != ULLONG_MAX)
186 			seq_printf(seq, " stop sector: %llu", stop_sector);
187 		seq_printf(seq, "\n");
188 	}
189 }
190 
191 static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
192 {
193 	struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
194 
195 	seq_printf(seq, "%5d %s %s\n", bme->rs_left,
196 		   bme->flags & BME_NO_WRITES ? "NO_WRITES" : "---------",
197 		   bme->flags & BME_LOCKED ? "LOCKED" : "------"
198 		   );
199 }
200 
201 static int drbd_seq_show(struct seq_file *seq, void *v)
202 {
203 	int i, prev_i = -1;
204 	const char *sn;
205 	struct drbd_conf *mdev;
206 	struct net_conf *nc;
207 	char wp;
208 
209 	static char write_ordering_chars[] = {
210 		[WO_none] = 'n',
211 		[WO_drain_io] = 'd',
212 		[WO_bdev_flush] = 'f',
213 	};
214 
215 	seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
216 		   API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
217 
218 	/*
219 	  cs .. connection state
220 	  ro .. node role (local/remote)
221 	  ds .. disk state (local/remote)
222 	     protocol
223 	     various flags
224 	  ns .. network send
225 	  nr .. network receive
226 	  dw .. disk write
227 	  dr .. disk read
228 	  al .. activity log write count
229 	  bm .. bitmap update write count
230 	  pe .. pending (waiting for ack or data reply)
231 	  ua .. unack'd (still need to send ack or data reply)
232 	  ap .. application requests accepted, but not yet completed
233 	  ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
234 	  wo .. write ordering mode currently in use
235 	 oos .. known out-of-sync kB
236 	*/
237 
238 	rcu_read_lock();
239 	idr_for_each_entry(&minors, mdev, i) {
240 		if (prev_i != i - 1)
241 			seq_printf(seq, "\n");
242 		prev_i = i;
243 
244 		sn = drbd_conn_str(mdev->state.conn);
245 
246 		if (mdev->state.conn == C_STANDALONE &&
247 		    mdev->state.disk == D_DISKLESS &&
248 		    mdev->state.role == R_SECONDARY) {
249 			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
250 		} else {
251 			/* reset mdev->congestion_reason */
252 			bdi_rw_congested(&mdev->rq_queue->backing_dev_info);
253 
254 			nc = rcu_dereference(mdev->tconn->net_conf);
255 			wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
256 			seq_printf(seq,
257 			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
258 			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
259 			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
260 			   i, sn,
261 			   drbd_role_str(mdev->state.role),
262 			   drbd_role_str(mdev->state.peer),
263 			   drbd_disk_str(mdev->state.disk),
264 			   drbd_disk_str(mdev->state.pdsk),
265 			   wp,
266 			   drbd_suspended(mdev) ? 's' : 'r',
267 			   mdev->state.aftr_isp ? 'a' : '-',
268 			   mdev->state.peer_isp ? 'p' : '-',
269 			   mdev->state.user_isp ? 'u' : '-',
270 			   mdev->congestion_reason ?: '-',
271 			   test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
272 			   mdev->send_cnt/2,
273 			   mdev->recv_cnt/2,
274 			   mdev->writ_cnt/2,
275 			   mdev->read_cnt/2,
276 			   mdev->al_writ_cnt,
277 			   mdev->bm_writ_cnt,
278 			   atomic_read(&mdev->local_cnt),
279 			   atomic_read(&mdev->ap_pending_cnt) +
280 			   atomic_read(&mdev->rs_pending_cnt),
281 			   atomic_read(&mdev->unacked_cnt),
282 			   atomic_read(&mdev->ap_bio_cnt),
283 			   mdev->tconn->epochs,
284 			   write_ordering_chars[mdev->tconn->write_ordering]
285 			);
286 			seq_printf(seq, " oos:%llu\n",
287 				   Bit2KB((unsigned long long)
288 					   drbd_bm_total_weight(mdev)));
289 		}
290 		if (mdev->state.conn == C_SYNC_SOURCE ||
291 		    mdev->state.conn == C_SYNC_TARGET ||
292 		    mdev->state.conn == C_VERIFY_S ||
293 		    mdev->state.conn == C_VERIFY_T)
294 			drbd_syncer_progress(mdev, seq);
295 
296 		if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
297 			lc_seq_printf_stats(seq, mdev->resync);
298 			lc_seq_printf_stats(seq, mdev->act_log);
299 			put_ldev(mdev);
300 		}
301 
302 		if (proc_details >= 2) {
303 			if (mdev->resync) {
304 				lc_seq_dump_details(seq, mdev->resync, "rs_left",
305 					resync_dump_detail);
306 			}
307 		}
308 	}
309 	rcu_read_unlock();
310 
311 	return 0;
312 }
313 
314 static int drbd_proc_open(struct inode *inode, struct file *file)
315 {
316 	if (try_module_get(THIS_MODULE))
317 		return single_open(file, drbd_seq_show, PDE(inode)->data);
318 	return -ENODEV;
319 }
320 
321 static int drbd_proc_release(struct inode *inode, struct file *file)
322 {
323 	module_put(THIS_MODULE);
324 	return single_release(inode, file);
325 }
326 
327 /* PROC FS stuff end */
328