linux/drivers/block/drbd/drbd_proc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3   drbd_proc.c
   4
   5   This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
   6
   7   Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
   8   Copyright (C) 1999-2008, Philipp Reisner <philipp.reisner@linbit.com>.
   9   Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
  10
  11
  12 */
  13
  14#include <linux/module.h>
  15
  16#include <linux/uaccess.h>
  17#include <linux/fs.h>
  18#include <linux/file.h>
  19#include <linux/proc_fs.h>
  20#include <linux/seq_file.h>
  21#include <linux/drbd.h>
  22#include "drbd_int.h"
  23
  24struct proc_dir_entry *drbd_proc;
  25
  26static void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
  27{
  28        /* v is in kB/sec. We don't expect TiByte/sec yet. */
  29        if (unlikely(v >= 1000000)) {
  30                /* cool: > GiByte/s */
  31                seq_printf(seq, "%ld,", v / 1000000);
  32                v %= 1000000;
  33                seq_printf(seq, "%03ld,%03ld", v/1000, v % 1000);
  34        } else if (likely(v >= 1000))
  35                seq_printf(seq, "%ld,%03ld", v/1000, v % 1000);
  36        else
  37                seq_printf(seq, "%ld", v);
  38}
  39
  40static void drbd_get_syncer_progress(struct drbd_device *device,
  41                union drbd_dev_state state, unsigned long *rs_total,
  42                unsigned long *bits_left, unsigned int *per_mil_done)
  43{
  44        /* this is to break it at compile time when we change that, in case we
  45         * want to support more than (1<<32) bits on a 32bit arch. */
  46        typecheck(unsigned long, device->rs_total);
  47        *rs_total = device->rs_total;
  48
  49        /* note: both rs_total and rs_left are in bits, i.e. in
  50         * units of BM_BLOCK_SIZE.
  51         * for the percentage, we don't care. */
  52
  53        if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
  54                *bits_left = device->ov_left;
  55        else
  56                *bits_left = drbd_bm_total_weight(device) - device->rs_failed;
  57        /* >> 10 to prevent overflow,
  58         * +1 to prevent division by zero */
  59        if (*bits_left > *rs_total) {
  60                /* D'oh. Maybe a logic bug somewhere.  More likely just a race
  61                 * between state change and reset of rs_total.
  62                 */
  63                *bits_left = *rs_total;
  64                *per_mil_done = *rs_total ? 0 : 1000;
  65        } else {
  66                /* Make sure the division happens in long context.
  67                 * We allow up to one petabyte storage right now,
  68                 * at a granularity of 4k per bit that is 2**38 bits.
  69                 * After shift right and multiplication by 1000,
  70                 * this should still fit easily into a 32bit long,
  71                 * so we don't need a 64bit division on 32bit arch.
  72                 * Note: currently we don't support such large bitmaps on 32bit
  73                 * arch anyways, but no harm done to be prepared for it here.
  74                 */
  75                unsigned int shift = *rs_total > UINT_MAX ? 16 : 10;
  76                unsigned long left = *bits_left >> shift;
  77                unsigned long total = 1UL + (*rs_total >> shift);
  78                unsigned long tmp = 1000UL - left * 1000UL/total;
  79                *per_mil_done = tmp;
  80        }
  81}
  82
  83
  84/*lge
  85 * progress bars shamelessly adapted from driver/md/md.c
  86 * output looks like
  87 *      [=====>..............] 33.5% (23456/123456)
  88 *      finish: 2:20:20 speed: 6,345 (6,456) K/sec
  89 */
  90static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq,
  91                union drbd_dev_state state)
  92{
  93        unsigned long db, dt, dbdt, rt, rs_total, rs_left;
  94        unsigned int res;
  95        int i, x, y;
  96        int stalled = 0;
  97
  98        drbd_get_syncer_progress(device, state, &rs_total, &rs_left, &res);
  99
 100        x = res/50;
 101        y = 20-x;
 102        seq_puts(seq, "\t[");
 103        for (i = 1; i < x; i++)
 104                seq_putc(seq, '=');
 105        seq_putc(seq, '>');
 106        for (i = 0; i < y; i++)
 107                seq_putc(seq, '.');
 108        seq_puts(seq, "] ");
 109
 110        if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
 111                seq_puts(seq, "verified:");
 112        else
 113                seq_puts(seq, "sync'ed:");
 114        seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
 115
 116        /* if more than a few GB, display in MB */
 117        if (rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
 118                seq_printf(seq, "(%lu/%lu)M",
 119                            (unsigned long) Bit2KB(rs_left >> 10),
 120                            (unsigned long) Bit2KB(rs_total >> 10));
 121        else
 122                seq_printf(seq, "(%lu/%lu)K",
 123                            (unsigned long) Bit2KB(rs_left),
 124                            (unsigned long) Bit2KB(rs_total));
 125
 126        seq_puts(seq, "\n\t");
 127
 128        /* see drivers/md/md.c
 129         * We do not want to overflow, so the order of operands and
 130         * the * 100 / 100 trick are important. We do a +1 to be
 131         * safe against division by zero. We only estimate anyway.
 132         *
 133         * dt: time from mark until now
 134         * db: blocks written from mark until now
 135         * rt: remaining time
 136         */
 137        /* Rolling marks. last_mark+1 may just now be modified.  last_mark+2 is
 138         * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
 139         * least DRBD_SYNC_MARK_STEP time before it will be modified. */
 140        /* ------------------------ ~18s average ------------------------ */
 141        i = (device->rs_last_mark + 2) % DRBD_SYNC_MARKS;
 142        dt = (jiffies - device->rs_mark_time[i]) / HZ;
 143        if (dt > 180)
 144                stalled = 1;
 145
 146        if (!dt)
 147                dt++;
 148        db = device->rs_mark_left[i] - rs_left;
 149        rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
 150
 151        seq_printf(seq, "finish: %lu:%02lu:%02lu",
 152                rt / 3600, (rt % 3600) / 60, rt % 60);
 153
 154        dbdt = Bit2KB(db/dt);
 155        seq_puts(seq, " speed: ");
 156        seq_printf_with_thousands_grouping(seq, dbdt);
 157        seq_puts(seq, " (");
 158        /* ------------------------- ~3s average ------------------------ */
 159        if (drbd_proc_details >= 1) {
 160                /* this is what drbd_rs_should_slow_down() uses */
 161                i = (device->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
 162                dt = (jiffies - device->rs_mark_time[i]) / HZ;
 163                if (!dt)
 164                        dt++;
 165                db = device->rs_mark_left[i] - rs_left;
 166                dbdt = Bit2KB(db/dt);
 167                seq_printf_with_thousands_grouping(seq, dbdt);
 168                seq_puts(seq, " -- ");
 169        }
 170
 171        /* --------------------- long term average ---------------------- */
 172        /* mean speed since syncer started
 173         * we do account for PausedSync periods */
 174        dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
 175        if (dt == 0)
 176                dt = 1;
 177        db = rs_total - rs_left;
 178        dbdt = Bit2KB(db/dt);
 179        seq_printf_with_thousands_grouping(seq, dbdt);
 180        seq_putc(seq, ')');
 181
 182        if (state.conn == C_SYNC_TARGET ||
 183            state.conn == C_VERIFY_S) {
 184                seq_puts(seq, " want: ");
 185                seq_printf_with_thousands_grouping(seq, device->c_sync_rate);
 186        }
 187        seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
 188
 189        if (drbd_proc_details >= 1) {
 190                /* 64 bit:
 191                 * we convert to sectors in the display below. */
 192                unsigned long bm_bits = drbd_bm_bits(device);
 193                unsigned long bit_pos;
 194                unsigned long long stop_sector = 0;
 195                if (state.conn == C_VERIFY_S ||
 196                    state.conn == C_VERIFY_T) {
 197                        bit_pos = bm_bits - device->ov_left;
 198                        if (verify_can_do_stop_sector(device))
 199                                stop_sector = device->ov_stop_sector;
 200                } else
 201                        bit_pos = device->bm_resync_fo;
 202                /* Total sectors may be slightly off for oddly
 203                 * sized devices. So what. */
 204                seq_printf(seq,
 205                        "\t%3d%% sector pos: %llu/%llu",
 206                        (int)(bit_pos / (bm_bits/100+1)),
 207                        (unsigned long long)bit_pos * BM_SECT_PER_BIT,
 208                        (unsigned long long)bm_bits * BM_SECT_PER_BIT);
 209                if (stop_sector != 0 && stop_sector != ULLONG_MAX)
 210                        seq_printf(seq, " stop sector: %llu", stop_sector);
 211                seq_putc(seq, '\n');
 212        }
 213}
 214
 215int drbd_seq_show(struct seq_file *seq, void *v)
 216{
 217        int i, prev_i = -1;
 218        const char *sn;
 219        struct drbd_device *device;
 220        struct net_conf *nc;
 221        union drbd_dev_state state;
 222        char wp;
 223
 224        static char write_ordering_chars[] = {
 225                [WO_NONE] = 'n',
 226                [WO_DRAIN_IO] = 'd',
 227                [WO_BDEV_FLUSH] = 'f',
 228        };
 229
 230        seq_printf(seq, "version: " REL_VERSION " (api:%d/proto:%d-%d)\n%s\n",
 231                   API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX, drbd_buildtag());
 232
 233        /*
 234          cs .. connection state
 235          ro .. node role (local/remote)
 236          ds .. disk state (local/remote)
 237             protocol
 238             various flags
 239          ns .. network send
 240          nr .. network receive
 241          dw .. disk write
 242          dr .. disk read
 243          al .. activity log write count
 244          bm .. bitmap update write count
 245          pe .. pending (waiting for ack or data reply)
 246          ua .. unack'd (still need to send ack or data reply)
 247          ap .. application requests accepted, but not yet completed
 248          ep .. number of epochs currently "on the fly", P_BARRIER_ACK pending
 249          wo .. write ordering mode currently in use
 250         oos .. known out-of-sync kB
 251        */
 252
 253        rcu_read_lock();
 254        idr_for_each_entry(&drbd_devices, device, i) {
 255                if (prev_i != i - 1)
 256                        seq_putc(seq, '\n');
 257                prev_i = i;
 258
 259                state = device->state;
 260                sn = drbd_conn_str(state.conn);
 261
 262                if (state.conn == C_STANDALONE &&
 263                    state.disk == D_DISKLESS &&
 264                    state.role == R_SECONDARY) {
 265                        seq_printf(seq, "%2d: cs:Unconfigured\n", i);
 266                } else {
 267                        /* reset device->congestion_reason */
 268                        bdi_rw_congested(device->rq_queue->backing_dev_info);
 269
 270                        nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 271                        wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
 272                        seq_printf(seq,
 273                           "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
 274                           "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
 275                           "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
 276                           i, sn,
 277                           drbd_role_str(state.role),
 278                           drbd_role_str(state.peer),
 279                           drbd_disk_str(state.disk),
 280                           drbd_disk_str(state.pdsk),
 281                           wp,
 282                           drbd_suspended(device) ? 's' : 'r',
 283                           state.aftr_isp ? 'a' : '-',
 284                           state.peer_isp ? 'p' : '-',
 285                           state.user_isp ? 'u' : '-',
 286                           device->congestion_reason ?: '-',
 287                           test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-',
 288                           device->send_cnt/2,
 289                           device->recv_cnt/2,
 290                           device->writ_cnt/2,
 291                           device->read_cnt/2,
 292                           device->al_writ_cnt,
 293                           device->bm_writ_cnt,
 294                           atomic_read(&device->local_cnt),
 295                           atomic_read(&device->ap_pending_cnt) +
 296                           atomic_read(&device->rs_pending_cnt),
 297                           atomic_read(&device->unacked_cnt),
 298                           atomic_read(&device->ap_bio_cnt),
 299                           first_peer_device(device)->connection->epochs,
 300                           write_ordering_chars[device->resource->write_ordering]
 301                        );
 302                        seq_printf(seq, " oos:%llu\n",
 303                                   Bit2KB((unsigned long long)
 304                                           drbd_bm_total_weight(device)));
 305                }
 306                if (state.conn == C_SYNC_SOURCE ||
 307                    state.conn == C_SYNC_TARGET ||
 308                    state.conn == C_VERIFY_S ||
 309                    state.conn == C_VERIFY_T)
 310                        drbd_syncer_progress(device, seq, state);
 311
 312                if (drbd_proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) {
 313                        lc_seq_printf_stats(seq, device->resync);
 314                        lc_seq_printf_stats(seq, device->act_log);
 315                        put_ldev(device);
 316                }
 317
 318                if (drbd_proc_details >= 2)
 319                        seq_printf(seq, "\tblocked on activity log: %d\n", atomic_read(&device->ap_actlog_cnt));
 320        }
 321        rcu_read_unlock();
 322
 323        return 0;
 324}
 325