Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
drbd_proc.c
Go to the documentation of this file.
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 <[email protected]>.
8  Copyright (C) 2002-2008, Lars Ellenberg <[email protected]>.
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 
42  .owner = THIS_MODULE,
43  .open = drbd_proc_open,
44  .read = seq_read,
45  .llseek = seq_lseek,
46  .release = drbd_proc_release,
47 };
48 
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  */
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;
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: ");
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);
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);
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: ");
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 
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 
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",
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  /* reset mdev->congestion_reason */
249  bdi_rw_congested(&mdev->rq_queue->backing_dev_info);
250 
251  seq_printf(seq,
252  "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
253  " ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
254  "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
255  i, sn,
256  drbd_role_str(mdev->state.role),
257  drbd_role_str(mdev->state.peer),
258  drbd_disk_str(mdev->state.disk),
259  drbd_disk_str(mdev->state.pdsk),
260  (mdev->net_conf == NULL ? ' ' :
261  (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
262  is_susp(mdev->state) ? 's' : 'r',
263  mdev->state.aftr_isp ? 'a' : '-',
264  mdev->state.peer_isp ? 'p' : '-',
265  mdev->state.user_isp ? 'u' : '-',
266  mdev->congestion_reason ?: '-',
267  test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
268  mdev->send_cnt/2,
269  mdev->recv_cnt/2,
270  mdev->writ_cnt/2,
271  mdev->read_cnt/2,
272  mdev->al_writ_cnt,
273  mdev->bm_writ_cnt,
274  atomic_read(&mdev->local_cnt),
275  atomic_read(&mdev->ap_pending_cnt) +
276  atomic_read(&mdev->rs_pending_cnt),
277  atomic_read(&mdev->unacked_cnt),
278  atomic_read(&mdev->ap_bio_cnt),
279  mdev->epochs,
280  write_ordering_chars[mdev->write_ordering]
281  );
282  seq_printf(seq, " oos:%llu\n",
283  Bit2KB((unsigned long long)
284  drbd_bm_total_weight(mdev)));
285  }
286  if (mdev->state.conn == C_SYNC_SOURCE ||
287  mdev->state.conn == C_SYNC_TARGET ||
288  mdev->state.conn == C_VERIFY_S ||
289  mdev->state.conn == C_VERIFY_T)
290  drbd_syncer_progress(mdev, seq);
291 
292  if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
293  lc_seq_printf_stats(seq, mdev->resync);
294  lc_seq_printf_stats(seq, mdev->act_log);
295  put_ldev(mdev);
296  }
297 
298  if (proc_details >= 2) {
299  if (mdev->resync) {
300  lc_seq_dump_details(seq, mdev->resync, "rs_left",
301  resync_dump_detail);
302  }
303  }
304  }
305 
306  return 0;
307 }
308 
309 static int drbd_proc_open(struct inode *inode, struct file *file)
310 {
311  if (try_module_get(THIS_MODULE))
312  return single_open(file, drbd_seq_show, PDE(inode)->data);
313  return -ENODEV;
314 }
315 
316 static int drbd_proc_release(struct inode *inode, struct file *file)
317 {
318  module_put(THIS_MODULE);
319  return single_release(inode, file);
320 }
321 
322 /* PROC FS stuff end */