From: Ben Chociej <[email protected]>

Add support for the new hot data functionality in-kernel. Three ioctls
were added to export hot data statistics and turn hot data tracking on
and off per inode. This patch enables btrfsctl to interact with those
ioctls.

Signed-off-by: Ben Chociej <[email protected]>
Signed-off-by: Matt Lupfer <[email protected]>
Tested-by: Conor Scott <[email protected]>
---
 btrfsctl.c   |  107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ioctl-test.c |    3 ++
 ioctl.h      |   24 +++++++++++++
 3 files changed, 134 insertions(+), 0 deletions(-)

diff --git a/btrfsctl.c b/btrfsctl.c
index be6bf25..8617d06 100644
--- a/btrfsctl.c
+++ b/btrfsctl.c
@@ -48,6 +48,7 @@ static void print_usage(void)
 {
        printf("usage: btrfsctl [ -d file|dir] [ -s snap_name subvol|tree ]\n");
        printf("                [-r size] [-A device] [-a] [-c] [-D dir .]\n");
+       printf("                [-t file] [-T file] [-h filename [0-2]]\n");
        printf("\t-d filename: defragments one file\n");
        printf("\t-d directory: defragments the entire Btree\n");
        printf("\t-s snap_name dir: creates a new snapshot of dir\n");
@@ -57,6 +58,14 @@ static void print_usage(void)
        printf("\t-a: scans all devices for Btrfs filesystems\n");
        printf("\t-c: forces a single FS sync\n");
        printf("\t-D: delete snapshot\n");
+       printf("\t-t filename: dump indexed heat information for a file\n");
+       printf("\t-T filename: dump live heat informaton for a file\n");
+       printf("\t-h filename: query heat tracking/migration status\n");
+       printf("\t-h filename level: set heat tracking level:\n");
+       printf("\t\tlevel =\n");
+       printf("\t\t0: no tracking or relocation\n");
+       printf("\t\t1: access tracking only\n");
+       printf("\t\t2: tracking and automatic migration to SSD\n");
        printf("\t-m [tree id] directory: set the default mounted subvolume"
               " to the [tree id] or the directory\n");
        printf("%s\n", BTRFS_BUILD_VERSION);
@@ -99,12 +108,14 @@ int main(int ac, char **av)
        int fd;
        int ret;
        struct btrfs_ioctl_vol_args args;
+       struct btrfs_ioctl_heat_info hotinfo;
        char *name = NULL;
        int i;
        unsigned long command = 0;
        int len;
        char *fullpath;
        u64 objectid = 0;
+       int heatarg;
 
        if (ac == 2 && strcmp(av[1], "-a") == 0) {
                fprintf(stderr, "Scanning for Btrfs filesystems\n");
@@ -205,6 +216,38 @@ int main(int ac, char **av)
                                        exit(1);
                                }
                        }
