14d3d5aa8SLars Ellenberg #define pr_fmt(fmt) "drbd debugfs: " fmt 24d3d5aa8SLars Ellenberg #include <linux/kernel.h> 34d3d5aa8SLars Ellenberg #include <linux/module.h> 44d3d5aa8SLars Ellenberg #include <linux/debugfs.h> 5*db1866ffSLars Ellenberg #include <linux/seq_file.h> 64d3d5aa8SLars Ellenberg #include <linux/stat.h> 7*db1866ffSLars Ellenberg #include <linux/jiffies.h> 84d3d5aa8SLars Ellenberg #include <linux/list.h> 94d3d5aa8SLars Ellenberg 104d3d5aa8SLars Ellenberg #include "drbd_int.h" 114d3d5aa8SLars Ellenberg #include "drbd_req.h" 124d3d5aa8SLars Ellenberg #include "drbd_debugfs.h" 134d3d5aa8SLars Ellenberg 144d3d5aa8SLars Ellenberg static struct dentry *drbd_debugfs_root; 154d3d5aa8SLars Ellenberg static struct dentry *drbd_debugfs_resources; 164d3d5aa8SLars Ellenberg static struct dentry *drbd_debugfs_minors; 174d3d5aa8SLars Ellenberg 18*db1866ffSLars Ellenberg static void seq_print_age_or_dash(struct seq_file *m, bool valid, unsigned long dt) 19*db1866ffSLars Ellenberg { 20*db1866ffSLars Ellenberg if (valid) 21*db1866ffSLars Ellenberg seq_printf(m, "\t%d", jiffies_to_msecs(dt)); 22*db1866ffSLars Ellenberg else 23*db1866ffSLars Ellenberg seq_printf(m, "\t-"); 24*db1866ffSLars Ellenberg } 25*db1866ffSLars Ellenberg 26*db1866ffSLars Ellenberg static void seq_print_rq_state_bit(struct seq_file *m, 27*db1866ffSLars Ellenberg bool is_set, char *sep, const char *name) 28*db1866ffSLars Ellenberg { 29*db1866ffSLars Ellenberg if (!is_set) 30*db1866ffSLars Ellenberg return; 31*db1866ffSLars Ellenberg seq_putc(m, *sep); 32*db1866ffSLars Ellenberg seq_puts(m, name); 33*db1866ffSLars Ellenberg *sep = '|'; 34*db1866ffSLars Ellenberg } 35*db1866ffSLars Ellenberg 36*db1866ffSLars Ellenberg /* pretty print enum drbd_req_state_bits req->rq_state */ 37*db1866ffSLars Ellenberg static void seq_print_request_state(struct seq_file *m, struct drbd_request *req) 38*db1866ffSLars Ellenberg { 39*db1866ffSLars Ellenberg unsigned int s = req->rq_state; 40*db1866ffSLars Ellenberg char sep = ' '; 41*db1866ffSLars Ellenberg seq_printf(m, "\t0x%08x", s); 42*db1866ffSLars Ellenberg seq_printf(m, "\tmaster: %s", req->master_bio ? "pending" : "completed"); 43*db1866ffSLars Ellenberg 44*db1866ffSLars Ellenberg /* RQ_WRITE ignored, already reported */ 45*db1866ffSLars Ellenberg seq_puts(m, "\tlocal:"); 46*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_IN_ACT_LOG, &sep, "in-AL"); 47*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_POSTPONED, &sep, "postponed"); 48*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_COMPLETION_SUSP, &sep, "suspended"); 49*db1866ffSLars Ellenberg sep = ' '; 50*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_LOCAL_PENDING, &sep, "pending"); 51*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_LOCAL_COMPLETED, &sep, "completed"); 52*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_LOCAL_ABORTED, &sep, "aborted"); 53*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_LOCAL_OK, &sep, "ok"); 54*db1866ffSLars Ellenberg if (sep == ' ') 55*db1866ffSLars Ellenberg seq_puts(m, " -"); 56*db1866ffSLars Ellenberg 57*db1866ffSLars Ellenberg /* for_each_connection ... */ 58*db1866ffSLars Ellenberg seq_printf(m, "\tnet:"); 59*db1866ffSLars Ellenberg sep = ' '; 60*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_NET_PENDING, &sep, "pending"); 61*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_NET_QUEUED, &sep, "queued"); 62*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_NET_SENT, &sep, "sent"); 63*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_NET_DONE, &sep, "done"); 64*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_NET_SIS, &sep, "sis"); 65*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_NET_OK, &sep, "ok"); 66*db1866ffSLars Ellenberg if (sep == ' ') 67*db1866ffSLars Ellenberg seq_puts(m, " -"); 68*db1866ffSLars Ellenberg 69*db1866ffSLars Ellenberg seq_printf(m, " :"); 70*db1866ffSLars Ellenberg sep = ' '; 71*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_EXP_RECEIVE_ACK, &sep, "B"); 72*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_EXP_WRITE_ACK, &sep, "C"); 73*db1866ffSLars Ellenberg seq_print_rq_state_bit(m, s & RQ_EXP_BARR_ACK, &sep, "barr"); 74*db1866ffSLars Ellenberg if (sep == ' ') 75*db1866ffSLars Ellenberg seq_puts(m, " -"); 76*db1866ffSLars Ellenberg seq_printf(m, "\n"); 77*db1866ffSLars Ellenberg } 78*db1866ffSLars Ellenberg 79*db1866ffSLars Ellenberg static void seq_print_one_request(struct seq_file *m, struct drbd_request *req, unsigned long now) 80*db1866ffSLars Ellenberg { 81*db1866ffSLars Ellenberg /* change anything here, fixup header below! */ 82*db1866ffSLars Ellenberg unsigned int s = req->rq_state; 83*db1866ffSLars Ellenberg 84*db1866ffSLars Ellenberg #define RQ_HDR_1 "epoch\tsector\tsize\trw" 85*db1866ffSLars Ellenberg seq_printf(m, "0x%x\t%llu\t%u\t%s", 86*db1866ffSLars Ellenberg req->epoch, 87*db1866ffSLars Ellenberg (unsigned long long)req->i.sector, req->i.size >> 9, 88*db1866ffSLars Ellenberg (s & RQ_WRITE) ? "W" : "R"); 89*db1866ffSLars Ellenberg 90*db1866ffSLars Ellenberg #define RQ_HDR_2 "\tstart\tin AL\tsubmit" 91*db1866ffSLars Ellenberg seq_printf(m, "\t%d", jiffies_to_msecs(now - req->start_jif)); 92*db1866ffSLars Ellenberg seq_print_age_or_dash(m, s & RQ_IN_ACT_LOG, now - req->in_actlog_jif); 93*db1866ffSLars Ellenberg seq_print_age_or_dash(m, s & RQ_LOCAL_PENDING, now - req->pre_submit_jif); 94*db1866ffSLars Ellenberg 95*db1866ffSLars Ellenberg #define RQ_HDR_3 "\tsent\tacked\tdone" 96*db1866ffSLars Ellenberg seq_print_age_or_dash(m, s & RQ_NET_SENT, now - req->pre_send_jif); 97*db1866ffSLars Ellenberg seq_print_age_or_dash(m, (s & RQ_NET_SENT) && !(s & RQ_NET_PENDING), now - req->acked_jif); 98*db1866ffSLars Ellenberg seq_print_age_or_dash(m, s & RQ_NET_DONE, now - req->net_done_jif); 99*db1866ffSLars Ellenberg 100*db1866ffSLars Ellenberg #define RQ_HDR_4 "\tstate\n" 101*db1866ffSLars Ellenberg seq_print_request_state(m, req); 102*db1866ffSLars Ellenberg } 103*db1866ffSLars Ellenberg #define RQ_HDR RQ_HDR_1 RQ_HDR_2 RQ_HDR_3 RQ_HDR_4 104*db1866ffSLars Ellenberg 105*db1866ffSLars Ellenberg static void seq_print_minor_vnr_req(struct seq_file *m, struct drbd_request *req, unsigned long now) 106*db1866ffSLars Ellenberg { 107*db1866ffSLars Ellenberg seq_printf(m, "%u\t%u\t", req->device->minor, req->device->vnr); 108*db1866ffSLars Ellenberg seq_print_one_request(m, req, now); 109*db1866ffSLars Ellenberg } 110*db1866ffSLars Ellenberg 111*db1866ffSLars Ellenberg static void seq_print_resource_transfer_log_summary(struct seq_file *m, 112*db1866ffSLars Ellenberg struct drbd_resource *resource, 113*db1866ffSLars Ellenberg struct drbd_connection *connection, 114*db1866ffSLars Ellenberg unsigned long now) 115*db1866ffSLars Ellenberg { 116*db1866ffSLars Ellenberg struct drbd_request *req; 117*db1866ffSLars Ellenberg unsigned int count = 0; 118*db1866ffSLars Ellenberg unsigned int show_state = 0; 119*db1866ffSLars Ellenberg 120*db1866ffSLars Ellenberg seq_puts(m, "n\tdevice\tvnr\t" RQ_HDR); 121*db1866ffSLars Ellenberg spin_lock_irq(&resource->req_lock); 122*db1866ffSLars Ellenberg list_for_each_entry(req, &connection->transfer_log, tl_requests) { 123*db1866ffSLars Ellenberg unsigned int tmp = 0; 124*db1866ffSLars Ellenberg unsigned int s; 125*db1866ffSLars Ellenberg ++count; 126*db1866ffSLars Ellenberg 127*db1866ffSLars Ellenberg /* don't disable irq "forever" */ 128*db1866ffSLars Ellenberg if (!(count & 0x1ff)) { 129*db1866ffSLars Ellenberg struct drbd_request *req_next; 130*db1866ffSLars Ellenberg kref_get(&req->kref); 131*db1866ffSLars Ellenberg spin_unlock_irq(&resource->req_lock); 132*db1866ffSLars Ellenberg cond_resched(); 133*db1866ffSLars Ellenberg spin_lock_irq(&resource->req_lock); 134*db1866ffSLars Ellenberg req_next = list_next_entry(req, tl_requests); 135*db1866ffSLars Ellenberg if (kref_put(&req->kref, drbd_req_destroy)) 136*db1866ffSLars Ellenberg req = req_next; 137*db1866ffSLars Ellenberg if (&req->tl_requests == &connection->transfer_log) 138*db1866ffSLars Ellenberg break; 139*db1866ffSLars Ellenberg } 140*db1866ffSLars Ellenberg 141*db1866ffSLars Ellenberg s = req->rq_state; 142*db1866ffSLars Ellenberg 143*db1866ffSLars Ellenberg /* This is meant to summarize timing issues, to be able to tell 144*db1866ffSLars Ellenberg * local disk problems from network problems. 145*db1866ffSLars Ellenberg * Skip requests, if we have shown an even older request with 146*db1866ffSLars Ellenberg * similar aspects already. */ 147*db1866ffSLars Ellenberg if (req->master_bio == NULL) 148*db1866ffSLars Ellenberg tmp |= 1; 149*db1866ffSLars Ellenberg if ((s & RQ_LOCAL_MASK) && (s & RQ_LOCAL_PENDING)) 150*db1866ffSLars Ellenberg tmp |= 2; 151*db1866ffSLars Ellenberg if (s & RQ_NET_MASK) { 152*db1866ffSLars Ellenberg if (!(s & RQ_NET_SENT)) 153*db1866ffSLars Ellenberg tmp |= 4; 154*db1866ffSLars Ellenberg if (s & RQ_NET_PENDING) 155*db1866ffSLars Ellenberg tmp |= 8; 156*db1866ffSLars Ellenberg if (!(s & RQ_NET_DONE)) 157*db1866ffSLars Ellenberg tmp |= 16; 158*db1866ffSLars Ellenberg } 159*db1866ffSLars Ellenberg if ((tmp & show_state) == tmp) 160*db1866ffSLars Ellenberg continue; 161*db1866ffSLars Ellenberg show_state |= tmp; 162*db1866ffSLars Ellenberg seq_printf(m, "%u\t", count); 163*db1866ffSLars Ellenberg seq_print_minor_vnr_req(m, req, now); 164*db1866ffSLars Ellenberg if (show_state == 0x1f) 165*db1866ffSLars Ellenberg break; 166*db1866ffSLars Ellenberg } 167*db1866ffSLars Ellenberg spin_unlock_irq(&resource->req_lock); 168*db1866ffSLars Ellenberg } 169*db1866ffSLars Ellenberg 170*db1866ffSLars Ellenberg /* TODO: transfer_log and friends should be moved to resource */ 171*db1866ffSLars Ellenberg static int in_flight_summary_show(struct seq_file *m, void *pos) 172*db1866ffSLars Ellenberg { 173*db1866ffSLars Ellenberg struct drbd_resource *resource = m->private; 174*db1866ffSLars Ellenberg struct drbd_connection *connection; 175*db1866ffSLars Ellenberg unsigned long jif = jiffies; 176*db1866ffSLars Ellenberg 177*db1866ffSLars Ellenberg connection = first_connection(resource); 178*db1866ffSLars Ellenberg /* This does not happen, actually. 179*db1866ffSLars Ellenberg * But be robust and prepare for future code changes. */ 180*db1866ffSLars Ellenberg if (!connection) 181*db1866ffSLars Ellenberg return 0; 182*db1866ffSLars Ellenberg 183*db1866ffSLars Ellenberg seq_puts(m, "oldest application requests\n"); 184*db1866ffSLars Ellenberg seq_print_resource_transfer_log_summary(m, resource, connection, jif); 185*db1866ffSLars Ellenberg seq_putc(m, '\n'); 186*db1866ffSLars Ellenberg 187*db1866ffSLars Ellenberg jif = jiffies - jif; 188*db1866ffSLars Ellenberg if (jif) 189*db1866ffSLars Ellenberg seq_printf(m, "generated in %d ms\n", jiffies_to_msecs(jif)); 190*db1866ffSLars Ellenberg return 0; 191*db1866ffSLars Ellenberg } 192*db1866ffSLars Ellenberg 193*db1866ffSLars Ellenberg static int in_flight_summary_open(struct inode *inode, struct file *file) 194*db1866ffSLars Ellenberg { 195*db1866ffSLars Ellenberg return single_open(file, in_flight_summary_show, inode->i_private); 196*db1866ffSLars Ellenberg } 197*db1866ffSLars Ellenberg 198*db1866ffSLars Ellenberg static const struct file_operations in_flight_summary_fops = { 199*db1866ffSLars Ellenberg .owner = THIS_MODULE, 200*db1866ffSLars Ellenberg .open = in_flight_summary_open, 201*db1866ffSLars Ellenberg .read = seq_read, 202*db1866ffSLars Ellenberg .llseek = seq_lseek, 203*db1866ffSLars Ellenberg .release = single_release, 204*db1866ffSLars Ellenberg }; 205*db1866ffSLars Ellenberg 2064d3d5aa8SLars Ellenberg void drbd_debugfs_resource_add(struct drbd_resource *resource) 2074d3d5aa8SLars Ellenberg { 2084d3d5aa8SLars Ellenberg struct dentry *dentry; 2094d3d5aa8SLars Ellenberg if (!drbd_debugfs_resources) 2104d3d5aa8SLars Ellenberg return; 2114d3d5aa8SLars Ellenberg 2124d3d5aa8SLars Ellenberg dentry = debugfs_create_dir(resource->name, drbd_debugfs_resources); 2134d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 2144d3d5aa8SLars Ellenberg goto fail; 2154d3d5aa8SLars Ellenberg resource->debugfs_res = dentry; 2164d3d5aa8SLars Ellenberg 2174d3d5aa8SLars Ellenberg dentry = debugfs_create_dir("volumes", resource->debugfs_res); 2184d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 2194d3d5aa8SLars Ellenberg goto fail; 2204d3d5aa8SLars Ellenberg resource->debugfs_res_volumes = dentry; 2214d3d5aa8SLars Ellenberg 2224d3d5aa8SLars Ellenberg dentry = debugfs_create_dir("connections", resource->debugfs_res); 2234d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 2244d3d5aa8SLars Ellenberg goto fail; 2254d3d5aa8SLars Ellenberg resource->debugfs_res_connections = dentry; 2264d3d5aa8SLars Ellenberg 227*db1866ffSLars Ellenberg dentry = debugfs_create_file("in_flight_summary", S_IRUSR|S_IRGRP, 228*db1866ffSLars Ellenberg resource->debugfs_res, resource, 229*db1866ffSLars Ellenberg &in_flight_summary_fops); 230*db1866ffSLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 231*db1866ffSLars Ellenberg goto fail; 232*db1866ffSLars Ellenberg resource->debugfs_res_in_flight_summary = dentry; 2334d3d5aa8SLars Ellenberg return; 2344d3d5aa8SLars Ellenberg 2354d3d5aa8SLars Ellenberg fail: 2364d3d5aa8SLars Ellenberg drbd_debugfs_resource_cleanup(resource); 2374d3d5aa8SLars Ellenberg drbd_err(resource, "failed to create debugfs dentry\n"); 2384d3d5aa8SLars Ellenberg } 2394d3d5aa8SLars Ellenberg 2404d3d5aa8SLars Ellenberg static void drbd_debugfs_remove(struct dentry **dp) 2414d3d5aa8SLars Ellenberg { 2424d3d5aa8SLars Ellenberg debugfs_remove(*dp); 2434d3d5aa8SLars Ellenberg *dp = NULL; 2444d3d5aa8SLars Ellenberg } 2454d3d5aa8SLars Ellenberg 2464d3d5aa8SLars Ellenberg void drbd_debugfs_resource_cleanup(struct drbd_resource *resource) 2474d3d5aa8SLars Ellenberg { 2484d3d5aa8SLars Ellenberg /* it is ok to call debugfs_remove(NULL) */ 2494d3d5aa8SLars Ellenberg drbd_debugfs_remove(&resource->debugfs_res_in_flight_summary); 2504d3d5aa8SLars Ellenberg drbd_debugfs_remove(&resource->debugfs_res_connections); 2514d3d5aa8SLars Ellenberg drbd_debugfs_remove(&resource->debugfs_res_volumes); 2524d3d5aa8SLars Ellenberg drbd_debugfs_remove(&resource->debugfs_res); 2534d3d5aa8SLars Ellenberg } 2544d3d5aa8SLars Ellenberg 2554d3d5aa8SLars Ellenberg void drbd_debugfs_connection_add(struct drbd_connection *connection) 2564d3d5aa8SLars Ellenberg { 2574d3d5aa8SLars Ellenberg struct dentry *conns_dir = connection->resource->debugfs_res_connections; 2584d3d5aa8SLars Ellenberg struct dentry *dentry; 2594d3d5aa8SLars Ellenberg if (!conns_dir) 2604d3d5aa8SLars Ellenberg return; 2614d3d5aa8SLars Ellenberg 2624d3d5aa8SLars Ellenberg /* Once we enable mutliple peers, 2634d3d5aa8SLars Ellenberg * these connections will have descriptive names. 2644d3d5aa8SLars Ellenberg * For now, it is just the one connection to the (only) "peer". */ 2654d3d5aa8SLars Ellenberg dentry = debugfs_create_dir("peer", conns_dir); 2664d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 2674d3d5aa8SLars Ellenberg goto fail; 2684d3d5aa8SLars Ellenberg connection->debugfs_conn = dentry; 2694d3d5aa8SLars Ellenberg return; 2704d3d5aa8SLars Ellenberg 2714d3d5aa8SLars Ellenberg fail: 2724d3d5aa8SLars Ellenberg drbd_debugfs_connection_cleanup(connection); 2734d3d5aa8SLars Ellenberg drbd_err(connection, "failed to create debugfs dentry\n"); 2744d3d5aa8SLars Ellenberg } 2754d3d5aa8SLars Ellenberg 2764d3d5aa8SLars Ellenberg void drbd_debugfs_connection_cleanup(struct drbd_connection *connection) 2774d3d5aa8SLars Ellenberg { 2784d3d5aa8SLars Ellenberg drbd_debugfs_remove(&connection->debugfs_conn_callback_history); 2794d3d5aa8SLars Ellenberg drbd_debugfs_remove(&connection->debugfs_conn_oldest_requests); 2804d3d5aa8SLars Ellenberg drbd_debugfs_remove(&connection->debugfs_conn); 2814d3d5aa8SLars Ellenberg } 2824d3d5aa8SLars Ellenberg 2834d3d5aa8SLars Ellenberg void drbd_debugfs_device_add(struct drbd_device *device) 2844d3d5aa8SLars Ellenberg { 2854d3d5aa8SLars Ellenberg struct dentry *vols_dir = device->resource->debugfs_res_volumes; 2864d3d5aa8SLars Ellenberg char minor_buf[8]; /* MINORMASK, MINORBITS == 20; */ 2874d3d5aa8SLars Ellenberg char vnr_buf[8]; /* volume number vnr is even 16 bit only; */ 2884d3d5aa8SLars Ellenberg char *slink_name = NULL; 2894d3d5aa8SLars Ellenberg 2904d3d5aa8SLars Ellenberg struct dentry *dentry; 2914d3d5aa8SLars Ellenberg if (!vols_dir || !drbd_debugfs_minors) 2924d3d5aa8SLars Ellenberg return; 2934d3d5aa8SLars Ellenberg 2944d3d5aa8SLars Ellenberg snprintf(vnr_buf, sizeof(vnr_buf), "%u", device->vnr); 2954d3d5aa8SLars Ellenberg dentry = debugfs_create_dir(vnr_buf, vols_dir); 2964d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 2974d3d5aa8SLars Ellenberg goto fail; 2984d3d5aa8SLars Ellenberg device->debugfs_vol = dentry; 2994d3d5aa8SLars Ellenberg 3004d3d5aa8SLars Ellenberg snprintf(minor_buf, sizeof(minor_buf), "%u", device->minor); 3014d3d5aa8SLars Ellenberg slink_name = kasprintf(GFP_KERNEL, "../resources/%s/volumes/%u", 3024d3d5aa8SLars Ellenberg device->resource->name, device->vnr); 3034d3d5aa8SLars Ellenberg if (!slink_name) 3044d3d5aa8SLars Ellenberg goto fail; 3054d3d5aa8SLars Ellenberg dentry = debugfs_create_symlink(minor_buf, drbd_debugfs_minors, slink_name); 3064d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 3074d3d5aa8SLars Ellenberg goto fail; 3084d3d5aa8SLars Ellenberg device->debugfs_minor = dentry; 3094d3d5aa8SLars Ellenberg kfree(slink_name); 3104d3d5aa8SLars Ellenberg 3114d3d5aa8SLars Ellenberg fail: 3124d3d5aa8SLars Ellenberg drbd_debugfs_device_cleanup(device); 3134d3d5aa8SLars Ellenberg drbd_err(device, "failed to create debugfs entries\n"); 3144d3d5aa8SLars Ellenberg } 3154d3d5aa8SLars Ellenberg 3164d3d5aa8SLars Ellenberg void drbd_debugfs_device_cleanup(struct drbd_device *device) 3174d3d5aa8SLars Ellenberg { 3184d3d5aa8SLars Ellenberg drbd_debugfs_remove(&device->debugfs_minor); 3194d3d5aa8SLars Ellenberg drbd_debugfs_remove(&device->debugfs_vol_oldest_requests); 3204d3d5aa8SLars Ellenberg drbd_debugfs_remove(&device->debugfs_vol_act_log_extents); 3214d3d5aa8SLars Ellenberg drbd_debugfs_remove(&device->debugfs_vol_resync_extents); 3224d3d5aa8SLars Ellenberg drbd_debugfs_remove(&device->debugfs_vol_data_gen_id); 3234d3d5aa8SLars Ellenberg drbd_debugfs_remove(&device->debugfs_vol); 3244d3d5aa8SLars Ellenberg } 3254d3d5aa8SLars Ellenberg 3264d3d5aa8SLars Ellenberg void drbd_debugfs_peer_device_add(struct drbd_peer_device *peer_device) 3274d3d5aa8SLars Ellenberg { 3284d3d5aa8SLars Ellenberg struct dentry *conn_dir = peer_device->connection->debugfs_conn; 3294d3d5aa8SLars Ellenberg struct dentry *dentry; 3304d3d5aa8SLars Ellenberg char vnr_buf[8]; 3314d3d5aa8SLars Ellenberg 3324d3d5aa8SLars Ellenberg if (!conn_dir) 3334d3d5aa8SLars Ellenberg return; 3344d3d5aa8SLars Ellenberg 3354d3d5aa8SLars Ellenberg snprintf(vnr_buf, sizeof(vnr_buf), "%u", peer_device->device->vnr); 3364d3d5aa8SLars Ellenberg dentry = debugfs_create_dir(vnr_buf, conn_dir); 3374d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 3384d3d5aa8SLars Ellenberg goto fail; 3394d3d5aa8SLars Ellenberg peer_device->debugfs_peer_dev = dentry; 3404d3d5aa8SLars Ellenberg return; 3414d3d5aa8SLars Ellenberg 3424d3d5aa8SLars Ellenberg fail: 3434d3d5aa8SLars Ellenberg drbd_debugfs_peer_device_cleanup(peer_device); 3444d3d5aa8SLars Ellenberg drbd_err(peer_device, "failed to create debugfs entries\n"); 3454d3d5aa8SLars Ellenberg } 3464d3d5aa8SLars Ellenberg 3474d3d5aa8SLars Ellenberg void drbd_debugfs_peer_device_cleanup(struct drbd_peer_device *peer_device) 3484d3d5aa8SLars Ellenberg { 3494d3d5aa8SLars Ellenberg drbd_debugfs_remove(&peer_device->debugfs_peer_dev); 3504d3d5aa8SLars Ellenberg } 3514d3d5aa8SLars Ellenberg 3524d3d5aa8SLars Ellenberg /* not __exit, may be indirectly called 3534d3d5aa8SLars Ellenberg * from the module-load-failure path as well. */ 3544d3d5aa8SLars Ellenberg void drbd_debugfs_cleanup(void) 3554d3d5aa8SLars Ellenberg { 3564d3d5aa8SLars Ellenberg drbd_debugfs_remove(&drbd_debugfs_resources); 3574d3d5aa8SLars Ellenberg drbd_debugfs_remove(&drbd_debugfs_minors); 3584d3d5aa8SLars Ellenberg drbd_debugfs_remove(&drbd_debugfs_root); 3594d3d5aa8SLars Ellenberg } 3604d3d5aa8SLars Ellenberg 3614d3d5aa8SLars Ellenberg int __init drbd_debugfs_init(void) 3624d3d5aa8SLars Ellenberg { 3634d3d5aa8SLars Ellenberg struct dentry *dentry; 3644d3d5aa8SLars Ellenberg 3654d3d5aa8SLars Ellenberg dentry = debugfs_create_dir("drbd", NULL); 3664d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 3674d3d5aa8SLars Ellenberg goto fail; 3684d3d5aa8SLars Ellenberg drbd_debugfs_root = dentry; 3694d3d5aa8SLars Ellenberg 3704d3d5aa8SLars Ellenberg dentry = debugfs_create_dir("resources", drbd_debugfs_root); 3714d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 3724d3d5aa8SLars Ellenberg goto fail; 3734d3d5aa8SLars Ellenberg drbd_debugfs_resources = dentry; 3744d3d5aa8SLars Ellenberg 3754d3d5aa8SLars Ellenberg dentry = debugfs_create_dir("minors", drbd_debugfs_root); 3764d3d5aa8SLars Ellenberg if (IS_ERR_OR_NULL(dentry)) 3774d3d5aa8SLars Ellenberg goto fail; 3784d3d5aa8SLars Ellenberg drbd_debugfs_minors = dentry; 3794d3d5aa8SLars Ellenberg return 0; 3804d3d5aa8SLars Ellenberg 3814d3d5aa8SLars Ellenberg fail: 3824d3d5aa8SLars Ellenberg drbd_debugfs_cleanup(); 3834d3d5aa8SLars Ellenberg if (dentry) 3844d3d5aa8SLars Ellenberg return PTR_ERR(dentry); 3854d3d5aa8SLars Ellenberg else 3864d3d5aa8SLars Ellenberg return -EINVAL; 3874d3d5aa8SLars Ellenberg } 388