]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Subvolume commands
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 4 Mar 2021 19:48:21 +0000 (14:48 -0500)
committerKent Overstreet <kent.overstreet@gmail.com>
Sun, 26 Sep 2021 23:50:47 +0000 (19:50 -0400)
bcachefs.c
cmd_subvolume.c [new file with mode: 0644]
cmds.h

index 239b114723831cb630d837c95bcf36f6e58b9cb9..1a06c171472454d526a72c2558f355e5092e6b98 100644 (file)
@@ -58,6 +58,11 @@ static void usage(void)
             "  device resize            Resize filesystem on a device\n"
             "  device journal-resize    Resize journal on a device\n"
             "\n"
+            "Commands for managing subvolumes and snapshots:\n"
+            "  subvolume create     Create a new subvolume\n"
+            "  subvolume delete     Delete an existing subvolume\n"
+            "  subvolume snapshot   Create a snapshot\n"
+            "\n"
             "Commands for managing filesystem data:\n"
             "  data rereplicate         Rereplicate degraded data\n"
             "  data job                 Kick off low level data jobs\n"
@@ -150,6 +155,21 @@ static int data_cmds(int argc, char *argv[])
        return 0;
 }
 
+static int subvolume_cmds(int argc, char *argv[])
+{
+       char *cmd = pop_cmd(&argc, argv);
+
+       if (!strcmp(cmd, "create"))
+               return cmd_subvolume_create(argc, argv);
+       if (!strcmp(cmd, "delete"))
+               return cmd_subvolume_delete(argc, argv);
+       if (!strcmp(cmd, "snapshot"))
+               return cmd_subvolume_snapshot(argc, argv);
+
+       usage();
+       return 0;
+}
+
 int main(int argc, char *argv[])
 {
        raid_init();
@@ -189,6 +209,8 @@ int main(int argc, char *argv[])
 
        if (!strcmp(cmd, "data"))
                return data_cmds(argc, argv);
+       if (!strcmp(cmd, "subvolume"))
+               return subvolume_cmds(argc, argv);
 
        if (!strcmp(cmd, "unlock"))
                return cmd_unlock(argc, argv);
diff --git a/cmd_subvolume.c b/cmd_subvolume.c
new file mode 100644 (file)
index 0000000..ee4eb75
--- /dev/null
@@ -0,0 +1,174 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "libbcachefs/bcachefs.h"
+#include "libbcachefs/bcachefs_ioctl.h"
+#include "cmds.h"
+#include "libbcachefs.h"
+#include "libbcachefs/opts.h"
+#include "tools-util.h"
+
+static void subvolume_create_usage(void)
+{
+       puts("bcachefs subvolume create - create a new subvolume\n"
+            "Usage: bcachefs subvolume create [OPTION]... path\n"
+            "\n"
+            "Options:\n"
+            "  -h, --help                  Display this help and exit\n"
+            "\n"
+            "Report bugs to <linux-bcachefs@vger.kernel.org>");
+}
+
+int cmd_subvolume_create(int argc, char *argv[])
+{
+       static const struct option longopts[] = {
+               { "help",               no_argument,            NULL, 'h' },
+               { NULL }
+       };
+       char *path;
+       int opt;
+
+       while ((opt = getopt_long(argc, argv, "h", longopts, NULL)) != -1)
+               switch (opt) {
+               case 'h':
+                       subvolume_create_usage();
+                       exit(EXIT_SUCCESS);
+               }
+       args_shift(optind);
+
+       while ((path = arg_pop())) {
+               char *dir = dirname(strdup(path));
+
+               struct bchfs_handle fs = bcache_fs_open(dir);
+
+               struct bch_ioctl_subvolume i = {
+                       .dirfd          = AT_FDCWD,
+                       .mode           = 0777,
+                       .dst_ptr        = (unsigned long)path,
+               };
+
+               xioctl(fs.ioctl_fd, BCH_IOCTL_SUBVOLUME_CREATE, &i);
+               bcache_fs_close(fs);
+       }
+
+       return 0;
+}
+
+static void subvolume_delete_usage(void)
+{
+       puts("bcachefs subvolume delete - delete an existing subvolume\n"
+            "Usage: bcachefs subvolume delete [OPTION]... path\n"
+            "\n"
+            "Options:\n"
+            "  -h, --help                  Display this help and exit\n"
+            "\n"
+            "Report bugs to <linux-bcachefs@vger.kernel.org>");
+}
+
+int cmd_subvolume_delete(int argc, char *argv[])
+{
+       static const struct option longopts[] = {
+               { "help",               no_argument,            NULL, 'h' },
+               { NULL }
+       };
+       char *path;
+       int opt;
+
+       while ((opt = getopt_long(argc, argv, "h", longopts, NULL)) != -1)
+               switch (opt) {
+               case 'h':
+                       subvolume_delete_usage();
+                       exit(EXIT_SUCCESS);
+               }
+       args_shift(optind);
+
+       while ((path = arg_pop())) {
+               char *dir = dirname(strdup(path));
+
+               struct bchfs_handle fs = bcache_fs_open(dir);
+
+               struct bch_ioctl_subvolume i = {
+                       .dirfd          = AT_FDCWD,
+                       .mode           = 0777,
+                       .dst_ptr        = (unsigned long)path,
+               };
+
+               xioctl(fs.ioctl_fd, BCH_IOCTL_SUBVOLUME_DESTROY, &i);
+               bcache_fs_close(fs);
+       }
+
+       return 0;
+}
+
+static void snapshot_create_usage(void)
+{
+       puts("bcachefs subvolume snapshot - create a snapshot \n"
+            "Usage: bcachefs subvolume snapshot [OPTION]... <source> <dest>\n"
+            "\n"
+            "Create a snapshot of <source> at <dest>. If specified, <source> must be a subvolume;\n"
+            "if not specified the snapshot will be of the subvolme containing <dest>.\n"
+            "Options:\n"
+            "  -r                          Make snapshot read only\n"
+            "  -h, --help                  Display this help and exit\n"
+            "\n"
+            "Report bugs to <linux-bcachefs@vger.kernel.org>");
+}
+
+int cmd_subvolume_snapshot(int argc, char *argv[])
+{
+       static const struct option longopts[] = {
+               { "help",               no_argument,            NULL, 'h' },
+               { NULL }
+       };
+       unsigned flags = BCH_SUBVOL_SNAPSHOT_CREATE;
+       int opt;
+
+       while ((opt = getopt_long(argc, argv, "rh", longopts, NULL)) != -1)
+               switch (opt) {
+               case 'r':
+                       flags |= BCH_SUBVOL_SNAPSHOT_RO;
+                       break;
+               case 'h':
+                       snapshot_create_usage();
+                       exit(EXIT_SUCCESS);
+               }
+       args_shift(optind);
+
+       char *src = arg_pop();
+       char *dst = arg_pop();
+
+       if (argc)
+               die("Too many arguments");
+
+       if (!dst)
+               swap(src, dst);
+       if (!dst)
+               die("Please specify a path to create");
+
+       char *dir = dirname(strdup(dst));
+
+       struct bchfs_handle fs = bcache_fs_open(dir);
+
+       struct bch_ioctl_subvolume i = {
+               .flags          = flags,
+               .dirfd          = AT_FDCWD,
+               .mode           = 0777,
+               .src_ptr        = (unsigned long)src,
+               .dst_ptr        = (unsigned long)dst,
+       };
+
+       xioctl(fs.ioctl_fd, BCH_IOCTL_SUBVOLUME_CREATE, &i);
+       bcache_fs_close(fs);
+       return 0;
+}
diff --git a/cmds.h b/cmds.h
index cc490844dc8684533a9ff99ce6d039d71999d186..0e27d6d73cc312a6da0a1724094745980935bfa6 100644 (file)
--- a/cmds.h
+++ b/cmds.h
@@ -50,6 +50,10 @@ int cmd_version(int argc, char *argv[]);
 
 int cmd_setattr(int argc, char *argv[]);
 
+int cmd_subvolume_create(int argc, char *argv[]);
+int cmd_subvolume_delete(int argc, char *argv[]);
+int cmd_subvolume_snapshot(int argc, char *argv[]);
+
 int cmd_fusemount(int argc, char *argv[]);
 
 #endif /* _CMDS_H */