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