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
49fbe0d91ca32243b3471ddd5fc50f954785c71a82Rashika Kheriastatic void 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);
55fc251d5c2466413fdd6851e6c3f63e9851bf9d84Lars 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
63a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenbergstatic void drbd_get_syncer_progress(struct drbd_device *device,
64a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		union drbd_dev_state state, unsigned long *rs_total,
65a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		unsigned long *bits_left, unsigned int *per_mil_done)
66a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg{
67a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	/* this is to break it at compile time when we change that, in case we
68a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	 * want to support more than (1<<32) bits on a 32bit arch. */
69a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	typecheck(unsigned long, device->rs_total);
70a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	*rs_total = device->rs_total;
71a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg
72a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	/* note: both rs_total and rs_left are in bits, i.e. in
73a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	 * units of BM_BLOCK_SIZE.
74a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	 * for the percentage, we don't care. */
75a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg
76a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
77a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		*bits_left = device->ov_left;
78a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	else
79a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		*bits_left = drbd_bm_total_weight(device) - device->rs_failed;
80a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	/* >> 10 to prevent overflow,
81a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	 * +1 to prevent division by zero */
82a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	if (*bits_left > *rs_total) {
83a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		/* D'oh. Maybe a logic bug somewhere.  More likely just a race
84a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 * between state change and reset of rs_total.
85a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 */
86a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		*bits_left = *rs_total;
87a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		*per_mil_done = *rs_total ? 0 : 1000;
88a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	} else {
89a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		/* Make sure the division happens in long context.
90a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 * We allow up to one petabyte storage right now,
91a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 * at a granularity of 4k per bit that is 2**38 bits.
92a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 * After shift right and multiplication by 1000,
93a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 * this should still fit easily into a 32bit long,
94a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 * so we don't need a 64bit division on 32bit arch.
95a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 * Note: currently we don't support such large bitmaps on 32bit
96a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 * arch anyways, but no harm done to be prepared for it here.
97a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		 */
98a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		unsigned int shift = *rs_total > UINT_MAX ? 16 : 10;
99a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		unsigned long left = *bits_left >> shift;
100a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		unsigned long total = 1UL + (*rs_total >> shift);
101a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		unsigned long tmp = 1000UL - left * 1000UL/total;
102a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		*per_mil_done = tmp;
103a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	}
104a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg}
105a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg
106a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg
107b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner/*lge
108b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner * progress bars shamelessly adapted from driver/md/md.c
109b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner * output looks like
110b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner *	[=====>..............] 33.5% (23456/123456)
111b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner *	finish: 2:20:20 speed: 6,345 (6,456) K/sec
112b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner */
113a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenbergstatic void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq,
114a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		union drbd_dev_state state)
115b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner{
116a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	unsigned long db, dt, dbdt, rt, rs_total, rs_left;
117b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	unsigned int res;
118b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	int i, x, y;
1191d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	int stalled = 0;
120b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
121a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	drbd_get_syncer_progress(device, state, &rs_total, &rs_left, &res);
122b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
123b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	x = res/50;
124b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	y = 20-x;
125b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "\t[");
126b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	for (i = 1; i < x; i++)
127b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		seq_printf(seq, "=");
128b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, ">");
129b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	for (i = 0; i < y; i++)
130b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		seq_printf(seq, ".");
131b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "] ");
132b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
133a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
1345f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf(seq, "verified:");
1355f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	else
1365f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf(seq, "sync'ed:");
1375f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
1385f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg
1394b0715f09655e76ca24c35a9e25e7c464c2f7346Lars Ellenberg	/* if more than a few GB, display in MB */
140a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	if (rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
1414b0715f09655e76ca24c35a9e25e7c464c2f7346Lars Ellenberg		seq_printf(seq, "(%lu/%lu)M",
142b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			    (unsigned long) Bit2KB(rs_left >> 10),
143a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			    (unsigned long) Bit2KB(rs_total >> 10));
144b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	else
145590001c229e86a0adab4a61a6d668940d7ce5299Philipp Reisner		seq_printf(seq, "(%lu/%lu)K",
146b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			    (unsigned long) Bit2KB(rs_left),
147a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			    (unsigned long) Bit2KB(rs_total));
148b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
149590001c229e86a0adab4a61a6d668940d7ce5299Philipp Reisner	seq_printf(seq, "\n\t");
150590001c229e86a0adab4a61a6d668940d7ce5299Philipp Reisner
151b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	/* see drivers/md/md.c
152b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * We do not want to overflow, so the order of operands and
153b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * the * 100 / 100 trick are important. We do a +1 to be
154b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * safe against division by zero. We only estimate anyway.
155b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 *
156b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * dt: time from mark until now
157b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * db: blocks written from mark until now
158b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * rt: remaining time
159b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 */
1601d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	/* Rolling marks. last_mark+1 may just now be modified.  last_mark+2 is
1611d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
1621d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
163439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	/* ------------------------ ~18s average ------------------------ */
164b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher	i = (device->rs_last_mark + 2) % DRBD_SYNC_MARKS;
165b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher	dt = (jiffies - device->rs_mark_time[i]) / HZ;
1669ae472605ad333d4db07da95cc42c68063d2cc0dLars Ellenberg	if (dt > 180)
1671d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg		stalled = 1;
168b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
169b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	if (!dt)
170b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		dt++;
171b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher	db = device->rs_mark_left[i] - rs_left;
172b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
173b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
174b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "finish: %lu:%02lu:%02lu",
175b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		rt / 3600, (rt % 3600) / 60, rt % 60);
176b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
177b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	dbdt = Bit2KB(db/dt);
178439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf(seq, " speed: ");
179439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf_with_thousands_grouping(seq, dbdt);
180439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf(seq, " (");
181439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	/* ------------------------- ~3s average ------------------------ */
182439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	if (proc_details >= 1) {
183439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		/* this is what drbd_rs_should_slow_down() uses */
184b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher		i = (device->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
185b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher		dt = (jiffies - device->rs_mark_time[i]) / HZ;
186439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		if (!dt)
187439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg			dt++;
188b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher		db = device->rs_mark_left[i] - rs_left;
189439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		dbdt = Bit2KB(db/dt);
190439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		seq_printf_with_thousands_grouping(seq, dbdt);
191439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg		seq_printf(seq, " -- ");
192439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	}
193b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
194439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	/* --------------------- long term average ---------------------- */
195b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	/* mean speed since syncer started
196b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 * we do account for PausedSync periods */
197b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher	dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
1982265769531afe267f864111c103b04b4427720b6Dan Carpenter	if (dt == 0)
199b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		dt = 1;
200a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	db = rs_total - rs_left;
201b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	dbdt = Bit2KB(db/dt);
202439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf_with_thousands_grouping(seq, dbdt);
203439d595379f87ec95249da21122eb085866f8ba9Lars Ellenberg	seq_printf(seq, ")");
204b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
205a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	if (state.conn == C_SYNC_TARGET ||
206a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	    state.conn == C_VERIFY_S) {
2075f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf(seq, " want: ");
208b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher		seq_printf_with_thousands_grouping(seq, device->c_sync_rate);
2091d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	}
2101d7734a0df02ff5068ff8baa1447c7baee601db1Lars Ellenberg	seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
2115f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg
2125f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	if (proc_details >= 1) {
2135f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		/* 64 bit:
2145f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		 * we convert to sectors in the display below. */
215b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher		unsigned long bm_bits = drbd_bm_bits(device);
2164896e8c1b8fb7e46a65a6676e271fc047a260a3eLars Ellenberg		unsigned long bit_pos;
21758ffa580a748dd16b1e5ab260bea39cdbd1e94efLars Ellenberg		unsigned long long stop_sector = 0;
218a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		if (state.conn == C_VERIFY_S ||
219a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		    state.conn == C_VERIFY_T) {
220b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			bit_pos = bm_bits - device->ov_left;
221b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			if (verify_can_do_stop_sector(device))
222b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher				stop_sector = device->ov_stop_sector;
22358ffa580a748dd16b1e5ab260bea39cdbd1e94efLars Ellenberg		} else
224b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			bit_pos = device->bm_resync_fo;
2255f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		/* Total sectors may be slightly off for oddly
2265f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		 * sized devices. So what. */
2275f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg		seq_printf(seq,
22858ffa580a748dd16b1e5ab260bea39cdbd1e94efLars Ellenberg			"\t%3d%% sector pos: %llu/%llu",
2295f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg			(int)(bit_pos / (bm_bits/100+1)),
2304896e8c1b8fb7e46a65a6676e271fc047a260a3eLars Ellenberg			(unsigned long long)bit_pos * BM_SECT_PER_BIT,
2314896e8c1b8fb7e46a65a6676e271fc047a260a3eLars Ellenberg			(unsigned long long)bm_bits * BM_SECT_PER_BIT);
23258ffa580a748dd16b1e5ab260bea39cdbd1e94efLars Ellenberg		if (stop_sector != 0 && stop_sector != ULLONG_MAX)
23358ffa580a748dd16b1e5ab260bea39cdbd1e94efLars Ellenberg			seq_printf(seq, " stop sector: %llu", stop_sector);
23458ffa580a748dd16b1e5ab260bea39cdbd1e94efLars Ellenberg		seq_printf(seq, "\n");
2355f9915bbb8e0975ce99f893c29b8e89100b33399Lars Ellenberg	}
236b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner}
237b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
238b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisnerstatic int drbd_seq_show(struct seq_file *seq, void *v)
239b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner{
24081a5d60ecfe1d94627abb54810445f0fd5892f42Philipp Reisner	int i, prev_i = -1;
241b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	const char *sn;
242b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher	struct drbd_device *device;
24344ed167da74825bfb7950d45a4f83bce3e84921cPhilipp Reisner	struct net_conf *nc;
244a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg	union drbd_dev_state state;
24544ed167da74825bfb7950d45a4f83bce3e84921cPhilipp Reisner	char wp;
246b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
247b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	static char write_ordering_chars[] = {
248b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		[WO_none] = 'n',
249b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		[WO_drain_io] = 'd',
250b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		[WO_bdev_flush] = 'f',
251b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	};
252b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
253b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
254b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		   API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
255b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
256b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	/*
257b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  cs .. connection state
258b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ro .. node role (local/remote)
259b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ds .. disk state (local/remote)
260b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	     protocol
261b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	     various flags
262b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ns .. network send
263b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  nr .. network receive
264b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  dw .. disk write
265b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  dr .. disk read
266b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  al .. activity log write count
267b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  bm .. bitmap update write count
268b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  pe .. pending (waiting for ack or data reply)
269b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ua .. unack'd (still need to send ack or data reply)
270b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ap .. application requests accepted, but not yet completed
271b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
272b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	  wo .. write ordering mode currently in use
273b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	 oos .. known out-of-sync kB
274b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	*/
275b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
276c141ebda031a0550d75634f7c94f7c85c2d5c9f5Philipp Reisner	rcu_read_lock();
27705a10ec7900dbdba008a24bf56b3490c4b568d2cAndreas Gruenbacher	idr_for_each_entry(&drbd_devices, device, i) {
27881a5d60ecfe1d94627abb54810445f0fd5892f42Philipp Reisner		if (prev_i != i - 1)
279b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			seq_printf(seq, "\n");
28081a5d60ecfe1d94627abb54810445f0fd5892f42Philipp Reisner		prev_i = i;
281b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
282a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		state = device->state;
283a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		sn = drbd_conn_str(state.conn);
284b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
285a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		if (state.conn == C_STANDALONE &&
286a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		    state.disk == D_DISKLESS &&
287a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		    state.role == R_SECONDARY) {
288b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
289b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		} else {
290b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			/* reset device->congestion_reason */
291b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			bdi_rw_congested(&device->rq_queue->backing_dev_info);
2928a943170711b7a4d63528ea8eb6a41cc91e79309Lars Ellenberg
293a6b32bc3cebd3fb6848c526763733b9dbc389c02Andreas Gruenbacher			nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
29444ed167da74825bfb7950d45a4f83bce3e84921cPhilipp Reisner			wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
295b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			seq_printf(seq,
2960778286a133d2d3f81861a4e5db308e359583006Philipp Reisner			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
297b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
298b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
299b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			   i, sn,
300a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			   drbd_role_str(state.role),
301a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			   drbd_role_str(state.peer),
302a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			   drbd_disk_str(state.disk),
303a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			   drbd_disk_str(state.pdsk),
30444ed167da74825bfb7950d45a4f83bce3e84921cPhilipp Reisner			   wp,
305b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   drbd_suspended(device) ? 's' : 'r',
306a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			   state.aftr_isp ? 'a' : '-',
307a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			   state.peer_isp ? 'p' : '-',
308a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			   state.user_isp ? 'u' : '-',
309b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   device->congestion_reason ?: '-',
310b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-',
311b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   device->send_cnt/2,
312b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   device->recv_cnt/2,
313b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   device->writ_cnt/2,
314b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   device->read_cnt/2,
315b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   device->al_writ_cnt,
316b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   device->bm_writ_cnt,
317b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   atomic_read(&device->local_cnt),
318b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   atomic_read(&device->ap_pending_cnt) +
319b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   atomic_read(&device->rs_pending_cnt),
320b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   atomic_read(&device->unacked_cnt),
321b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			   atomic_read(&device->ap_bio_cnt),
322a6b32bc3cebd3fb6848c526763733b9dbc389c02Andreas Gruenbacher			   first_peer_device(device)->connection->epochs,
323e952658020c5150ad4987d313e25e8e2fb38d529Philipp Reisner			   write_ordering_chars[device->resource->write_ordering]
324b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner			);
32518edc0b9d7dac2f74117a0bdb98f2e705eb74d82Lars Ellenberg			seq_printf(seq, " oos:%llu\n",
32618edc0b9d7dac2f74117a0bdb98f2e705eb74d82Lars Ellenberg				   Bit2KB((unsigned long long)
327b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher					   drbd_bm_total_weight(device)));
328b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		}
329a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		if (state.conn == C_SYNC_SOURCE ||
330a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		    state.conn == C_SYNC_TARGET ||
331a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		    state.conn == C_VERIFY_S ||
332a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg		    state.conn == C_VERIFY_T)
333a5655dac75b6c572e1ef430b61ad55245fffd523Lars Ellenberg			drbd_syncer_progress(device, seq, state);
334b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher
335b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher		if (proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) {
336b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			lc_seq_printf_stats(seq, device->resync);
337b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			lc_seq_printf_stats(seq, device->act_log);
338b30ab7913b0a7b1d3b1091c8cb3abb1a9f1e0824Andreas Gruenbacher			put_ldev(device);
339b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner		}
340ad3fee790088d36ad862e31535b5b99c25adeef4Lars Ellenberg
341ad3fee790088d36ad862e31535b5b99c25adeef4Lars Ellenberg		if (proc_details >= 2)
342ad3fee790088d36ad862e31535b5b99c25adeef4Lars Ellenberg			seq_printf(seq, "\tblocked on activity log: %d\n", atomic_read(&device->ap_actlog_cnt));
343b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	}
344c141ebda031a0550d75634f7c94f7c85c2d5c9f5Philipp Reisner	rcu_read_unlock();
345b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
346b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner	return 0;
347b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner}
348b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
349b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisnerstatic int drbd_proc_open(struct inode *inode, struct file *file)
350b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner{
351193d01532a730a53cbc74462799dbc43968b97fdAlexey Khoroshilov	int err;
352193d01532a730a53cbc74462799dbc43968b97fdAlexey Khoroshilov
353193d01532a730a53cbc74462799dbc43968b97fdAlexey Khoroshilov	if (try_module_get(THIS_MODULE)) {
354caa3db0e14cc301f07e758f4cadc36d4dead145aAndreas Gruenbacher		err = single_open(file, drbd_seq_show, NULL);
355193d01532a730a53cbc74462799dbc43968b97fdAlexey Khoroshilov		if (err)
356193d01532a730a53cbc74462799dbc43968b97fdAlexey Khoroshilov			module_put(THIS_MODULE);
357193d01532a730a53cbc74462799dbc43968b97fdAlexey Khoroshilov		return err;
358193d01532a730a53cbc74462799dbc43968b97fdAlexey Khoroshilov	}
3593da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg	return -ENODEV;
3603da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg}
3613da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg
3623da127fa887e5187ede702b835770634d705f8b2Lars Ellenbergstatic int drbd_proc_release(struct inode *inode, struct file *file)
3633da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg{
3643da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg	module_put(THIS_MODULE);
3653da127fa887e5187ede702b835770634d705f8b2Lars Ellenberg	return single_release(inode, file);
366b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner}
367b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner
368b411b3637fa71fce9cf2acf0639009500f5892fePhilipp Reisner/* PROC FS stuff end */
369