Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #define pr_fmt(fmt) "drbd debugfs: " fmt
0003 #include <linux/kernel.h>
0004 #include <linux/module.h>
0005 #include <linux/debugfs.h>
0006 #include <linux/seq_file.h>
0007 #include <linux/stat.h>
0008 #include <linux/jiffies.h>
0009 #include <linux/list.h>
0010 
0011 #include "drbd_int.h"
0012 #include "drbd_req.h"
0013 #include "drbd_debugfs.h"
0014 
0015 
0016 /**********************************************************************
0017  * Whenever you change the file format, remember to bump the version. *
0018  **********************************************************************/
0019 
0020 static struct dentry *drbd_debugfs_root;
0021 static struct dentry *drbd_debugfs_version;
0022 static struct dentry *drbd_debugfs_resources;
0023 static struct dentry *drbd_debugfs_minors;
0024 
0025 static void seq_print_age_or_dash(struct seq_file *m, bool valid, unsigned long dt)
0026 {
0027     if (valid)
0028         seq_printf(m, "\t%d", jiffies_to_msecs(dt));
0029     else
0030         seq_printf(m, "\t-");
0031 }
0032 
0033 static void __seq_print_rq_state_bit(struct seq_file *m,
0034     bool is_set, char *sep, const char *set_name, const char *unset_name)
0035 {
0036     if (is_set && set_name) {
0037         seq_putc(m, *sep);
0038         seq_puts(m, set_name);
0039         *sep = '|';
0040     } else if (!is_set && unset_name) {
0041         seq_putc(m, *sep);
0042         seq_puts(m, unset_name);
0043         *sep = '|';
0044     }
0045 }
0046 
0047 static void seq_print_rq_state_bit(struct seq_file *m,
0048     bool is_set, char *sep, const char *set_name)
0049 {
0050     __seq_print_rq_state_bit(m, is_set, sep, set_name, NULL);
0051 }
0052 
0053 /* pretty print enum drbd_req_state_bits req->rq_state */
0054 static void seq_print_request_state(struct seq_file *m, struct drbd_request *req)
0055 {
0056     unsigned int s = req->rq_state;
0057     char sep = ' ';
0058     seq_printf(m, "\t0x%08x", s);
0059     seq_printf(m, "\tmaster: %s", req->master_bio ? "pending" : "completed");
0060 
0061     /* RQ_WRITE ignored, already reported */
0062     seq_puts(m, "\tlocal:");
0063     seq_print_rq_state_bit(m, s & RQ_IN_ACT_LOG, &sep, "in-AL");
0064     seq_print_rq_state_bit(m, s & RQ_POSTPONED, &sep, "postponed");
0065     seq_print_rq_state_bit(m, s & RQ_COMPLETION_SUSP, &sep, "suspended");
0066     sep = ' ';
0067     seq_print_rq_state_bit(m, s & RQ_LOCAL_PENDING, &sep, "pending");
0068     seq_print_rq_state_bit(m, s & RQ_LOCAL_COMPLETED, &sep, "completed");
0069     seq_print_rq_state_bit(m, s & RQ_LOCAL_ABORTED, &sep, "aborted");
0070     seq_print_rq_state_bit(m, s & RQ_LOCAL_OK, &sep, "ok");
0071     if (sep == ' ')
0072         seq_puts(m, " -");
0073 
0074     /* for_each_connection ... */
0075     seq_printf(m, "\tnet:");
0076     sep = ' ';
0077     seq_print_rq_state_bit(m, s & RQ_NET_PENDING, &sep, "pending");
0078     seq_print_rq_state_bit(m, s & RQ_NET_QUEUED, &sep, "queued");
0079     seq_print_rq_state_bit(m, s & RQ_NET_SENT, &sep, "sent");
0080     seq_print_rq_state_bit(m, s & RQ_NET_DONE, &sep, "done");
0081     seq_print_rq_state_bit(m, s & RQ_NET_SIS, &sep, "sis");
0082     seq_print_rq_state_bit(m, s & RQ_NET_OK, &sep, "ok");
0083     if (sep == ' ')
0084         seq_puts(m, " -");
0085 
0086     seq_printf(m, " :");
0087     sep = ' ';
0088     seq_print_rq_state_bit(m, s & RQ_EXP_RECEIVE_ACK, &sep, "B");
0089     seq_print_rq_state_bit(m, s & RQ_EXP_WRITE_ACK, &sep, "C");
0090     seq_print_rq_state_bit(m, s & RQ_EXP_BARR_ACK, &sep, "barr");
0091     if (sep == ' ')
0092         seq_puts(m, " -");
0093     seq_printf(m, "\n");
0094 }
0095 
0096 static void seq_print_one_request(struct seq_file *m, struct drbd_request *req, unsigned long now)
0097 {
0098     /* change anything here, fixup header below! */
0099     unsigned int s = req->rq_state;
0100 
0101 #define RQ_HDR_1 "epoch\tsector\tsize\trw"
0102     seq_printf(m, "0x%x\t%llu\t%u\t%s",
0103         req->epoch,
0104         (unsigned long long)req->i.sector, req->i.size >> 9,
0105         (s & RQ_WRITE) ? "W" : "R");
0106 
0107 #define RQ_HDR_2 "\tstart\tin AL\tsubmit"
0108     seq_printf(m, "\t%d", jiffies_to_msecs(now - req->start_jif));
0109     seq_print_age_or_dash(m, s & RQ_IN_ACT_LOG, now - req->in_actlog_jif);
0110     seq_print_age_or_dash(m, s & RQ_LOCAL_PENDING, now - req->pre_submit_jif);
0111 
0112 #define RQ_HDR_3 "\tsent\tacked\tdone"
0113     seq_print_age_or_dash(m, s & RQ_NET_SENT, now - req->pre_send_jif);
0114     seq_print_age_or_dash(m, (s & RQ_NET_SENT) && !(s & RQ_NET_PENDING), now - req->acked_jif);
0115     seq_print_age_or_dash(m, s & RQ_NET_DONE, now - req->net_done_jif);
0116 
0117 #define RQ_HDR_4 "\tstate\n"
0118     seq_print_request_state(m, req);
0119 }
0120 #define RQ_HDR RQ_HDR_1 RQ_HDR_2 RQ_HDR_3 RQ_HDR_4
0121 
0122 static void seq_print_minor_vnr_req(struct seq_file *m, struct drbd_request *req, unsigned long now)
0123 {
0124     seq_printf(m, "%u\t%u\t", req->device->minor, req->device->vnr);
0125     seq_print_one_request(m, req, now);
0126 }
0127 
0128 static void seq_print_resource_pending_meta_io(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
0129 {
0130     struct drbd_device *device;
0131     unsigned int i;
0132 
0133     seq_puts(m, "minor\tvnr\tstart\tsubmit\tintent\n");
0134     rcu_read_lock();
0135     idr_for_each_entry(&resource->devices, device, i) {
0136         struct drbd_md_io tmp;
0137         /* In theory this is racy,
0138          * in the sense that there could have been a
0139          * drbd_md_put_buffer(); drbd_md_get_buffer();
0140          * between accessing these members here.  */
0141         tmp = device->md_io;
0142         if (atomic_read(&tmp.in_use)) {
0143             seq_printf(m, "%u\t%u\t%d\t",
0144                 device->minor, device->vnr,
0145                 jiffies_to_msecs(now - tmp.start_jif));
0146             if (time_before(tmp.submit_jif, tmp.start_jif))
0147                 seq_puts(m, "-\t");
0148             else
0149                 seq_printf(m, "%d\t", jiffies_to_msecs(now - tmp.submit_jif));
0150             seq_printf(m, "%s\n", tmp.current_use);
0151         }
0152     }
0153     rcu_read_unlock();
0154 }
0155 
0156 static void seq_print_waiting_for_AL(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
0157 {
0158     struct drbd_device *device;
0159     unsigned int i;
0160 
0161     seq_puts(m, "minor\tvnr\tage\t#waiting\n");
0162     rcu_read_lock();
0163     idr_for_each_entry(&resource->devices, device, i) {
0164         unsigned long jif;
0165         struct drbd_request *req;
0166         int n = atomic_read(&device->ap_actlog_cnt);
0167         if (n) {
0168             spin_lock_irq(&device->resource->req_lock);
0169             req = list_first_entry_or_null(&device->pending_master_completion[1],
0170                 struct drbd_request, req_pending_master_completion);
0171             /* if the oldest request does not wait for the activity log
0172              * it is not interesting for us here */
0173             if (req && !(req->rq_state & RQ_IN_ACT_LOG))
0174                 jif = req->start_jif;
0175             else
0176                 req = NULL;
0177             spin_unlock_irq(&device->resource->req_lock);
0178         }
0179         if (n) {
0180             seq_printf(m, "%u\t%u\t", device->minor, device->vnr);
0181             if (req)
0182                 seq_printf(m, "%u\t", jiffies_to_msecs(now - jif));
0183             else
0184                 seq_puts(m, "-\t");
0185             seq_printf(m, "%u\n", n);
0186         }
0187     }
0188     rcu_read_unlock();
0189 }
0190 
0191 static void seq_print_device_bitmap_io(struct seq_file *m, struct drbd_device *device, unsigned long now)
0192 {
0193     struct drbd_bm_aio_ctx *ctx;
0194     unsigned long start_jif;
0195     unsigned int in_flight;
0196     unsigned int flags;
0197     spin_lock_irq(&device->resource->req_lock);
0198     ctx = list_first_entry_or_null(&device->pending_bitmap_io, struct drbd_bm_aio_ctx, list);
0199     if (ctx && ctx->done)
0200         ctx = NULL;
0201     if (ctx) {
0202         start_jif = ctx->start_jif;
0203         in_flight = atomic_read(&ctx->in_flight);
0204         flags = ctx->flags;
0205     }
0206     spin_unlock_irq(&device->resource->req_lock);
0207     if (ctx) {
0208         seq_printf(m, "%u\t%u\t%c\t%u\t%u\n",
0209             device->minor, device->vnr,
0210             (flags & BM_AIO_READ) ? 'R' : 'W',
0211             jiffies_to_msecs(now - start_jif),
0212             in_flight);
0213     }
0214 }
0215 
0216 static void seq_print_resource_pending_bitmap_io(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
0217 {
0218     struct drbd_device *device;
0219     unsigned int i;
0220 
0221     seq_puts(m, "minor\tvnr\trw\tage\t#in-flight\n");
0222     rcu_read_lock();
0223     idr_for_each_entry(&resource->devices, device, i) {
0224         seq_print_device_bitmap_io(m, device, now);
0225     }
0226     rcu_read_unlock();
0227 }
0228 
0229 /* pretty print enum peer_req->flags */
0230 static void seq_print_peer_request_flags(struct seq_file *m, struct drbd_peer_request *peer_req)
0231 {
0232     unsigned long f = peer_req->flags;
0233     char sep = ' ';
0234 
0235     __seq_print_rq_state_bit(m, f & EE_SUBMITTED, &sep, "submitted", "preparing");
0236     __seq_print_rq_state_bit(m, f & EE_APPLICATION, &sep, "application", "internal");
0237     seq_print_rq_state_bit(m, f & EE_CALL_AL_COMPLETE_IO, &sep, "in-AL");
0238     seq_print_rq_state_bit(m, f & EE_SEND_WRITE_ACK, &sep, "C");
0239     seq_print_rq_state_bit(m, f & EE_MAY_SET_IN_SYNC, &sep, "set-in-sync");
0240     seq_print_rq_state_bit(m, f & EE_TRIM, &sep, "trim");
0241     seq_print_rq_state_bit(m, f & EE_ZEROOUT, &sep, "zero-out");
0242     seq_print_rq_state_bit(m, f & EE_WRITE_SAME, &sep, "write-same");
0243     seq_putc(m, '\n');
0244 }
0245 
0246 static void seq_print_peer_request(struct seq_file *m,
0247     struct drbd_device *device, struct list_head *lh,
0248     unsigned long now)
0249 {
0250     bool reported_preparing = false;
0251     struct drbd_peer_request *peer_req;
0252     list_for_each_entry(peer_req, lh, w.list) {
0253         if (reported_preparing && !(peer_req->flags & EE_SUBMITTED))
0254             continue;
0255 
0256         if (device)
0257             seq_printf(m, "%u\t%u\t", device->minor, device->vnr);
0258 
0259         seq_printf(m, "%llu\t%u\t%c\t%u\t",
0260             (unsigned long long)peer_req->i.sector, peer_req->i.size >> 9,
0261             (peer_req->flags & EE_WRITE) ? 'W' : 'R',
0262             jiffies_to_msecs(now - peer_req->submit_jif));
0263         seq_print_peer_request_flags(m, peer_req);
0264         if (peer_req->flags & EE_SUBMITTED)
0265             break;
0266         else
0267             reported_preparing = true;
0268     }
0269 }
0270 
0271 static void seq_print_device_peer_requests(struct seq_file *m,
0272     struct drbd_device *device, unsigned long now)
0273 {
0274     seq_puts(m, "minor\tvnr\tsector\tsize\trw\tage\tflags\n");
0275     spin_lock_irq(&device->resource->req_lock);
0276     seq_print_peer_request(m, device, &device->active_ee, now);
0277     seq_print_peer_request(m, device, &device->read_ee, now);
0278     seq_print_peer_request(m, device, &device->sync_ee, now);
0279     spin_unlock_irq(&device->resource->req_lock);
0280     if (test_bit(FLUSH_PENDING, &device->flags)) {
0281         seq_printf(m, "%u\t%u\t-\t-\tF\t%u\tflush\n",
0282             device->minor, device->vnr,
0283             jiffies_to_msecs(now - device->flush_jif));
0284     }
0285 }
0286 
0287 static void seq_print_resource_pending_peer_requests(struct seq_file *m,
0288     struct drbd_resource *resource, unsigned long now)
0289 {
0290     struct drbd_device *device;
0291     unsigned int i;
0292 
0293     rcu_read_lock();
0294     idr_for_each_entry(&resource->devices, device, i) {
0295         seq_print_device_peer_requests(m, device, now);
0296     }
0297     rcu_read_unlock();
0298 }
0299 
0300 static void seq_print_resource_transfer_log_summary(struct seq_file *m,
0301     struct drbd_resource *resource,
0302     struct drbd_connection *connection,
0303     unsigned long now)
0304 {
0305     struct drbd_request *req;
0306     unsigned int count = 0;
0307     unsigned int show_state = 0;
0308 
0309     seq_puts(m, "n\tdevice\tvnr\t" RQ_HDR);
0310     spin_lock_irq(&resource->req_lock);
0311     list_for_each_entry(req, &connection->transfer_log, tl_requests) {
0312         unsigned int tmp = 0;
0313         unsigned int s;
0314         ++count;
0315 
0316         /* don't disable irq "forever" */
0317         if (!(count & 0x1ff)) {
0318             struct drbd_request *req_next;
0319             kref_get(&req->kref);
0320             spin_unlock_irq(&resource->req_lock);
0321             cond_resched();
0322             spin_lock_irq(&resource->req_lock);
0323             req_next = list_next_entry(req, tl_requests);
0324             if (kref_put(&req->kref, drbd_req_destroy))
0325                 req = req_next;
0326             if (&req->tl_requests == &connection->transfer_log)
0327                 break;
0328         }
0329 
0330         s = req->rq_state;
0331 
0332         /* This is meant to summarize timing issues, to be able to tell
0333          * local disk problems from network problems.
0334          * Skip requests, if we have shown an even older request with
0335          * similar aspects already.  */
0336         if (req->master_bio == NULL)
0337             tmp |= 1;
0338         if ((s & RQ_LOCAL_MASK) && (s & RQ_LOCAL_PENDING))
0339             tmp |= 2;
0340         if (s & RQ_NET_MASK) {
0341             if (!(s & RQ_NET_SENT))
0342                 tmp |= 4;
0343             if (s & RQ_NET_PENDING)
0344                 tmp |= 8;
0345             if (!(s & RQ_NET_DONE))
0346                 tmp |= 16;
0347         }
0348         if ((tmp & show_state) == tmp)
0349             continue;
0350         show_state |= tmp;
0351         seq_printf(m, "%u\t", count);
0352         seq_print_minor_vnr_req(m, req, now);
0353         if (show_state == 0x1f)
0354             break;
0355     }
0356     spin_unlock_irq(&resource->req_lock);
0357 }
0358 
0359 /* TODO: transfer_log and friends should be moved to resource */
0360 static int in_flight_summary_show(struct seq_file *m, void *pos)
0361 {
0362     struct drbd_resource *resource = m->private;
0363     struct drbd_connection *connection;
0364     unsigned long jif = jiffies;
0365 
0366     connection = first_connection(resource);
0367     /* This does not happen, actually.
0368      * But be robust and prepare for future code changes. */
0369     if (!connection || !kref_get_unless_zero(&connection->kref))
0370         return -ESTALE;
0371 
0372     /* BUMP me if you change the file format/content/presentation */
0373     seq_printf(m, "v: %u\n\n", 0);
0374 
0375     seq_puts(m, "oldest bitmap IO\n");
0376     seq_print_resource_pending_bitmap_io(m, resource, jif);
0377     seq_putc(m, '\n');
0378 
0379     seq_puts(m, "meta data IO\n");
0380     seq_print_resource_pending_meta_io(m, resource, jif);
0381     seq_putc(m, '\n');
0382 
0383     seq_puts(m, "socket buffer stats\n");
0384     /* for each connection ... once we have more than one */
0385     rcu_read_lock();
0386     if (connection->data.socket) {
0387         /* open coded SIOCINQ, the "relevant" part */
0388         struct tcp_sock *tp = tcp_sk(connection->data.socket->sk);
0389         int answ = tp->rcv_nxt - tp->copied_seq;
0390         seq_printf(m, "unread receive buffer: %u Byte\n", answ);
0391         /* open coded SIOCOUTQ, the "relevant" part */
0392         answ = tp->write_seq - tp->snd_una;
0393         seq_printf(m, "unacked send buffer: %u Byte\n", answ);
0394     }
0395     rcu_read_unlock();
0396     seq_putc(m, '\n');
0397 
0398     seq_puts(m, "oldest peer requests\n");
0399     seq_print_resource_pending_peer_requests(m, resource, jif);
0400     seq_putc(m, '\n');
0401 
0402     seq_puts(m, "application requests waiting for activity log\n");
0403     seq_print_waiting_for_AL(m, resource, jif);
0404     seq_putc(m, '\n');
0405 
0406     seq_puts(m, "oldest application requests\n");
0407     seq_print_resource_transfer_log_summary(m, resource, connection, jif);
0408     seq_putc(m, '\n');
0409 
0410     jif = jiffies - jif;
0411     if (jif)
0412         seq_printf(m, "generated in %d ms\n", jiffies_to_msecs(jif));
0413     kref_put(&connection->kref, drbd_destroy_connection);
0414     return 0;
0415 }
0416 
0417 /* make sure at *open* time that the respective object won't go away. */
0418 static int drbd_single_open(struct file *file, int (*show)(struct seq_file *, void *),
0419                         void *data, struct kref *kref,
0420                 void (*release)(struct kref *))
0421 {
0422     struct dentry *parent;
0423     int ret = -ESTALE;
0424 
0425     /* Are we still linked,
0426      * or has debugfs_remove() already been called? */
0427     parent = file->f_path.dentry->d_parent;
0428     /* serialize with d_delete() */
0429     inode_lock(d_inode(parent));
0430     /* Make sure the object is still alive */
0431     if (simple_positive(file->f_path.dentry)
0432     && kref_get_unless_zero(kref))
0433         ret = 0;
0434     inode_unlock(d_inode(parent));
0435     if (!ret) {
0436         ret = single_open(file, show, data);
0437         if (ret)
0438             kref_put(kref, release);
0439     }
0440     return ret;
0441 }
0442 
0443 static int in_flight_summary_open(struct inode *inode, struct file *file)
0444 {
0445     struct drbd_resource *resource = inode->i_private;
0446     return drbd_single_open(file, in_flight_summary_show, resource,
0447                 &resource->kref, drbd_destroy_resource);
0448 }
0449 
0450 static int in_flight_summary_release(struct inode *inode, struct file *file)
0451 {
0452     struct drbd_resource *resource = inode->i_private;
0453     kref_put(&resource->kref, drbd_destroy_resource);
0454     return single_release(inode, file);
0455 }
0456 
0457 static const struct file_operations in_flight_summary_fops = {
0458     .owner      = THIS_MODULE,
0459     .open       = in_flight_summary_open,
0460     .read       = seq_read,
0461     .llseek     = seq_lseek,
0462     .release    = in_flight_summary_release,
0463 };
0464 
0465 void drbd_debugfs_resource_add(struct drbd_resource *resource)
0466 {
0467     struct dentry *dentry;
0468 
0469     dentry = debugfs_create_dir(resource->name, drbd_debugfs_resources);
0470     resource->debugfs_res = dentry;
0471 
0472     dentry = debugfs_create_dir("volumes", resource->debugfs_res);
0473     resource->debugfs_res_volumes = dentry;
0474 
0475     dentry = debugfs_create_dir("connections", resource->debugfs_res);
0476     resource->debugfs_res_connections = dentry;
0477 
0478     dentry = debugfs_create_file("in_flight_summary", 0440,
0479                      resource->debugfs_res, resource,
0480                      &in_flight_summary_fops);
0481     resource->debugfs_res_in_flight_summary = dentry;
0482 }
0483 
0484 static void drbd_debugfs_remove(struct dentry **dp)
0485 {
0486     debugfs_remove(*dp);
0487     *dp = NULL;
0488 }
0489 
0490 void drbd_debugfs_resource_cleanup(struct drbd_resource *resource)
0491 {
0492     /* it is ok to call debugfs_remove(NULL) */
0493     drbd_debugfs_remove(&resource->debugfs_res_in_flight_summary);
0494     drbd_debugfs_remove(&resource->debugfs_res_connections);
0495     drbd_debugfs_remove(&resource->debugfs_res_volumes);
0496     drbd_debugfs_remove(&resource->debugfs_res);
0497 }
0498 
0499 static void seq_print_one_timing_detail(struct seq_file *m,
0500     const struct drbd_thread_timing_details *tdp,
0501     unsigned long now)
0502 {
0503     struct drbd_thread_timing_details td;
0504     /* No locking...
0505      * use temporary assignment to get at consistent data. */
0506     do {
0507         td = *tdp;
0508     } while (td.cb_nr != tdp->cb_nr);
0509     if (!td.cb_addr)
0510         return;
0511     seq_printf(m, "%u\t%d\t%s:%u\t%ps\n",
0512             td.cb_nr,
0513             jiffies_to_msecs(now - td.start_jif),
0514             td.caller_fn, td.line,
0515             td.cb_addr);
0516 }
0517 
0518 static void seq_print_timing_details(struct seq_file *m,
0519         const char *title,
0520         unsigned int cb_nr, struct drbd_thread_timing_details *tdp, unsigned long now)
0521 {
0522     unsigned int start_idx;
0523     unsigned int i;
0524 
0525     seq_printf(m, "%s\n", title);
0526     /* If not much is going on, this will result in natural ordering.
0527      * If it is very busy, we will possibly skip events, or even see wrap
0528      * arounds, which could only be avoided with locking.
0529      */
0530     start_idx = cb_nr % DRBD_THREAD_DETAILS_HIST;
0531     for (i = start_idx; i < DRBD_THREAD_DETAILS_HIST; i++)
0532         seq_print_one_timing_detail(m, tdp+i, now);
0533     for (i = 0; i < start_idx; i++)
0534         seq_print_one_timing_detail(m, tdp+i, now);
0535 }
0536 
0537 static int callback_history_show(struct seq_file *m, void *ignored)
0538 {
0539     struct drbd_connection *connection = m->private;
0540     unsigned long jif = jiffies;
0541 
0542     /* BUMP me if you change the file format/content/presentation */
0543     seq_printf(m, "v: %u\n\n", 0);
0544 
0545     seq_puts(m, "n\tage\tcallsite\tfn\n");
0546     seq_print_timing_details(m, "worker", connection->w_cb_nr, connection->w_timing_details, jif);
0547     seq_print_timing_details(m, "receiver", connection->r_cb_nr, connection->r_timing_details, jif);
0548     return 0;
0549 }
0550 
0551 static int callback_history_open(struct inode *inode, struct file *file)
0552 {
0553     struct drbd_connection *connection = inode->i_private;
0554     return drbd_single_open(file, callback_history_show, connection,
0555                 &connection->kref, drbd_destroy_connection);
0556 }
0557 
0558 static int callback_history_release(struct inode *inode, struct file *file)
0559 {
0560     struct drbd_connection *connection = inode->i_private;
0561     kref_put(&connection->kref, drbd_destroy_connection);
0562     return single_release(inode, file);
0563 }
0564 
0565 static const struct file_operations connection_callback_history_fops = {
0566     .owner      = THIS_MODULE,
0567     .open       = callback_history_open,
0568     .read       = seq_read,
0569     .llseek     = seq_lseek,
0570     .release    = callback_history_release,
0571 };
0572 
0573 static int connection_oldest_requests_show(struct seq_file *m, void *ignored)
0574 {
0575     struct drbd_connection *connection = m->private;
0576     unsigned long now = jiffies;
0577     struct drbd_request *r1, *r2;
0578 
0579     /* BUMP me if you change the file format/content/presentation */
0580     seq_printf(m, "v: %u\n\n", 0);
0581 
0582     spin_lock_irq(&connection->resource->req_lock);
0583     r1 = connection->req_next;
0584     if (r1)
0585         seq_print_minor_vnr_req(m, r1, now);
0586     r2 = connection->req_ack_pending;
0587     if (r2 && r2 != r1) {
0588         r1 = r2;
0589         seq_print_minor_vnr_req(m, r1, now);
0590     }
0591     r2 = connection->req_not_net_done;
0592     if (r2 && r2 != r1)
0593         seq_print_minor_vnr_req(m, r2, now);
0594     spin_unlock_irq(&connection->resource->req_lock);
0595     return 0;
0596 }
0597 
0598 static int connection_oldest_requests_open(struct inode *inode, struct file *file)
0599 {
0600     struct drbd_connection *connection = inode->i_private;
0601     return drbd_single_open(file, connection_oldest_requests_show, connection,
0602                 &connection->kref, drbd_destroy_connection);
0603 }
0604 
0605 static int connection_oldest_requests_release(struct inode *inode, struct file *file)
0606 {
0607     struct drbd_connection *connection = inode->i_private;
0608     kref_put(&connection->kref, drbd_destroy_connection);
0609     return single_release(inode, file);
0610 }
0611 
0612 static const struct file_operations connection_oldest_requests_fops = {
0613     .owner      = THIS_MODULE,
0614     .open       = connection_oldest_requests_open,
0615     .read       = seq_read,
0616     .llseek     = seq_lseek,
0617     .release    = connection_oldest_requests_release,
0618 };
0619 
0620 void drbd_debugfs_connection_add(struct drbd_connection *connection)
0621 {
0622     struct dentry *conns_dir = connection->resource->debugfs_res_connections;
0623     struct dentry *dentry;
0624 
0625     /* Once we enable mutliple peers,
0626      * these connections will have descriptive names.
0627      * For now, it is just the one connection to the (only) "peer". */
0628     dentry = debugfs_create_dir("peer", conns_dir);
0629     connection->debugfs_conn = dentry;
0630 
0631     dentry = debugfs_create_file("callback_history", 0440,
0632                      connection->debugfs_conn, connection,
0633                      &connection_callback_history_fops);
0634     connection->debugfs_conn_callback_history = dentry;
0635 
0636     dentry = debugfs_create_file("oldest_requests", 0440,
0637                      connection->debugfs_conn, connection,
0638                      &connection_oldest_requests_fops);
0639     connection->debugfs_conn_oldest_requests = dentry;
0640 }
0641 
0642 void drbd_debugfs_connection_cleanup(struct drbd_connection *connection)
0643 {
0644     drbd_debugfs_remove(&connection->debugfs_conn_callback_history);
0645     drbd_debugfs_remove(&connection->debugfs_conn_oldest_requests);
0646     drbd_debugfs_remove(&connection->debugfs_conn);
0647 }
0648 
0649 static void resync_dump_detail(struct seq_file *m, struct lc_element *e)
0650 {
0651        struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
0652 
0653        seq_printf(m, "%5d %s %s %s", bme->rs_left,
0654           test_bit(BME_NO_WRITES, &bme->flags) ? "NO_WRITES" : "---------",
0655           test_bit(BME_LOCKED, &bme->flags) ? "LOCKED" : "------",
0656           test_bit(BME_PRIORITY, &bme->flags) ? "PRIORITY" : "--------"
0657           );
0658 }
0659 
0660 static int device_resync_extents_show(struct seq_file *m, void *ignored)
0661 {
0662     struct drbd_device *device = m->private;
0663 
0664     /* BUMP me if you change the file format/content/presentation */
0665     seq_printf(m, "v: %u\n\n", 0);
0666 
0667     if (get_ldev_if_state(device, D_FAILED)) {
0668         lc_seq_printf_stats(m, device->resync);
0669         lc_seq_dump_details(m, device->resync, "rs_left flags", resync_dump_detail);
0670         put_ldev(device);
0671     }
0672     return 0;
0673 }
0674 
0675 static int device_act_log_extents_show(struct seq_file *m, void *ignored)
0676 {
0677     struct drbd_device *device = m->private;
0678 
0679     /* BUMP me if you change the file format/content/presentation */
0680     seq_printf(m, "v: %u\n\n", 0);
0681 
0682     if (get_ldev_if_state(device, D_FAILED)) {
0683         lc_seq_printf_stats(m, device->act_log);
0684         lc_seq_dump_details(m, device->act_log, "", NULL);
0685         put_ldev(device);
0686     }
0687     return 0;
0688 }
0689 
0690 static int device_oldest_requests_show(struct seq_file *m, void *ignored)
0691 {
0692     struct drbd_device *device = m->private;
0693     struct drbd_resource *resource = device->resource;
0694     unsigned long now = jiffies;
0695     struct drbd_request *r1, *r2;
0696     int i;
0697 
0698     /* BUMP me if you change the file format/content/presentation */
0699     seq_printf(m, "v: %u\n\n", 0);
0700 
0701     seq_puts(m, RQ_HDR);
0702     spin_lock_irq(&resource->req_lock);
0703     /* WRITE, then READ */
0704     for (i = 1; i >= 0; --i) {
0705         r1 = list_first_entry_or_null(&device->pending_master_completion[i],
0706             struct drbd_request, req_pending_master_completion);
0707         r2 = list_first_entry_or_null(&device->pending_completion[i],
0708             struct drbd_request, req_pending_local);
0709         if (r1)
0710             seq_print_one_request(m, r1, now);
0711         if (r2 && r2 != r1)
0712             seq_print_one_request(m, r2, now);
0713     }
0714     spin_unlock_irq(&resource->req_lock);
0715     return 0;
0716 }
0717 
0718 static int device_data_gen_id_show(struct seq_file *m, void *ignored)
0719 {
0720     struct drbd_device *device = m->private;
0721     struct drbd_md *md;
0722     enum drbd_uuid_index idx;
0723 
0724     if (!get_ldev_if_state(device, D_FAILED))
0725         return -ENODEV;
0726 
0727     md = &device->ldev->md;
0728     spin_lock_irq(&md->uuid_lock);
0729     for (idx = UI_CURRENT; idx <= UI_HISTORY_END; idx++) {
0730         seq_printf(m, "0x%016llX\n", md->uuid[idx]);
0731     }
0732     spin_unlock_irq(&md->uuid_lock);
0733     put_ldev(device);
0734     return 0;
0735 }
0736 
0737 static int device_ed_gen_id_show(struct seq_file *m, void *ignored)
0738 {
0739     struct drbd_device *device = m->private;
0740     seq_printf(m, "0x%016llX\n", (unsigned long long)device->ed_uuid);
0741     return 0;
0742 }
0743 
0744 #define drbd_debugfs_device_attr(name)                      \
0745 static int device_ ## name ## _open(struct inode *inode, struct file *file) \
0746 {                                       \
0747     struct drbd_device *device = inode->i_private;              \
0748     return drbd_single_open(file, device_ ## name ## _show, device,     \
0749                 &device->kref, drbd_destroy_device);        \
0750 }                                       \
0751 static int device_ ## name ## _release(struct inode *inode, struct file *file)  \
0752 {                                       \
0753     struct drbd_device *device = inode->i_private;              \
0754     kref_put(&device->kref, drbd_destroy_device);               \
0755     return single_release(inode, file);                 \
0756 }                                       \
0757 static const struct file_operations device_ ## name ## _fops = {        \
0758     .owner      = THIS_MODULE,                      \
0759     .open       = device_ ## name ## _open,             \
0760     .read       = seq_read,                     \
0761     .llseek     = seq_lseek,                        \
0762     .release    = device_ ## name ## _release,              \
0763 };
0764 
0765 drbd_debugfs_device_attr(oldest_requests)
0766 drbd_debugfs_device_attr(act_log_extents)
0767 drbd_debugfs_device_attr(resync_extents)
0768 drbd_debugfs_device_attr(data_gen_id)
0769 drbd_debugfs_device_attr(ed_gen_id)
0770 
0771 void drbd_debugfs_device_add(struct drbd_device *device)
0772 {
0773     struct dentry *vols_dir = device->resource->debugfs_res_volumes;
0774     char minor_buf[8]; /* MINORMASK, MINORBITS == 20; */
0775     char vnr_buf[8];   /* volume number vnr is even 16 bit only; */
0776     char *slink_name = NULL;
0777 
0778     struct dentry *dentry;
0779     if (!vols_dir || !drbd_debugfs_minors)
0780         return;
0781 
0782     snprintf(vnr_buf, sizeof(vnr_buf), "%u", device->vnr);
0783     dentry = debugfs_create_dir(vnr_buf, vols_dir);
0784     device->debugfs_vol = dentry;
0785 
0786     snprintf(minor_buf, sizeof(minor_buf), "%u", device->minor);
0787     slink_name = kasprintf(GFP_KERNEL, "../resources/%s/volumes/%u",
0788             device->resource->name, device->vnr);
0789     if (!slink_name)
0790         goto fail;
0791     dentry = debugfs_create_symlink(minor_buf, drbd_debugfs_minors, slink_name);
0792     device->debugfs_minor = dentry;
0793     kfree(slink_name);
0794     slink_name = NULL;
0795 
0796 #define DCF(name)   do {                    \
0797     dentry = debugfs_create_file(#name, 0440,   \
0798             device->debugfs_vol, device,        \
0799             &device_ ## name ## _fops);     \
0800     device->debugfs_vol_ ## name = dentry;          \
0801     } while (0)
0802 
0803     DCF(oldest_requests);
0804     DCF(act_log_extents);
0805     DCF(resync_extents);
0806     DCF(data_gen_id);
0807     DCF(ed_gen_id);
0808 #undef DCF
0809     return;
0810 
0811 fail:
0812     drbd_debugfs_device_cleanup(device);
0813     drbd_err(device, "failed to create debugfs entries\n");
0814 }
0815 
0816 void drbd_debugfs_device_cleanup(struct drbd_device *device)
0817 {
0818     drbd_debugfs_remove(&device->debugfs_minor);
0819     drbd_debugfs_remove(&device->debugfs_vol_oldest_requests);
0820     drbd_debugfs_remove(&device->debugfs_vol_act_log_extents);
0821     drbd_debugfs_remove(&device->debugfs_vol_resync_extents);
0822     drbd_debugfs_remove(&device->debugfs_vol_data_gen_id);
0823     drbd_debugfs_remove(&device->debugfs_vol_ed_gen_id);
0824     drbd_debugfs_remove(&device->debugfs_vol);
0825 }
0826 
0827 void drbd_debugfs_peer_device_add(struct drbd_peer_device *peer_device)
0828 {
0829     struct dentry *conn_dir = peer_device->connection->debugfs_conn;
0830     struct dentry *dentry;
0831     char vnr_buf[8];
0832 
0833     snprintf(vnr_buf, sizeof(vnr_buf), "%u", peer_device->device->vnr);
0834     dentry = debugfs_create_dir(vnr_buf, conn_dir);
0835     peer_device->debugfs_peer_dev = dentry;
0836 }
0837 
0838 void drbd_debugfs_peer_device_cleanup(struct drbd_peer_device *peer_device)
0839 {
0840     drbd_debugfs_remove(&peer_device->debugfs_peer_dev);
0841 }
0842 
0843 static int drbd_version_show(struct seq_file *m, void *ignored)
0844 {
0845     seq_printf(m, "# %s\n", drbd_buildtag());
0846     seq_printf(m, "VERSION=%s\n", REL_VERSION);
0847     seq_printf(m, "API_VERSION=%u\n", API_VERSION);
0848     seq_printf(m, "PRO_VERSION_MIN=%u\n", PRO_VERSION_MIN);
0849     seq_printf(m, "PRO_VERSION_MAX=%u\n", PRO_VERSION_MAX);
0850     return 0;
0851 }
0852 
0853 static int drbd_version_open(struct inode *inode, struct file *file)
0854 {
0855     return single_open(file, drbd_version_show, NULL);
0856 }
0857 
0858 static const struct file_operations drbd_version_fops = {
0859     .owner = THIS_MODULE,
0860     .open = drbd_version_open,
0861     .llseek = seq_lseek,
0862     .read = seq_read,
0863     .release = single_release,
0864 };
0865 
0866 /* not __exit, may be indirectly called
0867  * from the module-load-failure path as well. */
0868 void drbd_debugfs_cleanup(void)
0869 {
0870     drbd_debugfs_remove(&drbd_debugfs_resources);
0871     drbd_debugfs_remove(&drbd_debugfs_minors);
0872     drbd_debugfs_remove(&drbd_debugfs_version);
0873     drbd_debugfs_remove(&drbd_debugfs_root);
0874 }
0875 
0876 void __init drbd_debugfs_init(void)
0877 {
0878     struct dentry *dentry;
0879 
0880     dentry = debugfs_create_dir("drbd", NULL);
0881     drbd_debugfs_root = dentry;
0882 
0883     dentry = debugfs_create_file("version", 0444, drbd_debugfs_root, NULL, &drbd_version_fops);
0884     drbd_debugfs_version = dentry;
0885 
0886     dentry = debugfs_create_dir("resources", drbd_debugfs_root);
0887     drbd_debugfs_resources = dentry;
0888 
0889     dentry = debugfs_create_dir("minors", drbd_debugfs_root);
0890     drbd_debugfs_minors = dentry;
0891 }