mirror of
https://github.com/versity/scoutfs.git
synced 2026-06-06 03:32:35 +00:00
scoutfs-utils: add statfs wrapper
Add a scoutfs command wrapper around the statfs_moe ioctl. It's the same as the stat_more ioctl but has different fields and a different ioctl. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -347,4 +347,26 @@ struct scoutfs_ioctl_find_xattrs {
|
||||
#define SCOUTFS_IOC_FIND_XATTRS _IOR(SCOUTFS_IOCTL_MAGIC, 10, \
|
||||
struct scoutfs_ioctl_find_xattrs)
|
||||
|
||||
/*
|
||||
* Give the user information about the filesystem.
|
||||
*
|
||||
* @valid_bytes stores the number of bytes that are valid in the
|
||||
* structure. The caller sets this to the size of the struct that they
|
||||
* understand. The kernel then fills and copies back the min of the
|
||||
* size they and the user caller understand. The user can tell if a
|
||||
* field is set if all of its bytes are within the valid_bytes that the
|
||||
* kernel set on return.
|
||||
*
|
||||
* New fields are only added to the end of the struct.
|
||||
*/
|
||||
struct scoutfs_ioctl_statfs_more {
|
||||
__u64 valid_bytes;
|
||||
__u64 fsid;
|
||||
__u64 rid;
|
||||
} __packed;
|
||||
|
||||
#define SCOUTFS_IOC_STATFS_MORE _IOR(SCOUTFS_IOCTL_MAGIC, 11, \
|
||||
struct scoutfs_ioctl_statfs_more)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
144
utils/src/stat.c
144
utils/src/stat.c
@@ -16,43 +16,115 @@
|
||||
#include "ioctl.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#define FIELD(f) { \
|
||||
.name = #f, \
|
||||
.offset = offsetof(struct scoutfs_ioctl_stat_more, f), \
|
||||
}
|
||||
|
||||
static struct stat_more_field {
|
||||
struct stat_more_field {
|
||||
char *name;
|
||||
size_t offset;
|
||||
} fields[] = {
|
||||
FIELD(meta_seq),
|
||||
FIELD(data_seq),
|
||||
FIELD(data_version),
|
||||
FIELD(online_blocks),
|
||||
FIELD(offline_blocks),
|
||||
};
|
||||
|
||||
#define FIELD(f, o) { \
|
||||
.name = #f, \
|
||||
.offset = o, \
|
||||
}
|
||||
|
||||
#define INODE_FIELD_OFF(f) offsetof(struct scoutfs_ioctl_stat_more, f)
|
||||
#define INODE_FIELD(f) FIELD(f, INODE_FIELD_OFF(f))
|
||||
|
||||
static struct stat_more_field inode_fields[] = {
|
||||
INODE_FIELD(meta_seq),
|
||||
INODE_FIELD(data_seq),
|
||||
INODE_FIELD(data_version),
|
||||
INODE_FIELD(online_blocks),
|
||||
INODE_FIELD(offline_blocks),
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
#define for_each_field(f) \
|
||||
static void print_inode_field(void *st, size_t off)
|
||||
{
|
||||
struct scoutfs_ioctl_stat_more *stm = st;
|
||||
|
||||
switch(off) {
|
||||
case INODE_FIELD_OFF(meta_seq):
|
||||
printf("%llu", stm->meta_seq);
|
||||
break;
|
||||
case INODE_FIELD_OFF(data_seq):
|
||||
printf("%llu", stm->data_seq);
|
||||
break;
|
||||
case INODE_FIELD_OFF(data_version):
|
||||
printf("%llu", stm->data_version);
|
||||
break;
|
||||
case INODE_FIELD_OFF(online_blocks):
|
||||
printf("%llu", stm->online_blocks);
|
||||
break;
|
||||
case INODE_FIELD_OFF(offline_blocks):
|
||||
printf("%llu", stm->offline_blocks);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
#define FS_FIELD_OFF(f) offsetof(struct scoutfs_ioctl_statfs_more, f)
|
||||
#define FS_FIELD(f) FIELD(f, FS_FIELD_OFF(f))
|
||||
|
||||
static struct stat_more_field fs_fields[] = {
|
||||
FS_FIELD(fsid),
|
||||
FS_FIELD(rid),
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
static void print_fs_field(void *st, size_t off)
|
||||
{
|
||||
struct scoutfs_ioctl_statfs_more *sfm = st;
|
||||
|
||||
switch(off) {
|
||||
case FS_FIELD_OFF(fsid):
|
||||
printf("%016llx", sfm->fsid);
|
||||
break;
|
||||
case FS_FIELD_OFF(rid):
|
||||
printf("%016llx", sfm->rid);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
#define for_each_field(f, fields) \
|
||||
for (f = fields; f->name; f++)
|
||||
|
||||
typedef void (*print_field_t)(void *st, size_t off);
|
||||
|
||||
static struct option long_ops[] = {
|
||||
{ "single_field", 1, NULL, 's' },
|
||||
{ NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
static int stat_more_cmd(int argc, char **argv)
|
||||
static int do_stat(int argc, char **argv, int is_inode)
|
||||
{
|
||||
struct scoutfs_ioctl_stat_more stm;
|
||||
union {
|
||||
struct scoutfs_ioctl_stat_more stm;
|
||||
struct scoutfs_ioctl_statfs_more sfm;
|
||||
} st;
|
||||
struct stat_more_field *single = NULL;
|
||||
struct stat_more_field *fields;
|
||||
struct stat_more_field *fi;
|
||||
char *single_name = NULL;
|
||||
print_field_t pr = NULL;
|
||||
char *path;
|
||||
int cmd;
|
||||
int ret;
|
||||
int fd;
|
||||
int i;
|
||||
int c;
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
if (is_inode) {
|
||||
cmd = SCOUTFS_IOC_STAT_MORE;
|
||||
fields = inode_fields;
|
||||
st.stm.valid_bytes = sizeof(struct scoutfs_ioctl_stat_more);
|
||||
pr = print_inode_field;
|
||||
} else {
|
||||
cmd = SCOUTFS_IOC_STATFS_MORE;
|
||||
fields = fs_fields;
|
||||
st.sfm.valid_bytes = sizeof(struct scoutfs_ioctl_statfs_more);
|
||||
pr = print_fs_field;
|
||||
}
|
||||
|
||||
while ((c = getopt_long(argc, argv, "s:", long_ops, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 's':
|
||||
@@ -66,15 +138,14 @@ static int stat_more_cmd(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (single_name) {
|
||||
for_each_field(fi) {
|
||||
for_each_field(fi, fields) {
|
||||
if (strcmp(fi->name, single_name) == 0) {
|
||||
single = fi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!single) {
|
||||
fprintf(stderr, "unknown stat_more field: '%s'\n",
|
||||
single_name);
|
||||
fprintf(stderr, "unknown field: '%s'\n", single_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -95,24 +166,21 @@ static int stat_more_cmd(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&stm, 0, sizeof(stm));
|
||||
stm.valid_bytes = sizeof(stm);
|
||||
|
||||
ret = ioctl(fd, SCOUTFS_IOC_STAT_MORE, &stm);
|
||||
ret = ioctl(fd, cmd, &st);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "stat_more ioctl failed on '%s': "
|
||||
fprintf(stderr, "ioctl failed on '%s': "
|
||||
"%s (%d)\n", path, strerror(errno), errno);
|
||||
|
||||
} else if (single) {
|
||||
printf("%llu\n",
|
||||
*(u64 *)((void *)&stm + single->offset));
|
||||
|
||||
pr(&st, single->offset);
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%-17s %s\n", "path", path);
|
||||
for_each_field(fi) {
|
||||
printf("%-17s %llu\n", fi->name,
|
||||
*(u64 *)((void *)&stm + fi->offset));
|
||||
for_each_field(fi, fields) {
|
||||
printf("%-17s ", fi->name);
|
||||
pr(&st, fi->offset);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,8 +190,24 @@ static int stat_more_cmd(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stat_more_cmd(int argc, char **argv)
|
||||
{
|
||||
return do_stat(argc, argv, 1);
|
||||
}
|
||||
|
||||
static int statfs_more_cmd(int argc, char **argv)
|
||||
{
|
||||
return do_stat(argc, argv, 0);
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) stat_more_ctor(void)
|
||||
{
|
||||
cmd_register("stat", "<path>",
|
||||
"print scoutfs stat information for path", stat_more_cmd);
|
||||
"show scoutfs inode information", stat_more_cmd);
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) statfs_more_ctor(void)
|
||||
{
|
||||
cmd_register("statfs", "<path>",
|
||||
"show scoutfs file system information", statfs_more_cmd);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user