aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/nbd.c
diff options
context:
space:
mode:
authorMarkus Pargmann <mpa@pengutronix.de>2015-08-17 02:20:06 -0400
committerJens Axboe <axboe@fb.com>2015-08-17 10:22:56 -0400
commit30d53d9c11b6c2f71253a2be582969d7e6fa7f10 (patch)
treefb982a8aa6d4b2e7cd84fef7a7064b736ebee894 /drivers/block/nbd.c
parent6521d39a64b3f9c3acb0fd25a34cfaf9a40e548e (diff)
nbd: Add debugfs entries
Add some debugfs files that help to understand the internal state of NBD. This exports the different sizes, flags, tasks and so on. Signed-off-by: Markus Pargmann <mpa@pengutronix.de> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block/nbd.c')
-rw-r--r--drivers/block/nbd.c178
1 files changed, 177 insertions, 1 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index eeefa5cac520..6dd8305840bb 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -33,6 +33,7 @@
33#include <linux/net.h> 33#include <linux/net.h>
34#include <linux/kthread.h> 34#include <linux/kthread.h>
35#include <linux/types.h> 35#include <linux/types.h>
36#include <linux/debugfs.h>
36 37
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
38#include <asm/types.h> 39#include <asm/types.h>
@@ -61,8 +62,18 @@ struct nbd_device {
61 struct timer_list timeout_timer; 62 struct timer_list timeout_timer;
62 struct task_struct *task_recv; 63 struct task_struct *task_recv;
63 struct task_struct *task_send; 64 struct task_struct *task_send;
65
66#if IS_ENABLED(CONFIG_DEBUG_FS)
67 struct dentry *dbg_dir;
68#endif
64}; 69};
65 70
71#if IS_ENABLED(CONFIG_DEBUG_FS)
72static struct dentry *nbd_dbg_dir;
73#endif
74
75#define nbd_name(nbd) ((nbd)->disk->disk_name)
76
66#define NBD_MAGIC 0x68797548 77#define NBD_MAGIC 0x68797548
67 78
68static unsigned int nbds_max = 16; 79static unsigned int nbds_max = 16;
@@ -609,6 +620,9 @@ static void do_nbd_request(struct request_queue *q)
609 } 620 }
610} 621}
611 622
623static int nbd_dev_dbg_init(struct nbd_device *nbd);
624static void nbd_dev_dbg_close(struct nbd_device *nbd);
625
612/* Must be called with tx_lock held */ 626/* Must be called with tx_lock held */
613 627
614static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, 628static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
@@ -725,13 +739,15 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
725 blk_queue_flush(nbd->disk->queue, 0); 739 blk_queue_flush(nbd->disk->queue, 0);
726 740
727 thread = kthread_run(nbd_thread, nbd, "%s", 741 thread = kthread_run(nbd_thread, nbd, "%s",
728 nbd->disk->disk_name); 742 nbd_name(nbd));
729 if (IS_ERR(thread)) { 743 if (IS_ERR(thread)) {
730 mutex_lock(&nbd->tx_lock); 744 mutex_lock(&nbd->tx_lock);
731 return PTR_ERR(thread); 745 return PTR_ERR(thread);
732 } 746 }
733 747
748 nbd_dev_dbg_init(nbd);
734 error = nbd_do_it(nbd); 749 error = nbd_do_it(nbd);
750 nbd_dev_dbg_close(nbd);
735 kthread_stop(thread); 751 kthread_stop(thread);
736 752
737 mutex_lock(&nbd->tx_lock); 753 mutex_lock(&nbd->tx_lock);
@@ -797,6 +813,161 @@ static const struct block_device_operations nbd_fops =
797 .ioctl = nbd_ioctl, 813 .ioctl = nbd_ioctl,
798}; 814};
799 815
816#if IS_ENABLED(CONFIG_DEBUG_FS)
817
818static int nbd_dbg_tasks_show(struct seq_file *s, void *unused)
819{
820 struct nbd_device *nbd = s->private;
821
822 if (nbd->task_recv)
823 seq_printf(s, "recv: %d\n", task_pid_nr(nbd->task_recv));
824 if (nbd->task_send)
825 seq_printf(s, "send: %d\n", task_pid_nr(nbd->task_send));
826
827 return 0;
828}
829
830static int nbd_dbg_tasks_open(struct inode *inode, struct file *file)
831{
832 return single_open(file, nbd_dbg_tasks_show, inode->i_private);
833}
834
835static const struct file_operations nbd_dbg_tasks_ops = {
836 .open = nbd_dbg_tasks_open,
837 .read = seq_read,
838 .llseek = seq_lseek,
839 .release = single_release,
840};
841
842static int nbd_dbg_flags_show(struct seq_file *s, void *unused)
843{
844 struct nbd_device *nbd = s->private;
845 u32 flags = nbd->flags;
846
847 seq_printf(s, "Hex: 0x%08x\n\n", flags);
848
849 seq_puts(s, "Known flags:\n");
850
851 if (flags & NBD_FLAG_HAS_FLAGS)
852 seq_puts(s, "NBD_FLAG_HAS_FLAGS\n");
853 if (flags & NBD_FLAG_READ_ONLY)
854 seq_puts(s, "NBD_FLAG_READ_ONLY\n");
855 if (flags & NBD_FLAG_SEND_FLUSH)
856 seq_puts(s, "NBD_FLAG_SEND_FLUSH\n");
857 if (flags & NBD_FLAG_SEND_TRIM)
858 seq_puts(s, "NBD_FLAG_SEND_TRIM\n");
859
860 return 0;
861}
862
863static int nbd_dbg_flags_open(struct inode *inode, struct file *file)
864{
865 return single_open(file, nbd_dbg_flags_show, inode->i_private);
866}
867
868static const struct file_operations nbd_dbg_flags_ops = {
869 .open = nbd_dbg_flags_open,
870 .read = seq_read,
871 .llseek = seq_lseek,
872 .release = single_release,
873};
874
875static int nbd_dev_dbg_init(struct nbd_device *nbd)
876{
877 struct dentry *dir;
878 struct dentry *f;
879
880 dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir);
881 if (IS_ERR_OR_NULL(dir)) {
882 dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s' (%ld)\n",
883 nbd_name(nbd), PTR_ERR(dir));
884 return PTR_ERR(dir);
885 }
886 nbd->dbg_dir = dir;
887
888 f = debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops);
889 if (IS_ERR_OR_NULL(f)) {
890 dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'tasks', %ld\n",
891 PTR_ERR(f));
892 return PTR_ERR(f);
893 }
894
895 f = debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
896 if (IS_ERR_OR_NULL(f)) {
897 dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'size_bytes', %ld\n",
898 PTR_ERR(f));
899 return PTR_ERR(f);
900 }
901
902 f = debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout);
903 if (IS_ERR_OR_NULL(f)) {
904 dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'timeout', %ld\n",
905 PTR_ERR(f));
906 return PTR_ERR(f);
907 }
908
909 f = debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
910 if (IS_ERR_OR_NULL(f)) {
911 dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'blocksize', %ld\n",
912 PTR_ERR(f));
913 return PTR_ERR(f);
914 }
915
916 f = debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops);
917 if (IS_ERR_OR_NULL(f)) {
918 dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'flags', %ld\n",
919 PTR_ERR(f));
920 return PTR_ERR(f);
921 }
922
923 return 0;
924}
925
926static void nbd_dev_dbg_close(struct nbd_device *nbd)
927{
928 debugfs_remove_recursive(nbd->dbg_dir);
929}
930
931static int nbd_dbg_init(void)
932{
933 struct dentry *dbg_dir;
934
935 dbg_dir = debugfs_create_dir("nbd", NULL);
936 if (IS_ERR(dbg_dir))
937 return PTR_ERR(dbg_dir);
938
939 nbd_dbg_dir = dbg_dir;
940
941 return 0;
942}
943
944static void nbd_dbg_close(void)
945{
946 debugfs_remove_recursive(nbd_dbg_dir);
947}
948
949#else /* IS_ENABLED(CONFIG_DEBUG_FS) */
950
951static int nbd_dev_dbg_init(struct nbd_device *nbd)
952{
953 return 0;
954}
955
956static void nbd_dev_dbg_close(struct nbd_device *nbd)
957{
958}
959
960static int nbd_dbg_init(void)
961{
962 return 0;
963}
964
965static void nbd_dbg_close(void)
966{
967}
968
969#endif
970
800/* 971/*
801 * And here should be modules and kernel interface 972 * And here should be modules and kernel interface
802 * (Just smiley confuses emacs :-) 973 * (Just smiley confuses emacs :-)
@@ -874,6 +1045,8 @@ static int __init nbd_init(void)
874 1045
875 printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR); 1046 printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR);
876 1047
1048 nbd_dbg_init();
1049
877 for (i = 0; i < nbds_max; i++) { 1050 for (i = 0; i < nbds_max; i++) {
878 struct gendisk *disk = nbd_dev[i].disk; 1051 struct gendisk *disk = nbd_dev[i].disk;
879 nbd_dev[i].magic = NBD_MAGIC; 1052 nbd_dev[i].magic = NBD_MAGIC;
@@ -910,6 +1083,9 @@ out:
910static void __exit nbd_cleanup(void) 1083static void __exit nbd_cleanup(void)
911{ 1084{
912 int i; 1085 int i;
1086
1087 nbd_dbg_close();
1088
913 for (i = 0; i < nbds_max; i++) { 1089 for (i = 0; i < nbds_max; i++) {
914 struct gendisk *disk = nbd_dev[i].disk; 1090 struct gendisk *disk = nbd_dev[i].disk;
915 nbd_dev[i].magic = 0; 1091 nbd_dev[i].magic = 0;