diff mbox

btrfs: debug: procfs-devlist: introduce procfs interface for the device list for debugging

Message ID 1459261880-32336-1-git-send-email-anand.jain@oracle.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Anand Jain March 29, 2016, 2:31 p.m. UTC
From: Anand Jain <Anand.Jain@oracle.com>

This patch introduces profs interface /proc/fs/btrfs/devlist, which as of now exports all the members of kernel fs_devices.

The current /sys/fs/btrfs interface works when the fs is mounted, and is on the file directory hierarchy and also has the sysfs limitation max output of U64 per file.

Here btrfs procfs uses seq_file to export all the members of fs_devices. Also shows the contents when device is not mounted, but have registered with btrfs kernel (useful as an alternative to buggy ready ioctl)

An attempt is made to follow the some standard file format output such as ini. So that a simple warper python script will provide end user useful interfaces.

Further planning to add few more members to the interface such as group profile info. The long term idea is to make procfs interface a onestop btrfs application interface for the device and fs info from the kernel, where a simple python script can make
use of it.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 fs/btrfs/Makefile |   2 +-
 fs/btrfs/ctree.h  |   4 +
 fs/btrfs/procfs.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/procfs.h |   1 +
 fs/btrfs/super.c  |   4 +
 5 files changed, 260 insertions(+), 1 deletion(-)
 create mode 100644 fs/btrfs/procfs.c
 create mode 100644 fs/btrfs/procfs.h

Comments

Anand Jain March 29, 2016, 2:36 p.m. UTC | #1
Sorry the commit log should have been..

----
** This patch is not for integration but to debug/visualize the
btrfs device tree. **

This patch introduces profs interface /proc/fs/btrfs/devlist,
which as of now exports all the members of kernel fs_devices
including some of the patches in the ML.

usage:
    cat /proc/fs/btrfs/devlist
----
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
kernel test robot March 29, 2016, 3:20 p.m. UTC | #2
Hi Anand,

[auto build test ERROR on btrfs/next]
[also build test ERROR on v4.6-rc1 next-20160329]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Anand-Jain/btrfs-debug-procfs-devlist-introduce-procfs-interface-for-the-device-list-for-debugging/20160329-223332
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git next
config: x86_64-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
   fs/btrfs/procfs.c:64:17: sparse: no member 'spare' in struct btrfs_fs_devices
   fs/btrfs/procfs.c:81:25: sparse: incompatible types in comparison expression (different address spaces)
   fs/btrfs/procfs.c:101:25: sparse: no member 'failed' in struct btrfs_device
   fs/btrfs/procfs.c:102:25: sparse: no member 'offline' in struct btrfs_device
   fs/btrfs/procfs.c:193:66: sparse: no member 'spare' in struct btrfs_fs_devices
   fs/btrfs/procfs.c:213:48: sparse: incompatible types in comparison expression (different address spaces)
   fs/btrfs/procfs.c:232:71: sparse: no member 'failed' in struct btrfs_device
   fs/btrfs/procfs.c:233:70: sparse: no member 'offline' in struct btrfs_device
   fs/btrfs/procfs.c: In function 'btrfs_print_devlist':
>> fs/btrfs/procfs.c:64:51: error: 'struct btrfs_fs_devices' has no member named 'spare'
      BTRFS_SEQ_PRINT("\tspare:\t\t\t%d\n", fs_devices->spare);
                                                      ^
   fs/btrfs/procfs.c:19:30: note: in definition of macro 'BTRFS_SEQ_PRINT'
      snprintf(str, BPSL, plist, arg);\
                                 ^
>> fs/btrfs/procfs.c:101:49: error: 'struct btrfs_device' has no member named 'failed'
       BTRFS_SEQ_PRINT("\t\tfailed:\t\t%d\n", device->failed);
                                                    ^
   fs/btrfs/procfs.c:19:30: note: in definition of macro 'BTRFS_SEQ_PRINT'
      snprintf(str, BPSL, plist, arg);\
                                 ^
>> fs/btrfs/procfs.c:102:48: error: 'struct btrfs_device' has no member named 'offline'
       BTRFS_SEQ_PRINT("\t\toffline:\t%d\n", device->offline);
                                                   ^
   fs/btrfs/procfs.c:19:30: note: in definition of macro 'BTRFS_SEQ_PRINT'
      snprintf(str, BPSL, plist, arg);\
                                 ^
   fs/btrfs/procfs.c: In function 'btrfs_printk_fsdev':
   fs/btrfs/procfs.c:193:52: error: 'struct btrfs_fs_devices' has no member named 'spare'
      printk(KERN_INFO "\tspare:\t\t\t%d\n", fs_devices->spare);
                                                       ^
   fs/btrfs/procfs.c:232:50: error: 'struct btrfs_device' has no member named 'failed'
       printk(KERN_INFO "\t\tfailed:\t\t%d\n", device->failed);
                                                     ^
   fs/btrfs/procfs.c:233:49: error: 'struct btrfs_device' has no member named 'offline'
       printk(KERN_INFO "\t\toffline:\t%d\n", device->offline);
                                                    ^

