btrfsprogs/0027-btrfs-progs-cleanup-filesystem-device-usage-code.patch

373 lines
11 KiB
Diff
Raw Normal View History

Accepting request 232435 from home:dsterba:branches:filesystems - update to upstream 3.14.1 - mkfs: - fix TRIM detection - do not zero-out end of device unconditionally - no crash with --features option - fsck: - clear log tree in repair mode - check reloc roots - btrfs - reworked space reporting (bnc#873106) - btrfs fi usage - new command - btrfs dev usage - new command - btrfs fi df - enhanced output with GlobalReserve - Removed patches: * 0001-btrfs-progs-move-arg_strtou64-to-a-separate-file-for.patch - Added patches: * 0001-Btrfs-progs-fix-check-to-test-trim-support.patch * 0002-Btrfs-progs-fsck-fix-double-free-memory-crash.patch * 0003-Btrfs-progs-mkfs-Remove-zero_end-1-since-it-has-been.patch * 0004-btrfs-progs-fix-wrong-max-system-array-size-check-in.patch * 0005-btrfs-progs-move-arg_strtou64-to-a-separate-file-for.patch * 0006-Btrfs-progs-fsck-clear-out-log-tree-in-repair-mode.patch * 0007-Btrfs-progs-fsck-avoid-pinning-same-block-several-ti.patch * 0008-Btrfs-progs-fsck-add-ability-to-check-reloc-roots.patch * 0009-btrfs-progs-prevent-close_root-if-the-root-to-close-.patch * 0010-btrfs-progs-fix-mkfs.btrfs-segfault-with-features-op.patch * 0011-btrfs-progs-Enhance-the-command-btrfs-filesystem-df.patch * 0012-btrfs-progs-Add-helpers-functions-to-handle-the-prin.patch * 0013-btrfs-progs-Add-command-btrfs-filesystem-disk-usage.patch * 0014-btrfs-progs-Add-btrfs-device-disk-usage-command.patch * 0015-btrfs-progs-cleanup-dead-return-after-usage-for-fi-d.patch * 0016-btrfs-progs-Fix-memleak-in-get_raid56_used.patch * 0017-Btrfs-progs-fi-usage-free-memory-if-realloc-fails.patch * 0018-btrfs-progs-read-global-reserve-size-from-space-info.patch * 0019-btrfs-progs-add-original-df-and-rename-disk_usage-to.patch * 0020-btrfs-progs-move-device-usage-to-cmds-device-more-cl.patch * 0021-btrfs-progs-check-if-we-can-t-get-info-from-ioctls-d.patch * 0022-btrfs-progs-zero-out-structures-before-calling-ioctl.patch * 0023-btrfs-progs-print-B-for-bytes.patch * 0024-btrfs-progs-Print-more-info-about-device-sizes.patch * 0025-btrfs-progs-compare-unallocated-space-against-the-co.patch * 0026-btrfs-progs-add-section-of-overall-filesystem-usage.patch * 0027-btrfs-progs-cleanup-filesystem-device-usage-code.patch * 0028-btrfs-progs-extend-pretty-printers-with-unit-mode.patch * 0029-btrfs-progs-replace-df_pretty_sizes-with-pretty_size.patch * 0030-btrfs-progs-clean-up-return-codes-and-paths.patch * 0031-btrfs-progs-move-global-reserve-to-overall-summary.patch OBS-URL: https://build.opensuse.org/request/show/232435 OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=156
2014-05-02 16:21:40 +02:00
From e81d2614ff21e3e9e723cc645cc73646a42d06e8 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Fri, 25 Apr 2014 19:39:11 +0200
Subject: [PATCH 38/42] btrfs-progs: cleanup filesystem/device usage code
The main point of this is to load the device and chunk infos at one
place and pass down to the printers. The EPERM is handled separately, in
case kernel does not give us all the information about chunks or
devices, but we want to warn and print at least something.
For non-root users, 'filesystem usage' prints only the overall stats and
warns about RAID5/6.
The sole cleanup changes affect mostly the modified code and the related
functions, should be reasonably small.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-device.c | 31 +++++-----
cmds-fi-disk_usage.c | 163 +++++++++++++++++++++++++++------------------------
cmds-fi-disk_usage.h | 5 +-
3 files changed, 105 insertions(+), 94 deletions(-)
diff --git a/cmds-device.c b/cmds-device.c
index 3e851badc116..bf5898f6da68 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -441,31 +441,29 @@ static int _cmd_device_usage(int fd, char *path, int mode)
{
int i;
int ret = 0;
- int info_count = 0;
- struct chunk_info *info_ptr = 0;
- struct device_info *device_info_ptr = 0;
- int device_info_count = 0;
+ struct chunk_info *chunkinfo = NULL;
+ struct device_info *devinfo = NULL;
+ int chunkcount = 0;
+ int devcount = 0;
- if (load_chunk_info(fd, &info_ptr, &info_count) ||
- load_device_info(fd, &device_info_ptr, &device_info_count)) {
+ ret = load_chunk_and_device_info(fd, &chunkinfo, &chunkcount, &devinfo,
+ &devcount);
+ if (ret) {
ret = -1;
goto exit;
}
- for (i = 0; i < device_info_count; i++) {
- printf("%s, ID: %llu\n", device_info_ptr[i].path,
- device_info_ptr[i].devid);
- print_device_sizes(fd, &device_info_ptr[i], mode);
- print_device_chunks(fd, &device_info_ptr[i],
- info_ptr, info_count, mode);
+ for (i = 0; i < devcount; i++) {
+ printf("%s, ID: %llu\n", devinfo[i].path, devinfo[i].devid);
+ print_device_sizes(fd, &devinfo[i], mode);
+ print_device_chunks(fd, &devinfo[i], chunkinfo, chunkcount,
+ mode);
printf("\n");
}
exit:
- if (device_info_ptr)
- free(device_info_ptr);
- if (info_ptr)
- free(info_ptr);
+ free(devinfo);
+ free(chunkinfo);
return ret;
}
@@ -507,6 +505,7 @@ int cmd_device_usage(int argc, char **argv)
argv[1]);
return 12;
}
+
r = _cmd_device_usage(fd, argv[i], flags);
close_file_or_dir(fd, dirstream);
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index e17f04e31d35..9d1c4085b4ea 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -141,7 +141,7 @@ static int cmp_chunk_info(const void *a, const void *b)
((struct chunk_info *)b)->type);
}
-int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count)
+static int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count)
{
int ret;
struct btrfs_ioctl_search_args args;
@@ -172,11 +172,8 @@ int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count)
while (1) {
ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
e = errno;
- if (ret == -EPERM) {
- fprintf(stderr,
- "ERROR: can't read detailed chunk info from ioctl(TREE_SEARCH), run as root\n");
- return 0;
- }
+ if (ret == -EPERM)
+ return ret;
if (ret < 0) {
fprintf(stderr,
@@ -308,30 +305,23 @@ static struct btrfs_ioctl_space_args *load_space_info(int fd, char *path)
* which compose the chunk, which could be different from the number of devices
* if a disk is added later.
*/
-static int get_raid56_used(int fd, u64 *raid5_used, u64 *raid6_used)
+static void get_raid56_used(int fd, struct chunk_info *chunks, int chunkcount,
+ u64 *raid5_used, u64 *raid6_used)
{
- struct chunk_info *info_ptr=0, *p;
- int info_count=0;
- int ret;
-
- *raid5_used = *raid6_used =0;
-
- ret = load_chunk_info(fd, &info_ptr, &info_count);
- if( ret < 0)
- return ret;
-
- for ( p = info_ptr; info_count ; info_count--, p++ ) {
- if (p->type & BTRFS_BLOCK_GROUP_RAID5)
- (*raid5_used) += p->size / (p->num_stripes -1);
- if (p->type & BTRFS_BLOCK_GROUP_RAID6)
- (*raid6_used) += p->size / (p->num_stripes -2);
+ *raid5_used = 0;
+ *raid6_used = 0;
+
+ while (chunkcount-- > 0) {
+ if (chunks->type & BTRFS_BLOCK_GROUP_RAID5)
+ (*raid5_used) += chunks->size / (chunks->num_stripes - 1);
+ if (chunks->type & BTRFS_BLOCK_GROUP_RAID6)
+ (*raid6_used) += chunks->size / (chunks->num_stripes - 2);
}
- free(info_ptr);
-
- return 0;
}
-static int _cmd_disk_free(int fd, char *path, int mode)
+static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
+ int chunkcount, struct device_info *devinfo, int devcount,
+ char *path, int mode)
{
struct btrfs_ioctl_space_args *sargs = 0;
int i;
@@ -360,15 +350,11 @@ static int _cmd_disk_free(int fd, char *path, int mode)
ret = 19;
goto exit;
}
- if (get_raid56_used(fd, &raid5_used, &raid6_used) < 0) {
- fprintf(stderr,
- "ERROR: couldn't get space info on '%s'\n",
- path );
- ret = 20;
- goto exit;
- }
+ get_raid56_used(fd, chunkinfo, chunkcount, &raid5_used, &raid6_used);
- total_chunks = total_used = total_free = 0;
+ total_chunks = 0;
+ total_used = 0;
+ total_free = 0;
for (i = 0; i < sargs->total_spaces; i++) {
float ratio = 1;
@@ -453,7 +439,7 @@ static int cmp_device_info(const void *a, const void *b)
/*
* This function loads the device_info structure and put them in an array
*/
-int load_device_info(int fd, struct device_info **device_info_ptr,
+static int load_device_info(int fd, struct device_info **device_info_ptr,
int *device_info_count)
{
int ret, i, ndevs;
@@ -465,10 +451,8 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
*device_info_ptr = 0;
ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
- if (ret == -EPERM) {
- fprintf(stderr, "ERROR: can't get filesystem info from ioctl(FS_INFO), run as root\n");
- return -1;
- }
+ if (ret == -EPERM)
+ return ret;
if (ret < 0) {
fprintf(stderr, "ERROR: cannot get filesystem info\n");
return -1;
@@ -512,6 +496,29 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
return 0;
}
+int load_chunk_and_device_info(int fd, struct chunk_info **chunkinfo,
+ int *chunkcount, struct device_info **devinfo, int *devcount)
+{
+ int ret;
+
+ ret = load_chunk_info(fd, chunkinfo, chunkcount);
+ if (ret == -EPERM) {
+ fprintf(stderr,
+ "WARNING: can't read detailed chunk info, RAID5/6 numbers will be incorrect, run as root\n");
+ } else if (ret) {
+ return ret;
+ }
+
+ ret = load_device_info(fd, devinfo, devcount);
+ if (ret == -EPERM) {
+ fprintf(stderr,
+ "WARNING: can't get filesystem info from ioctl(FS_INFO), run as root\n");
+ ret = 0;
+ }
+
+ return ret;
+}
+
/*
* This function computes the size of a chunk in a disk
*/
@@ -744,43 +751,32 @@ static void _cmd_filesystem_usage_linear(int mode,
mode);
}
-static int _cmd_filesystem_usage(int fd, char *path, int mode, int tabular)
+static int print_filesystem_usage_by_chunk(int fd,
+ struct chunk_info *chunkinfo, int chunkcount,
+ struct device_info *devinfo, int devcount,
+ char *path, int mode, int tabular)
{
- struct btrfs_ioctl_space_args *sargs = 0;
- int info_count = 0;
- struct chunk_info *info_ptr = 0;
- struct device_info *device_info_ptr = 0;
- int device_info_count = 0;
+ struct btrfs_ioctl_space_args *sargs;
int ret = 0;
- if (load_chunk_info(fd, &info_ptr, &info_count) ||
- load_device_info(fd, &device_info_ptr, &device_info_count)) {
- ret = -1;
- goto exit;
- }
+ if (!chunkinfo)
+ return 0;
- if ((sargs = load_space_info(fd, path)) == NULL) {
- ret = -1;
+ sargs = load_space_info(fd, path);
+ if (!sargs) {
+ ret = 1;
goto exit;
}
if (tabular)
- _cmd_filesystem_usage_tabular(mode, sargs,
- info_ptr, info_count,
- device_info_ptr, device_info_count);
+ _cmd_filesystem_usage_tabular(mode, sargs, chunkinfo,
+ chunkcount, devinfo, devcount);
else
- _cmd_filesystem_usage_linear(mode, sargs,
- info_ptr, info_count,
- device_info_ptr, device_info_count);
+ _cmd_filesystem_usage_linear(mode, sargs, chunkinfo,
+ chunkcount, devinfo, devcount);
exit:
-
- if (sargs)
- free(sargs);
- if (device_info_ptr)
- free(device_info_ptr);
- if (info_ptr)
- free(info_ptr);
+ free(sargs);
return ret;
}
@@ -796,16 +792,17 @@ const char * const cmd_filesystem_usage_usage[] = {
int cmd_filesystem_usage(int argc, char **argv)
{
-
int flags = DF_HUMAN_UNIT;
int i, more_than_one = 0;
int tabular = 0;
optind = 1;
while (1) {
- char c = getopt(argc, argv, "bt");
+ int c = getopt(argc, argv, "bt");
+
if (c < 0)
break;
+
switch (c) {
case 'b':
flags &= ~DF_HUMAN_UNIT;
@@ -821,9 +818,14 @@ int cmd_filesystem_usage(int argc, char **argv)
if (check_argc_min(argc - optind, 1))
usage(cmd_filesystem_usage_usage);
- for (i = optind; i < argc ; i++) {
- int r, fd;
- DIR *dirstream = NULL;
+ for (i = optind; i < argc; i++) {
+ int ret;
+ int fd;
+ DIR *dirstream = NULL;
+ struct chunk_info *chunkinfo = NULL;
+ struct device_info *devinfo = NULL;
+ int chunkcount = 0;
+ int devcount = 0;
fd = open_file_or_dir(argv[i], &dirstream);
if (fd < 0) {
@@ -834,15 +836,26 @@ int cmd_filesystem_usage(int argc, char **argv)
if (more_than_one)
printf("\n");
- r = _cmd_disk_free(fd, argv[i], flags);
+ ret = load_chunk_and_device_info(fd, &chunkinfo, &chunkcount,
+ &devinfo, &devcount);
+ if (ret)
+ goto cleanup;
+
+ ret = print_filesystem_usage_overall(fd, chunkinfo, chunkcount,
+ devinfo, devcount, argv[i], flags);
+ if (ret)
+ goto cleanup;
printf("\n");
- r = _cmd_filesystem_usage(fd, argv[i], flags, tabular);
+ ret = print_filesystem_usage_by_chunk(fd, chunkinfo, chunkcount,
+ devinfo, devcount, argv[i], flags, tabular);
+cleanup:
close_file_or_dir(fd, dirstream);
+ free(chunkinfo);
+ free(devinfo);
- if (r)
- return r;
+ if (ret)
+ return ret;
more_than_one = 1;
-
}
return 0;
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index dbc2a10f31eb..0779defc71db 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -46,9 +46,8 @@ struct chunk_info {
u64 num_stripes;
};
-int load_device_info(int fd, struct device_info **device_info_ptr,
- int *device_info_count);
-int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count);
+int load_chunk_and_device_info(int fd, struct chunk_info **chunkinfo,
+ int *chunkcount, struct device_info **devinfo, int *devcount);
char *df_pretty_sizes(u64 size, int mode);
void print_device_chunks(int fd, struct device_info *devinfo,
struct chunk_info *chunks_info_ptr,
--
1.9.0