blob: c3adb1c43848e72e27e435a02459a7ec927e7b9d [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "global.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/types.h>
#ifdef HAVE_STRUCT_BTRFS_IOCTL_VOL_ARGS_V2
#include <linux/btrfs.h>
#else
#ifndef BTRFS_IOCTL_MAGIC
#define BTRFS_IOCTL_MAGIC 0x94
#endif
#ifndef BTRFS_IOC_SNAP_DESTROY_V2
#define BTRFS_IOC_SNAP_DESTROY_V2 \
_IOW(BTRFS_IOCTL_MAGIC, 63, struct btrfs_ioctl_vol_args_v2)
#endif
#ifndef BTRFS_IOC_SNAP_CREATE_V2
#define BTRFS_IOC_SNAP_CREATE_V2 \
_IOW(BTRFS_IOCTL_MAGIC, 23, struct btrfs_ioctl_vol_args_v2)
#endif
#ifndef BTRFS_IOC_SUBVOL_CREATE_V2
#define BTRFS_IOC_SUBVOL_CREATE_V2 \
_IOW(BTRFS_IOCTL_MAGIC, 24, struct btrfs_ioctl_vol_args_v2)
#endif
#ifndef BTRFS_SUBVOL_NAME_MAX
#define BTRFS_SUBVOL_NAME_MAX 4039
#endif
struct btrfs_ioctl_vol_args_v2 {
__s64 fd;
__u64 transid;
__u64 flags;
union {
struct {
__u64 size;
struct btrfs_qgroup_inherit *qgroup_inherit;
};
__u64 unused[4];
};
union {
char name[BTRFS_SUBVOL_NAME_MAX + 1];
__u64 devid;
__u64 subvolid;
};
};
#endif
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: %s PATH\n", argv[0]);
return EXIT_FAILURE;
}
int dirfd = open(argv[1], O_RDONLY | O_DIRECTORY);
if (dirfd < 0) {
perror(argv[1]);
return EXIT_FAILURE;
}
struct btrfs_ioctl_vol_args_v2 subvol_args = {};
strcpy(subvol_args.name, "subvol");
if (ioctl(dirfd, BTRFS_IOC_SUBVOL_CREATE_V2, &subvol_args) < 0) {
perror("BTRFS_IOC_SUBVOL_CREATE_V2");
return EXIT_FAILURE;
}
int subvolfd = openat(dirfd, "subvol", O_RDONLY | O_DIRECTORY);
if (subvolfd < 0) {
perror("openat");
return EXIT_FAILURE;
}
if (ioctl(dirfd, BTRFS_IOC_SNAP_DESTROY_V2, &subvol_args) < 0) {
perror("BTRFS_IOC_SNAP_DESTROY_V2");
return EXIT_FAILURE;
}
struct btrfs_ioctl_vol_args_v2 snap_args = { .fd = subvolfd };
strcpy(snap_args.name, "snap");
if (ioctl(dirfd, BTRFS_IOC_SNAP_CREATE_V2, &snap_args) < 0) {
if (errno == ENOENT)
return EXIT_SUCCESS;
perror("BTRFS_IOC_SNAP_CREATE_V2");
return EXIT_FAILURE;
}
fprintf(stderr, "BTRFS_IOC_SNAP_CREATE_V2 should've failed\n");
return EXIT_FAILURE;
}