aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/xen/debugfs.c104
-rw-r--r--arch/x86/xen/debugfs.h4
-rw-r--r--arch/x86/xen/spinlock.c12
-rw-r--r--fs/debugfs/file.c128
-rw-r--r--include/linux/debugfs.h11
5 files changed, 145 insertions, 114 deletions
diff --git a/arch/x86/xen/debugfs.c b/arch/x86/xen/debugfs.c
index ef1db1900d86..c8377fb26cdf 100644
--- a/arch/x86/xen/debugfs.c
+++ b/arch/x86/xen/debugfs.c
@@ -19,107 +19,3 @@ struct dentry * __init xen_init_debugfs(void)
19 return d_xen_debug; 19 return d_xen_debug;
20} 20}
21 21
22struct array_data
23{
24 void *array;
25 unsigned elements;
26};
27
28static int u32_array_open(struct inode *inode, struct file *file)
29{
30 file->private_data = NULL;
31 return nonseekable_open(inode, file);
32}
33
34static size_t format_array(char *buf, size_t bufsize, const char *fmt,
35 u32 *array, unsigned array_size)
36{
37 size_t ret = 0;
38 unsigned i;
39
40 for(i = 0; i < array_size; i++) {
41 size_t len;
42
43 len = snprintf(buf, bufsize, fmt, array[i]);
44 len++; /* ' ' or '\n' */
45 ret += len;
46
47 if (buf) {
48 buf += len;
49 bufsize -= len;
50 buf[-1] = (i == array_size-1) ? '\n' : ' ';
51 }
52 }
53
54 ret++; /* \0 */
55 if (buf)
56 *buf = '\0';
57
58 return ret;
59}
60
61static char *format_array_alloc(const char *fmt, u32 *array, unsigned array_size)
62{
63 size_t len = format_array(NULL, 0, fmt, array, array_size);
64 char *ret;
65
66 ret = kmalloc(len, GFP_KERNEL);
67 if (ret == NULL)
68 return NULL;
69
70 format_array(ret, len, fmt, array, array_size);
71 return ret;
72}
73
74static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
75 loff_t *ppos)
76{
77 struct inode *inode = file->f_path.dentry->d_inode;
78 struct array_data *data = inode->i_private;
79 size_t size;
80
81 if (*ppos == 0) {
82 if (file->private_data) {
83 kfree(file->private_data);
84 file->private_data = NULL;
85 }
86
87 file->private_data = format_array_alloc("%u", data->array, data->elements);
88 }
89
90 size = 0;
91 if (file->private_data)
92 size = strlen(file->private_data);
93
94 return simple_read_from_buffer(buf, len, ppos, file->private_data, size);
95}
96
97static int xen_array_release(struct inode *inode, struct file *file)
98{
99 kfree(file->private_data);
100
101 return 0;
102}
103
104static const struct file_operations u32_array_fops = {
105 .owner = THIS_MODULE,
106 .open = u32_array_open,
107 .release= xen_array_release,
108 .read = u32_array_read,
109 .llseek = no_llseek,
110};
111
112struct dentry *xen_debugfs_create_u32_array(const char *name, umode_t mode,
113 struct dentry *parent,
114 u32 *array, unsigned elements)
115{
116 struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
117
118 if (data == NULL)
119 return NULL;
120
121 data->array = array;
122 data->elements = elements;
123
124 return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
125}
diff --git a/arch/x86/xen/debugfs.h b/arch/x86/xen/debugfs.h
index 78d25499be5b..12ebf3325c7b 100644
--- a/arch/x86/xen/debugfs.h
+++ b/arch/x86/xen/debugfs.h
@@ -3,8 +3,4 @@
3 3
4struct dentry * __init xen_init_debugfs(void); 4struct dentry * __init xen_init_debugfs(void);
5 5
6struct dentry *xen_debugfs_create_u32_array(const char *name, umode_t mode,
7 struct dentry *parent,
8 u32 *array, unsigned elements);
9
10#endif /* _XEN_DEBUGFS_H */ 6#endif /* _XEN_DEBUGFS_H */
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index d69cc6c3f808..83e866d714ce 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -440,12 +440,12 @@ static int __init xen_spinlock_debugfs(void)
440 debugfs_create_u64("time_total", 0444, d_spin_debug, 440 debugfs_create_u64("time_total", 0444, d_spin_debug,
441 &spinlock_stats.time_total); 441 &spinlock_stats.time_total);
442 442
443 xen_debugfs_create_u32_array("histo_total", 0444, d_spin_debug, 443 debugfs_create_u32_array("histo_total", 0444, d_spin_debug,
444 spinlock_stats.histo_spin_total, HISTO_BUCKETS + 1); 444 spinlock_stats.histo_spin_total, HISTO_BUCKETS + 1);
445 xen_debugfs_create_u32_array("histo_spinning", 0444, d_spin_debug, 445 debugfs_create_u32_array("histo_spinning", 0444, d_spin_debug,
446 spinlock_stats.histo_spin_spinning, HISTO_BUCKETS + 1); 446 spinlock_stats.histo_spin_spinning, HISTO_BUCKETS + 1);
447 xen_debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug, 447 debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
448 spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1); 448 spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
449 449
450 return 0; 450 return 0;
451} 451}
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 5dfafdd1dbd3..2340f6978d6e 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -20,6 +20,7 @@
20#include <linux/namei.h> 20#include <linux/namei.h>
21#include <linux/debugfs.h> 21#include <linux/debugfs.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/slab.h>
23 24
24static ssize_t default_read_file(struct file *file, char __user *buf, 25static ssize_t default_read_file(struct file *file, char __user *buf,
25 size_t count, loff_t *ppos) 26 size_t count, loff_t *ppos)
@@ -520,6 +521,133 @@ struct dentry *debugfs_create_blob(const char *name, umode_t mode,
520} 521}
521EXPORT_SYMBOL_GPL(debugfs_create_blob); 522EXPORT_SYMBOL_GPL(debugfs_create_blob);
522 523
524struct array_data {
525 void *array;
526 u32 elements;
527};
528
529static int u32_array_open(struct inode *inode, struct file *file)
530{
531 file->private_data = NULL;
532 return nonseekable_open(inode, file);
533}
534
535static size_t format_array(char *buf, size_t bufsize, const char *fmt,
536 u32 *array, u32 array_size)
537{
538 size_t ret = 0;
539 u32 i;
540
541 for (i = 0; i < array_size; i++) {
542 size_t len;
543
544 len = snprintf(buf, bufsize, fmt, array[i]);
545 len++; /* ' ' or '\n' */
546 ret += len;
547
548 if (buf) {
549 buf += len;
550 bufsize -= len;
551 buf[-1] = (i == array_size-1) ? '\n' : ' ';
552 }
553 }
554
555 ret++; /* \0 */
556 if (buf)
557 *buf = '\0';
558
559 return ret;
560}
561
562static char *format_array_alloc(const char *fmt, u32 *array,
563 u32 array_size)
564{
565 size_t len = format_array(NULL, 0, fmt, array, array_size);
566 char *ret;
567
568 ret = kmalloc(len, GFP_KERNEL);
569 if (ret == NULL)
570 return NULL;
571
572 format_array(ret, len, fmt, array, array_size);
573 return ret;
574}
575
576static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
577 loff_t *ppos)
578{
579 struct inode *inode = file->f_path.dentry->d_inode;
580 struct array_data *data = inode->i_private;
581 size_t size;
582
583 if (*ppos == 0) {
584 if (file->private_data) {
585 kfree(file->private_data);
586 file->private_data = NULL;
587 }
588
589 file->private_data = format_array_alloc("%u", data->array,
590 data->elements);
591 }
592
593 size = 0;
594 if (file->private_data)
595 size = strlen(file->private_data);
596
597 return simple_read_from_buffer(buf, len, ppos,
598 file->private_data, size);
599}
600
601static int u32_array_release(struct inode *inode, struct file *file)
602{
603 kfree(file->private_data);
604
605 return 0;
606}
607
608static const struct file_operations u32_array_fops = {
609 .owner = THIS_MODULE,
610 .open = u32_array_open,
611 .release = u32_array_release,
612 .read = u32_array_read,
613 .llseek = no_llseek,
614};
615
616/**
617 * debugfs_create_u32_array - create a debugfs file that is used to read u32
618 * array.
619 * @name: a pointer to a string containing the name of the file to create.
620 * @mode: the permission that the file should have.
621 * @parent: a pointer to the parent dentry for this file. This should be a
622 * directory dentry if set. If this parameter is %NULL, then the
623 * file will be created in the root of the debugfs filesystem.
624 * @array: u32 array that provides data.
625 * @elements: total number of elements in the array.
626 *
627 * This function creates a file in debugfs with the given name that exports
628 * @array as data. If the @mode variable is so set it can be read from.
629 * Writing is not supported. Seek within the file is also not supported.
630 * Once array is created its size can not be changed.
631 *
632 * The function returns a pointer to dentry on success. If debugfs is not
633 * enabled in the kernel, the value -%ENODEV will be returned.
634 */
635struct dentry *debugfs_create_u32_array(const char *name, umode_t mode,
636 struct dentry *parent,
637 u32 *array, u32 elements)
638{
639 struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
640
641 if (data == NULL)
642 return NULL;
643
644 data->array = array;
645 data->elements = elements;
646
647 return debugfs_create_file(name, mode, parent, data, &u32_array_fops);
648}
649EXPORT_SYMBOL_GPL(debugfs_create_u32_array);
650
523#ifdef CONFIG_HAS_IOMEM 651#ifdef CONFIG_HAS_IOMEM
524 652
525/* 653/*
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index ae36b72c22f3..66c434f5dd1e 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -93,6 +93,10 @@ struct dentry *debugfs_create_regset32(const char *name, umode_t mode,
93int debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs, 93int debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
94 int nregs, void __iomem *base, char *prefix); 94 int nregs, void __iomem *base, char *prefix);
95 95
96struct dentry *debugfs_create_u32_array(const char *name, umode_t mode,
97 struct dentry *parent,
98 u32 *array, u32 elements);
99
96bool debugfs_initialized(void); 100bool debugfs_initialized(void);
97 101
98#else 102#else
@@ -219,6 +223,13 @@ static inline bool debugfs_initialized(void)
219 return false; 223 return false;
220} 224}
221 225
226static inline struct dentry *debugfs_create_u32_array(const char *name, umode_t mode,
227 struct dentry *parent,
228 u32 *array, u32 elements)
229{
230 return ERR_PTR(-ENODEV);
231}
232
222#endif 233#endif
223 234
224#endif 235#endif