sparse warnings: (new ones prefixed by >>)

   include/linux/compiler.h:228:8: sparse: attribute 'no_sanitize_address': unknown attribute
   fs/btrfs/procfs.c:64:17: sparse: no member 'spare' in struct btrfs_fs_devices
>> fs/btrfs/procfs.c:81:25: sparse: incompatible types in comparison expression (different address spaces)
   fs/btrfs/procfs.c:101:25: sparse: no member 'failed' in struct btrfs_device
   fs/btrfs/procfs.c:102:25: sparse: no member 'offline' in struct btrfs_device
   fs/btrfs/procfs.c:193:66: sparse: no member 'spare' in struct btrfs_fs_devices
   fs/btrfs/procfs.c:213:48: sparse: incompatible types in comparison expression (different address spaces)
   fs/btrfs/procfs.c:232:71: sparse: no member 'failed' in struct btrfs_device
   fs/btrfs/procfs.c:233:70: sparse: no member 'offline' in struct btrfs_device
   fs/btrfs/procfs.c: In function 'btrfs_print_devlist':
   fs/btrfs/procfs.c:64:51: error: 'struct btrfs_fs_devices' has no member named 'spare'
      BTRFS_SEQ_PRINT("\tspare:\t\t\t%d\n", fs_devices->spare);
                                                      ^
   fs/btrfs/procfs.c:19:30: note: in definition of macro 'BTRFS_SEQ_PRINT'
      snprintf(str, BPSL, plist, arg);\
                                 ^
   fs/btrfs/procfs.c:101:49: error: 'struct btrfs_device' has no member named 'failed'
       BTRFS_SEQ_PRINT("\t\tfailed:\t\t%d\n", device->failed);
                                                    ^
   fs/btrfs/procfs.c:19:30: note: in definition of macro 'BTRFS_SEQ_PRINT'
      snprintf(str, BPSL, plist, arg);\
                                 ^
   fs/btrfs/procfs.c:102:48: error: 'struct btrfs_device' has no member named 'offline'
       BTRFS_SEQ_PRINT("\t\toffline:\t%d\n", device->offline);
                                                   ^
   fs/btrfs/procfs.c:19:30: note: in definition of macro 'BTRFS_SEQ_PRINT'
      snprintf(str, BPSL, plist, arg);\
                                 ^
   fs/btrfs/procfs.c: In function 'btrfs_printk_fsdev':
   fs/btrfs/procfs.c:193:52: error: 'struct btrfs_fs_devices' has no member named 'spare'
      printk(KERN_INFO "\tspare:\t\t\t%d\n", fs_devices->spare);
                                                       ^
   fs/btrfs/procfs.c:232:50: error: 'struct btrfs_device' has no member named 'failed'
       printk(KERN_INFO "\t\tfailed:\t\t%d\n", device->failed);
                                                     ^
   fs/btrfs/procfs.c:233:49: error: 'struct btrfs_device' has no member named 'offline'
       printk(KERN_INFO "\t\toffline:\t%d\n", device->offline);
                                                    ^

