1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <fcntl.h>
4 
5 #include "btrfs-util.h"
6 #include "fd-util.h"
7 #include "fileio.h"
8 #include "format-util.h"
9 #include "log.h"
10 #include "string-util.h"
11 #include "util.h"
12 
main(int argc,char * argv[])13 int main(int argc, char *argv[]) {
14         BtrfsQuotaInfo quota;
15         int r, fd;
16 
17         fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
18         if (fd < 0)
19                 log_error_errno(errno, "Failed to open root directory: %m");
20         else {
21                 BtrfsSubvolInfo info;
22 
23                 r = btrfs_subvol_get_info_fd(fd, 0, &info);
24                 if (r < 0)
25                         log_error_errno(r, "Failed to get subvolume info: %m");
26                 else {
27                         log_info("otime: %s", FORMAT_TIMESTAMP(info.otime));
28                         log_info("read-only (search): %s", yes_no(info.read_only));
29                 }
30 
31                 r = btrfs_qgroup_get_quota_fd(fd, 0, &quota);
32                 if (r < 0)
33                         log_error_errno(r, "Failed to get quota info: %m");
34                 else {
35                         log_info("referenced: %s", strna(FORMAT_BYTES(quota.referenced)));
36                         log_info("exclusive: %s", strna(FORMAT_BYTES(quota.exclusive)));
37                         log_info("referenced_max: %s", strna(FORMAT_BYTES(quota.referenced_max)));
38                         log_info("exclusive_max: %s", strna(FORMAT_BYTES(quota.exclusive_max)));
39                 }
40 
41                 r = btrfs_subvol_get_read_only_fd(fd);
42                 if (r < 0)
43                         log_error_errno(r, "Failed to get read only flag: %m");
44                 else
45                         log_info("read-only (ioctl): %s", yes_no(r));
46 
47                 safe_close(fd);
48         }
49 
50         r = btrfs_subvol_make("/xxxtest");
51         if (r < 0)
52                 log_error_errno(r, "Failed to make subvolume: %m");
53 
54         r = write_string_file("/xxxtest/afile", "ljsadhfljasdkfhlkjdsfha", WRITE_STRING_FILE_CREATE);
55         if (r < 0)
56                 log_error_errno(r, "Failed to write file: %m");
57 
58         r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest2", 0);
59         if (r < 0)
60                 log_error_errno(r, "Failed to make snapshot: %m");
61 
62         r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest3", BTRFS_SNAPSHOT_READ_ONLY);
63         if (r < 0)
64                 log_error_errno(r, "Failed to make snapshot: %m");
65 
66         r = btrfs_subvol_remove("/xxxtest", BTRFS_REMOVE_QUOTA);
67         if (r < 0)
68                 log_error_errno(r, "Failed to remove subvolume: %m");
69 
70         r = btrfs_subvol_remove("/xxxtest2", BTRFS_REMOVE_QUOTA);
71         if (r < 0)
72                 log_error_errno(r, "Failed to remove subvolume: %m");
73 
74         r = btrfs_subvol_remove("/xxxtest3", BTRFS_REMOVE_QUOTA);
75         if (r < 0)
76                 log_error_errno(r, "Failed to remove subvolume: %m");
77 
78         r = btrfs_subvol_snapshot("/etc", "/etc2", BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_FALLBACK_COPY);
79         if (r < 0)
80                 log_error_errno(r, "Failed to make snapshot: %m");
81 
82         r = btrfs_subvol_remove("/etc2", BTRFS_REMOVE_QUOTA);
83         if (r < 0)
84                 log_error_errno(r, "Failed to remove subvolume: %m");
85 
86         r = btrfs_subvol_make("/xxxrectest");
87         if (r < 0)
88                 log_error_errno(r, "Failed to make subvolume: %m");
89 
90         r = btrfs_subvol_make("/xxxrectest/xxxrectest2");
91         if (r < 0)
92                 log_error_errno(r, "Failed to make subvolume: %m");
93 
94         r = btrfs_subvol_make("/xxxrectest/xxxrectest3");
95         if (r < 0)
96                 log_error_errno(r, "Failed to make subvolume: %m");
97 
98         r = btrfs_subvol_make("/xxxrectest/xxxrectest3/sub");
99         if (r < 0)
100                 log_error_errno(r, "Failed to make subvolume: %m");
101 
102         if (mkdir("/xxxrectest/dir", 0755) < 0)
103                 log_error_errno(errno, "Failed to make directory: %m");
104 
105         r = btrfs_subvol_make("/xxxrectest/dir/xxxrectest4");
106         if (r < 0)
107                 log_error_errno(r, "Failed to make subvolume: %m");
108 
109         if (mkdir("/xxxrectest/dir/xxxrectest4/dir", 0755) < 0)
110                 log_error_errno(errno, "Failed to make directory: %m");
111 
112         r = btrfs_subvol_make("/xxxrectest/dir/xxxrectest4/dir/xxxrectest5");
113         if (r < 0)
114                 log_error_errno(r, "Failed to make subvolume: %m");
115 
116         if (mkdir("/xxxrectest/mnt", 0755) < 0)
117                 log_error_errno(errno, "Failed to make directory: %m");
118 
119         r = btrfs_subvol_snapshot("/xxxrectest", "/xxxrectest2", BTRFS_SNAPSHOT_RECURSIVE);
120         if (r < 0)
121                 log_error_errno(r, "Failed to snapshot subvolume: %m");
122 
123         r = btrfs_subvol_remove("/xxxrectest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
124         if (r < 0)
125                 log_error_errno(r, "Failed to recursively remove subvolume: %m");
126 
127         r = btrfs_subvol_remove("/xxxrectest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
128         if (r < 0)
129                 log_error_errno(r, "Failed to recursively remove subvolume: %m");
130 
131         r = btrfs_subvol_make("/xxxquotatest");
132         if (r < 0)
133                 log_error_errno(r, "Failed to make subvolume: %m");
134 
135         r = btrfs_subvol_auto_qgroup("/xxxquotatest", 0, true);
136         if (r < 0)
137                 log_error_errno(r, "Failed to set up auto qgroup: %m");
138 
139         r = btrfs_subvol_make("/xxxquotatest/beneath");
140         if (r < 0)
141                 log_error_errno(r, "Failed to make subvolume: %m");
142 
143         r = btrfs_subvol_auto_qgroup("/xxxquotatest/beneath", 0, false);
144         if (r < 0)
145                 log_error_errno(r, "Failed to set up auto qgroup: %m");
146 
147         r = btrfs_qgroup_set_limit("/xxxquotatest/beneath", 0, 4ULL * 1024 * 1024 * 1024);
148         if (r < 0)
149                 log_error_errno(r, "Failed to set up quota limit: %m");
150 
151         r = btrfs_subvol_set_subtree_quota_limit("/xxxquotatest", 0, 5ULL * 1024 * 1024 * 1024);
152         if (r < 0)
153                 log_error_errno(r, "Failed to set up quota limit: %m");
154 
155         r = btrfs_subvol_snapshot("/xxxquotatest", "/xxxquotatest2", BTRFS_SNAPSHOT_RECURSIVE|BTRFS_SNAPSHOT_QUOTA);
156         if (r < 0)
157                 log_error_errno(r, "Failed to set up snapshot: %m");
158 
159         r = btrfs_qgroup_get_quota("/xxxquotatest2/beneath", 0, &quota);
160         if (r < 0)
161                 log_error_errno(r, "Failed to query quota: %m");
162 
163         assert_se(quota.referenced_max == 4ULL * 1024 * 1024 * 1024);
164 
165         r = btrfs_subvol_get_subtree_quota("/xxxquotatest2", 0, &quota);
166         if (r < 0)
167                 log_error_errno(r, "Failed to query quota: %m");
168 
169         assert_se(quota.referenced_max == 5ULL * 1024 * 1024 * 1024);
170 
171         r = btrfs_subvol_remove("/xxxquotatest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
172         if (r < 0)
173                 log_error_errno(r, "Failed remove subvolume: %m");
174 
175         r = btrfs_subvol_remove("/xxxquotatest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
176         if (r < 0)
177                 log_error_errno(r, "Failed remove subvolume: %m");
178 
179         return 0;
180 }
181