+               } else if (strcmp(av[i], "-t") == 0) {
+                       if (i >= ac - 1) {
+                               fprintf(stderr,
+                                       "-t requires a file argument\n");
+                               print_usage();
+                       }
+                       hotinfo.live = 0;
+                       command = BTRFS_IOC_GET_HEAT_INFO;
+               } else if (strcmp(av[i], "-T") == 0) {
+                       if (i >= ac - 1) {
+                               fprintf(stderr,
+                                       "-T requires a file argument\n");
+                               print_usage();
+                       }
+                       hotinfo.live = 1;
+                       command = BTRFS_IOC_GET_HEAT_INFO;
+               } else if (strcmp(av[i], "-h") == 0) {
+                       if (i == ac - 2) {
+                               command = BTRFS_IOC_GET_HEAT_OPTS;
+                       } else if (i == ac - 3) {
+                               command = BTRFS_IOC_SET_HEAT_OPTS;
+                               heatarg = atoi(av[i + 2]);
+                       } else {
+                               fprintf(stderr, "-h invalid number of "
+                                       "arguments\n");
+                               print_usage();
+                               exit(1);
+                       }
+
+                       fprintf(stderr, "Btrfs hot data tracking: `%s'\n\n",
+                               av[i + 1]);
+                       av[i + 2] = av[i + 1];
                }
        }
        if (command == 0) {
@@ -236,6 +279,70 @@ int main(int ac, char **av)
        } else if (command == BTRFS_IOC_DEFAULT_SUBVOL) {
                printf("objectid is %llu\n", objectid);
                ret = ioctl(fd, command, &objectid);
+       } else if (command == BTRFS_IOC_GET_HEAT_INFO) {
+               strcpy(hotinfo.filename, fname);
+               ret = ioctl(fd, command, &hotinfo);
+               if (ret == 0) {
+                       printf("Btrfs file hotness information\n");
+                       printf("%s\n\n", hotinfo.filename);
+                       printf("Last write: %llu\n",
+                               (u64) hotinfo.last_write_time);
+                       printf("Last read: %llu\n",
+                               (u64) hotinfo.last_read_time);
+                       printf("Average write delta: %llu\n",
+                               (u64) hotinfo.avg_delta_writes);
+                       printf("Average read delta: %llu\n",
+                               (u64) hotinfo.avg_delta_reads);
+                       printf("Number of writes: %u\n",
+                               (u32) hotinfo.num_writes);
+                       printf("Number of reads: %u\n\n",
+                               (u32) hotinfo.num_reads);
+                       if (hotinfo.live > 0)
+                               printf("Temperature (live): %u\n\n",
+                                       hotinfo.temperature);
+                       else
+                               printf("Temperature (indexed): %u\n\n",
+                                       hotinfo.temperature);
+               }
+       } else if (command == BTRFS_IOC_SET_HEAT_OPTS) {
+               ret = ioctl(fd, command, &heatarg);
+               switch (heatarg) {
+               case 0:
+                       printf("Turning OFF heat tracking and migration inode "
+                               "flags.\n");
+                       break;
+               case 1:
+                       printf("Turning ON the heat tracking inode flag.\n");
+                       printf("Turning OFF the migration inode flag.\n");
+                       break;
+               case 2:
+                       printf("Turning ON heat tracking and migration inode "
+                               "flags.\n");
+                       break;
+               default:
+                       printf("Invalid heat tracking argument.\n");
+               }
+               printf("(Inode flags can be overridden by mount options)\n\n");
+       } else if (command == BTRFS_IOC_GET_HEAT_OPTS) {
+               ret = ioctl(fd, command, &heatarg);
+               switch (heatarg) {
+               case 0:
+                       printf("Heat tracking and migration inode flags are "
+                               "OFF.\n");
+                       break;
+               case 1:
+                       printf("Heat tracking inode flag is ON, migration "
+                               "inode flag is OFF.\n");
+                       break;
+               case 2:
+                       printf("Heat tracking and migration inode flags are "
+                               "both ON.\n");
+                       break;
+               default:
+                       printf("Wrong filesystem type, or invalid status "
+                               "returned.\n");
+               }
+               printf("(Inode flags can be overridden by mount options)\n\n");
        } else
                ret = ioctl(fd, command, &args);
        if (ret < 0) {
diff --git a/ioctl-test.c b/ioctl-test.c
index 7cf3bc2..8d54301 100644
--- a/ioctl-test.c
+++ b/ioctl-test.c
@@ -22,6 +22,9 @@ unsigned long ioctls[] = {
        BTRFS_IOC_INO_LOOKUP,
        BTRFS_IOC_DEFAULT_SUBVOL,
        BTRFS_IOC_SPACE_INFO,
+       BTRFS_IOC_GET_HEAT_INFO,
+       BTRFS_IOC_SET_HEAT_OPTS,
+       BTRFS_IOC_GET_HEAT_OPTS,
        0 };
 
 int main(int ac, char **av)
diff --git a/ioctl.h b/ioctl.h
index 776d7a9..5827338 100644
--- a/ioctl.h
+++ b/ioctl.h
@@ -132,6 +132,18 @@ struct btrfs_ioctl_space_args {
        struct btrfs_ioctl_space_info spaces[0];
 };
 
+struct btrfs_ioctl_heat_info {
+       __u64 avg_delta_reads;
+       __u64 avg_delta_writes;
+       __u64 last_read_time;
+       __u64 last_write_time;
+       __u32 num_reads;
+       __u32 num_writes;
+       char filename[BTRFS_PATH_NAME_MAX + 1];
+       int temperature;
+       __u8 live;
+};
+
 #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
                                   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -169,4 +181,16 @@ struct btrfs_ioctl_space_args {
 #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64)
 #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \
                                    struct btrfs_ioctl_space_args)
+
+/*
+ * Hot data tracking ioctls:
+ *
+ * GET_HEAT_INFO - retrieve frequency of access info on a file
+ * SET_HEAT_OPTS - set whether a file is tracked/migratable
+ * GET_HEAT_OPTS - check whether a file is tracked/migratable
+ */
+#define BTRFS_IOC_GET_HEAT_INFO _IOWR(BTRFS_IOCTL_MAGIC, 21, \
+                               struct btrfs_ioctl_heat_info)
+#define BTRFS_IOC_SET_HEAT_OPTS _IOW(BTRFS_IOCTL_MAGIC, 22, int)
+#define BTRFS_IOC_GET_HEAT_OPTS _IOR(BTRFS_IOCTL_MAGIC, 23, int)
 #endif
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to