]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/libcephfs/vxattr.cc
import quincy 17.2.0
[ceph.git] / ceph / src / test / libcephfs / vxattr.cc
CommitLineData
1d09f67e
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2021 Red Hat Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include "include/compat.h"
16#include "gtest/gtest.h"
17#include "include/cephfs/libcephfs.h"
18#include "mds/mdstypes.h"
19#include "include/stat.h"
20#include <errno.h>
21#include <fcntl.h>
22#include <unistd.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <dirent.h>
26#include <sys/uio.h>
27#include <sys/time.h>
28#include <sys/resource.h>
29#include <string.h>
30
31#include "common/Clock.h"
32#include "common/ceph_json.h"
33
34#ifdef __linux__
35#include <limits.h>
36#include <sys/xattr.h>
37#endif
38
39#include <fmt/format.h>
40#include <map>
41#include <vector>
42#include <thread>
43#include <regex>
44#include <string>
45
46#ifndef ALLPERMS
47#define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
48#endif
49
50using namespace std;
51
52TEST(LibCephFS, LayoutVerifyDefaultLayout) {
53
54 struct ceph_mount_info *cmount;
55 ASSERT_EQ(0, ceph_create(&cmount, NULL));
56 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
57 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
58 ASSERT_EQ(0, ceph_mount(cmount, "/"));
59
60 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d0/subdir", 0777));
61
62 {
63 char value[1024] = "";
64 int r = 0;
65
66 // check for default layout
67 r = ceph_getxattr(cmount, "/", "ceph.dir.layout.json", (void*)value, sizeof(value));
68 ASSERT_GT(r, 0);
69 ASSERT_LT(r, sizeof value);
70 std::clog << "layout:" << value << std::endl;
71 ASSERT_STRNE((char*)NULL, strstr(value, "\"inheritance\": \"@default\""));
72 }
73
74 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0/subdir"));
75 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0"));
76 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
77
78 ceph_shutdown(cmount);
79}
80
81TEST(LibCephFS, LayoutSetAndVerifyNewAndInheritedLayout) {
82
83 struct ceph_mount_info *cmount;
84 ASSERT_EQ(0, ceph_create(&cmount, NULL));
85 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
86 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
87 ASSERT_EQ(0, ceph_mount(cmount, "/"));
88
89 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d0/subdir", 0777));
90
91 std::string pool_name_set;
92
93 {
94 char value[1024] = "";
95 int r = 0;
96
97 r = ceph_getxattr(cmount, "/", "ceph.dir.layout.json", (void*)value, sizeof(value));
98 ASSERT_GT(r, 0);
99 ASSERT_LT(r, sizeof value);
100
101 JSONParser json_parser;
102 ASSERT_EQ(json_parser.parse(value, r), 1);
103 ASSERT_EQ(json_parser.is_object(), 1);
104
105 std::string pool_name;
106
107 JSONDecoder::decode_json("pool_name", pool_name, &json_parser, true);
108
109 pool_name_set = pool_name;
110
111 // set a new layout
112 std::string new_layout;
113 new_layout += "{";
114 new_layout += "\"stripe_unit\": 65536, ";
115 new_layout += "\"stripe_count\": 1, ";
116 new_layout += "\"object_size\": 65536, ";
117 new_layout += "\"pool_name\": \"" + pool_name + "\"";
118 new_layout += "}";
119
120 ASSERT_EQ(0, ceph_setxattr(cmount, "test/d0", "ceph.dir.layout.json", (void*)new_layout.c_str(), new_layout.length(), XATTR_CREATE));
121 }
122
123 {
124 char value[1024] = "";
125 int r = 0;
126
127 r = ceph_getxattr(cmount, "test/d0", "ceph.dir.layout.json", (void*)value, sizeof(value));
128 ASSERT_GT(r, 0);
129 ASSERT_LT(r, sizeof value);
130 std::clog << "layout:" << value << std::endl;
131
132 JSONParser json_parser;
133 ASSERT_EQ(json_parser.parse(value, r), 1);
134 ASSERT_EQ(json_parser.is_object(), 1);
135
136 int64_t object_size;
137 int64_t stripe_unit;
138 int64_t stripe_count;
139 std::string pool_name;
140 std::string inheritance;
141
142 JSONDecoder::decode_json("pool_name", pool_name, &json_parser, true);
143 JSONDecoder::decode_json("object_size", object_size, &json_parser, true);
144 JSONDecoder::decode_json("stripe_unit", stripe_unit, &json_parser, true);
145 JSONDecoder::decode_json("stripe_count", stripe_count, &json_parser, true);
146 JSONDecoder::decode_json("inheritance", inheritance, &json_parser, true);
147
148 // now verify the layout
149 ASSERT_EQ(pool_name.compare(pool_name_set), 0);
150 ASSERT_EQ(object_size, 65536);
151 ASSERT_EQ(stripe_unit, 65536);
152 ASSERT_EQ(stripe_count, 1);
153 ASSERT_EQ(inheritance.compare("@set"), 0);
154 }
155
156 {
157 char value[1024] = "";
158 int r = 0;
159
160 JSONParser json_parser;
161 std::string inheritance;
162
163 // now check that the subdir layout is inherited
164 r = ceph_getxattr(cmount, "test/d0/subdir", "ceph.dir.layout.json", (void*)value, sizeof(value));
165 ASSERT_GT(r, 0);
166 ASSERT_LT(r, sizeof value);
167 std::clog << "layout:" << value << std::endl;
168 ASSERT_EQ(json_parser.parse(value, r), 1);
169 ASSERT_EQ(json_parser.is_object(), 1);
170 JSONDecoder::decode_json("inheritance", inheritance, &json_parser, true);
171 ASSERT_EQ(inheritance.compare("@inherited"), 0);
172 }
173
174 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0/subdir"));
175 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0"));
176 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
177
178 ceph_shutdown(cmount);
179}
180
181TEST(LibCephFS, LayoutSetBadJSON) {
182
183 struct ceph_mount_info *cmount;
184 ASSERT_EQ(0, ceph_create(&cmount, NULL));
185 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
186 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
187 ASSERT_EQ(0, ceph_mount(cmount, "/"));
188
189 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d0/subdir", 0777));
190
191 {
192 // set a new layout and verify the same
193 const char *new_layout = "" // bad json without starting brace
194 "\"stripe_unit\": 65536, "
195 "\"stripe_count\": 1, "
196 "\"object_size\": 65536, "
197 "\"pool_name\": \"cephfs.a.data\", "
198 "}";
199 // try to set a malformed JSON, eg. without an open brace
200 ASSERT_EQ(-EINVAL, ceph_setxattr(cmount, "test/d0", "ceph.dir.layout.json", (void*)new_layout, strlen(new_layout), XATTR_CREATE));
201 }
202
203 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0/subdir"));
204 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0"));
205 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
206
207 ceph_shutdown(cmount);
208}
209
210TEST(LibCephFS, LayoutSetBadPoolName) {
211
212 struct ceph_mount_info *cmount;
213 ASSERT_EQ(0, ceph_create(&cmount, NULL));
214 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
215 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
216 ASSERT_EQ(0, ceph_mount(cmount, "/"));
217
218 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d0/subdir", 0777));
219
220 {
221 // try setting a bad pool name
222 ASSERT_EQ(-EINVAL, ceph_setxattr(cmount, "test/d0", "ceph.dir.layout.pool_name", (void*)"UglyPoolName", 12, XATTR_CREATE));
223 }
224
225 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0/subdir"));
226 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0"));
227 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
228
229 ceph_shutdown(cmount);
230}
231
232TEST(LibCephFS, LayoutSetBadPoolId) {
233
234 struct ceph_mount_info *cmount;
235 ASSERT_EQ(0, ceph_create(&cmount, NULL));
236 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
237 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
238 ASSERT_EQ(0, ceph_mount(cmount, "/"));
239
240 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d0/subdir", 0777));
241
242 {
243 // try setting a bad pool id
244 ASSERT_EQ(-EINVAL, ceph_setxattr(cmount, "test/d0", "ceph.dir.layout.pool_id", (void*)"300", 3, XATTR_CREATE));
245 }
246
247 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0/subdir"));
248 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0"));
249 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
250
251 ceph_shutdown(cmount);
252}
253
254TEST(LibCephFS, LayoutSetInvalidFieldName) {
255
256 struct ceph_mount_info *cmount;
257 ASSERT_EQ(0, ceph_create(&cmount, NULL));
258 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
259 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
260 ASSERT_EQ(0, ceph_mount(cmount, "/"));
261
262 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d0/subdir", 0777));
263
264 {
265 // try to set in invalid field
266 ASSERT_EQ(-ENODATA, ceph_setxattr(cmount, "test/d0", "ceph.dir.layout.bad_field", (void*)"300", 3, XATTR_CREATE));
267 }
268
269 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0/subdir"));
270 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d0"));
271 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
272
273 ceph_shutdown(cmount);
274}
275
276TEST(LibCephFS, GetAndSetDirPin) {
277
278 struct ceph_mount_info *cmount;
279 ASSERT_EQ(0, ceph_create(&cmount, NULL));
280 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
281 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
282 ASSERT_EQ(0, ceph_mount(cmount, "/"));
283
284 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d1", 0777));
285
286 {
287 char value[1024] = "";
288 int r = ceph_getxattr(cmount, "test/d1", "ceph.dir.pin", (void*)value, sizeof(value));
289 ASSERT_GT(r, 0);
290 ASSERT_LT(r, sizeof value);
291 ASSERT_STREQ("-1", value);
292 }
293
294 {
295 char value[1024] = "";
296 int r = -1;
297
298 ASSERT_EQ(0, ceph_setxattr(cmount, "test/d1", "ceph.dir.pin", (void*)"1", 1, XATTR_CREATE));
299
300 r = ceph_getxattr(cmount, "test/d1", "ceph.dir.pin", (void*)value, sizeof(value));
301 ASSERT_GT(r, 0);
302 ASSERT_LT(r, sizeof value);
303 ASSERT_STREQ("1", value);
304 }
305
306 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d1"));
307 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
308
309 ceph_shutdown(cmount);
310}
311
312TEST(LibCephFS, GetAndSetDirDistribution) {
313
314 struct ceph_mount_info *cmount;
315 ASSERT_EQ(0, ceph_create(&cmount, NULL));
316 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
317 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
318 ASSERT_EQ(0, ceph_mount(cmount, "/"));
319
320 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d2", 0777));
321
322 {
323 char value[1024] = "";
324 int r = ceph_getxattr(cmount, "test/d2", "ceph.dir.pin.distributed", (void*)value, sizeof(value));
325 ASSERT_GT(r, 0);
326 ASSERT_LT(r, sizeof value);
327 ASSERT_STREQ("0", value);
328 }
329
330 {
331 char value[1024] = "";
332 int r = -1;
333
334 ASSERT_EQ(0, ceph_setxattr(cmount, "test/d2", "ceph.dir.pin.distributed", (void*)"1", 1, XATTR_CREATE));
335
336 r = ceph_getxattr(cmount, "test/d2", "ceph.dir.pin.distributed", (void*)value, sizeof(value));
337 ASSERT_GT(r, 0);
338 ASSERT_LT(r, sizeof value);
339 ASSERT_STREQ("1", value);
340 }
341
342 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d2"));
343 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
344
345 ceph_shutdown(cmount);
346}
347
348TEST(LibCephFS, GetAndSetDirRandom) {
349
350 struct ceph_mount_info *cmount;
351 ASSERT_EQ(0, ceph_create(&cmount, NULL));
352 ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
353 ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
354 ASSERT_EQ(0, ceph_mount(cmount, "/"));
355
356 ASSERT_EQ(0, ceph_mkdirs(cmount, "test/d3", 0777));
357
358 {
359 char value[1024] = "";
360 int r = ceph_getxattr(cmount, "test/d3", "ceph.dir.pin.random", (void*)value, sizeof(value));
361 ASSERT_GT(r, 0);
362 ASSERT_LT(r, sizeof value);
363 ASSERT_STREQ("0", value);
364 }
365
366 {
367 double val = (double)1.0/(double)128.0;
368 std::stringstream ss;
369 ss << val;
370 ASSERT_EQ(0, ceph_setxattr(cmount, "test/d3", "ceph.dir.pin.random", (void*)ss.str().c_str(), strlen(ss.str().c_str()), XATTR_CREATE));
371
372 char value[1024] = "";
373 int r = -1;
374
375 r = ceph_getxattr(cmount, "test/d3", "ceph.dir.pin.random", (void*)value, sizeof(value));
376 ASSERT_GT(r, 0);
377 ASSERT_LT(r, sizeof value);
378 ASSERT_STREQ(ss.str().c_str(), value);
379 }
380
381 ASSERT_EQ(0, ceph_rmdir(cmount, "test/d3"));
382 ASSERT_EQ(0, ceph_rmdir(cmount, "test"));
383
384 ceph_shutdown(cmount);
385}