btrfs-progs: read partition size from sysfs as fallback
Reading partition size using an ioctl requires the device open, but that does not work for unprivileged users. This leads to 0 size in device info structures filled by device_get_partition_size. As a consequence, this also misreports such devices as missing in 'fi us' overview: $ btrfs fi us / WARNING: cannot read detailed chunk info, per-device usage will not be shown, run as root Overall: Device size: 411.35GiB Device allocated: 53.01GiB Device unallocated: 358.34GiB Device missing: 411.35GiB Used: 31.99GiB Free (estimated): 379.16GiB (min: 379.16GiB) Free (statfs, df): 379.35GiB Data ratio: 1.00 Metadata ratio: 1.00 Global reserve: 194.77MiB (used: 0.00B) Multiple profiles: no There should be 0 for 'Device missing'. Add a fallback to read the device size from sysfs in case the ioctl is not available. Issue: #395 Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
56e9963474
commit
4980de3a5f
|
@ -26,6 +26,7 @@
|
|||
#include <dirent.h>
|
||||
#include <blkid/blkid.h>
|
||||
#include <linux/limits.h>
|
||||
#include <limits.h>
|
||||
#include "kernel-lib/sizes.h"
|
||||
#include "kernel-shared/disk-io.h"
|
||||
#include "kernel-shared/zoned.h"
|
||||
|
@ -303,13 +304,50 @@ u64 device_get_partition_size_fd(int fd)
|
|||
return result;
|
||||
}
|
||||
|
||||
u64 device_get_partition_size_sysfs(const char *dev)
|
||||
{
|
||||
int ret;
|
||||
char path[PATH_MAX] = {};
|
||||
char sysfs[PATH_MAX] = {};
|
||||
char sizebuf[128] = {};
|
||||
char *name = NULL;
|
||||
int sysfd;
|
||||
unsigned long long size = 0;
|
||||
|
||||
name = realpath(dev, path);
|
||||
if (!name)
|
||||
return 0;
|
||||
name = basename(path);
|
||||
|
||||
ret = path_cat3_out(sysfs, "/sys/class/block", name, "size");
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
sysfd = open(sysfs, O_RDONLY);
|
||||
if (sysfd < 0)
|
||||
return 0;
|
||||
ret = sysfs_read_file(sysfd, sizebuf, sizeof(sizebuf));
|
||||
if (ret < 0) {
|
||||
close(sysfd);
|
||||
return 0;
|
||||
}
|
||||
errno = 0;
|
||||
size = strtoull(sizebuf, NULL, 10);
|
||||
if (size == ULLONG_MAX && errno == ERANGE) {
|
||||
close(sysfd);
|
||||
return 0;
|
||||
}
|
||||
close(sysfd);
|
||||
return size;
|
||||
}
|
||||
|
||||
u64 device_get_partition_size(const char *dev)
|
||||
{
|
||||
u64 result;
|
||||
int fd = open(dev, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
return device_get_partition_size_sysfs(dev);
|
||||
|
||||
if (ioctl(fd, BLKGETSIZE64, &result) < 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue