From: Douglas Gilbert <dgilbert@interlog.com>
To: linux-scsi@vger.kernel.org
Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com,
hare@suse.de, bvanassche@acm.org
Subject: [PATCH v3 19/20] sg: first debugfs support
Date: Wed, 7 Aug 2019 13:42:51 +0200 [thread overview]
Message-ID: <20190807114252.2565-20-dgilbert@interlog.com> (raw)
In-Reply-To: <20190807114252.2565-1-dgilbert@interlog.com>
Duplicate the semantics of 'cat /proc/scsi/sg/debug' on
'cat /sys/kernel/debug/scsi_generic/snapshot'. Make code
that generates the snapshot conditional on either
CONFIG_SCSI_PROC_FS or CONFIG_DEBUG_FS being defined.
-
Use "scsi_generic" in the debugfs path as "sg" may be
confused with scatter gather in the wider kernel.
As implemented, the snapshot is on all sg devices. If many sg
devices are in use, restricting the output to one (or a list)
of sg device numbers may declutter the output. Perhaps a
writable snapshot_devs attribute could be added that takes a
single integer, a comma separated list or integers, or '*'
which maps to -1 which is the default and means all devices.
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
drivers/scsi/sg.c | 207 ++++++++++++++++++++++++++++++----------------
1 file changed, 136 insertions(+), 71 deletions(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index fe79f5f354f2..82c4147ba4f1 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -43,6 +43,7 @@ static char *sg_version_date = "20190606";
#include <linux/uio.h>
#include <linux/cred.h> /* for sg_check_file_access() */
#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
@@ -68,6 +69,10 @@ static char *sg_version_date = "20190606";
#endif
#endif
+#if IS_ENABLED(CONFIG_SCSI_PROC_FS) || IS_ENABLED(CONFIG_DEBUG_FS)
+#define SG_PROC_OR_DEBUG_FS 1
+#endif
+
/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
* of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater
* than 16 bytes are "variable length" whose length is a multiple of 4, so:
@@ -268,6 +273,8 @@ struct sg_comm_wr_t { /* arguments to sg_common_write() */
static void sg_rq_end_io(struct request *rq, blk_status_t status);
/* Declarations of other static functions used before they are defined */
static int sg_proc_init(void);
+static void sg_dfs_init(void);
+static void sg_dfs_exit(void);
static int sg_start_req(struct sg_request *srp, struct sg_comm_wr_t *cwrp,
int dxfer_dir);
static void sg_finish_scsi_blk_rq(struct sg_request *srp);
@@ -341,7 +348,7 @@ static void sg_rep_rq_state_fail(struct sg_fd *sfp,
pr_info("sg: sdp or sfp NULL, " fmt, ##a); \
} while (0)
#else
-#define SG_LOG(depth, sfp, fmt, a...)
+#define SG_LOG(depth, sfp, fmt, a...) do { } while (0)
#endif /* end of CONFIG_SCSI_LOGGING && SG_DEBUG conditional */
@@ -2650,6 +2657,7 @@ init_sg(void)
rc = scsi_register_interface(&sg_interface);
if (rc == 0) {
sg_proc_init();
+ sg_dfs_init();
return 0;
}
class_destroy(sg_sysfs_class);
@@ -2674,6 +2682,7 @@ sg_proc_init(void)
static void __exit
exit_sg(void)
{
+ sg_dfs_exit();
if (IS_ENABLED(CONFIG_SCSI_PROC_FS))
remove_proc_subtree("scsi/sg", NULL);
scsi_unregister_interface(&sg_interface);
@@ -3130,7 +3139,7 @@ sg_find_srp_by_id(struct sg_fd *sfp, int pack_id)
rcu_read_unlock();
if (IS_ENABLED(CONFIG_SCSI_PROC_FS)) {
if (search_for_1) {
- const char *cptp = "pack_id=";
+ __maybe_unused const char *cptp = "pack_id=";
if (is_bad_st)
SG_LOG(1, sfp, "%s: %s%d wrong state: %s\n",
@@ -3248,7 +3257,7 @@ sg_add_request(struct sg_comm_wr_t *cwrp, int dxfr_len)
enum sg_rq_state sr_st;
struct sg_fd *fp = cwrp->sfp;
struct sg_request *r_srp = NULL; /* request to return */
- struct sg_request *rsv_srp; /* current fd's reserve request */
+ __maybe_unused struct sg_request *rsv_srp;
__maybe_unused const char *cp;
spin_lock_irqsave(&fp->rq_list_lock, iflags);
@@ -3348,7 +3357,7 @@ sg_deact_request(struct sg_fd *sfp, struct sg_request *srp)
u8 *sbp;
struct sg_request *t_srp;
struct sg_scatter_hold *schp;
- const char *cp = "head";
+ __maybe_unused const char *cp = "head";
if (WARN_ON(!sfp || !srp))
return;
@@ -3551,18 +3560,6 @@ sg_remove_sfp(struct kref *kref)
schedule_work(&sfp->ew_fd.work);
}
-static int
-sg_idr_max_id(int id, void *p, void *data)
- __must_hold(&sg_index_lock)
-{
- int *k = data;
-
- if (*k < id)
- *k = id;
-
- return 0;
-}
-
/* must be called with sg_index_lock held */
static struct sg_device *
sg_lookup_dev(int dev)
@@ -3592,7 +3589,7 @@ sg_get_dev(int dev)
return sdp;
}
-#if IS_ENABLED(CONFIG_SCSI_PROC_FS)
+#if IS_ENABLED(SG_PROC_OR_DEBUG_FS)
static const char *
sg_rq_st_str(enum sg_rq_state rq_st, bool long_str)
{
@@ -3619,7 +3616,72 @@ sg_rq_st_str(enum sg_rq_state rq_st, bool long_str)
}
#endif
-#if IS_ENABLED(CONFIG_SCSI_PROC_FS) /* long, almost to end of file */
+#if IS_ENABLED(SG_PROC_OR_DEBUG_FS)
+
+struct sg_proc_deviter {
+ loff_t index;
+ size_t max;
+ int fd_index;
+};
+
+static int
+sg_idr_max_id(int id, void *p, void *data)
+ __must_hold(&sg_index_lock)
+{
+ int *k = data;
+
+ if (*k < id)
+ *k = id;
+ return 0;
+}
+
+static int
+sg_last_dev(void)
+{
+ int k = -1;
+ unsigned long iflags;
+
+ read_lock_irqsave(&sg_index_lock, iflags);
+ idr_for_each(&sg_index_idr, sg_idr_max_id, &k);
+ read_unlock_irqrestore(&sg_index_lock, iflags);
+ return k + 1; /* origin 1 */
+}
+
+static void *
+dev_seq_start(struct seq_file *s, loff_t *pos)
+{
+ struct sg_proc_deviter *it = kzalloc(sizeof(*it), GFP_KERNEL);
+
+ s->private = it;
+ if (!it)
+ return NULL;
+
+ it->index = *pos;
+ it->max = sg_last_dev();
+ if (it->index >= it->max)
+ return NULL;
+ return it;
+}
+
+static void *
+dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct sg_proc_deviter *it = s->private;
+
+ *pos = ++it->index;
+ return (it->index < it->max) ? it : NULL;
+}
+
+static void
+dev_seq_stop(struct seq_file *s, void *v)
+{
+ kfree(s->private);
+}
+
+#endif /* SG_PROC_OR_DEBUG_FS */
+
+#if IS_ENABLED(CONFIG_SCSI_PROC_FS) /* long, around 200 lines */
+
static int sg_proc_seq_show_int(struct seq_file *s, void *v);
static int sg_proc_single_open_adio(struct inode *inode, struct file *filp);
@@ -3649,9 +3711,6 @@ static const struct file_operations dressz_fops = {
static int sg_proc_seq_show_version(struct seq_file *s, void *v);
static int sg_proc_seq_show_devhdr(struct seq_file *s, void *v);
static int sg_proc_seq_show_dev(struct seq_file *s, void *v);
-static void * dev_seq_start(struct seq_file *s, loff_t *pos);
-static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos);
-static void dev_seq_stop(struct seq_file *s, void *v);
static const struct seq_operations dev_seq_ops = {
.start = dev_seq_start,
.next = dev_seq_next,
@@ -3694,18 +3753,6 @@ sg_proc_init(void)
return 0;
}
-static int
-sg_last_dev(void)
-{
- int k = -1;
- unsigned long iflags;
-
- read_lock_irqsave(&sg_index_lock, iflags);
- idr_for_each(&sg_index_idr, sg_idr_max_id, &k);
- read_unlock_irqrestore(&sg_index_lock, iflags);
- return k + 1; /* origin 1 */
-}
-
static int
sg_proc_seq_show_int(struct seq_file *s, void *v)
{
@@ -3776,43 +3823,6 @@ sg_proc_seq_show_devhdr(struct seq_file *s, void *v)
return 0;
}
-struct sg_proc_deviter {
- loff_t index;
- size_t max;
- int fd_index;
-};
-
-static void *
-dev_seq_start(struct seq_file *s, loff_t *pos)
-{
- struct sg_proc_deviter *it = kzalloc(sizeof(*it), GFP_KERNEL);
-
- s->private = it;
- if (! it)
- return NULL;
-
- it->index = *pos;
- it->max = sg_last_dev();
- if (it->index >= it->max)
- return NULL;
- return it;
-}
-
-static void *
-dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
- struct sg_proc_deviter *it = s->private;
-
- *pos = ++it->index;
- return (it->index < it->max) ? it : NULL;
-}
-
-static void
-dev_seq_stop(struct seq_file *s, void *v)
-{
- kfree(s->private);
-}
-
static int
sg_proc_seq_show_dev(struct seq_file *s, void *v)
{
@@ -3859,6 +3869,10 @@ sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
return 0;
}
+#endif /* CONFIG_SCSI_PROC_FS (~200 lines back) */
+
+#if IS_ENABLED(SG_PROC_OR_DEBUG_FS)
+
/* Writes debug info for one sg_request in obp buffer */
static int
sg_proc_debug_sreq(struct sg_request *srp, int to, char *obp, int len)
@@ -4049,7 +4063,58 @@ sg_proc_seq_show_debug(struct seq_file *s, void *v)
return 0;
}
-#endif /* CONFIG_SCSI_PROC_FS (~400 lines back) */
+#endif /* SG_PROC_OR_DEBUG_FS */
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+
+static int
+sg_dfs_snapshot_show(struct seq_file *s, void *v)
+{
+ int res = 0;
+ loff_t my_pos = 0;
+ void *it;
+
+ it = dev_seq_start(s, &my_pos);
+ while (it) {
+ res = sg_proc_seq_show_debug(s, it);
+ if (res)
+ break;
+ it = dev_seq_next(s, it, &my_pos);
+ }
+ dev_seq_stop(s, it);
+ return res;
+}
+DEFINE_SHOW_ATTRIBUTE(sg_dfs_snapshot);
+
+static struct dentry *sg_dfs_rootdir;
+static struct dentry *sg_dfs_snapshot;
+
+static void
+sg_dfs_init(void)
+{
+ /* /sys/kernel/debug/scsi_generic/ */
+ if (!sg_dfs_rootdir)
+ sg_dfs_rootdir = debugfs_create_dir("scsi_generic", NULL);
+
+ sg_dfs_snapshot = debugfs_create_file("snapshot", S_IFREG | 0444,
+ sg_dfs_rootdir, NULL,
+ &sg_dfs_snapshot_fops);
+}
+
+static void
+sg_dfs_exit(void)
+{
+ debugfs_remove(sg_dfs_snapshot);
+ debugfs_remove(sg_dfs_rootdir);
+}
+
+#else /* not defined: CONFIG_DEBUG_FS */
+
+static void sg_dfs_init(void) {}
+static void sg_dfs_exit(void) {}
+
+#endif /* CONFIG_DEBUG_FS */
+
module_init(init_sg);
module_exit(exit_sg);
--
2.22.0
next prev parent reply other threads:[~2019-08-07 11:43 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-07 11:42 [PATCH v3 00/20] sg: add v4 interface Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 01/20] sg: move functions around Douglas Gilbert
2019-08-12 14:22 ` Christoph Hellwig
2019-08-07 11:42 ` [PATCH v3 02/20] sg: remove typedefs, type+formatting cleanup Douglas Gilbert
2019-08-12 14:22 ` Christoph Hellwig
2019-08-07 11:42 ` [PATCH v3 03/20] sg: sg_log and is_enabled Douglas Gilbert
2019-08-12 14:23 ` Christoph Hellwig
2019-08-13 22:57 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 04/20] sg: rework sg_poll(), minor changes Douglas Gilbert
2019-08-12 14:23 ` Christoph Hellwig
2019-08-13 0:35 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 05/20] sg: bitops in sg_device Douglas Gilbert
2019-08-12 14:23 ` Christoph Hellwig
2019-08-14 1:35 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 06/20] sg: make open count an atomic Douglas Gilbert
2019-08-12 14:23 ` Christoph Hellwig
2019-08-07 11:42 ` [PATCH v3 07/20] sg: move header to uapi section Douglas Gilbert
2019-08-12 14:24 ` Christoph Hellwig
2019-08-12 14:32 ` Greg KH
2019-08-12 14:35 ` James Bottomley
2019-08-13 0:21 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 08/20] sg: speed sg_poll and sg_get_num_waiting Douglas Gilbert
2019-08-12 14:31 ` Christoph Hellwig
2019-08-12 16:31 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 09/20] sg: sg_allow_if_err_recovery and renames Douglas Gilbert
2019-08-12 14:31 ` Christoph Hellwig
2019-08-14 1:26 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 10/20] sg: remove most access_ok functions Douglas Gilbert
2019-08-12 14:32 ` Christoph Hellwig
2019-08-07 11:42 ` [PATCH v3 11/20] sg: replace rq array with lists Douglas Gilbert
2019-08-12 14:35 ` Christoph Hellwig
2019-08-13 23:46 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 12/20] sg: sense buffer rework Douglas Gilbert
2019-08-12 14:37 ` Christoph Hellwig
2019-08-12 16:26 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 13/20] sg: add sg v4 interface support Douglas Gilbert
2019-08-09 23:12 ` James Bottomley
2019-08-11 19:21 ` Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 14/20] sg: rework debug info Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 15/20] sg: add 8 byte SCSI LUN to sg_scsi_id Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 16/20] sg: expand sg_comm_wr_t Douglas Gilbert
2019-08-07 11:42 ` [PATCH v3 17/20] sg: add sg_iosubmit_v3 and sg_ioreceive_v3 ioctls Douglas Gilbert
2019-08-09 23:15 ` James Bottomley
2019-08-12 15:37 ` Douglas Gilbert
2019-08-12 16:14 ` Tony Battersby
2019-08-12 18:46 ` James Bottomley
2019-08-12 19:37 ` Tony Battersby
2019-08-07 11:42 ` [PATCH v3 18/20] sg: add some __must_hold macros Douglas Gilbert
2019-08-07 11:42 ` Douglas Gilbert [this message]
2019-08-07 11:42 ` [PATCH v3 20/20] sg: bump version to 4.0.03 Douglas Gilbert
2019-08-08 19:10 ` [PATCH v3 00/20] sg: add v4 interface James Bottomley
2019-08-08 21:08 ` Douglas Gilbert
2019-08-08 21:37 ` Tony Battersby
2019-08-08 22:25 ` Bart Van Assche
2019-08-09 13:28 ` Tony Battersby
2019-08-08 23:00 ` James Bottomley
2019-08-14 4:19 ` Douglas Gilbert
2019-08-15 17:30 ` Bart Van Assche
2019-08-16 15:59 ` Douglas Gilbert
2019-08-16 17:19 ` Greg KH
2019-08-16 18:10 ` Bart Van Assche
2019-08-16 18:44 ` Douglas Gilbert
2019-08-12 15:23 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190807114252.2565-20-dgilbert@interlog.com \
--to=dgilbert@interlog.com \
--cc=bvanassche@acm.org \
--cc=hare@suse.de \
--cc=jejb@linux.vnet.ibm.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.