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