drbd_proc.c revision 81a5d60ecfe1d94627abb54810445f0fd5892f42
1b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner/*
2b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   drbd_proc.c
3b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
4b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
5b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
6b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
7b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   Copyright (C) 1999-2008, Philipp Reisner <philipp.reisner@linbit.com>.
8b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
9b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
10b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   drbd is free software; you can redistribute it and/or modify
11b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   it under the terms of the GNU General Public License as published by
12b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   the Free Software Foundation; either version 2, or (at your option)
13b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   any later version.
14b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
15b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   drbd is distributed in the hope that it will be useful,
16b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   but WITHOUT ANY WARRANTY; without even the implied warranty of
17b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   GNU General Public License for more details.
19b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
20b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   You should have received a copy of the GNU General Public License
21b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   along with drbd; see the file COPYING.  If not, write to
22b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
24b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner */
25b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
26b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner#include <linux/module.h>
27b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
28b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner#include <asm/uaccess.h>
29b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner#include <linux/fs.h>
30b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner#include <linux/file.h>
31b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner#include <linux/proc_fs.h>
32b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner#include <linux/seq_file.h>
33b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner#include <linux/drbd.h>
34b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner#include "drbd_int.h"
35b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
36b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisnerstatic int drbd_proc_open(struct inode *inode, struct file *file);
373da127fa887e5187ede702b835770634d705f8b2Lars Ellenbergstatic int drbd_proc_release(struct inode *inode, struct file *file);
38b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
39b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
40b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisnerstruct proc_dir_entry *drbd_proc;
417d4e9d0962cd0f6a30b01e256756dd10606dab30Emese Revfyconst struct file_operations drbd_proc_fops = {
42b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	.owner		= THIS_MODULE,
43b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	.open		= drbd_proc_open,
44b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	.read		= seq_read,
45b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	.llseek		= seq_lseek,
463da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg	.release	= drbd_proc_release,
47b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner};
48b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
49439d595379f87ec95249da21122eb085866f8ba9Lars Ellenbergvoid seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
50439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg{
51439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	/* v is in kB/sec. We don't expect TiByte/sec yet. */
52439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	if (unlikely(v >= 1000000)) {
53439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		/* cool: > GiByte/s */
54439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		seq_printf(seq, "%ld,", v / 1000000);
55439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		v /= 1000000;
56439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		seq_printf(seq, "%03ld,%03ld", v/1000, v % 1000);
57439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	} else if (likely(v >= 1000))
58439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		seq_printf(seq, "%ld,%03ld", v/1000, v % 1000);
59439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	else
60439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		seq_printf(seq, "%ld", v);
61439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg}
62b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
63b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner/*lge
64b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner * progress bars shamelessly adapted from driver/md/md.c
65b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner * output looks like
66b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner *	[=====>..............] 33.5% (23456/123456)
67b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner *	finish: 2:20:20 speed: 6,345 (6,456) K/sec
68b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner */
69b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisnerstatic void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
70b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner{
71b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	unsigned long db, dt, dbdt, rt, rs_left;
72b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	unsigned int res;
73b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	int i, x, y;
741d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	int stalled = 0;
75b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
76b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	drbd_get_syncer_progress(mdev, &rs_left, &res);
77b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
78b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	x = res/50;
79b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	y = 20-x;
80b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "\t[");
81b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	for (i = 1; i < x; i++)
82b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		seq_printf(seq, "=");
83b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, ">");
84b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	for (i = 0; i < y; i++)
85b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		seq_printf(seq, ".");
86b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "] ");
87b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
885f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
895f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf(seq, "verified:");
905f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	else
915f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf(seq, "sync'ed:");
925f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
935f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg
944b0715f09655e76ca24c35a9e25e7c464c2f7346Lars Ellenberg	/* if more than a few GB, display in MB */
954b0715f09655e76ca24c35a9e25e7c464c2f7346Lars Ellenberg	if (mdev->rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
964b0715f09655e76ca24c35a9e25e7c464c2f7346Lars Ellenberg		seq_printf(seq, "(%lu/%lu)M",
97b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			    (unsigned long) Bit2KB(rs_left >> 10),
98b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			    (unsigned long) Bit2KB(mdev->rs_total >> 10));
99b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	else
100e7f52dfb4f378ea1bbfd4476f4e8ba42f5fb332cLars Ellenberg		seq_printf(seq, "(%lu/%lu)K\n\t",
101b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			    (unsigned long) Bit2KB(rs_left),
102b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			    (unsigned long) Bit2KB(mdev->rs_total));
103b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
104b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	/* see drivers/md/md.c
105b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * We do not want to overflow, so the order of operands and
106b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * the * 100 / 100 trick are important. We do a +1 to be
107b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * safe against division by zero. We only estimate anyway.
108b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 *
109b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * dt: time from mark until now
110b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * db: blocks written from mark until now
111b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * rt: remaining time
112b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 */
1131d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	/* Rolling marks. last_mark+1 may just now be modified.  last_mark+2 is
1141d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
1151d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
116439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	/* ------------------------ ~18s average ------------------------ */
1171d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
1181d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
1191d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
1201d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg		stalled = 1;
121b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
122b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	if (!dt)
123b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		dt++;
1241d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	db = mdev->rs_mark_left[i] - rs_left;
125b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
126b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
127b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "finish: %lu:%02lu:%02lu",
128b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		rt / 3600, (rt % 3600) / 60, rt % 60);
129b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
130b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	dbdt = Bit2KB(db/dt);
131439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf(seq, " speed: ");
132439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf_with_thousands_grouping(seq, dbdt);
133439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf(seq, " (");
134439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	/* ------------------------- ~3s average ------------------------ */
135439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	if (proc_details >= 1) {
136439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		/* this is what drbd_rs_should_slow_down() uses */
137439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
138439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
139439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		if (!dt)
140439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg			dt++;
141439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		db = mdev->rs_mark_left[i] - rs_left;
142439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		dbdt = Bit2KB(db/dt);
143439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		seq_printf_with_thousands_grouping(seq, dbdt);
144439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		seq_printf(seq, " -- ");
145439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	}
146b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
147439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	/* --------------------- long term average ---------------------- */
148b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	/* mean speed since syncer started
149b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * we do account for PausedSync periods */
150b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
1512265769531afe267f864111c103b04b4427720b6Dan Carpenter	if (dt == 0)
152b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		dt = 1;
153b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	db = mdev->rs_total - rs_left;
154b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	dbdt = Bit2KB(db/dt);
155439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf_with_thousands_grouping(seq, dbdt);
156439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf(seq, ")");
157b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
1582649f0809f55e4df98c333a2b85c6fc8fee04804Lars Ellenberg	if (mdev->state.conn == C_SYNC_TARGET ||
1592649f0809f55e4df98c333a2b85c6fc8fee04804Lars Ellenberg	    mdev->state.conn == C_VERIFY_S) {
1605f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf(seq, " want: ");
1615f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf_with_thousands_grouping(seq, mdev->c_sync_rate);
1621d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	}
1631d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
1645f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg
1655f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	if (proc_details >= 1) {
1665f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		/* 64 bit:
1675f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		 * we convert to sectors in the display below. */
1684896e8c1b8fb7e46a65a6676e271fc047a260a3eLars Ellenberg		unsigned long bm_bits = drbd_bm_bits(mdev);
1694896e8c1b8fb7e46a65a6676e271fc047a260a3eLars Ellenberg		unsigned long bit_pos;
1705f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		if (mdev->state.conn == C_VERIFY_S ||
1715f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		    mdev->state.conn == C_VERIFY_T)
1725f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg			bit_pos = bm_bits - mdev->ov_left;
1735f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		else
1745f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg			bit_pos = mdev->bm_resync_fo;
1755f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		/* Total sectors may be slightly off for oddly
1765f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		 * sized devices. So what. */
1775f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf(seq,
1785f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg			"\t%3d%% sector pos: %llu/%llu\n",
1795f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg			(int)(bit_pos / (bm_bits/100+1)),
1804896e8c1b8fb7e46a65a6676e271fc047a260a3eLars Ellenberg			(unsigned long long)bit_pos * BM_SECT_PER_BIT,
1814896e8c1b8fb7e46a65a6676e271fc047a260a3eLars Ellenberg			(unsigned long long)bm_bits * BM_SECT_PER_BIT);
1825f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	}
183b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner}
184b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
185b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisnerstatic void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
186b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner{
187b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
188b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
189b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "%5d %s %s\n", bme->rs_left,
190b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		   bme->flags & BME_NO_WRITES ? "NO_WRITES" : "---------",
191b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		   bme->flags & BME_LOCKED ? "LOCKED" : "------"
192b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		   );
193b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner}
194b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
195b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisnerstatic int drbd_seq_show(struct seq_file *seq, void *v)
196b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner{
19781a5d60ecfe1d94627abb54810445f0fd5892f42Philipp Reisner	int i, prev_i = -1;
198b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	const char *sn;
199b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	struct drbd_conf *mdev;
200b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
201b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	static char write_ordering_chars[] = {
202b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		[WO_none] = 'n',
203b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		[WO_drain_io] = 'd',
204b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		[WO_bdev_flush] = 'f',
205b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	};
206b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
207b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
208b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		   API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
209b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
210b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	/*
211b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  cs .. connection state
212b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ro .. node role (local/remote)
213b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ds .. disk state (local/remote)
214b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	     protocol
215b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	     various flags
216b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ns .. network send
217b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  nr .. network receive
218b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  dw .. disk write
219b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  dr .. disk read
220b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  al .. activity log write count
221b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  bm .. bitmap update write count
222b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  pe .. pending (waiting for ack or data reply)
223b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ua .. unack'd (still need to send ack or data reply)
224b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ap .. application requests accepted, but not yet completed
225b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
226b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  wo .. write ordering mode currently in use
227b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 oos .. known out-of-sync kB
228b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	*/
229b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
23081a5d60ecfe1d94627abb54810445f0fd5892f42Philipp Reisner	idr_for_each_entry(&minors, mdev, i) {
23181a5d60ecfe1d94627abb54810445f0fd5892f42Philipp Reisner		if (prev_i != i - 1)
232b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			seq_printf(seq, "\n");
23381a5d60ecfe1d94627abb54810445f0fd5892f42Philipp Reisner		prev_i = i;
234b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
235b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		sn = drbd_conn_str(mdev->state.conn);
236b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
237b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		if (mdev->state.conn == C_STANDALONE &&
238b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		    mdev->state.disk == D_DISKLESS &&
239b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		    mdev->state.role == R_SECONDARY) {
240b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
241b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		} else {
242b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			seq_printf(seq,
2430778286a133d2d3f81861a4e5db308e359583006Philipp Reisner			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
244b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
245b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
246b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   i, sn,
247b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   drbd_role_str(mdev->state.role),
248b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   drbd_role_str(mdev->state.peer),
249b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   drbd_disk_str(mdev->state.disk),
250b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   drbd_disk_str(mdev->state.pdsk),
25189e58e755e37137135c28a90c93be1b28faff485Philipp Reisner			   (mdev->tconn->net_conf == NULL ? ' ' :
25289e58e755e37137135c28a90c93be1b28faff485Philipp Reisner			    (mdev->tconn->net_conf->wire_protocol - DRBD_PROT_A+'A')),
253fb22c402ffdf61dd121795b5809de587185d5240Philipp Reisner			   is_susp(mdev->state) ? 's' : 'r',
254b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->state.aftr_isp ? 'a' : '-',
255b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->state.peer_isp ? 'p' : '-',
256b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->state.user_isp ? 'u' : '-',
257b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->congestion_reason ?: '-',
2580778286a133d2d3f81861a4e5db308e359583006Philipp Reisner			   test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
259b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->send_cnt/2,
260b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->recv_cnt/2,
261b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->writ_cnt/2,
262b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->read_cnt/2,
263b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->al_writ_cnt,
264b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->bm_writ_cnt,
265b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   atomic_read(&mdev->local_cnt),
266b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   atomic_read(&mdev->ap_pending_cnt) +
267b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   atomic_read(&mdev->rs_pending_cnt),
268b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   atomic_read(&mdev->unacked_cnt),
269b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   atomic_read(&mdev->ap_bio_cnt),
270b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   mdev->epochs,
271b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   write_ordering_chars[mdev->write_ordering]
272b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			);
27318edc0b9d7dac2f74117a0bdb98f2e705eb74d82Lars Ellenberg			seq_printf(seq, " oos:%llu\n",
27418edc0b9d7dac2f74117a0bdb98f2e705eb74d82Lars Ellenberg				   Bit2KB((unsigned long long)
27518edc0b9d7dac2f74117a0bdb98f2e705eb74d82Lars Ellenberg					   drbd_bm_total_weight(mdev)));
276b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		}
277b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		if (mdev->state.conn == C_SYNC_SOURCE ||
278439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		    mdev->state.conn == C_SYNC_TARGET ||
279439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		    mdev->state.conn == C_VERIFY_S ||
280439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		    mdev->state.conn == C_VERIFY_T)
281b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			drbd_syncer_progress(mdev, seq);
282b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
283b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
284b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			lc_seq_printf_stats(seq, mdev->resync);
285b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			lc_seq_printf_stats(seq, mdev->act_log);
286b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			put_ldev(mdev);
287b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		}
288b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
289b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		if (proc_details >= 2) {
290b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			if (mdev->resync) {
291b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner				lc_seq_dump_details(seq, mdev->resync, "rs_left",
292b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner					resync_dump_detail);
293b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			}
294b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		}
295b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	}
296b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
297b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	return 0;
298b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner}
299b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
300b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisnerstatic int drbd_proc_open(struct inode *inode, struct file *file)
301b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner{
3023da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg	if (try_module_get(THIS_MODULE))
3033da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg		return single_open(file, drbd_seq_show, PDE(inode)->data);
3043da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg	return -ENODEV;
3053da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg}
3063da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg
3073da127fa887e5187ede702b835770634d705f8b2Lars Ellenbergstatic int drbd_proc_release(struct inode *inode, struct file *file)
3083da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg{
3093da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg	module_put(THIS_MODULE);
3103da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg	return single_release(inode, file);
311b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner}
312b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
313b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner/* PROC FS stuff end */
314