#include <errno.h>
#include <stdarg.h>
#include <getopt.h>
+#include <fcntl.h>
#include "utils.h"
#include "kerncompat.h"
#include "string-table.h"
#include "cmds-fi-usage.h"
#include "commands.h"
+#include "disk-io.h"
#include "version.h"
#include "help.h"
return -e;
if (ret < 0) {
- error("cannot look up chunk tree info: %s",
- strerror(e));
+ error("cannot look up chunk tree info: %m");
return 1;
}
/* the ioctl returns the number of item it found in nr_items */
ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
if (ret < 0) {
- error("cannot get space info on '%s': %s", path,
- strerror(errno));
+ error("cannot get space info on '%s': %m", path);
free(sargs);
return NULL;
}
ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
if (ret < 0) {
- error("cannot get space info with %u slots: %s",
- count, strerror(errno));
+ error("cannot get space info with %u slots: %m",
+ count);
free(sargs);
return NULL;
}
}
if (r_total_size == 0) {
- error("cannot get space info on '%s': %s",
- path, strerror(errno));
+ error("cannot get space info on '%s': %m", path);
ret = 1;
goto exit;
((struct device_info *)b)->path);
}
+int dev_to_fsid(const char *dev, u8 *fsid)
+{
+ struct btrfs_super_block *disk_super;
+ char buf[BTRFS_SUPER_INFO_SIZE];
+ int ret;
+ int fd;
+
+ fd = open(dev, O_RDONLY);
+ if (fd < 0) {
+ ret = -errno;
+ return ret;
+ }
+
+ disk_super = (struct btrfs_super_block *)buf;
+ ret = btrfs_read_dev_super(fd, disk_super,
+ BTRFS_SUPER_INFO_OFFSET, SBREAD_DEFAULT);
+ if (ret)
+ goto out;
+
+ memcpy(fsid, disk_super->fsid, BTRFS_FSID_SIZE);
+ ret = 0;
+
+out:
+ close(fd);
+ return ret;
+}
+
/*
* This function loads the device_info structure and put them in an array
*/
struct btrfs_ioctl_fs_info_args fi_args;
struct btrfs_ioctl_dev_info_args dev_info;
struct device_info *info;
+ u8 fsid[BTRFS_UUID_SIZE];
*device_info_count = 0;
*device_info_ptr = NULL;
if (ret < 0) {
if (errno == EPERM)
return -errno;
- error("cannot get filesystem info: %s",
- strerror(errno));
+ error("cannot get filesystem info: %m");
return 1;
}
if (ndevs >= fi_args.num_devices) {
error("unexpected number of devices: %d >= %llu", ndevs,
(unsigned long long)fi_args.num_devices);
+ error(
+ "if seed device is used, try running this command as root");
goto out;
}
memset(&dev_info, 0, sizeof(dev_info));
goto out;
}
+ /*
+ * Skip seed device by checking device's fsid (requires root).
+ * And we will skip only if dev_to_fsid is successful and dev
+ * is a seed device.
+ * Ignore any other error including -EACCES, which is seen when
+ * a non-root process calls dev_to_fsid(path)->open(path).
+ */
+ ret = dev_to_fsid((const char *)dev_info.path, fsid);
+ if (!ret && memcmp(fi_args.fsid, fsid, BTRFS_FSID_SIZE) != 0)
+ continue;
+
info[ndevs].devid = dev_info.devid;
if (!dev_info.path[0]) {
strcpy(info[ndevs].path, "missing");
return !!ret;
}
-void print_device_chunks(int fd, struct device_info *devinfo,
+void print_device_chunks(struct device_info *devinfo,
struct chunk_info *chunks_info_ptr,
int chunks_info_count, unsigned unit_mode)
{
unit_mode | UNITS_NEGATIVE));
}
-void print_device_sizes(int fd, struct device_info *devinfo, unsigned unit_mode)
+void print_device_sizes(struct device_info *devinfo, unsigned unit_mode)
{
printf(" Device size: %*s%10s\n",
(int)(20 - strlen("Device size")), "",
pretty_size_mode(devinfo->device_size, unit_mode));
printf(" Device slack: %*s%10s\n",
(int)(20 - strlen("Device slack")), "",
- pretty_size_mode(devinfo->device_size - devinfo->size,
+ pretty_size_mode(devinfo->device_size > 0 ?
+ devinfo->device_size - devinfo->size : 0,
unit_mode));
}