diff options
| author | Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com> | 2012-03-23 04:06:28 -0400 |
|---|---|---|
| committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-04-17 00:18:36 -0400 |
| commit | 9fe2a7015393dc0203ac39242ae9c89038994f3c (patch) | |
| tree | bfc2da0985afec7b951946029db8607d9c6d2e8d /fs/debugfs | |
| parent | e816b57a337ea3b755de72bec38c10c864f23015 (diff) | |
debugfs: Add support to print u32 array in debugfs
Move the code from Xen to debugfs to make the code common
for other users as well.
Accked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
[v1: Fixed rebase issues]
[v2: Fixed PPC compile issues]
Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'fs/debugfs')
| -rw-r--r-- | fs/debugfs/file.c | 128 |
1 files changed, 128 insertions, 0 deletions
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 | ||
| 24 | static ssize_t default_read_file(struct file *file, char __user *buf, | 25 | static 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 | } |
| 521 | EXPORT_SYMBOL_GPL(debugfs_create_blob); | 522 | EXPORT_SYMBOL_GPL(debugfs_create_blob); |
| 522 | 523 | ||
| 524 | struct array_data { | ||
| 525 | void *array; | ||
| 526 | u32 elements; | ||
| 527 | }; | ||
| 528 | |||
| 529 | static int u32_array_open(struct inode *inode, struct file *file) | ||
| 530 | { | ||
| 531 | file->private_data = NULL; | ||
| 532 | return nonseekable_open(inode, file); | ||
| 533 | } | ||
| 534 | |||
| 535 | static 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 | |||
| 562 | static 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 | |||
| 576 | static 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 | |||
| 601 | static int u32_array_release(struct inode *inode, struct file *file) | ||
| 602 | { | ||
| 603 | kfree(file->private_data); | ||
| 604 | |||
| 605 | return 0; | ||
| 606 | } | ||
| 607 | |||
| 608 | static 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 | */ | ||
| 635 | struct 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 | } | ||
| 649 | EXPORT_SYMBOL_GPL(debugfs_create_u32_array); | ||
| 650 | |||
| 523 | #ifdef CONFIG_HAS_IOMEM | 651 | #ifdef CONFIG_HAS_IOMEM |
| 524 | 652 | ||
| 525 | /* | 653 | /* |
