• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/block/drbd/
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
36static int drbd_proc_open(struct inode *inode, struct file *file);
37
38
39struct proc_dir_entry *drbd_proc;
40const struct file_operations drbd_proc_fops = {
41	.owner		= THIS_MODULE,
42	.open		= drbd_proc_open,
43	.read		= seq_read,
44	.llseek		= seq_lseek,
45	.release	= single_release,
46};
47
48
49/*lge
50 * progress bars shamelessly adapted from driver/md/md.c
51 * output looks like
52 *	[=====>..............] 33.5% (23456/123456)
53 *	finish: 2:20:20 speed: 6,345 (6,456) K/sec
54 */
55static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
56{
57	unsigned long db, dt, dbdt, rt, rs_left;
58	unsigned int res;
59	int i, x, y;
60
61	drbd_get_syncer_progress(mdev, &rs_left, &res);
62
63	x = res/50;
64	y = 20-x;
65	seq_printf(seq, "\t[");
66	for (i = 1; i < x; i++)
67		seq_printf(seq, "=");
68	seq_printf(seq, ">");
69	for (i = 0; i < y; i++)
70		seq_printf(seq, ".");
71	seq_printf(seq, "] ");
72
73	seq_printf(seq, "sync'ed:%3u.%u%% ", res / 10, res % 10);
74	/* if more than 1 GB display in MB */
75	if (mdev->rs_total > 0x100000L)
76		seq_printf(seq, "(%lu/%lu)M\n\t",
77			    (unsigned long) Bit2KB(rs_left >> 10),
78			    (unsigned long) Bit2KB(mdev->rs_total >> 10));
79	else
80		seq_printf(seq, "(%lu/%lu)K\n\t",
81			    (unsigned long) Bit2KB(rs_left),
82			    (unsigned long) Bit2KB(mdev->rs_total));
83
84	/* see drivers/md/md.c
85	 * We do not want to overflow, so the order of operands and
86	 * the * 100 / 100 trick are important. We do a +1 to be
87	 * safe against division by zero. We only estimate anyway.
88	 *
89	 * dt: time from mark until now
90	 * db: blocks written from mark until now
91	 * rt: remaining time
92	 */
93	dt = (jiffies - mdev->rs_mark_time) / HZ;
94
95	if (dt > 20) {
96		/* if we made no update to rs_mark_time for too long,
97		 * we are stalled. show that. */
98		seq_printf(seq, "stalled\n");
99		return;
100	}
101
102	if (!dt)
103		dt++;
104	db = mdev->rs_mark_left - rs_left;
105	rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
106
107	seq_printf(seq, "finish: %lu:%02lu:%02lu",
108		rt / 3600, (rt % 3600) / 60, rt % 60);
109
110	/* current speed average over (SYNC_MARKS * SYNC_MARK_STEP) jiffies */
111	dbdt = Bit2KB(db/dt);
112	if (dbdt > 1000)
113		seq_printf(seq, " speed: %ld,%03ld",
114			dbdt/1000, dbdt % 1000);
115	else
116		seq_printf(seq, " speed: %ld", dbdt);
117
118	/* mean speed since syncer started
119	 * we do account for PausedSync periods */
120	dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
121	if (dt <= 0)
122		dt = 1;
123	db = mdev->rs_total - rs_left;
124	dbdt = Bit2KB(db/dt);
125	if (dbdt > 1000)
126		seq_printf(seq, " (%ld,%03ld)",
127			dbdt/1000, dbdt % 1000);
128	else
129		seq_printf(seq, " (%ld)", dbdt);
130
131	seq_printf(seq, " K/sec\n");
132}
133
134static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
135{
136	struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
137
138	seq_printf(seq, "%5d %s %s\n", bme->rs_left,
139		   bme->flags & BME_NO_WRITES ? "NO_WRITES" : "---------",
140		   bme->flags & BME_LOCKED ? "LOCKED" : "------"
141		   );
142}
143
144static int drbd_seq_show(struct seq_file *seq, void *v)
145{
146	int i, hole = 0;
147	const char *sn;
148	struct drbd_conf *mdev;
149
150	static char write_ordering_chars[] = {
151		[WO_none] = 'n',
152		[WO_drain_io] = 'd',
153		[WO_bdev_flush] = 'f',
154		[WO_bio_barrier] = 'b',
155	};
156
157	seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
158		   API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
159
160	/*
161	  cs .. connection state
162	  ro .. node role (local/remote)
163	  ds .. disk state (local/remote)
164	     protocol
165	     various flags
166	  ns .. network send
167	  nr .. network receive
168	  dw .. disk write
169	  dr .. disk read
170	  al .. activity log write count
171	  bm .. bitmap update write count
172	  pe .. pending (waiting for ack or data reply)
173	  ua .. unack'd (still need to send ack or data reply)
174	  ap .. application requests accepted, but not yet completed
175	  ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
176	  wo .. write ordering mode currently in use
177	 oos .. known out-of-sync kB
178	*/
179
180	for (i = 0; i < minor_count; i++) {
181		mdev = minor_to_mdev(i);
182		if (!mdev) {
183			hole = 1;
184			continue;
185		}
186		if (hole) {
187			hole = 0;
188			seq_printf(seq, "\n");
189		}
190
191		sn = drbd_conn_str(mdev->state.conn);
192
193		if (mdev->state.conn == C_STANDALONE &&
194		    mdev->state.disk == D_DISKLESS &&
195		    mdev->state.role == R_SECONDARY) {
196			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
197		} else {
198			seq_printf(seq,
199			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c\n"
200			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
201			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
202			   i, sn,
203			   drbd_role_str(mdev->state.role),
204			   drbd_role_str(mdev->state.peer),
205			   drbd_disk_str(mdev->state.disk),
206			   drbd_disk_str(mdev->state.pdsk),
207			   (mdev->net_conf == NULL ? ' ' :
208			    (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
209			   mdev->state.susp ? 's' : 'r',
210			   mdev->state.aftr_isp ? 'a' : '-',
211			   mdev->state.peer_isp ? 'p' : '-',
212			   mdev->state.user_isp ? 'u' : '-',
213			   mdev->congestion_reason ?: '-',
214			   mdev->send_cnt/2,
215			   mdev->recv_cnt/2,
216			   mdev->writ_cnt/2,
217			   mdev->read_cnt/2,
218			   mdev->al_writ_cnt,
219			   mdev->bm_writ_cnt,
220			   atomic_read(&mdev->local_cnt),
221			   atomic_read(&mdev->ap_pending_cnt) +
222			   atomic_read(&mdev->rs_pending_cnt),
223			   atomic_read(&mdev->unacked_cnt),
224			   atomic_read(&mdev->ap_bio_cnt),
225			   mdev->epochs,
226			   write_ordering_chars[mdev->write_ordering]
227			);
228			seq_printf(seq, " oos:%lu\n",
229				   Bit2KB(drbd_bm_total_weight(mdev)));
230		}
231		if (mdev->state.conn == C_SYNC_SOURCE ||
232		    mdev->state.conn == C_SYNC_TARGET)
233			drbd_syncer_progress(mdev, seq);
234
235		if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
236			seq_printf(seq, "\t%3d%%      %lu/%lu\n",
237				   (int)((mdev->rs_total-mdev->ov_left) /
238					 (mdev->rs_total/100+1)),
239				   mdev->rs_total - mdev->ov_left,
240				   mdev->rs_total);
241
242		if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
243			lc_seq_printf_stats(seq, mdev->resync);
244			lc_seq_printf_stats(seq, mdev->act_log);
245			put_ldev(mdev);
246		}
247
248		if (proc_details >= 2) {
249			if (mdev->resync) {
250				lc_seq_dump_details(seq, mdev->resync, "rs_left",
251					resync_dump_detail);
252			}
253		}
254	}
255
256	return 0;
257}
258
259static int drbd_proc_open(struct inode *inode, struct file *file)
260{
261	return single_open(file, drbd_seq_show, PDE(inode)->data);
262}
263
264/* PROC FS stuff end */
265