strncpy(args_v2.name, name.c_str(), sizeof(args_v2.name) - 1);
#ifdef ENABLE_BTRFS_QUOTA
+
if (qgroup != no_qgroup)
{
size_t size = sizeof(btrfs_qgroup_inherit) + sizeof(((btrfs_qgroup_inherit*) 0)->qgroups[0]);
args_v2.size = size;
args_v2.qgroup_inherit = inherit;
}
+
#endif
if (ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args_v2) == 0)
return args.treeid;
}
+
+ bool
+ does_subvolume_exist(int fd, subvolid_t subvolid)
+ {
+ struct btrfs_ioctl_search_args args;
+ struct btrfs_ioctl_search_key* sk = &args.key;
+
+ sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
+ sk->min_objectid = subvolid;
+ sk->max_objectid = subvolid;
+ sk->min_type = BTRFS_ROOT_ITEM_KEY;
+ sk->max_type = BTRFS_ROOT_ITEM_KEY;
+ sk->min_offset = 0;
+ sk->max_offset = (u64) -1;
+ sk->min_transid = 0;
+ sk->max_transid = (u64) -1;
+ sk->nr_items = 1;
+
+ if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) != 0)
+ throw runtime_error_with_errno("ioctl(BTRFS_IOC_TREE_SEARCH) failed", errno);
+
+ return sk->nr_items == 0;
+ }
+
#endif
+#ifdef ENABLE_BTRFS_QUOTA
+
qgroup_t
- make_qgroup(uint64_t level, subvolid_t id)
+ calc_qgroup(uint64_t level, subvolid_t id)
{
return (level << 48) | id;
}
qgroup_t
- make_qgroup(const string& str)
+ parse_qgroup(const string& str)
{
string::size_type pos = str.find('/');
if (pos == string::npos)
if (b.fail() || !b.eof())
throw std::runtime_error("parsing qgroup failed");
- return make_qgroup(level, id);
+ return calc_qgroup(level, id);
}
-#ifdef HAVE_LIBBTRFS
+ void
+ qgroup_create(int fd, qgroup_t qgroup)
+ {
+ struct btrfs_ioctl_qgroup_create_args args;
+ memset(&args, 0, sizeof(args));
+ args.create = 1;
+ args.qgroupid = qgroup;
- bool
- does_subvolume_exist(int fd, subvolid_t subvolid)
+ if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) != 0)
+ throw runtime_error_with_errno("ioctl(BTRFS_IOC_QGROUP_CREATE) failed", errno);
+ }
+
+
+ void
+ qgroup_destroy(int fd, qgroup_t qgroup)
{
- struct btrfs_ioctl_search_args args;
- struct btrfs_ioctl_search_key* sk = &args.key;
+ struct btrfs_ioctl_qgroup_create_args args;
+ memset(&args, 0, sizeof(args));
+ args.create = 0;
+ args.qgroupid = qgroup;
- sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
- sk->min_objectid = subvolid;
- sk->max_objectid = subvolid;
- sk->min_type = BTRFS_ROOT_ITEM_KEY;
- sk->max_type = BTRFS_ROOT_ITEM_KEY;
- sk->min_offset = 0;
- sk->max_offset = (u64) -1;
- sk->min_transid = 0;
- sk->max_transid = (u64) -1;
- sk->nr_items = 1;
+ if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) != 0)
+ throw runtime_error_with_errno("ioctl(BTRFS_IOC_QGROUP_CREATE) failed", errno);
+ }
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) != 0)
- throw runtime_error_with_errno("ioctl(BTRFS_IOC_TREE_SEARCH) failed", errno);
- return sk->nr_items == 0;
+ void
+ qgroup_assign(int fd, qgroup_t src, qgroup_t dst)
+ {
+ struct btrfs_ioctl_qgroup_assign_args args;
+ memset(&args, 0, sizeof(args));
+ args.assign = 1;
+ args.src = src;
+ args.dst = dst;
+
+ if (ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args) != 0)
+ throw runtime_error_with_errno("ioctl(BTRFS_IOC_QGROUP_ASSIGN) failed", errno);
}
-#endif
+ void
+ qgroup_remove(int fd, qgroup_t src, qgroup_t dst)
+ {
+ struct btrfs_ioctl_qgroup_assign_args args;
+ memset(&args, 0, sizeof(args));
+ args.assign = 0;
+ args.src = src;
+ args.dst = dst;
+
+ if (ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args) != 0)
+ throw runtime_error_with_errno("ioctl(BTRFS_IOC_QGROUP_ASSIGN) failed", errno);
+ }
+
+
+ void
+ quota_rescan(int fd)
+ {
+ struct btrfs_ioctl_quota_rescan_args args;
+ memset(&args, 0, sizeof(args));
+
+ if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN, &args) < 0)
+ throw runtime_error_with_errno("ioctl(BTRFS_IOC_QUOTA_RESCAN) failed", errno);
+
+ while (true)
+ {
+ sleep(1);
+
+ memset(&args, 0, sizeof(args));
+
+ if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_STATUS, &args) < 0)
+ throw runtime_error_with_errno("ioctl(BTRFS_IOC_QUOTA_STATUS) failed", errno);
+
+ if (!args.flags)
+ break;
+ }
+ }
+
+#endif
void
sync(int fd)