|
|
@@ -0,0 +1,600 @@ |
|
|
#include <linux/seq_file.h> |
|
|
#include <linux/vmalloc.h> |
|
|
#include <linux/proc_fs.h> |
|
|
#include "ctree.h" |
|
|
#include "volumes.h" |
|
|
#include "rcu-string.h" |
|
|
#include "procfs.h" |
|
|
|
|
|
#define BPSL 256 |
|
|
|
|
|
#define BTRFS_PROC_PATH "fs/btrfs" |
|
|
#define BTRFS_PROC_DEVLIST "devlist" |
|
|
#define BTRFS_PROC_FSINFO "fsinfo" |
|
|
|
|
|
//#define USE_ALLOC_LIST |
|
|
//#define VOL_FLAGS |
|
|
//#define FS_OPEN_RW |
|
|
#define BALANCE_RUNNING |
|
|
//#define OLD_PROC |
|
|
|
|
|
struct proc_dir_entry *btrfs_proc_root; |
|
|
|
|
|
static void fs_state_to_str(struct btrfs_fs_info *fs_info, char *str) |
|
|
{ |
|
|
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) |
|
|
strcat(str, "|ERROR"); |
|
|
if (test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state)) |
|
|
strcat(str, "|REMOUNTING"); |
|
|
if (test_bit(BTRFS_FS_STATE_TRANS_ABORTED, &fs_info->fs_state)) |
|
|
strcat(str, "|TRANS_ABORTED"); |
|
|
if (test_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state)) |
|
|
strcat(str, "|REPLACING"); |
|
|
if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
|
|
strcat(str, "|DUMMY"); |
|
|
} |
|
|
|
|
|
static void fs_flags_to_str(struct btrfs_fs_info *fs_info, char *str) |
|
|
{ |
|
|
if (test_bit(BTRFS_FS_BARRIER, &fs_info->flags)) |
|
|
strcat(str, "|BARRIER"); |
|
|
if (test_bit(BTRFS_FS_CLOSING_START, &fs_info->flags)) |
|
|
strcat(str, "|CLOSING_START"); |
|
|
if (test_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags)) |
|
|
strcat(str, "|CLOSING_DONE"); |
|
|
if (test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) |
|
|
strcat(str, "|RECOVERING"); |
|
|
if (test_bit(BTRFS_FS_OPEN, &fs_info->flags)) |
|
|
strcat(str, "|OPEN"); |
|
|
if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) |
|
|
strcat(str, "|QUOTA_ENABLED"); |
|
|
if (test_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags)) |
|
|
strcat(str, "|UPDATE_UUID_TREE_GEN"); |
|
|
if (test_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags)) |
|
|
strcat(str, "|FREE_SPACE_TREE"); |
|
|
if (test_bit(BTRFS_FS_BTREE_ERR, &fs_info->flags)) |
|
|
strcat(str, "|BTREE_ERR"); |
|
|
if (test_bit(BTRFS_FS_LOG1_ERR, &fs_info->flags)) |
|
|
strcat(str, "|LOG1_ERR"); |
|
|
if (test_bit(BTRFS_FS_LOG2_ERR, &fs_info->flags)) |
|
|
strcat(str, "|LOG2_ERR"); |
|
|
if (test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags)) |
|
|
strcat(str, "|QUOTA_OVERRIDE"); |
|
|
if (test_bit(BTRFS_FS_FROZEN, &fs_info->flags)) |
|
|
strcat(str, "|FROZEN"); |
|
|
if (test_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) |
|
|
strcat(str, "|EXCL_OP"); |
|
|
#ifdef BALANCE_RUNNING |
|
|
if (test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags)) |
|
|
strcat(str, "|BALANCE_RUNNING"); |
|
|
#else |
|
|
if (atomic_read(&fs_info->balance_running)) |
|
|
strcat(str, "|BALANCE_RUNNING"); |
|
|
#endif |
|
|
if (atomic_read(&fs_info->balance_pause_req)) |
|
|
strcat(str, "|BALANCE_PAUSEREQ"); |
|
|
if (atomic_read(&fs_info->balance_cancel_req)) |
|
|
strcat(str, "|BALANCE_CANCELREQ"); |
|
|
} |
|
|
|
|
|
static void balance_ctl_flags_to_str(struct btrfs_balance_control *bctl, |
|
|
char *str) |
|
|
{ |
|
|
if (BTRFS_BALANCE_DATA & bctl->flags) |
|
|
strcat(str, "|DATA"); |
|
|
if (BTRFS_BALANCE_SYSTEM & bctl->flags) |
|
|
strcat(str, "|SYSTEM"); |
|
|
if (BTRFS_BALANCE_METADATA & bctl->flags) |
|
|
strcat(str, "|METADATA"); |
|
|
if (BTRFS_BALANCE_FORCE & bctl->flags) |
|
|
strcat(str, "|FORCE"); |
|
|
if (BTRFS_BALANCE_RESUME & bctl->flags) |
|
|
strcat(str, "|RESUME"); |
|
|
} |
|
|
|
|
|
static char *bg_flags_to_str(u64 chunk_type, char *str) |
|
|
{ |
|
|
if (chunk_type & BTRFS_BLOCK_GROUP_RAID0) |
|
|
strcat(str, "|RAID0"); |
|
|
if (chunk_type & BTRFS_BLOCK_GROUP_RAID1) |
|
|
strcat(str, "|RAID1"); |
|
|
if (chunk_type & BTRFS_BLOCK_GROUP_RAID5) |
|
|
strcat(str, "|RAID5"); |
|
|
if (chunk_type & BTRFS_BLOCK_GROUP_RAID6) |
|
|
strcat(str, "|RAID6"); |
|
|
if (chunk_type & BTRFS_BLOCK_GROUP_DUP) |
|
|
strcat(str, "|DUP"); |
|
|
if (chunk_type & BTRFS_BLOCK_GROUP_RAID10) |
|
|
strcat(str, "|RAID10"); |
|
|
if (chunk_type & BTRFS_AVAIL_ALLOC_BIT_SINGLE) |
|
|
strcat(str, "|ALLOC_SINGLE"); |
|
|
|
|
|
return str; |
|
|
} |
|
|
|
|
|
static void balance_args_to_str(struct btrfs_balance_args *bargs, char *str, |
|
|
char *prefix) |
|
|
{ |
|
|
int ret = 0; |
|
|
|
|
|
ret = sprintf(str, "\tbalance_args.%s\t", prefix); |
|
|
str=str+ret; |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_SOFT) |
|
|
strcat(str, "|SOFT"); |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_PROFILES) { |
|
|
strcat(str, "|profiles="); |
|
|
str = bg_flags_to_str(bargs->profiles, str); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_USAGE) { |
|
|
ret = sprintf(str, "|usage=%llu ", bargs->usage); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_USAGE_RANGE) { |
|
|
ret = sprintf(str, "|usage_min=%u usage_max=%u", |
|
|
bargs->usage_min, bargs->usage_max); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_DEVID) { |
|
|
ret = sprintf(str, "|devid=%llu ", bargs->devid); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_DRANGE) { |
|
|
ret = sprintf(str, "|DRANGE pstart=%llu pend=%llu ", |
|
|
bargs->pstart, bargs->pend); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_VRANGE) { |
|
|
ret = sprintf(str, "|VRANGE vstart=%llu vend %llu", |
|
|
bargs->vstart, bargs->vend); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_LIMIT) { |
|
|
ret = sprintf(str, "|limit=%llu ", bargs->limit); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_LIMIT_RANGE) { |
|
|
ret = sprintf(str, "|limit_min=%u limit_max=%u", |
|
|
bargs->limit_min, bargs->limit_max); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_STRIPES_RANGE) { |
|
|
ret = sprintf(str, "|stripes_min=%u stripes_max=%u ", |
|
|
bargs->stripes_min, bargs->stripes_max); |
|
|
str=str+ret; |
|
|
} |
|
|
|
|
|
if (bargs->flags & BTRFS_BALANCE_ARGS_CONVERT) { |
|
|
strcat(str, "|convert="); |
|
|
str = bg_flags_to_str(bargs->target, str); |
|
|
} |
|
|
} |
|
|
|
|
|
static void print_balance_args(struct btrfs_balance_args *bargs, char *prefix, |
|
|
struct seq_file *seq) |
|
|
{ |
|
|
#define BTRFS_SEQ_PRINT3(plist, arg)\ |
|
|
snprintf(__str, BPSL, plist, arg);\ |
|
|
seq_printf(seq, __str) |
|
|
char __str[BPSL]; |
|
|
|
|
|
char tmp_str[BPSL]; |
|
|
|
|
|
memset(tmp_str, '\0', 256); |
|
|
balance_args_to_str(bargs, tmp_str, prefix); |
|
|
BTRFS_SEQ_PRINT3("%s\n", tmp_str); |
|
|
} |
|
|
|
|
|
static void balance_progress_to_str(struct btrfs_balance_progress *bstat, char *str) |
|
|
{ |
|
|
int ret=0; |
|
|
ret = sprintf(str, "expected=%llu ", bstat->expected); |
|
|
str=str+ret; |
|
|
ret = sprintf(str, "considered=%llu ", bstat->considered); |
|
|
str=str+ret; |
|
|
ret = sprintf(str, "completed=%llu ", bstat->completed); |
|
|
} |
|
|
|
|
|
void btrfs_print_fsinfo(struct seq_file *seq) |
|
|
{ |
|
|
/* Btrfs Procfs String Len */ |
|
|
#define BTRFS_SEQ_PRINT2(plist, arg)\ |
|
|
snprintf(str, BPSL, plist, arg);\ |
|
|
seq_printf(seq, str) |
|
|
|
|
|
char str[BPSL]; |
|
|
char b[BDEVNAME_SIZE]; |
|
|
struct list_head *cur_uuid; |
|
|
struct btrfs_fs_info *fs_info; |
|
|
struct btrfs_fs_devices *fs_devices; |
|
|
struct list_head *fs_uuids = btrfs_get_fs_uuids(); |
|
|
|
|
|
seq_printf(seq, "\n#Its for debugging and experimental only, parameters may change without notice.\n\n"); |
|
|
|
|
|
list_for_each(cur_uuid, fs_uuids) { |
|
|
char fs_str[256] = {0}; |
|
|
fs_devices = list_entry(cur_uuid, struct btrfs_fs_devices, fs_list); |
|
|
fs_info = fs_devices->fs_info; |
|
|
if (!fs_info) |
|
|
continue; |
|
|
|
|
|
BTRFS_SEQ_PRINT2("[fsid: %pU]\n", fs_devices->fsid); |
|
|
BTRFS_SEQ_PRINT2("\tsb->s_bdev:\t\t%s\n", |
|
|
fs_info->sb->s_bdev ? |
|
|
bdevname(fs_info->sb->s_bdev, b): |
|
|
"null"); |
|
|
BTRFS_SEQ_PRINT2("\tlatest_bdev:\t\t%s\n", |
|
|
fs_devices->latest_bdev ? |
|
|
bdevname(fs_devices->latest_bdev, b): |
|
|
"null"); |
|
|
|
|
|
fs_state_to_str(fs_info, fs_str); |
|
|
BTRFS_SEQ_PRINT2("\tfs_state:\t\t%s\n", fs_str); |
|
|
|
|
|
memset(fs_str, '\0', 256); |
|
|
fs_flags_to_str(fs_info, fs_str); |
|
|
BTRFS_SEQ_PRINT2("\tfs_flags:\t\t%s\n", fs_str); |
|
|
|
|
|
BTRFS_SEQ_PRINT2("\tsuper_copy->flags\t0x%llx\n", |
|
|
fs_info->super_copy->flags); |
|
|
BTRFS_SEQ_PRINT2("\tsuper_for_commit->flags\t0x%llx\n", |
|
|
fs_info->super_for_commit->flags); |
|
|
BTRFS_SEQ_PRINT2("\tnodesize\t\t%u\n", fs_info->nodesize); |
|
|
BTRFS_SEQ_PRINT2("\tsectorsize\t\t%u\n", fs_info->sectorsize); |
|
|
|
|
|
if (fs_info->balance_ctl) { |
|
|
memset(fs_str, '\0', 256); |
|
|
balance_ctl_flags_to_str(fs_info->balance_ctl, fs_str); |
|
|
BTRFS_SEQ_PRINT2("\tbalance_control\t\t%s\n", fs_str); |
|
|
|
|
|
if (fs_info->balance_ctl->flags & BTRFS_BALANCE_DATA) |
|
|
print_balance_args(&fs_info->balance_ctl->data, "data", seq); |
|
|
if (fs_info->balance_ctl->flags & BTRFS_BALANCE_METADATA) |
|
|
print_balance_args(&fs_info->balance_ctl->meta, "meta", seq); |
|
|
if (fs_info->balance_ctl->flags & BTRFS_BALANCE_SYSTEM) |
|
|
print_balance_args(&fs_info->balance_ctl->sys, "sys", seq); |
|
|
|
|
|
memset(fs_str, '\0', 256); |
|
|
balance_progress_to_str(&fs_info->balance_ctl->stat, fs_str); |
|
|
BTRFS_SEQ_PRINT2("\tbalance_progress\t%s\n", fs_str); |
|
|
|
|
|
} else { |
|
|
BTRFS_SEQ_PRINT2("\tbalance_control\t\t%s\n", "null"); |
|
|
} |
|
|
|
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.replace_state\t\t%llu\n", |
|
|
fs_info->dev_replace.replace_state); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.time start\t\t%lld\n", |
|
|
fs_info->dev_replace.time_started); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.time stopped\t%lld\n", |
|
|
fs_info->dev_replace.time_stopped); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.cursor_left\t\t%llu\n", |
|
|
fs_info->dev_replace.cursor_left); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.committed_cursor_left\t%llu\n", |
|
|
fs_info->dev_replace.committed_cursor_left); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.cursor_left_last_write_of_item\t%llu\n", |
|
|
fs_info->dev_replace.cursor_left_last_write_of_item); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.cursor_right\t\t%llu\n", |
|
|
fs_info->dev_replace.cursor_right); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.cont_reading_from_srcdev_mode\t%llu\n", |
|
|
fs_info->dev_replace.cont_reading_from_srcdev_mode); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.is_valid\t\t\t%d\n", |
|
|
fs_info->dev_replace.is_valid); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.item_needs_writeback\t%d\n", |
|
|
fs_info->dev_replace.item_needs_writeback); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.srcdev\t\t\t%p\n", |
|
|
fs_info->dev_replace.srcdev); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.tgtdev\t\t\t%p\n", |
|
|
fs_info->dev_replace.tgtdev); |
|
|
BTRFS_SEQ_PRINT2("\tdev_replace.bio_counter.count\t\t%llu\n", |
|
|
fs_info->dev_replace.bio_counter.count); |
|
|
} |
|
|
} |
|
|
|
|
|
static void dev_state_to_str(struct btrfs_device *device, char *dev_state_str) |
|
|
{ |
|
|
if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) |
|
|
strcat(dev_state_str, "|WRITEABLE"); |
|
|
if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state)) |
|
|
strcat(dev_state_str, "|IN_FS_METADATA"); |
|
|
if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) |
|
|
strcat(dev_state_str, "|MISSING"); |
|
|
if (test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state)) |
|
|
strcat(dev_state_str, "|REPLACE_TGT"); |
|
|
if (test_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state)) |
|
|
strcat(dev_state_str, "|FLUSH_SENT"); |
|
|
#ifdef READPOLICY |
|
|
if (test_bit(BTRFS_DEV_STATE_RD_PREFERRED, &device->dev_state)) |
|
|
strcat(dev_state_str, "|RD_PREFFRRED"); |
|
|
#endif |
|
|
if (device->dev_stats_valid) |
|
|
strcat(dev_state_str, "|dev_stats_valid"); |
|
|
} |
|
|
|
|
|
#ifdef VOL_FLAGS |
|
|
static void vol_flags_to_str(struct btrfs_fs_devices *fs_devices, char *vol_flags) |
|
|
{ |
|
|
if (test_bit(BTRFS_VOL_FLAG_ROTATING, &fs_devices->vol_flags)) |
|
|
strcat(vol_flags, "|ROTATING"); |
|
|
if (test_bit(BTRFS_VOL_FLAG_SEEDING, &fs_devices->vol_flags)) |
|
|
strcat(vol_flags, "|SEEDING"); |
|
|
if (test_bit(BTRFS_VOL_FLAG_EXCL_OPS, &fs_devices->vol_flags)) |
|
|
strcat(vol_flags, "|EXCL_OPS"); |
|
|
} |
|
|
#endif |
|
|
|
|
|
void btrfs_print_devlist(struct seq_file *seq, struct btrfs_fs_devices *the_fs_devices) |
|
|
{ |
|
|
/* Btrfs Procfs String Len */ |
|
|
#define BTRFS_SEQ_PRINT(plist, arg)\ |
|
|
snprintf(str, BPSL, plist, arg);\ |
|
|
if (sprt) {\ |
|
|
if (seq) {\ |
|
|
seq_printf(seq, "\t");\ |
|
|
}\ |
|
|
}\ |
|
|
if (seq) {\ |
|
|
seq_printf(seq, str);\ |
|
|
} else {\ |
|
|
printk("boilerplate: %s", 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; |
|
|
|
|
|
if (seq) |
|
|
seq_printf(seq, "\n#Its for debugging and experimental only, parameters may change without notice.\n\n"); |
|
|
|
|
|
/* Todo: there must be better way than nested locks */ |
|
|
list_for_each(cur_uuid, fs_uuids) { |
|
|
#ifdef VOL_FLAGS |
|
|
char vol_flags[256] = {0}; |
|
|
#endif |
|
|
cur_fs_devices = list_entry(cur_uuid, struct btrfs_fs_devices, fs_list); |
|
|
|
|
|
mutex_lock(&cur_fs_devices->device_list_mutex); |
|
|
|
|
|
fs_devices = cur_fs_devices; |
|
|
sprt = NULL; |
|
|
|
|
|
again_fs_devs: |
|
|
if (the_fs_devices && the_fs_devices != cur_fs_devices) |
|
|
goto skip; |
|
|
|
|
|
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("\tmetadata_uuid:\t\t%pU\n", fs_devices->metadata_uuid); |
|
|
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_bytes:\t\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); |
|
|
#ifdef VOL_FLAGS |
|
|
vol_flags_to_str(fs_devices, vol_flags); |
|
|
BTRFS_SEQ_PRINT("\vol_flags:\\%s\n", vol_flags); |
|
|
#else |
|
|
BTRFS_SEQ_PRINT("\tseeding:\t\t%d\n", fs_devices->seeding); |
|
|
BTRFS_SEQ_PRINT("\trotating:\t\t%d\n", fs_devices->rotating); |
|
|
#endif |
|
|
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->devices_kobj) { |
|
|
BTRFS_SEQ_PRINT("\tkobj_state:\t\t%d\n", fs_devices->devices_kobj->state_initialized); |
|
|
BTRFS_SEQ_PRINT("\tkobj_insysfs:\t\t%d\n", fs_devices->devices_kobj->state_in_sysfs); |
|
|
} else { |
|
|
BTRFS_SEQ_PRINT("\tkobj_state:\t\t%s\n", "null"); |
|
|
BTRFS_SEQ_PRINT("\tkobj_insysfs:\t\t%s\n", "null"); |
|
|
} |
|
|
|
|
|
#ifdef READPOLICY |
|
|
switch (fs_devices->read_policy) { |
|
|
case BTRFS_READ_POLICY_PID: |
|
|
BTRFS_SEQ_PRINT2("\tread_policy\t\t%s\n", "BTRFS_READ_POLICY_PID:"); |
|
|
break; |
|
|
case BTRFS_READ_POLICY_DEVICE: |
|
|
list_for_each_entry(device, &fs_devices->devices, dev_list) { |
|
|
if (test_bit(BTRFS_DEV_STATE_RD_PREFERRED, &device->dev_state)) { |
|
|
BTRFS_SEQ_PRINT("%llu ", device->devid); |
|
|
} |
|
|
} |
|
|
BTRFS_SEQ_PRINT("%s\n", " "); |
|
|
break; |
|
|
default: |
|
|
BTRFS_SEQ_PRINT2("\tread_policy\t%s\n", "unknown\n"); |
|
|
} |
|
|
#endif |
|
|
list_for_each_entry(device, &fs_devices->devices, dev_list) { |
|
|
char dev_state_str[256] = {0}; |
|
|
|
|
|
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); |
|
|
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); |
|
|
dev_state_to_str(device, dev_state_str); |
|
|
if (strlen(dev_state_str) == 0) { |
|
|
BTRFS_SEQ_PRINT("\t\tdev_state:\t0x%lx\n", device->dev_state); |
|
|
} else { |
|
|
BTRFS_SEQ_PRINT("\t\tdev_state:\t%s\n", dev_state_str); |
|
|
} |
|
|
BTRFS_SEQ_PRINT("\t\tbdev:\t\t%s\n", device->bdev ? "not_null":"null"); |
|
|
if (device->bdev) { |
|
|
struct backing_dev_info *bdi = device->bdev->bd_bdi; |
|
|
BTRFS_SEQ_PRINT("\t\tbdi:\t\t%s\n", bdi ? "not_null": "null"); |
|
|
if (bdi) { |
|
|
struct bdi_writeback *wb = &bdi->wb; |
|
|
BTRFS_SEQ_PRINT("\t\twb:\t\t%s\n", wb ? "not_null": "null"); |
|
|
if (wb) { |
|
|
BTRFS_SEQ_PRINT("\t\twb congested state:\t%lx\n", wb->congested->state); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
#ifdef USE_ALLOC_LIST |
|
|
/* print device from the alloc_list */ |
|
|
list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) { |
|
|
char dev_state_str[256] = {0}; |
|
|
|
|
|
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); |
|
|
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); |
|
|
dev_state_to_str(device, dev_state_str); |
|
|
if (strlen(dev_state_str) == 0) { |
|
|
BTRFS_SEQ_PRINT("\t\tdev_state:\t0x%lx\n", device->dev_state); |
|
|
} else { |
|
|
BTRFS_SEQ_PRINT("\t\tdev_state:\t%s\n", dev_state_str); |
|
|
} |
|
|
BTRFS_SEQ_PRINT("\t\tbdev:\t\t%s\n", device->bdev ? "not_null":"null"); |
|
|
if (device->bdev) { |
|
|
struct backing_dev_info *bdi = device->bdev->bd_bdi; |
|
|
BTRFS_SEQ_PRINT("\t\tbdi:\t\t%s\n", bdi ? "not_null": "null"); |
|
|
if (bdi) { |
|
|
struct bdi_writeback *wb = &bdi->wb; |
|
|
BTRFS_SEQ_PRINT("\t\twb:\t\t%s\n", wb ? "not_null": "null"); |
|
|
if (wb) { |
|
|
BTRFS_SEQ_PRINT("\t\twb congested state:\t%lx\n", wb->congested->state); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
#endif |
|
|
skip: |
|
|
if (fs_devices->seed) { |
|
|
sprt = fs_devices; |
|
|
fs_devices = fs_devices->seed; |
|
|
goto again_fs_devs; |
|
|
} |
|
|
if (seq) |
|
|
seq_printf(seq, "\n"); |
|
|
|
|
|
mutex_unlock(&cur_fs_devices->device_list_mutex); |
|
|
} |
|
|
} |
|
|
|
|
|
static int btrfs_fsinfo_show(struct seq_file *seq, void *offset) |
|
|
{ |
|
|
btrfs_print_fsinfo(seq); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
static int btrfs_devlist_show(struct seq_file *seq, void *offset) |
|
|
{ |
|
|
btrfs_print_devlist(seq, NULL); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
static int btrfs_seq_fsinfo_open(struct inode *inode, struct file *file) |
|
|
{ |
|
|
return single_open(file, btrfs_fsinfo_show, PDE_DATA(inode)); |
|
|
} |
|
|
|
|
|
static int btrfs_seq_devlist_open(struct inode *inode, struct file *file) |
|
|
{ |
|
|
return single_open(file, btrfs_devlist_show, PDE_DATA(inode)); |
|
|
} |
|
|
|
|
|
#ifdef OLD_PROC |
|
|
static const struct file_operations btrfs_seq_devlist_fops = { |
|
|
.owner = THIS_MODULE, |
|
|
.open = btrfs_seq_devlist_open, |
|
|
.read = seq_read, |
|
|
.llseek = seq_lseek, |
|
|
.release = single_release, |
|
|
}; |
|
|
#else |
|
|
static const struct proc_ops btrfs_seq_devlist_fops = { |
|
|
.proc_open = btrfs_seq_devlist_open, |
|
|
.proc_read = seq_read, |
|
|
.proc_lseek = seq_lseek, |
|
|
.proc_release = single_release, |
|
|
}; |
|
|
#endif |
|
|
|
|
|
#ifdef OLD_PROC |
|
|
static const struct file_operations btrfs_seq_fsinfo_fops = { |
|
|
.owner = THIS_MODULE, |
|
|
.open = btrfs_seq_fsinfo_open, |
|
|
.read = seq_read, |
|
|
.llseek = seq_lseek, |
|
|
.release = single_release, |
|
|
}; |
|
|
#else |
|
|
static const struct proc_ops btrfs_seq_fsinfo_fops = { |
|
|
.proc_open = btrfs_seq_fsinfo_open, |
|
|
.proc_read = seq_read, |
|
|
.proc_lseek = seq_lseek, |
|
|
.proc_release = single_release, |
|
|
}; |
|
|
#endif |
|
|
|
|
|
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_devlist_fops, NULL); |
|
|
proc_create_data(BTRFS_PROC_FSINFO, S_IRUGO, btrfs_proc_root, |
|
|
&btrfs_seq_fsinfo_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_FSINFO, btrfs_proc_root); |
|
|
} |
|
|
remove_proc_entry(BTRFS_PROC_PATH, NULL); |
|
|
} |