blob: 3b10fa6cb039339a2301350862b7d87e95c6a0cb [file] [log] [blame]
Philipp Reisnerb411b362009-09-25 16:07:19 -07001/*
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
Philipp Reisnerb411b362009-09-25 16:07:19 -070026#include <linux/module.h>
27
28#include <asm/uaccess.h>
29#include <linux/fs.h>
30#include <linux/file.h>
Philipp Reisnerb411b362009-09-25 16:07:19 -070031#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);
Lars Ellenberg3da127f2010-11-24 10:33:02 +010037static int drbd_proc_release(struct inode *inode, struct file *file);
Philipp Reisnerb411b362009-09-25 16:07:19 -070038
39
40struct proc_dir_entry *drbd_proc;
Emese Revfy7d4e9d02009-12-14 00:59:30 +010041const struct file_operations drbd_proc_fops = {
Philipp Reisnerb411b362009-09-25 16:07:19 -070042 .owner = THIS_MODULE,
43 .open = drbd_proc_open,
44 .read = seq_read,
45 .llseek = seq_lseek,
Lars Ellenberg3da127f2010-11-24 10:33:02 +010046 .release = drbd_proc_release,
Philipp Reisnerb411b362009-09-25 16:07:19 -070047};
48
Rashika Kheriafbe0d912013-12-19 15:04:47 +053049static void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
Lars Ellenberg439d5952010-11-05 09:52:46 +010050{
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);
Lars Ellenbergfc251d52011-06-03 21:13:17 +020055 v %= 1000000;
Lars Ellenberg439d5952010-11-05 09:52:46 +010056 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}
Philipp Reisnerb411b362009-09-25 16:07:19 -070062
Lars Ellenberga5655da2014-03-11 13:47:55 +010063static void drbd_get_syncer_progress(struct drbd_device *device,
64 union drbd_dev_state state, unsigned long *rs_total,
65 unsigned long *bits_left, unsigned int *per_mil_done)
66{
67 /* this is to break it at compile time when we change that, in case we
68 * want to support more than (1<<32) bits on a 32bit arch. */
69 typecheck(unsigned long, device->rs_total);
70 *rs_total = device->rs_total;
71
72 /* note: both rs_total and rs_left are in bits, i.e. in
73 * units of BM_BLOCK_SIZE.
74 * for the percentage, we don't care. */
75
76 if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
77 *bits_left = device->ov_left;
78 else
79 *bits_left = drbd_bm_total_weight(device) - device->rs_failed;
80 /* >> 10 to prevent overflow,
81 * +1 to prevent division by zero */
82 if (*bits_left > *rs_total) {
83 /* D'oh. Maybe a logic bug somewhere. More likely just a race
84 * between state change and reset of rs_total.
85 */
86 *bits_left = *rs_total;
87 *per_mil_done = *rs_total ? 0 : 1000;
88 } else {
89 /* Make sure the division happens in long context.
90 * We allow up to one petabyte storage right now,
91 * at a granularity of 4k per bit that is 2**38 bits.
92 * After shift right and multiplication by 1000,
93 * this should still fit easily into a 32bit long,
94 * so we don't need a 64bit division on 32bit arch.
95 * Note: currently we don't support such large bitmaps on 32bit
96 * arch anyways, but no harm done to be prepared for it here.
97 */
98 unsigned int shift = *rs_total > UINT_MAX ? 16 : 10;
99 unsigned long left = *bits_left >> shift;
100 unsigned long total = 1UL + (*rs_total >> shift);
101 unsigned long tmp = 1000UL - left * 1000UL/total;
102 *per_mil_done = tmp;
103 }
104}
105
106
Philipp Reisnerb411b362009-09-25 16:07:19 -0700107/*lge
108 * progress bars shamelessly adapted from driver/md/md.c
109 * output looks like
110 * [=====>..............] 33.5% (23456/123456)
111 * finish: 2:20:20 speed: 6,345 (6,456) K/sec
112 */
Lars Ellenberga5655da2014-03-11 13:47:55 +0100113static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq,
114 union drbd_dev_state state)
Philipp Reisnerb411b362009-09-25 16:07:19 -0700115{
Lars Ellenberga5655da2014-03-11 13:47:55 +0100116 unsigned long db, dt, dbdt, rt, rs_total, rs_left;
Philipp Reisnerb411b362009-09-25 16:07:19 -0700117 unsigned int res;
118 int i, x, y;
Lars Ellenberg1d7734a2010-08-11 21:21:50 +0200119 int stalled = 0;
Philipp Reisnerb411b362009-09-25 16:07:19 -0700120
Lars Ellenberga5655da2014-03-11 13:47:55 +0100121 drbd_get_syncer_progress(device, state, &rs_total, &rs_left, &res);
Philipp Reisnerb411b362009-09-25 16:07:19 -0700122
123 x = res/50;
124 y = 20-x;
125 seq_printf(seq, "\t[");
126 for (i = 1; i < x; i++)
127 seq_printf(seq, "=");
128 seq_printf(seq, ">");
129 for (i = 0; i < y; i++)
130 seq_printf(seq, ".");
131 seq_printf(seq, "] ");
132
Lars Ellenberga5655da2014-03-11 13:47:55 +0100133 if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
Lars Ellenberg5f9915b2010-11-09 14:15:24 +0100134 seq_printf(seq, "verified:");
135 else
136 seq_printf(seq, "sync'ed:");
137 seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
138
Lars Ellenberg4b0715f2010-12-14 15:13:04 +0100139 /* if more than a few GB, display in MB */
Lars Ellenberga5655da2014-03-11 13:47:55 +0100140 if (rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
Lars Ellenberg4b0715f2010-12-14 15:13:04 +0100141 seq_printf(seq, "(%lu/%lu)M",
Philipp Reisnerb411b362009-09-25 16:07:19 -0700142 (unsigned long) Bit2KB(rs_left >> 10),
Lars Ellenberga5655da2014-03-11 13:47:55 +0100143 (unsigned long) Bit2KB(rs_total >> 10));
Philipp Reisnerb411b362009-09-25 16:07:19 -0700144 else
Philipp Reisner590001c2014-09-11 14:29:13 +0200145 seq_printf(seq, "(%lu/%lu)K",
Philipp Reisnerb411b362009-09-25 16:07:19 -0700146 (unsigned long) Bit2KB(rs_left),
Lars Ellenberga5655da2014-03-11 13:47:55 +0100147 (unsigned long) Bit2KB(rs_total));
Philipp Reisnerb411b362009-09-25 16:07:19 -0700148
Philipp Reisner590001c2014-09-11 14:29:13 +0200149 seq_printf(seq, "\n\t");
150
Philipp Reisnerb411b362009-09-25 16:07:19 -0700151 /* see drivers/md/md.c
152 * We do not want to overflow, so the order of operands and
153 * the * 100 / 100 trick are important. We do a +1 to be
154 * safe against division by zero. We only estimate anyway.
155 *
156 * dt: time from mark until now
157 * db: blocks written from mark until now
158 * rt: remaining time
159 */
Lars Ellenberg1d7734a2010-08-11 21:21:50 +0200160 /* Rolling marks. last_mark+1 may just now be modified. last_mark+2 is
161 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
162 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
Lars Ellenberg439d5952010-11-05 09:52:46 +0100163 /* ------------------------ ~18s average ------------------------ */
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200164 i = (device->rs_last_mark + 2) % DRBD_SYNC_MARKS;
165 dt = (jiffies - device->rs_mark_time[i]) / HZ;
Lars Ellenberg9ae47262014-04-28 18:43:16 +0200166 if (dt > 180)
Lars Ellenberg1d7734a2010-08-11 21:21:50 +0200167 stalled = 1;
Philipp Reisnerb411b362009-09-25 16:07:19 -0700168
169 if (!dt)
170 dt++;
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200171 db = device->rs_mark_left[i] - rs_left;
Philipp Reisnerb411b362009-09-25 16:07:19 -0700172 rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
173
174 seq_printf(seq, "finish: %lu:%02lu:%02lu",
175 rt / 3600, (rt % 3600) / 60, rt % 60);
176
Philipp Reisnerb411b362009-09-25 16:07:19 -0700177 dbdt = Bit2KB(db/dt);
Lars Ellenberg439d5952010-11-05 09:52:46 +0100178 seq_printf(seq, " speed: ");
179 seq_printf_with_thousands_grouping(seq, dbdt);
180 seq_printf(seq, " (");
181 /* ------------------------- ~3s average ------------------------ */
182 if (proc_details >= 1) {
183 /* this is what drbd_rs_should_slow_down() uses */
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200184 i = (device->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
185 dt = (jiffies - device->rs_mark_time[i]) / HZ;
Lars Ellenberg439d5952010-11-05 09:52:46 +0100186 if (!dt)
187 dt++;
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200188 db = device->rs_mark_left[i] - rs_left;
Lars Ellenberg439d5952010-11-05 09:52:46 +0100189 dbdt = Bit2KB(db/dt);
190 seq_printf_with_thousands_grouping(seq, dbdt);
191 seq_printf(seq, " -- ");
192 }
193
194 /* --------------------- long term average ---------------------- */
Philipp Reisnerb411b362009-09-25 16:07:19 -0700195 /* mean speed since syncer started
196 * we do account for PausedSync periods */
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200197 dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
Dan Carpenter22657692010-08-12 00:38:45 +0200198 if (dt == 0)
Philipp Reisnerb411b362009-09-25 16:07:19 -0700199 dt = 1;
Lars Ellenberga5655da2014-03-11 13:47:55 +0100200 db = rs_total - rs_left;
Philipp Reisnerb411b362009-09-25 16:07:19 -0700201 dbdt = Bit2KB(db/dt);
Lars Ellenberg439d5952010-11-05 09:52:46 +0100202 seq_printf_with_thousands_grouping(seq, dbdt);
203 seq_printf(seq, ")");
Philipp Reisnerb411b362009-09-25 16:07:19 -0700204
Lars Ellenberga5655da2014-03-11 13:47:55 +0100205 if (state.conn == C_SYNC_TARGET ||
206 state.conn == C_VERIFY_S) {
Lars Ellenberg5f9915b2010-11-09 14:15:24 +0100207 seq_printf(seq, " want: ");
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200208 seq_printf_with_thousands_grouping(seq, device->c_sync_rate);
Lars Ellenberg1d7734a2010-08-11 21:21:50 +0200209 }
210 seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
Lars Ellenberg5f9915b2010-11-09 14:15:24 +0100211
212 if (proc_details >= 1) {
213 /* 64 bit:
214 * we convert to sectors in the display below. */
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200215 unsigned long bm_bits = drbd_bm_bits(device);
Lars Ellenberg4896e8c2010-11-11 22:41:04 +0100216 unsigned long bit_pos;
Lars Ellenberg58ffa582012-07-26 14:09:49 +0200217 unsigned long long stop_sector = 0;
Lars Ellenberga5655da2014-03-11 13:47:55 +0100218 if (state.conn == C_VERIFY_S ||
219 state.conn == C_VERIFY_T) {
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200220 bit_pos = bm_bits - device->ov_left;
221 if (verify_can_do_stop_sector(device))
222 stop_sector = device->ov_stop_sector;
Lars Ellenberg58ffa582012-07-26 14:09:49 +0200223 } else
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200224 bit_pos = device->bm_resync_fo;
Lars Ellenberg5f9915b2010-11-09 14:15:24 +0100225 /* Total sectors may be slightly off for oddly
226 * sized devices. So what. */
227 seq_printf(seq,
Lars Ellenberg58ffa582012-07-26 14:09:49 +0200228 "\t%3d%% sector pos: %llu/%llu",
Lars Ellenberg5f9915b2010-11-09 14:15:24 +0100229 (int)(bit_pos / (bm_bits/100+1)),
Lars Ellenberg4896e8c2010-11-11 22:41:04 +0100230 (unsigned long long)bit_pos * BM_SECT_PER_BIT,
231 (unsigned long long)bm_bits * BM_SECT_PER_BIT);
Lars Ellenberg58ffa582012-07-26 14:09:49 +0200232 if (stop_sector != 0 && stop_sector != ULLONG_MAX)
233 seq_printf(seq, " stop sector: %llu", stop_sector);
234 seq_printf(seq, "\n");
Lars Ellenberg5f9915b2010-11-09 14:15:24 +0100235 }
Philipp Reisnerb411b362009-09-25 16:07:19 -0700236}
237
Philipp Reisnerb411b362009-09-25 16:07:19 -0700238static int drbd_seq_show(struct seq_file *seq, void *v)
239{
Philipp Reisner81a5d602011-02-22 19:53:16 -0500240 int i, prev_i = -1;
Philipp Reisnerb411b362009-09-25 16:07:19 -0700241 const char *sn;
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200242 struct drbd_device *device;
Philipp Reisner44ed1672011-04-19 17:10:19 +0200243 struct net_conf *nc;
Lars Ellenberga5655da2014-03-11 13:47:55 +0100244 union drbd_dev_state state;
Philipp Reisner44ed1672011-04-19 17:10:19 +0200245 char wp;
Philipp Reisnerb411b362009-09-25 16:07:19 -0700246
247 static char write_ordering_chars[] = {
248 [WO_none] = 'n',
249 [WO_drain_io] = 'd',
250 [WO_bdev_flush] = 'f',
Philipp Reisnerb411b362009-09-25 16:07:19 -0700251 };
252
253 seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
254 API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
255
256 /*
257 cs .. connection state
258 ro .. node role (local/remote)
259 ds .. disk state (local/remote)
260 protocol
261 various flags
262 ns .. network send
263 nr .. network receive
264 dw .. disk write
265 dr .. disk read
266 al .. activity log write count
267 bm .. bitmap update write count
268 pe .. pending (waiting for ack or data reply)
269 ua .. unack'd (still need to send ack or data reply)
270 ap .. application requests accepted, but not yet completed
271 ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
272 wo .. write ordering mode currently in use
273 oos .. known out-of-sync kB
274 */
275
Philipp Reisnerc141ebd2011-05-05 16:13:10 +0200276 rcu_read_lock();
Andreas Gruenbacher05a10ec2011-06-07 22:54:17 +0200277 idr_for_each_entry(&drbd_devices, device, i) {
Philipp Reisner81a5d602011-02-22 19:53:16 -0500278 if (prev_i != i - 1)
Philipp Reisnerb411b362009-09-25 16:07:19 -0700279 seq_printf(seq, "\n");
Philipp Reisner81a5d602011-02-22 19:53:16 -0500280 prev_i = i;
Philipp Reisnerb411b362009-09-25 16:07:19 -0700281
Lars Ellenberga5655da2014-03-11 13:47:55 +0100282 state = device->state;
283 sn = drbd_conn_str(state.conn);
Philipp Reisnerb411b362009-09-25 16:07:19 -0700284
Lars Ellenberga5655da2014-03-11 13:47:55 +0100285 if (state.conn == C_STANDALONE &&
286 state.disk == D_DISKLESS &&
287 state.role == R_SECONDARY) {
Philipp Reisnerb411b362009-09-25 16:07:19 -0700288 seq_printf(seq, "%2d: cs:Unconfigured\n", i);
289 } else {
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200290 /* reset device->congestion_reason */
291 bdi_rw_congested(&device->rq_queue->backing_dev_info);
Lars Ellenberg8a943172012-07-30 09:09:36 +0200292
Andreas Gruenbachera6b32bc2011-05-31 14:33:49 +0200293 nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
Philipp Reisner44ed1672011-04-19 17:10:19 +0200294 wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
Philipp Reisnerb411b362009-09-25 16:07:19 -0700295 seq_printf(seq,
Philipp Reisner07782862010-08-31 12:00:50 +0200296 "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
Philipp Reisnerb411b362009-09-25 16:07:19 -0700297 " ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
298 "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
299 i, sn,
Lars Ellenberga5655da2014-03-11 13:47:55 +0100300 drbd_role_str(state.role),
301 drbd_role_str(state.peer),
302 drbd_disk_str(state.disk),
303 drbd_disk_str(state.pdsk),
Philipp Reisner44ed1672011-04-19 17:10:19 +0200304 wp,
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200305 drbd_suspended(device) ? 's' : 'r',
Lars Ellenberga5655da2014-03-11 13:47:55 +0100306 state.aftr_isp ? 'a' : '-',
307 state.peer_isp ? 'p' : '-',
308 state.user_isp ? 'u' : '-',
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200309 device->congestion_reason ?: '-',
310 test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-',
311 device->send_cnt/2,
312 device->recv_cnt/2,
313 device->writ_cnt/2,
314 device->read_cnt/2,
315 device->al_writ_cnt,
316 device->bm_writ_cnt,
317 atomic_read(&device->local_cnt),
318 atomic_read(&device->ap_pending_cnt) +
319 atomic_read(&device->rs_pending_cnt),
320 atomic_read(&device->unacked_cnt),
321 atomic_read(&device->ap_bio_cnt),
Andreas Gruenbachera6b32bc2011-05-31 14:33:49 +0200322 first_peer_device(device)->connection->epochs,
Philipp Reisnere9526582013-11-22 15:53:41 +0100323 write_ordering_chars[device->resource->write_ordering]
Philipp Reisnerb411b362009-09-25 16:07:19 -0700324 );
Lars Ellenberg18edc0b2010-11-09 14:12:10 +0100325 seq_printf(seq, " oos:%llu\n",
326 Bit2KB((unsigned long long)
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200327 drbd_bm_total_weight(device)));
Philipp Reisnerb411b362009-09-25 16:07:19 -0700328 }
Lars Ellenberga5655da2014-03-11 13:47:55 +0100329 if (state.conn == C_SYNC_SOURCE ||
330 state.conn == C_SYNC_TARGET ||
331 state.conn == C_VERIFY_S ||
332 state.conn == C_VERIFY_T)
333 drbd_syncer_progress(device, seq, state);
Philipp Reisnerb411b362009-09-25 16:07:19 -0700334
Andreas Gruenbacherb30ab792011-07-03 13:26:43 +0200335 if (proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) {
336 lc_seq_printf_stats(seq, device->resync);
337 lc_seq_printf_stats(seq, device->act_log);
338 put_ldev(device);
Philipp Reisnerb411b362009-09-25 16:07:19 -0700339 }
Lars Ellenbergad3fee72013-12-20 11:22:13 +0100340
341 if (proc_details >= 2)
342 seq_printf(seq, "\tblocked on activity log: %d\n", atomic_read(&device->ap_actlog_cnt));
Philipp Reisnerb411b362009-09-25 16:07:19 -0700343 }
Philipp Reisnerc141ebd2011-05-05 16:13:10 +0200344 rcu_read_unlock();
Philipp Reisnerb411b362009-09-25 16:07:19 -0700345
346 return 0;
347}
348
349static int drbd_proc_open(struct inode *inode, struct file *file)
350{
Alexey Khoroshilov193d0152013-03-27 14:08:46 +0100351 int err;
352
353 if (try_module_get(THIS_MODULE)) {
Andreas Gruenbachercaa3db02014-02-27 20:49:54 +0100354 err = single_open(file, drbd_seq_show, NULL);
Alexey Khoroshilov193d0152013-03-27 14:08:46 +0100355 if (err)
356 module_put(THIS_MODULE);
357 return err;
358 }
Lars Ellenberg3da127f2010-11-24 10:33:02 +0100359 return -ENODEV;
360}
361
362static int drbd_proc_release(struct inode *inode, struct file *file)
363{
364 module_put(THIS_MODULE);
365 return single_release(inode, file);
Philipp Reisnerb411b362009-09-25 16:07:19 -0700366}
367
368/* PROC FS stuff end */