Add inode-paths via link backrefs

Add the inode-paths command which uses the ioctl to display all the
paths that lead to the given inode.  We add support for printing
the new link backref items and inode and dirent fields.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2016-08-11 16:50:57 -07:00
parent be4a137479
commit 43619a245d
4 changed files with 138 additions and 7 deletions
+17 -4
View File
@@ -97,10 +97,11 @@ struct scoutfs_key {
* isn't necessary. We could have an arbitrary sort order. So we don't
* have to stress about cleverly allocating the types.
*/
#define SCOUTFS_INODE_KEY 1
#define SCOUTFS_XATTR_KEY 2
#define SCOUTFS_DIRENT_KEY 3
#define SCOUTFS_BMAP_KEY 4
#define SCOUTFS_INODE_KEY 1
#define SCOUTFS_XATTR_KEY 2
#define SCOUTFS_DIRENT_KEY 3
#define SCOUTFS_LINK_BACKREF_KEY 4
#define SCOUTFS_BMAP_KEY 5
#define SCOUTFS_MAX_ITEM_LEN 512
@@ -173,6 +174,7 @@ struct scoutfs_timespec {
struct scoutfs_inode {
__le64 size;
__le64 blocks;
__le64 link_counter;
__le32 nlink;
__le32 uid;
__le32 gid;
@@ -192,6 +194,7 @@ struct scoutfs_inode {
*/
struct scoutfs_dirent {
__le64 ino;
__le64 counter;
__u8 type;
__u8 name[0];
} __packed;
@@ -262,4 +265,14 @@ struct scoutfs_block_map {
__le64 blkno[SCOUTFS_BLOCK_MAP_COUNT];
};
/*
* link backrefs give us a way to find all the hard links that refer
* to a target inode. They're stored at an offset determined by an
* advancing counter in their inode.
*/
struct scoutfs_link_backref {
__le64 ino;
__le64 offset;
} __packed;
#endif
+92
View File
@@ -0,0 +1,92 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include "sparse.h"
#include "util.h"
#include "ioctl.h"
#include "cmd.h"
static int inode_paths_cmd(int argc, char **argv)
{
struct scoutfs_ioctl_inode_paths args;
char *endptr;
void *ptr = NULL;
char *path;
u64 ino;
int len;
int ret;
int fd;
if (argc != 2) {
fprintf(stderr, "must specify ino and path\n");
return -EINVAL;
}
ino = strtoull(argv[0], &endptr, 0);
if (*endptr != '\0' ||
((ino == LLONG_MIN || ino == LLONG_MAX) && errno == ERANGE)) {
fprintf(stderr, "error parsing inode number '%s'\n",
argv[0]);
return -EINVAL;
}
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
ret = -errno;
fprintf(stderr, "failed to open '%s': %s (%d)\n",
argv[1], strerror(errno), errno);
return ret;
}
len = 16 * PATH_MAX;
do {
free(ptr);
ptr = malloc(len);
if (!ptr) {
fprintf(stderr, "couldn't allocate %d byte buffer\n",
len);
ret = -EINVAL;
goto out;
}
args.ino = ino;
args.buf_ptr = (intptr_t)ptr;
args.buf_len = len;
ret = ioctl(fd, SCOUTFS_IOC_INODE_PATHS, &args);
if (ret < 0 && errno != EOVERFLOW) {
ret = -errno;
fprintf(stderr, "inodes_since ioctl failed: %s (%d)\n",
strerror(errno), errno);
goto out;
}
len *= 2;
} while (ret < 0 && errno == EOVERFLOW);
path = ptr;
while (*path) {
printf("%s\n", path);
path += strlen(path) + 1;
}
out:
free(ptr);
close(fd);
return ret;
};
static void __attribute__((constructor)) since_ctor(void)
{
cmd_register("inode-paths", "<ino> <path>",
"print paths that refer to inode #", inode_paths_cmd);
}
+13
View File
@@ -24,4 +24,17 @@ struct scoutfs_ioctl_inodes_since {
#define SCOUTFS_IOC_INODES_SINCE _IOW(SCOUTFS_IOCTL_MAGIC, 1, \
struct scoutfs_ioctl_inodes_since)
struct scoutfs_ioctl_inode_paths {
__u64 ino;
__u64 buf_ptr;
__u32 buf_len;
} __packed;
/*
* Fills the callers buffer with all the paths from the root to the
* target inode.
*/
#define SCOUTFS_IOC_INODE_PATHS _IOW(SCOUTFS_IOCTL_MAGIC, 2, \
struct scoutfs_ioctl_inode_paths)
#endif
+16 -3
View File
@@ -58,12 +58,13 @@ static void print_block_header(struct scoutfs_block_header *hdr)
static void print_inode(struct scoutfs_inode *inode)
{
printf(" inode: size: %llu blocks: %llu nlink: %u\n"
printf(" inode: size: %llu blocks: %llu lctr: %llu nlink: %u\n"
" uid: %u gid: %u mode: 0%o rdev: 0x%x\n"
" salt: 0x%x\n"
" atime: %llu.%08u ctime: %llu.%08u\n"
" mtime: %llu.%08u\n",
le64_to_cpu(inode->size), le64_to_cpu(inode->blocks),
le64_to_cpu(inode->link_counter),
le32_to_cpu(inode->nlink), le32_to_cpu(inode->uid),
le32_to_cpu(inode->gid), le32_to_cpu(inode->mode),
le32_to_cpu(inode->rdev), le32_to_cpu(inode->salt),
@@ -85,8 +86,16 @@ static void print_dirent(struct scoutfs_dirent *dent, unsigned int val_len)
name[i] = isprint(dent->name[i]) ? dent->name[i] : '.';
name[i] = '\0';
printf(" dirent: ino: %llu type: %u name: \"%.*s\"\n",
le64_to_cpu(dent->ino), dent->type, i, name);
printf(" dirent: ino: %llu ctr: %llu type: %u name: \"%.*s\"\n",
le64_to_cpu(dent->ino), le64_to_cpu(dent->counter),
dent->type, i, name);
}
static void print_link_backref(struct scoutfs_link_backref *lref,
unsigned int val_len)
{
printf(" lref: ino: %llu offset: %llu\n",
le64_to_cpu(lref->ino), le64_to_cpu(lref->offset));
}
static void print_block_map(struct scoutfs_block_map *map)
@@ -121,6 +130,10 @@ static void print_btree_val(struct scoutfs_btree_item *item, u8 level)
case SCOUTFS_DIRENT_KEY:
print_dirent((void *)item->val, le16_to_cpu(item->val_len));
break;
case SCOUTFS_LINK_BACKREF_KEY:
print_link_backref((void *)item->val,
le16_to_cpu(item->val_len));
break;
case SCOUTFS_BMAP_KEY:
print_block_map((void *)item->val);
break;