vim +64 fs/btrfs/procfs.c

    13	void btrfs_print_devlist(struct seq_file *seq)
    14	{
    15	
    16		/* Btrfs Procfs String Len */
    17	#define BPSL	256
    18	#define BTRFS_SEQ_PRINT(plist, arg)\
  > 19			snprintf(str, BPSL, plist, arg);\
    20			if (sprt)\
    21				seq_printf(seq, "\t");\
    22			seq_printf(seq, str)
    23	
    24		char str[BPSL];
    25		struct btrfs_device *device;
    26		struct btrfs_fs_devices *fs_devices;
    27		struct btrfs_fs_devices *cur_fs_devices;
    28		struct btrfs_fs_devices *sprt; //sprout fs devices
    29		struct list_head *fs_uuids = btrfs_get_fs_uuids();
    30		struct list_head *cur_uuid;
    31	
    32		seq_printf(seq, "\n#Its Experimental, parameters may change without notice.\n\n");
    33	
    34		mutex_lock(&uuid_mutex);
    35		/* Todo: there must be better way than nested locks */
    36		list_for_each(cur_uuid, fs_uuids) {
    37			cur_fs_devices  = list_entry(cur_uuid, struct btrfs_fs_devices, list);
    38	
    39			mutex_lock(&cur_fs_devices->device_list_mutex);
    40	
    41			fs_devices = cur_fs_devices;
    42			sprt = NULL;
    43	
    44	again_fs_devs:
    45			if (sprt) {
    46				BTRFS_SEQ_PRINT("[[seed_fsid: %pU]]\n", fs_devices->fsid);
    47				BTRFS_SEQ_PRINT("\tsprout_fsid:\t\t%pU\n", sprt->fsid);
    48			} else {
    49				BTRFS_SEQ_PRINT("[fsid: %pU]\n", fs_devices->fsid);
    50			}
    51			if (fs_devices->seed) {
    52				BTRFS_SEQ_PRINT("\tseed_fsid:\t\t%pU\n", fs_devices->seed->fsid);
    53			}
    54			BTRFS_SEQ_PRINT("\tfs_devs_addr:\t\t%p\n", fs_devices);
    55			BTRFS_SEQ_PRINT("\tnum_devices:\t\t%llu\n", fs_devices->num_devices);
    56			BTRFS_SEQ_PRINT("\topen_devices:\t\t%llu\n", fs_devices->open_devices);
    57			BTRFS_SEQ_PRINT("\trw_devices:\t\t%llu\n", fs_devices->rw_devices);
    58			BTRFS_SEQ_PRINT("\tmissing_devices:\t%llu\n", fs_devices->missing_devices);
    59			BTRFS_SEQ_PRINT("\ttotal_rw_devices:\t%llu\n", fs_devices->total_rw_bytes);
    60			BTRFS_SEQ_PRINT("\ttotal_devices:\t\t%llu\n", fs_devices->total_devices);
    61			BTRFS_SEQ_PRINT("\topened:\t\t\t%d\n", fs_devices->opened);
    62			BTRFS_SEQ_PRINT("\tseeding:\t\t%d\n", fs_devices->seeding);
    63			BTRFS_SEQ_PRINT("\trotating:\t\t%d\n", fs_devices->rotating);
  > 64			BTRFS_SEQ_PRINT("\tspare:\t\t\t%d\n", fs_devices->spare);
    65	
    66			BTRFS_SEQ_PRINT("\tfsid_kobj_state:\t%d\n", fs_devices->fsid_kobj.state_initialized);
    67			BTRFS_SEQ_PRINT("\tfsid_kobj_insysfs:\t%d\n", fs_devices->fsid_kobj.state_in_sysfs);
    68	
    69			if (fs_devices->device_dir_kobj) {
    70			BTRFS_SEQ_PRINT("\tdevice_kobj_state:\t%d\n", fs_devices->device_dir_kobj->state_initialized);
    71			BTRFS_SEQ_PRINT("\tdevice_kobj_insysfs:\t%d\n", fs_devices->device_dir_kobj->state_in_sysfs);
    72			} else {
    73			BTRFS_SEQ_PRINT("\tdevice_kobj_state:\t%s\n", "null");
    74			BTRFS_SEQ_PRINT("\tdevice_kobj_insysfs:\t%s\n", "null");
    75			}
    76	
    77			list_for_each_entry(device, &fs_devices->devices, dev_list) {
    78				BTRFS_SEQ_PRINT("\t[[uuid: %pU]]\n", device->uuid);
    79				BTRFS_SEQ_PRINT("\t\tdev_addr:\t%p\n", device);
    80				rcu_read_lock();
  > 81				BTRFS_SEQ_PRINT("\t\tdevice:\t\t%s\n",
    82					device->name ? rcu_str_deref(device->name): "(null)");
    83				rcu_read_unlock();
    84				BTRFS_SEQ_PRINT("\t\tdevid:\t\t%llu\n", device->devid);
    85				if (device->dev_root) {
    86					BTRFS_SEQ_PRINT("\t\tdev_root_fsid:\t%pU\n",
    87							device->dev_root->fs_info->fsid);
    88				}
    89				BTRFS_SEQ_PRINT("\t\tgeneration:\t%llu\n", device->generation);
    90				BTRFS_SEQ_PRINT("\t\ttotal_bytes:\t%llu\n", device->total_bytes);
    91				BTRFS_SEQ_PRINT("\t\tdev_totalbytes:\t%llu\n", device->disk_total_bytes);
    92				BTRFS_SEQ_PRINT("\t\tbytes_used:\t%llu\n", device->bytes_used);
    93				BTRFS_SEQ_PRINT("\t\ttype:\t\t%llu\n", device->type);
    94				BTRFS_SEQ_PRINT("\t\tio_align:\t%u\n", device->io_align);
    95				BTRFS_SEQ_PRINT("\t\tio_width:\t%u\n", device->io_width);
    96				BTRFS_SEQ_PRINT("\t\tsector_size:\t%u\n", device->sector_size);
    97				BTRFS_SEQ_PRINT("\t\tmode:\t\t0x%llx\n", (u64)device->mode);
    98				BTRFS_SEQ_PRINT("\t\twriteable:\t%d\n", device->writeable);
    99				BTRFS_SEQ_PRINT("\t\tin_fs_metadata:\t%d\n", device->in_fs_metadata);
   100				BTRFS_SEQ_PRINT("\t\tmissing:\t%d\n", device->missing);
 > 101				BTRFS_SEQ_PRINT("\t\tfailed:\t\t%d\n", device->failed);
 > 102				BTRFS_SEQ_PRINT("\t\toffline:\t%d\n", device->offline);
   103				BTRFS_SEQ_PRINT("\t\tcan_discard:\t%d\n", device->can_discard);
   104				BTRFS_SEQ_PRINT("\t\treplace_tgtdev:\t%d\n",
   105									device->is_tgtdev_for_dev_replace);
   106				BTRFS_SEQ_PRINT("\t\tactive_pending:\t%d\n", device->running_pending);
   107				BTRFS_SEQ_PRINT("\t\tnobarriers:\t%d\n", device->nobarriers);
   108				BTRFS_SEQ_PRINT("\t\tdevstats_valid:\t%d\n", device->dev_stats_valid);
   109				BTRFS_SEQ_PRINT("\t\tbdev:\t\t%s\n", device->bdev ? "not_null":"null");
   110			}
   111	
   112			if (fs_devices->seed) {
   113				sprt = fs_devices;
   114				fs_devices = fs_devices->seed;
   115				goto again_fs_devs;
   116			}
   117			seq_printf(seq, "\n");
   118	
   119			mutex_unlock(&cur_fs_devices->device_list_mutex);
   120		}
   121		mutex_unlock(&uuid_mutex);
   122	}
   123	static int btrfs_devlist_show(struct seq_file *seq, void *offset)
   124	{
   125		btrfs_print_devlist(seq);
   126		return 0;
   127	}
   128	
   129	static int btrfs_seq_open(struct inode *inode, struct file *file)
   130	{
   131		return single_open(file, btrfs_devlist_show, PDE_DATA(inode));
   132	}
   133	
   134	static const struct file_operations btrfs_seq_fops = {
   135		.owner   = THIS_MODULE,
   136		.open    = btrfs_seq_open,
   137		.read    = seq_read,
   138		.llseek  = seq_lseek,
   139		.release = single_release,
   140	};
   141	
   142	void btrfs_init_procfs(void)
   143	{
   144		btrfs_proc_root = proc_mkdir(BTRFS_PROC_PATH, NULL);
   145		if (btrfs_proc_root)
   146			proc_create_data(BTRFS_PROC_DEVLIST, S_IRUGO, btrfs_proc_root,
   147						&btrfs_seq_fops, NULL);
   148		return;
   149	}
   150	
   151	void btrfs_exit_procfs(void)
   152	{
   153		if (btrfs_proc_root)
   154			remove_proc_entry(BTRFS_PROC_DEVLIST, btrfs_proc_root);
   155		remove_proc_entry(BTRFS_PROC_PATH, NULL);
   156	}
   157	
   158	void btrfs_printk_fsdev(void)
   159	{
   160		struct btrfs_device *device;
   161		struct btrfs_fs_devices *fs_devices;
   162		struct btrfs_fs_devices *cur_fs_devices;
   163		struct btrfs_fs_devices *sprt; //sprout fs devices
   164		struct list_head *fs_uuids = btrfs_get_fs_uuids();
   165		struct list_head *cur_uuid;
   166	
   167		list_for_each(cur_uuid, fs_uuids) {
   168			cur_fs_devices  = list_entry(cur_uuid, struct btrfs_fs_devices, list);
   169	
   170			fs_devices = cur_fs_devices;
   171			sprt = NULL;
   172	
   173	again_fs_devs:
   174			if (sprt) {
   175				printk(KERN_INFO "[[seed_fsid: %pU]]\n", fs_devices->fsid);
   176				printk(KERN_INFO "\tsprout_fsid:\t\t%pU\n", sprt->fsid);
   177			} else {
   178				printk(KERN_INFO "[fsid: %pU]\n", fs_devices->fsid);
   179			}
   180			if (fs_devices->seed) {
   181				printk(KERN_INFO "\tseed_fsid:\t\t%pU\n", fs_devices->seed->fsid);
   182			}
   183			printk(KERN_INFO "\tfs_devs_addr:\t\t%p\n", fs_devices);
   184			printk(KERN_INFO "\tnum_devices:\t\t%llu\n", fs_devices->num_devices);
   185			printk(KERN_INFO "\topen_devices:\t\t%llu\n", fs_devices->open_devices);
   186			printk(KERN_INFO "\trw_devices:\t\t%llu\n", fs_devices->rw_devices);
   187			printk(KERN_INFO "\tmissing_devices:\t%llu\n", fs_devices->missing_devices);
   188			printk(KERN_INFO "\ttotal_rw_devices:\t%llu\n", fs_devices->total_rw_bytes);
   189			printk(KERN_INFO "\ttotal_devices:\t\t%llu\n", fs_devices->total_devices);
   190			printk(KERN_INFO "\topened:\t\t\t%d\n", fs_devices->opened);
   191			printk(KERN_INFO "\tseeding:\t\t%d\n", fs_devices->seeding);
   192			printk(KERN_INFO "\trotating:\t\t%d\n", fs_devices->rotating);
   193			printk(KERN_INFO "\tspare:\t\t\t%d\n", fs_devices->spare);
   194	
   195			printk(KERN_INFO "\tfsid_kobj_state:\t%d\n", fs_devices->fsid_kobj.state_initialized);
   196			printk(KERN_INFO "\tfsid_kobj_insysfs:\t%d\n", fs_devices->fsid_kobj.state_in_sysfs);
   197	
   198			if (fs_devices->device_dir_kobj) {
   199			printk(KERN_INFO "\tdevice_kobj_state:\t%d\n", fs_devices->device_dir_kobj->state_initialized);
   200			printk(KERN_INFO "\tdevice_kobj_insysfs:\t%d\n", fs_devices->device_dir_kobj->state_in_sysfs);
   201			} else {
   202			printk(KERN_INFO "\tdevice_kobj_state:\t%s\n", "null");
   203			printk(KERN_INFO "\tdevice_kobj_insysfs:\t%s\n", "null");
   204			}
   205	
   206			printk(KERN_INFO "\tfs_info:\t\t%pK\n", fs_devices->fs_info);
   207	
   208			list_for_each_entry(device, &fs_devices->devices, dev_list) {
   209				printk(KERN_INFO "\t[[uuid: %pU]]\n", device->uuid);
   210				printk(KERN_INFO "\t\tdev_addr:\t%p\n", device);
   211				rcu_read_lock();
   212				printk(KERN_INFO "\t\tdevice:\t\t%s\n",
   213					device->name ? rcu_str_deref(device->name): "(null)");
   214				rcu_read_unlock();
   215				printk(KERN_INFO "\t\tdevid:\t\t%llu\n", device->devid);
   216				if (device->dev_root) {
   217					printk(KERN_INFO "\t\tdev_root_fsid:\t%pU\n",
   218							device->dev_root->fs_info->fsid);
   219				}
   220				printk(KERN_INFO "\t\tgeneration:\t%llu\n", device->generation);
   221				printk(KERN_INFO "\t\ttotal_bytes:\t%llu\n", device->total_bytes);
   222				printk(KERN_INFO "\t\tdev_totalbytes:\t%llu\n", device->disk_total_bytes);
   223				printk(KERN_INFO "\t\tbytes_used:\t%llu\n", device->bytes_used);
   224				printk(KERN_INFO "\t\ttype:\t\t%llu\n", device->type);
   225				printk(KERN_INFO "\t\tio_align:\t%u\n", device->io_align);
   226				printk(KERN_INFO "\t\tio_width:\t%u\n", device->io_width);
   227				printk(KERN_INFO "\t\tsector_size:\t%u\n", device->sector_size);
   228				printk(KERN_INFO "\t\tmode:\t\t0x%llx\n", (u64)device->mode);
   229				printk(KERN_INFO "\t\twriteable:\t%d\n", device->writeable);
   230				printk(KERN_INFO "\t\tin_fs_metadata:\t%d\n", device->in_fs_metadata);
   231				printk(KERN_INFO "\t\tmissing:\t%d\n", device->missing);
 > 232				printk(KERN_INFO "\t\tfailed:\t\t%d\n", device->failed);
   233				printk(KERN_INFO "\t\toffline:\t%d\n", device->offline);
   234				printk(KERN_INFO "\t\tcan_discard:\t%d\n", device->can_discard);
   235				printk(KERN_INFO "\t\treplace_tgtdev:\t%d\n",

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index 128ce17a80b0..019f936788cc 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -4,7 +4,7 @@  obj-$(CONFIG_BTRFS_FS) := btrfs.o
 btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
 	   file-item.o inode-item.o inode-map.o disk-io.o \
 	   transaction.o inode.o file.o tree-defrag.o \
-	   extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
+	   extent_map.o sysfs.o procfs.o struct-funcs.o xattr.o ordered-data.o \
 	   extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
 	   export.o tree-log.o free-space-cache.o zlib.o lzo.o \
 	   compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 36f1c29e00a0..429364a4b487 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -4593,4 +4593,8 @@  static inline int btrfs_test_is_dummy_root(struct btrfs_root *root)
 	return 0;
 }
 
+/* procfs.c */
+void btrfs_exit_procfs(void);
+void btrfs_init_procfs(void);
+
 #endif
diff --git a/fs/btrfs/procfs.c b/fs/btrfs/procfs.c
new file mode 100644
index 000000000000..99edcad8a825
--- /dev/null
+++ b/fs/btrfs/procfs.c
@@ -0,0 +1,250 @@ 
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include "ctree.h"
+#include "volumes.h"
+#include "rcu-string.h"
+
+#define BTRFS_PROC_PATH		"fs/btrfs"
+#define BTRFS_PROC_DEVLIST	"devlist"
+
+struct proc_dir_entry	*btrfs_proc_root;
+
+void btrfs_print_devlist(struct seq_file *seq)
+{
+
+	/* Btrfs Procfs String Len */
+#define BPSL	256
+#define BTRFS_SEQ_PRINT(plist, arg)\
+		snprintf(str, BPSL, plist, arg);\
+		if (sprt)\
+			seq_printf(seq, "\t");\
+		seq_printf(seq, str)
+
+	char str[BPSL];
+	struct btrfs_device *device;
+	struct btrfs_fs_devices *fs_devices;
+	struct btrfs_fs_devices *cur_fs_devices;
+	struct btrfs_fs_devices *sprt; //sprout fs devices
+	struct list_head *fs_uuids = btrfs_get_fs_uuids();
+	struct list_head *cur_uuid;
+
+	seq_printf(seq, "\n#Its Experimental, parameters may change without notice.\n\n");
+
+	mutex_lock(&uuid_mutex);
+	/* Todo: there must be better way than nested locks */
+	list_for_each(cur_uuid, fs_uuids) {
+		cur_fs_devices  = list_entry(cur_uuid, struct btrfs_fs_devices, list);
+
+		mutex_lock(&cur_fs_devices->device_list_mutex);
+
+		fs_devices = cur_fs_devices;
+		sprt = NULL;
+
+again_fs_devs:
+		if (sprt) {
+			BTRFS_SEQ_PRINT("[[seed_fsid: %pU]]\n", fs_devices->fsid);
+			BTRFS_SEQ_PRINT("\tsprout_fsid:\t\t%pU\n", sprt->fsid);
+		} else {
+			BTRFS_SEQ_PRINT("[fsid: %pU]\n", fs_devices->fsid);
+		}
+		if (fs_devices->seed) {
+			BTRFS_SEQ_PRINT("\tseed_fsid:\t\t%pU\n", fs_devices->seed->fsid);
+		}
+		BTRFS_SEQ_PRINT("\tfs_devs_addr:\t\t%p\n", fs_devices);
+		BTRFS_SEQ_PRINT("\tnum_devices:\t\t%llu\n", fs_devices->num_devices);
+		BTRFS_SEQ_PRINT("\topen_devices:\t\t%llu\n", fs_devices->open_devices);
+		BTRFS_SEQ_PRINT("\trw_devices:\t\t%llu\n", fs_devices->rw_devices);
+		BTRFS_SEQ_PRINT("\tmissing_devices:\t%llu\n", fs_devices->missing_devices);
+		BTRFS_SEQ_PRINT("\ttotal_rw_devices:\t%llu\n", fs_devices->total_rw_bytes);
+		BTRFS_SEQ_PRINT("\ttotal_devices:\t\t%llu\n", fs_devices->total_devices);
+		BTRFS_SEQ_PRINT("\topened:\t\t\t%d\n", fs_devices->opened);
+		BTRFS_SEQ_PRINT("\tseeding:\t\t%d\n", fs_devices->seeding);
+		BTRFS_SEQ_PRINT("\trotating:\t\t%d\n", fs_devices->rotating);
+		BTRFS_SEQ_PRINT("\tspare:\t\t\t%d\n", fs_devices->spare);
+
+		BTRFS_SEQ_PRINT("\tfsid_kobj_state:\t%d\n", fs_devices->fsid_kobj.state_initialized);
+		BTRFS_SEQ_PRINT("\tfsid_kobj_insysfs:\t%d\n", fs_devices->fsid_kobj.state_in_sysfs);
+
+		if (fs_devices->device_dir_kobj) {
+		BTRFS_SEQ_PRINT("\tdevice_kobj_state:\t%d\n", fs_devices->device_dir_kobj->state_initialized);
+		BTRFS_SEQ_PRINT("\tdevice_kobj_insysfs:\t%d\n", fs_devices->device_dir_kobj->state_in_sysfs);
+		} else {
+		BTRFS_SEQ_PRINT("\tdevice_kobj_state:\t%s\n", "null");
+		BTRFS_SEQ_PRINT("\tdevice_kobj_insysfs:\t%s\n", "null");
+		}
+
+		list_for_each_entry(device, &fs_devices->devices, dev_list) {
+			BTRFS_SEQ_PRINT("\t[[uuid: %pU]]\n", device->uuid);
+			BTRFS_SEQ_PRINT("\t\tdev_addr:\t%p\n", device);
+			rcu_read_lock();
+			BTRFS_SEQ_PRINT("\t\tdevice:\t\t%s\n",
+				device->name ? rcu_str_deref(device->name): "(null)");
+			rcu_read_unlock();
+			BTRFS_SEQ_PRINT("\t\tdevid:\t\t%llu\n", device->devid);
+			if (device->dev_root) {
+				BTRFS_SEQ_PRINT("\t\tdev_root_fsid:\t%pU\n",
+						device->dev_root->fs_info->fsid);
+			}
+			BTRFS_SEQ_PRINT("\t\tgeneration:\t%llu\n", device->generation);
+			BTRFS_SEQ_PRINT("\t\ttotal_bytes:\t%llu\n", device->total_bytes);
+			BTRFS_SEQ_PRINT("\t\tdev_totalbytes:\t%llu\n", device->disk_total_bytes);
+			BTRFS_SEQ_PRINT("\t\tbytes_used:\t%llu\n", device->bytes_used);
+			BTRFS_SEQ_PRINT("\t\ttype:\t\t%llu\n", device->type);
+			BTRFS_SEQ_PRINT("\t\tio_align:\t%u\n", device->io_align);
+			BTRFS_SEQ_PRINT("\t\tio_width:\t%u\n", device->io_width);
+			BTRFS_SEQ_PRINT("\t\tsector_size:\t%u\n", device->sector_size);
+			BTRFS_SEQ_PRINT("\t\tmode:\t\t0x%llx\n", (u64)device->mode);
+			BTRFS_SEQ_PRINT("\t\twriteable:\t%d\n", device->writeable);
+			BTRFS_SEQ_PRINT("\t\tin_fs_metadata:\t%d\n", device->in_fs_metadata);
+			BTRFS_SEQ_PRINT("\t\tmissing:\t%d\n", device->missing);
+			BTRFS_SEQ_PRINT("\t\tfailed:\t\t%d\n", device->failed);
+			BTRFS_SEQ_PRINT("\t\toffline:\t%d\n", device->offline);
+			BTRFS_SEQ_PRINT("\t\tcan_discard:\t%d\n", device->can_discard);
+			BTRFS_SEQ_PRINT("\t\treplace_tgtdev:\t%d\n",
+								device->is_tgtdev_for_dev_replace);
+			BTRFS_SEQ_PRINT("\t\tactive_pending:\t%d\n", device->running_pending);
+			BTRFS_SEQ_PRINT("\t\tnobarriers:\t%d\n", device->nobarriers);
+			BTRFS_SEQ_PRINT("\t\tdevstats_valid:\t%d\n", device->dev_stats_valid);
+			BTRFS_SEQ_PRINT("\t\tbdev:\t\t%s\n", device->bdev ? "not_null":"null");
+		}
+
+		if (fs_devices->seed) {
+			sprt = fs_devices;
+			fs_devices = fs_devices->seed;
+			goto again_fs_devs;
+		}
+		seq_printf(seq, "\n");
+
+		mutex_unlock(&cur_fs_devices->device_list_mutex);
+	}
+	mutex_unlock(&uuid_mutex);
+}
+static int btrfs_devlist_show(struct seq_file *seq, void *offset)
+{
+	btrfs_print_devlist(seq);
+	return 0;
+}
+
+static int btrfs_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, btrfs_devlist_show, PDE_DATA(inode));
+}
+
+static const struct file_operations btrfs_seq_fops = {
+	.owner   = THIS_MODULE,
+	.open    = btrfs_seq_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+void btrfs_init_procfs(void)
+{
+	btrfs_proc_root = proc_mkdir(BTRFS_PROC_PATH, NULL);
+	if (btrfs_proc_root)
+		proc_create_data(BTRFS_PROC_DEVLIST, S_IRUGO, btrfs_proc_root,
+					&btrfs_seq_fops, NULL);
+	return;
+}
+
+void btrfs_exit_procfs(void)
+{
+	if (btrfs_proc_root)
+		remove_proc_entry(BTRFS_PROC_DEVLIST, btrfs_proc_root);
+	remove_proc_entry(BTRFS_PROC_PATH, NULL);
+}
+
+void btrfs_printk_fsdev(void)
+{
+	struct btrfs_device *device;
+	struct btrfs_fs_devices *fs_devices;
+	struct btrfs_fs_devices *cur_fs_devices;
+	struct btrfs_fs_devices *sprt; //sprout fs devices
+	struct list_head *fs_uuids = btrfs_get_fs_uuids();
+	struct list_head *cur_uuid;
+
+	list_for_each(cur_uuid, fs_uuids) {
+		cur_fs_devices  = list_entry(cur_uuid, struct btrfs_fs_devices, list);
+
+		fs_devices = cur_fs_devices;
+		sprt = NULL;
+
+again_fs_devs:
+		if (sprt) {
+			printk(KERN_INFO "[[seed_fsid: %pU]]\n", fs_devices->fsid);
+			printk(KERN_INFO "\tsprout_fsid:\t\t%pU\n", sprt->fsid);
+		} else {
+			printk(KERN_INFO "[fsid: %pU]\n", fs_devices->fsid);
+		}
+		if (fs_devices->seed) {
+			printk(KERN_INFO "\tseed_fsid:\t\t%pU\n", fs_devices->seed->fsid);
+		}
+		printk(KERN_INFO "\tfs_devs_addr:\t\t%p\n", fs_devices);
+		printk(KERN_INFO "\tnum_devices:\t\t%llu\n", fs_devices->num_devices);
+		printk(KERN_INFO "\topen_devices:\t\t%llu\n", fs_devices->open_devices);
+		printk(KERN_INFO "\trw_devices:\t\t%llu\n", fs_devices->rw_devices);
+		printk(KERN_INFO "\tmissing_devices:\t%llu\n", fs_devices->missing_devices);
+		printk(KERN_INFO "\ttotal_rw_devices:\t%llu\n", fs_devices->total_rw_bytes);
+		printk(KERN_INFO "\ttotal_devices:\t\t%llu\n", fs_devices->total_devices);
+		printk(KERN_INFO "\topened:\t\t\t%d\n", fs_devices->opened);
+		printk(KERN_INFO "\tseeding:\t\t%d\n", fs_devices->seeding);
+		printk(KERN_INFO "\trotating:\t\t%d\n", fs_devices->rotating);
+		printk(KERN_INFO "\tspare:\t\t\t%d\n", fs_devices->spare);
+
+		printk(KERN_INFO "\tfsid_kobj_state:\t%d\n", fs_devices->fsid_kobj.state_initialized);
+		printk(KERN_INFO "\tfsid_kobj_insysfs:\t%d\n", fs_devices->fsid_kobj.state_in_sysfs);
+
+		if (fs_devices->device_dir_kobj) {
+		printk(KERN_INFO "\tdevice_kobj_state:\t%d\n", fs_devices->device_dir_kobj->state_initialized);
+		printk(KERN_INFO "\tdevice_kobj_insysfs:\t%d\n", fs_devices->device_dir_kobj->state_in_sysfs);
+		} else {
+		printk(KERN_INFO "\tdevice_kobj_state:\t%s\n", "null");
+		printk(KERN_INFO "\tdevice_kobj_insysfs:\t%s\n", "null");
+		}
+
+		printk(KERN_INFO "\tfs_info:\t\t%pK\n", fs_devices->fs_info);
+
+		list_for_each_entry(device, &fs_devices->devices, dev_list) {
+			printk(KERN_INFO "\t[[uuid: %pU]]\n", device->uuid);
+			printk(KERN_INFO "\t\tdev_addr:\t%p\n", device);
+			rcu_read_lock();
+			printk(KERN_INFO "\t\tdevice:\t\t%s\n",
+				device->name ? rcu_str_deref(device->name): "(null)");
+			rcu_read_unlock();
+			printk(KERN_INFO "\t\tdevid:\t\t%llu\n", device->devid);
+			if (device->dev_root) {
+				printk(KERN_INFO "\t\tdev_root_fsid:\t%pU\n",
+						device->dev_root->fs_info->fsid);
+			}
+			printk(KERN_INFO "\t\tgeneration:\t%llu\n", device->generation);
+			printk(KERN_INFO "\t\ttotal_bytes:\t%llu\n", device->total_bytes);
+			printk(KERN_INFO "\t\tdev_totalbytes:\t%llu\n", device->disk_total_bytes);
+			printk(KERN_INFO "\t\tbytes_used:\t%llu\n", device->bytes_used);
+			printk(KERN_INFO "\t\ttype:\t\t%llu\n", device->type);
+			printk(KERN_INFO "\t\tio_align:\t%u\n", device->io_align);
+			printk(KERN_INFO "\t\tio_width:\t%u\n", device->io_width);
+			printk(KERN_INFO "\t\tsector_size:\t%u\n", device->sector_size);
+			printk(KERN_INFO "\t\tmode:\t\t0x%llx\n", (u64)device->mode);
+			printk(KERN_INFO "\t\twriteable:\t%d\n", device->writeable);
+			printk(KERN_INFO "\t\tin_fs_metadata:\t%d\n", device->in_fs_metadata);
+			printk(KERN_INFO "\t\tmissing:\t%d\n", device->missing);
+			printk(KERN_INFO "\t\tfailed:\t\t%d\n", device->failed);
+			printk(KERN_INFO "\t\toffline:\t%d\n", device->offline);
+			printk(KERN_INFO "\t\tcan_discard:\t%d\n", device->can_discard);
+			printk(KERN_INFO "\t\treplace_tgtdev:\t%d\n",
+								device->is_tgtdev_for_dev_replace);
+			printk(KERN_INFO "\t\tactive_pending:\t%d\n", device->running_pending);
+			printk(KERN_INFO "\t\tnobarriers:\t%d\n", device->nobarriers);
+			printk(KERN_INFO "\t\tdevstats_valid:\t%d\n", device->dev_stats_valid);
+			printk(KERN_INFO "\t\tbdev:\t\t%s\n", device->bdev ? "not_null":"null");
+		}
+
+		if (fs_devices->seed) {
+			sprt = fs_devices;
+			fs_devices = fs_devices->seed;
+			goto again_fs_devs;
+		}
+		printk(KERN_INFO "\n");
+	}
+}
diff --git a/fs/btrfs/procfs.h b/fs/btrfs/procfs.h
new file mode 100644
index 000000000000..e36d2145804e
--- /dev/null
+++ b/fs/btrfs/procfs.h
@@ -0,0 +1 @@ 
+void btrfs_printk_fsdev(void);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 138fca39ffbb..868ad9e4cde0 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2361,6 +2361,8 @@  static int __init init_btrfs_fs(void)
 	if (err)
 		goto free_hash;
 
+	btrfs_init_procfs();
+
 	btrfs_init_compress();
 
 	err = btrfs_init_cachep();
@@ -2439,6 +2441,7 @@  free_cachep:
 	btrfs_destroy_cachep();
 free_compress:
 	btrfs_exit_compress();
+	btrfs_exit_procfs();
 	btrfs_exit_sysfs();
 free_hash:
 	btrfs_hash_exit();
@@ -2458,6 +2461,7 @@  static void __exit exit_btrfs_fs(void)
 	btrfs_interface_exit();
 	btrfs_end_io_wq_exit();
 	unregister_filesystem(&btrfs_fs_type);
+	btrfs_exit_procfs();
 	btrfs_exit_sysfs();
 	btrfs_cleanup_fs_uuids();
 	btrfs_exit_compress();