1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
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.
15 #include "include/compat.h"
16 #include "gtest/gtest.h"
17 #include "include/cephfs/libcephfs.h"
18 #include "include/stat.h"
22 #include <sys/types.h>
27 #include <sys/resource.h>
29 #include "common/Clock.h"
33 #include <sys/xattr.h>
36 #include <fmt/format.h>
42 #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
45 TEST(LibCephFS
, OpenEmptyComponent
) {
47 pid_t mypid
= getpid();
48 struct ceph_mount_info
*cmount
;
49 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
50 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
51 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
52 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
55 sprintf(c_dir
, "/open_test_%d", mypid
);
56 struct ceph_dir_result
*dirp
;
58 ASSERT_EQ(0, ceph_mkdirs(cmount
, c_dir
, 0777));
60 ASSERT_EQ(0, ceph_opendir(cmount
, c_dir
, &dirp
));
63 sprintf(c_path
, "/open_test_%d//created_file_%d", mypid
, mypid
);
64 int fd
= ceph_open(cmount
, c_path
, O_RDONLY
|O_CREAT
, 0666);
67 ASSERT_EQ(0, ceph_close(cmount
, fd
));
68 ASSERT_EQ(0, ceph_closedir(cmount
, dirp
));
69 ceph_shutdown(cmount
);
71 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
72 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
73 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
75 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
77 fd
= ceph_open(cmount
, c_path
, O_RDONLY
, 0666);
80 ASSERT_EQ(0, ceph_close(cmount
, fd
));
81 ceph_shutdown(cmount
);
84 TEST(LibCephFS
, OpenReadTruncate
) {
85 struct ceph_mount_info
*cmount
;
86 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
87 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
88 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
89 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
91 auto path
= fmt::format("test_open_rdt_{}", getpid());
92 int fd
= ceph_open(cmount
, path
.c_str(), O_WRONLY
|O_CREAT
, 0666);
95 auto data
= std::string("hello world");
96 ASSERT_EQ(ceph_write(cmount
, fd
, data
.c_str(), data
.size(), 0), (int)data
.size());
97 ASSERT_EQ(0, ceph_close(cmount
, fd
));
99 fd
= ceph_open(cmount
, path
.c_str(), O_RDONLY
, 0);
101 ASSERT_EQ(ceph_ftruncate(cmount
, fd
, 0), -EBADF
);
102 ASSERT_EQ(ceph_ftruncate(cmount
, fd
, 1), -EBADF
);
103 ASSERT_EQ(0, ceph_close(cmount
, fd
));
105 ceph_shutdown(cmount
);
108 TEST(LibCephFS
, OpenReadWrite
) {
109 struct ceph_mount_info
*cmount
;
110 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
111 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
112 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
113 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
116 sprintf(c_path
, "test_open_rdwr_%d", getpid());
117 int fd
= ceph_open(cmount
, c_path
, O_WRONLY
|O_CREAT
, 0666);
120 const char *out_buf
= "hello world";
121 size_t size
= strlen(out_buf
);
123 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), (int)size
);
124 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), -EBADF
);
125 ASSERT_EQ(0, ceph_close(cmount
, fd
));
127 fd
= ceph_open(cmount
, c_path
, O_RDONLY
, 0);
129 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), -EBADF
);
130 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), (int)size
);
131 ASSERT_EQ(0, ceph_close(cmount
, fd
));
133 fd
= ceph_open(cmount
, c_path
, O_RDWR
, 0);
135 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), (int)size
);
136 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), (int)size
);
137 ASSERT_EQ(0, ceph_close(cmount
, fd
));
139 ceph_shutdown(cmount
);
142 TEST(LibCephFS
, MountNonExist
) {
144 struct ceph_mount_info
*cmount
;
146 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
147 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
148 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
149 ASSERT_NE(0, ceph_mount(cmount
, "/non-exist"));
150 ceph_shutdown(cmount
);
153 TEST(LibCephFS
, MountDouble
) {
155 struct ceph_mount_info
*cmount
;
157 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
158 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
159 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
160 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
161 ASSERT_EQ(-EISCONN
, ceph_mount(cmount
, "/"));
162 ceph_shutdown(cmount
);
165 TEST(LibCephFS
, MountRemount
) {
167 struct ceph_mount_info
*cmount
;
169 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
170 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
171 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
173 CephContext
*cct
= ceph_get_mount_context(cmount
);
174 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
175 ASSERT_EQ(0, ceph_unmount(cmount
));
177 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
178 ASSERT_EQ(cct
, ceph_get_mount_context(cmount
));
180 ceph_shutdown(cmount
);
183 TEST(LibCephFS
, UnmountUnmounted
) {
185 struct ceph_mount_info
*cmount
;
187 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
188 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
189 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
190 ASSERT_EQ(-ENOTCONN
, ceph_unmount(cmount
));
191 ceph_shutdown(cmount
);
194 TEST(LibCephFS
, ReleaseUnmounted
) {
196 struct ceph_mount_info
*cmount
;
198 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
199 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
200 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
201 ASSERT_EQ(0, ceph_release(cmount
));
204 TEST(LibCephFS
, ReleaseMounted
) {
206 struct ceph_mount_info
*cmount
;
208 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
209 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
210 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
211 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
212 ASSERT_EQ(-EISCONN
, ceph_release(cmount
));
213 ASSERT_EQ(0, ceph_unmount(cmount
));
214 ASSERT_EQ(0, ceph_release(cmount
));
217 TEST(LibCephFS
, UnmountRelease
) {
219 struct ceph_mount_info
*cmount
;
221 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
222 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
223 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
224 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
225 ASSERT_EQ(0, ceph_unmount(cmount
));
226 ASSERT_EQ(0, ceph_release(cmount
));
229 TEST(LibCephFS
, Mount
) {
230 struct ceph_mount_info
*cmount
;
231 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
232 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
233 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
234 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
235 ceph_shutdown(cmount
);
237 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
238 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
239 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
240 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
241 ceph_shutdown(cmount
);
244 TEST(LibCephFS
, OpenLayout
) {
245 struct ceph_mount_info
*cmount
;
246 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
247 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
248 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
249 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
252 char test_layout_file
[256];
253 sprintf(test_layout_file
, "test_layout_%d_b", getpid());
254 int fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
|O_WRONLY
, 0666, (1<<20), 7, (1<<20), NULL
);
257 ASSERT_LT(0, ceph_get_file_pool_name(cmount
, fd
, poolname
, sizeof(poolname
)));
258 ASSERT_LT(0, ceph_get_file_pool_name(cmount
, fd
, poolname
, 0));
260 /* on already-written file (ENOTEMPTY) */
261 ceph_write(cmount
, fd
, "hello world", 11, 0);
262 ceph_close(cmount
, fd
);
266 sprintf(xattrk
, "ceph.file.layout.stripe_unit");
267 sprintf(xattrv
, "65536");
268 ASSERT_EQ(-ENOTEMPTY
, ceph_setxattr(cmount
, test_layout_file
, xattrk
, (void *)xattrv
, 5, 0));
271 sprintf(test_layout_file
, "test_layout_%d_c", getpid());
272 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 1, 19, NULL
);
273 ASSERT_EQ(fd
, -EINVAL
);
276 sprintf(test_layout_file
, "test_layout_%d_d", getpid());
277 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), poolname
);
279 ceph_close(cmount
, fd
);
281 /* with metadata pool (invalid) */
282 sprintf(test_layout_file
, "test_layout_%d_e", getpid());
283 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), "metadata");
284 ASSERT_EQ(fd
, -EINVAL
);
286 /* with metadata pool (does not exist) */
287 sprintf(test_layout_file
, "test_layout_%d_f", getpid());
288 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), "asdfjasdfjasdf");
289 ASSERT_EQ(fd
, -EINVAL
);
291 ceph_shutdown(cmount
);
294 TEST(LibCephFS
, DirLs
) {
296 pid_t mypid
= getpid();
298 struct ceph_mount_info
*cmount
;
299 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
300 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
301 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
302 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
304 struct ceph_dir_result
*ls_dir
= NULL
;
306 sprintf(foostr
, "dir_ls%d", mypid
);
307 ASSERT_EQ(ceph_opendir(cmount
, foostr
, &ls_dir
), -ENOENT
);
309 ASSERT_EQ(ceph_mkdir(cmount
, foostr
, 0777), 0);
310 struct ceph_statx stx
;
311 ASSERT_EQ(ceph_statx(cmount
, foostr
, &stx
, 0, 0), 0);
312 ASSERT_NE(S_ISDIR(stx
.stx_mode
), 0);
315 sprintf(barstr
, "dir_ls2%d", mypid
);
316 ASSERT_EQ(ceph_statx(cmount
, barstr
, &stx
, 0, AT_SYMLINK_NOFOLLOW
), -ENOENT
);
318 // insert files into directory and test open
320 int i
= 0, r
= rand() % 4096;
321 if (getenv("LIBCEPHFS_RAND")) {
322 r
= atoi(getenv("LIBCEPHFS_RAND"));
324 printf("rand: %d\n", r
);
327 sprintf(bazstr
, "dir_ls%d/dirf%d", mypid
, i
);
328 int fd
= ceph_open(cmount
, bazstr
, O_CREAT
|O_RDONLY
, 0666);
330 ASSERT_EQ(ceph_close(cmount
, fd
), 0);
332 // set file sizes for readdirplus
333 ceph_truncate(cmount
, bazstr
, i
);
336 ASSERT_EQ(ceph_opendir(cmount
, foostr
, &ls_dir
), 0);
338 // not guaranteed to get . and .. first, but its a safe assumption in this case
339 struct dirent
*result
= ceph_readdir(cmount
, ls_dir
);
340 ASSERT_TRUE(result
!= NULL
);
341 ASSERT_STREQ(result
->d_name
, ".");
342 result
= ceph_readdir(cmount
, ls_dir
);
343 ASSERT_TRUE(result
!= NULL
);
344 ASSERT_STREQ(result
->d_name
, "..");
346 std::vector
<std::string
> entries
;
347 std::map
<std::string
, int64_t> offset_map
;
348 int64_t offset
= ceph_telldir(cmount
, ls_dir
);
349 for(i
= 0; i
< r
; ++i
) {
350 result
= ceph_readdir(cmount
, ls_dir
);
351 ASSERT_TRUE(result
!= NULL
);
352 entries
.push_back(result
->d_name
);
353 offset_map
[result
->d_name
] = offset
;
354 offset
= ceph_telldir(cmount
, ls_dir
);
357 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) == NULL
);
358 offset
= ceph_telldir(cmount
, ls_dir
);
360 ASSERT_EQ(offset_map
.size(), entries
.size());
361 for(i
= 0; i
< r
; ++i
) {
362 sprintf(bazstr
, "dirf%d", i
);
363 ASSERT_TRUE(offset_map
.count(bazstr
) == 1);
367 ceph_seekdir(cmount
, ls_dir
, offset
);
368 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) == NULL
);
370 for (auto p
= offset_map
.begin(); p
!= offset_map
.end(); ++p
) {
371 ceph_seekdir(cmount
, ls_dir
, p
->second
);
372 result
= ceph_readdir(cmount
, ls_dir
);
373 ASSERT_TRUE(result
!= NULL
);
374 std::string
d_name(result
->d_name
);
375 ASSERT_EQ(p
->first
, d_name
);
379 ceph_rewinddir(cmount
, ls_dir
);
381 result
= ceph_readdir(cmount
, ls_dir
);
382 ASSERT_TRUE(result
!= NULL
);
383 ASSERT_STREQ(result
->d_name
, ".");
384 result
= ceph_readdir(cmount
, ls_dir
);
385 ASSERT_TRUE(result
!= NULL
);
386 ASSERT_STREQ(result
->d_name
, "..");
388 ceph_rewinddir(cmount
, ls_dir
);
390 int t
= ceph_telldir(cmount
, ls_dir
);
393 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) != NULL
);
395 // test seekdir - move back to the beginning
396 ceph_seekdir(cmount
, ls_dir
, t
);
399 struct dirent
*getdents_entries
;
400 size_t getdents_entries_len
= (r
+ 2) * sizeof(*getdents_entries
);
401 getdents_entries
= (struct dirent
*)malloc(getdents_entries_len
);
404 std::vector
<std::string
> found
;
406 int len
= ceph_getdents(cmount
, ls_dir
, (char *)getdents_entries
, getdents_entries_len
);
410 ASSERT_TRUE((len
% sizeof(*getdents_entries
)) == 0);
411 int n
= len
/ sizeof(*getdents_entries
);
414 ASSERT_STREQ(getdents_entries
[0].d_name
, ".");
415 ASSERT_STREQ(getdents_entries
[1].d_name
, "..");
421 for(; j
< n
; ++i
, ++j
) {
422 const char *name
= getdents_entries
[j
].d_name
;
423 found
.push_back(name
);
426 ASSERT_EQ(found
, entries
);
427 free(getdents_entries
);
430 ceph_rewinddir(cmount
, ls_dir
);
432 result
= ceph_readdir(cmount
, ls_dir
);
433 ASSERT_TRUE(result
!= NULL
);
434 ASSERT_STREQ(result
->d_name
, ".");
435 result
= ceph_readdir(cmount
, ls_dir
);
436 ASSERT_TRUE(result
!= NULL
);
437 ASSERT_STREQ(result
->d_name
, "..");
442 int len
= ceph_readdir_r(cmount
, ls_dir
, &rdent
);
446 found
.push_back(rdent
.d_name
);
448 ASSERT_EQ(found
, entries
);
451 ceph_rewinddir(cmount
, ls_dir
);
453 result
= ceph_readdir(cmount
, ls_dir
);
454 ASSERT_TRUE(result
!= NULL
);
455 ASSERT_STREQ(result
->d_name
, ".");
456 result
= ceph_readdir(cmount
, ls_dir
);
457 ASSERT_TRUE(result
!= NULL
);
458 ASSERT_STREQ(result
->d_name
, "..");
463 struct ceph_statx stx
;
464 int len
= ceph_readdirplus_r(cmount
, ls_dir
, &rdent
, &stx
,
465 CEPH_STATX_SIZE
, AT_NO_ATTR_SYNC
, NULL
);
469 const char *name
= rdent
.d_name
;
470 found
.push_back(name
);
472 sscanf(name
, "dirf%d", &size
);
473 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_SIZE
);
474 ASSERT_EQ(stx
.stx_size
, (size_t)size
);
475 ASSERT_EQ(stx
.stx_ino
, rdent
.d_ino
);
476 //ASSERT_EQ(st.st_mode, (mode_t)0666);
478 ASSERT_EQ(found
, entries
);
480 ASSERT_EQ(ceph_closedir(cmount
, ls_dir
), 0);
482 ceph_shutdown(cmount
);
485 TEST(LibCephFS
, ManyNestedDirs
) {
486 struct ceph_mount_info
*cmount
;
487 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
488 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
489 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
490 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
492 const char *many_path
= "a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a";
493 ASSERT_EQ(ceph_mkdirs(cmount
, many_path
, 0755), 0);
498 ASSERT_EQ(ceph_chdir(cmount
, "a"), 0);
500 struct ceph_dir_result
*dirp
;
501 ASSERT_EQ(ceph_opendir(cmount
, "a", &dirp
), 0);
502 struct dirent
*dent
= ceph_readdir(cmount
, dirp
);
503 ASSERT_TRUE(dent
!= NULL
);
504 ASSERT_STREQ(dent
->d_name
, ".");
505 dent
= ceph_readdir(cmount
, dirp
);
506 ASSERT_TRUE(dent
!= NULL
);
507 ASSERT_STREQ(dent
->d_name
, "..");
508 dent
= ceph_readdir(cmount
, dirp
);
509 ASSERT_TRUE(dent
!= NULL
);
510 ASSERT_STREQ(dent
->d_name
, "a");
511 ASSERT_EQ(ceph_closedir(cmount
, dirp
), 0);
514 ASSERT_STREQ(ceph_getcwd(cmount
), "/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a");
516 ASSERT_EQ(ceph_chdir(cmount
, "a/a/a"), 0);
518 for(i
= 0; i
< 39; ++i
) {
519 ASSERT_EQ(ceph_chdir(cmount
, ".."), 0);
520 ASSERT_EQ(ceph_rmdir(cmount
, "a"), 0);
523 ASSERT_EQ(ceph_chdir(cmount
, "/"), 0);
525 ASSERT_EQ(ceph_rmdir(cmount
, "a/a/a"), 0);
527 ceph_shutdown(cmount
);
530 TEST(LibCephFS
, Xattrs
) {
531 struct ceph_mount_info
*cmount
;
532 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
533 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
534 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
535 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
537 char test_xattr_file
[256];
538 sprintf(test_xattr_file
, "test_xattr_%d", getpid());
539 int fd
= ceph_open(cmount
, test_xattr_file
, O_CREAT
, 0666);
545 for(; i
< 'a'+26; ++i
) {
546 sprintf(xattrk
, "user.test_xattr_%c", i
);
547 int len
= sprintf(xattrv
, "testxattr%c", i
);
548 ASSERT_EQ(ceph_setxattr(cmount
, test_xattr_file
, xattrk
, (void *) xattrv
, len
, XATTR_CREATE
), 0);
551 // zero size should return required buffer length
552 int len_needed
= ceph_listxattr(cmount
, test_xattr_file
, NULL
, 0);
553 ASSERT_GT(len_needed
, 0);
555 // buffer size smaller than needed should fail
556 char xattrlist
[128*26];
557 ASSERT_GT(sizeof(xattrlist
), (size_t)len_needed
);
558 int len
= ceph_listxattr(cmount
, test_xattr_file
, xattrlist
, len_needed
- 1);
559 ASSERT_EQ(-ERANGE
, len
);
561 len
= ceph_listxattr(cmount
, test_xattr_file
, xattrlist
, sizeof(xattrlist
));
562 ASSERT_EQ(len
, len_needed
);
567 // ceph.* xattrs should not be listed
568 ASSERT_NE(strncmp(p
, "ceph.", 5), 0);
570 sprintf(xattrk
, "user.test_xattr_%c", i
);
571 ASSERT_STREQ(p
, xattrk
);
574 std::cout
<< "getting attr " << p
<< std::endl
;
575 int alen
= ceph_getxattr(cmount
, test_xattr_file
, p
, (void *) gxattrv
, 128);
577 sprintf(xattrv
, "testxattr%c", i
);
578 ASSERT_TRUE(!strncmp(xattrv
, gxattrv
, alen
));
588 for(i
= 'a'; i
< 'a'+26; ++i
) {
589 sprintf(xattrk
, "user.test_xattr_%c", i
);
590 ASSERT_EQ(ceph_removexattr(cmount
, test_xattr_file
, xattrk
), 0);
593 ceph_close(cmount
, fd
);
594 ceph_shutdown(cmount
);
598 TEST(LibCephFS
, Xattrs_ll
) {
599 struct ceph_mount_info
*cmount
;
600 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
601 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
602 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
603 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
605 char test_xattr_file
[256];
606 sprintf(test_xattr_file
, "test_xattr_%d", getpid());
607 int fd
= ceph_open(cmount
, test_xattr_file
, O_CREAT
, 0666);
609 ceph_close(cmount
, fd
);
612 Inode
*existent_file_handle
= NULL
;
614 int res
= ceph_ll_lookup_root(cmount
, &root
);
617 UserPerm
*perms
= ceph_mount_perms(cmount
);
618 struct ceph_statx stx
;
620 res
= ceph_ll_lookup(cmount
, root
, test_xattr_file
, &existent_file_handle
,
624 const char *valid_name
= "user.attrname";
625 const char *value
= "attrvalue";
626 char value_buf
[256] = { 0 };
628 res
= ceph_ll_setxattr(cmount
, existent_file_handle
, valid_name
, value
, strlen(value
), 0, perms
);
631 res
= ceph_ll_getxattr(cmount
, existent_file_handle
, valid_name
, value_buf
, 256, perms
);
632 ASSERT_EQ(res
, (int)strlen(value
));
634 value_buf
[res
] = '\0';
635 ASSERT_STREQ(value_buf
, value
);
637 ceph_shutdown(cmount
);
640 TEST(LibCephFS
, LstatSlashdot
) {
641 struct ceph_mount_info
*cmount
;
642 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
643 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
644 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
645 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
647 struct ceph_statx stx
;
648 ASSERT_EQ(ceph_statx(cmount
, "/.", &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
649 ASSERT_EQ(ceph_statx(cmount
, ".", &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
651 ceph_shutdown(cmount
);
654 TEST(LibCephFS
, StatDirNlink
) {
655 struct ceph_mount_info
*cmount
;
656 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
657 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
658 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
659 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
662 sprintf(test_dir1
, "dir1_symlinks_%d", getpid());
663 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
665 int fd
= ceph_open(cmount
, test_dir1
, O_DIRECTORY
|O_RDONLY
, 0);
667 struct ceph_statx stx
;
668 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
669 ASSERT_EQ(stx
.stx_nlink
, 2u);
673 sprintf(test_dir2
, "%s/.", test_dir1
);
674 ASSERT_EQ(ceph_statx(cmount
, test_dir2
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
675 ASSERT_EQ(stx
.stx_nlink
, 2u);
680 sprintf(test_dir2
, "%s/1", test_dir1
);
681 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
682 ASSERT_EQ(ceph_statx(cmount
, test_dir2
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
683 ASSERT_EQ(stx
.stx_nlink
, 2u);
684 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
685 ASSERT_EQ(stx
.stx_nlink
, 3u);
686 sprintf(test_dir2
, "%s/2", test_dir1
);
687 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
688 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
689 ASSERT_EQ(stx
.stx_nlink
, 4u);
690 sprintf(test_dir2
, "%s/1/1", test_dir1
);
691 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
692 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
693 ASSERT_EQ(stx
.stx_nlink
, 4u);
694 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
695 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
696 ASSERT_EQ(stx
.stx_nlink
, 4u);
697 sprintf(test_dir2
, "%s/1", test_dir1
);
698 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
699 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
700 ASSERT_EQ(stx
.stx_nlink
, 3u);
701 sprintf(test_dir2
, "%s/2", test_dir1
);
702 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
703 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
704 ASSERT_EQ(stx
.stx_nlink
, 2u);
707 ASSERT_EQ(ceph_rmdir(cmount
, test_dir1
), 0);
708 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
709 ASSERT_EQ(stx
.stx_nlink
, 0u);
711 ceph_close(cmount
, fd
);
713 ceph_shutdown(cmount
);
716 TEST(LibCephFS
, DoubleChmod
) {
718 struct ceph_mount_info
*cmount
;
719 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
720 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
721 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
722 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
725 sprintf(test_file
, "test_perms_%d", getpid());
727 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
731 const char *bytes
= "foobarbaz";
732 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
734 ceph_close(cmount
, fd
);
736 // set perms to read but can't write
737 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0400), 0);
739 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
740 ASSERT_EQ(fd
, -EACCES
);
742 fd
= ceph_open(cmount
, test_file
, O_RDONLY
, 0);
746 int ret
= ceph_read(cmount
, fd
, buf
, 100, 0);
747 ASSERT_EQ(ret
, (int)strlen(bytes
));
749 ASSERT_STREQ(buf
, bytes
);
751 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), -EBADF
);
753 ceph_close(cmount
, fd
);
755 // reset back to writeable
756 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0600), 0);
758 // ensure perms are correct
759 struct ceph_statx stx
;
760 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
, CEPH_STATX_MODE
, AT_SYMLINK_NOFOLLOW
), 0);
761 ASSERT_EQ(stx
.stx_mode
, 0100600U);
763 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
766 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
767 ceph_close(cmount
, fd
);
769 ceph_shutdown(cmount
);
772 TEST(LibCephFS
, Fchmod
) {
773 struct ceph_mount_info
*cmount
;
774 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
775 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
776 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
777 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
780 sprintf(test_file
, "test_perms_%d", getpid());
782 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
786 const char *bytes
= "foobarbaz";
787 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
789 // set perms to read but can't write
790 ASSERT_EQ(ceph_fchmod(cmount
, fd
, 0400), 0);
793 int ret
= ceph_read(cmount
, fd
, buf
, 100, 0);
794 ASSERT_EQ(ret
, (int)strlen(bytes
));
796 ASSERT_STREQ(buf
, bytes
);
798 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
800 ceph_close(cmount
, fd
);
802 ASSERT_EQ(ceph_open(cmount
, test_file
, O_RDWR
, 0), -EACCES
);
804 // reset back to writeable
805 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0600), 0);
807 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
810 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
811 ceph_close(cmount
, fd
);
813 ceph_shutdown(cmount
);
816 TEST(LibCephFS
, Lchmod
) {
817 struct ceph_mount_info
*cmount
;
818 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
819 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
820 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
821 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
824 sprintf(test_file
, "test_perms_lchmod_%d", getpid());
826 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
830 const char *bytes
= "foobarbaz";
831 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
832 ceph_close(cmount
, fd
);
835 char test_symlink
[256];
836 sprintf(test_symlink
, "test_lchmod_sym_%d", getpid());
837 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
839 // get symlink stat - lstat
840 struct ceph_statx stx_orig1
;
841 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_orig1
, CEPH_STATX_ALL_STATS
, AT_SYMLINK_NOFOLLOW
), 0);
843 // Change mode on symlink file
844 ASSERT_EQ(ceph_lchmod(cmount
, test_symlink
, 0400), 0);
845 struct ceph_statx stx_orig2
;
846 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_orig2
, CEPH_STATX_ALL_STATS
, AT_SYMLINK_NOFOLLOW
), 0);
849 ASSERT_NE(stx_orig1
.stx_mode
, stx_orig2
.stx_mode
);
850 static const int permbits
= S_IRWXU
|S_IRWXG
|S_IRWXO
;
851 ASSERT_EQ(permbits
&stx_orig1
.stx_mode
, 0777);
852 ASSERT_EQ(permbits
&stx_orig2
.stx_mode
, 0400);
854 ceph_shutdown(cmount
);
857 TEST(LibCephFS
, Fchown
) {
858 struct ceph_mount_info
*cmount
;
859 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
860 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
861 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
862 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
865 sprintf(test_file
, "test_fchown_%d", getpid());
867 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
870 // set perms to readable and writeable only by owner
871 ASSERT_EQ(ceph_fchmod(cmount
, fd
, 0600), 0);
873 // change ownership to nobody -- we assume nobody exists and id is always 65534
874 ASSERT_EQ(ceph_conf_set(cmount
, "client_permissions", "0"), 0);
875 ASSERT_EQ(ceph_fchown(cmount
, fd
, 65534, 65534), 0);
876 ASSERT_EQ(ceph_conf_set(cmount
, "client_permissions", "1"), 0);
878 ceph_close(cmount
, fd
);
880 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
881 ASSERT_EQ(fd
, -EACCES
);
883 ceph_shutdown(cmount
);
886 #if defined(__linux__) && defined(O_PATH)
887 TEST(LibCephFS
, FlagO_PATH
) {
888 struct ceph_mount_info
*cmount
;
890 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
891 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
892 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
893 ASSERT_EQ(0, ceph_mount(cmount
, NULL
));
895 char test_file
[PATH_MAX
];
896 sprintf(test_file
, "test_oflag_%d", getpid());
898 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
|O_PATH
, 0666);
899 ASSERT_EQ(-ENOENT
, fd
);
901 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
903 ASSERT_EQ(0, ceph_close(cmount
, fd
));
905 // ok, the file has been created. perform real checks now
906 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
|O_PATH
, 0666);
910 ASSERT_EQ(-EBADF
, ceph_read(cmount
, fd
, buf
, sizeof(buf
), 0));
911 ASSERT_EQ(-EBADF
, ceph_write(cmount
, fd
, buf
, sizeof(buf
), 0));
913 // set perms to readable and writeable only by owner
914 ASSERT_EQ(-EBADF
, ceph_fchmod(cmount
, fd
, 0600));
916 // change ownership to nobody -- we assume nobody exists and id is always 65534
917 ASSERT_EQ(-EBADF
, ceph_fchown(cmount
, fd
, 65534, 65534));
920 ASSERT_EQ(-EBADF
, ceph_fsync(cmount
, fd
, false));
922 struct ceph_statx stx
;
923 ASSERT_EQ(0, ceph_fstatx(cmount
, fd
, &stx
, 0, 0));
925 ASSERT_EQ(0, ceph_close(cmount
, fd
));
926 ceph_shutdown(cmount
);
930 TEST(LibCephFS
, Symlinks
) {
931 struct ceph_mount_info
*cmount
;
932 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
933 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
934 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
935 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
938 sprintf(test_file
, "test_symlinks_%d", getpid());
940 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
943 ceph_close(cmount
, fd
);
945 char test_symlink
[256];
946 sprintf(test_symlink
, "test_symlinks_sym_%d", getpid());
948 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
950 // test the O_NOFOLLOW case
951 fd
= ceph_open(cmount
, test_symlink
, O_NOFOLLOW
, 0);
952 ASSERT_EQ(fd
, -ELOOP
);
954 // stat the original file
955 struct ceph_statx stx_orig
;
956 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
958 struct ceph_statx stx_symlink_orig
;
959 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_symlink_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
960 // ensure the statx bufs are equal
961 ASSERT_EQ(memcmp(&stx_orig
, &stx_symlink_orig
, sizeof(stx_orig
)), 0);
963 sprintf(test_file
, "/test_symlinks_abs_%d", getpid());
965 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
968 ceph_close(cmount
, fd
);
970 sprintf(test_symlink
, "/test_symlinks_abs_sym_%d", getpid());
972 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
974 // stat the original file
975 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
977 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_symlink_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
978 // ensure the statx bufs are equal
979 ASSERT_TRUE(!memcmp(&stx_orig
, &stx_symlink_orig
, sizeof(stx_orig
)));
982 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_orig
, CEPH_STATX_ALL_STATS
, AT_SYMLINK_NOFOLLOW
), 0);
983 ASSERT_TRUE(S_ISLNK(stx_orig
.stx_mode
));
985 ceph_shutdown(cmount
);
988 TEST(LibCephFS
, DirSyms
) {
989 struct ceph_mount_info
*cmount
;
990 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
991 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
992 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
993 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
996 sprintf(test_dir1
, "dir1_symlinks_%d", getpid());
998 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
1000 char test_symdir
[256];
1001 sprintf(test_symdir
, "symdir_symlinks_%d", getpid());
1003 ASSERT_EQ(ceph_symlink(cmount
, test_dir1
, test_symdir
), 0);
1005 char test_file
[256];
1006 sprintf(test_file
, "/symdir_symlinks_%d/test_symdir_file", getpid());
1007 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0600);
1009 ceph_close(cmount
, fd
);
1011 struct ceph_statx stx
;
1012 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
1014 // ensure that its a file not a directory we get back
1015 ASSERT_TRUE(S_ISREG(stx
.stx_mode
));
1017 ceph_shutdown(cmount
);
1020 TEST(LibCephFS
, LoopSyms
) {
1021 struct ceph_mount_info
*cmount
;
1022 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1023 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1024 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1025 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1027 char test_dir1
[256];
1028 sprintf(test_dir1
, "dir1_loopsym_%d", getpid());
1030 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
1032 char test_dir2
[256];
1033 sprintf(test_dir2
, "/dir1_loopsym_%d/loop_dir", getpid());
1035 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
1037 // symlink it itself: /path/to/mysym -> /path/to/mysym
1038 char test_symdir
[256];
1039 sprintf(test_symdir
, "/dir1_loopsym_%d/loop_dir/symdir", getpid());
1041 ASSERT_EQ(ceph_symlink(cmount
, test_symdir
, test_symdir
), 0);
1043 char test_file
[256];
1044 sprintf(test_file
, "/dir1_loopsym_%d/loop_dir/symdir/test_loopsym_file", getpid());
1045 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0600);
1046 ASSERT_EQ(fd
, -ELOOP
);
1048 // loop: /a -> /b, /b -> /c, /c -> /a
1049 char a
[264], b
[264], c
[264];
1050 sprintf(a
, "/%s/a", test_dir1
);
1051 sprintf(b
, "/%s/b", test_dir1
);
1052 sprintf(c
, "/%s/c", test_dir1
);
1053 ASSERT_EQ(ceph_symlink(cmount
, a
, b
), 0);
1054 ASSERT_EQ(ceph_symlink(cmount
, b
, c
), 0);
1055 ASSERT_EQ(ceph_symlink(cmount
, c
, a
), 0);
1056 ASSERT_EQ(ceph_open(cmount
, a
, O_RDWR
, 0), -ELOOP
);
1058 ceph_shutdown(cmount
);
1061 TEST(LibCephFS
, HardlinkNoOriginal
) {
1063 int mypid
= getpid();
1065 struct ceph_mount_info
*cmount
;
1066 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1067 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1068 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1069 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1072 sprintf(dir
, "/test_rmdirfail%d", mypid
);
1073 ASSERT_EQ(ceph_mkdir(cmount
, dir
, 0777), 0);
1075 ASSERT_EQ(ceph_chdir(cmount
, dir
), 0);
1077 int fd
= ceph_open(cmount
, "f1", O_CREAT
, 0644);
1080 ceph_close(cmount
, fd
);
1083 ASSERT_EQ(ceph_link(cmount
, "f1", "hardl1"), 0);
1085 // remove file link points to
1086 ASSERT_EQ(ceph_unlink(cmount
, "f1"), 0);
1088 ceph_shutdown(cmount
);
1091 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1092 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1093 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1094 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1095 ASSERT_EQ(ceph_chdir(cmount
, dir
), 0);
1096 ASSERT_EQ(ceph_unlink(cmount
, "hardl1"), 0);
1097 ASSERT_EQ(ceph_rmdir(cmount
, dir
), 0);
1099 ceph_shutdown(cmount
);
1102 TEST(LibCephFS
, BadArgument
) {
1103 struct ceph_mount_info
*cmount
;
1104 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1105 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1106 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1107 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1109 int fd
= ceph_open(cmount
, "test_file", O_CREAT
|O_RDWR
, 0666);
1112 ASSERT_EQ(ceph_write(cmount
, fd
, buf
, sizeof(buf
), 0), (int)sizeof(buf
));
1113 ASSERT_EQ(ceph_read(cmount
, fd
, buf
, 0, 5), 0);
1114 ceph_close(cmount
, fd
);
1115 ASSERT_EQ(ceph_unlink(cmount
, "test_file"), 0);
1117 ceph_shutdown(cmount
);
1120 TEST(LibCephFS
, BadFileDesc
) {
1121 struct ceph_mount_info
*cmount
;
1122 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1123 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1124 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1125 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1127 ASSERT_EQ(ceph_fchmod(cmount
, -1, 0655), -EBADF
);
1128 ASSERT_EQ(ceph_close(cmount
, -1), -EBADF
);
1129 ASSERT_EQ(ceph_lseek(cmount
, -1, 0, SEEK_SET
), -EBADF
);
1132 ASSERT_EQ(ceph_read(cmount
, -1, buf
, 0, 0), -EBADF
);
1133 ASSERT_EQ(ceph_write(cmount
, -1, buf
, 0, 0), -EBADF
);
1135 ASSERT_EQ(ceph_ftruncate(cmount
, -1, 0), -EBADF
);
1136 ASSERT_EQ(ceph_fsync(cmount
, -1, 0), -EBADF
);
1138 struct ceph_statx stx
;
1139 ASSERT_EQ(ceph_fstatx(cmount
, -1, &stx
, 0, 0), -EBADF
);
1141 struct sockaddr_storage addr
;
1142 ASSERT_EQ(ceph_get_file_stripe_address(cmount
, -1, 0, &addr
, 1), -EBADF
);
1144 ASSERT_EQ(ceph_get_file_stripe_unit(cmount
, -1), -EBADF
);
1145 ASSERT_EQ(ceph_get_file_pool(cmount
, -1), -EBADF
);
1147 ASSERT_EQ(ceph_get_file_pool_name(cmount
, -1, poolname
, sizeof(poolname
)), -EBADF
);
1148 ASSERT_EQ(ceph_get_file_replication(cmount
, -1), -EBADF
);
1149 ASSERT_EQ(ceph_get_file_object_size(cmount
, -1), -EBADF
);
1150 int stripe_unit
, stripe_count
, object_size
, pg_pool
;
1151 ASSERT_EQ(ceph_get_file_layout(cmount
, -1, &stripe_unit
, &stripe_count
, &object_size
, &pg_pool
), -EBADF
);
1152 ASSERT_EQ(ceph_get_file_stripe_count(cmount
, -1), -EBADF
);
1154 ceph_shutdown(cmount
);
1157 TEST(LibCephFS
, ReadEmptyFile
) {
1158 struct ceph_mount_info
*cmount
;
1159 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1160 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1161 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1162 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1164 // test the read_sync path in the client for zero files
1165 ASSERT_EQ(ceph_conf_set(cmount
, "client_debug_force_sync_read", "true"), 0);
1167 int mypid
= getpid();
1170 sprintf(testf
, "test_reademptyfile%d", mypid
);
1171 int fd
= ceph_open(cmount
, testf
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644);
1174 ceph_close(cmount
, fd
);
1176 fd
= ceph_open(cmount
, testf
, O_RDONLY
, 0);
1180 ASSERT_EQ(ceph_read(cmount
, fd
, buf
, 4096, 0), 0);
1182 ceph_close(cmount
, fd
);
1183 ceph_shutdown(cmount
);
1186 TEST(LibCephFS
, PreadvPwritev
) {
1187 struct ceph_mount_info
*cmount
;
1188 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1189 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1190 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1191 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1193 int mypid
= getpid();
1196 sprintf(testf
, "test_preadvpwritevfile%d", mypid
);
1197 int fd
= ceph_open(cmount
, testf
, O_CREAT
|O_RDWR
, 0666);
1200 char out0
[] = "hello ";
1201 char out1
[] = "world\n";
1202 struct iovec iov_out
[2] = {
1203 {out0
, sizeof(out0
)},
1204 {out1
, sizeof(out1
)},
1206 char in0
[sizeof(out0
)];
1207 char in1
[sizeof(out1
)];
1208 struct iovec iov_in
[2] = {
1212 ssize_t nwritten
= iov_out
[0].iov_len
+ iov_out
[1].iov_len
;
1213 ssize_t nread
= iov_in
[0].iov_len
+ iov_in
[1].iov_len
;
1215 ASSERT_EQ(ceph_pwritev(cmount
, fd
, iov_out
, 2, 0), nwritten
);
1216 ASSERT_EQ(ceph_preadv(cmount
, fd
, iov_in
, 2, 0), nread
);
1217 ASSERT_EQ(0, strncmp((const char*)iov_in
[0].iov_base
, (const char*)iov_out
[0].iov_base
, iov_out
[0].iov_len
));
1218 ASSERT_EQ(0, strncmp((const char*)iov_in
[1].iov_base
, (const char*)iov_out
[1].iov_base
, iov_out
[1].iov_len
));
1220 ceph_close(cmount
, fd
);
1221 ceph_shutdown(cmount
);
1224 TEST(LibCephFS
, LlreadvLlwritev
) {
1225 struct ceph_mount_info
*cmount
;
1226 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1227 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1228 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1229 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1231 int mypid
= getpid();
1234 sprintf(filename
, "test_llreadvllwritevfile%u", mypid
);
1237 ASSERT_EQ(ceph_ll_lookup_root(cmount
, &root
), 0);
1240 struct ceph_statx stx
;
1241 UserPerm
*perms
= ceph_mount_perms(cmount
);
1243 ASSERT_EQ(ceph_ll_create(cmount
, root
, filename
, 0666,
1244 O_RDWR
|O_CREAT
|O_TRUNC
, &file
, &fh
, &stx
, 0, 0, perms
), 0);
1246 /* Reopen read-only */
1247 char out0
[] = "hello ";
1248 char out1
[] = "world\n";
1249 struct iovec iov_out
[2] = {
1250 {out0
, sizeof(out0
)},
1251 {out1
, sizeof(out1
)},
1253 char in0
[sizeof(out0
)];
1254 char in1
[sizeof(out1
)];
1255 struct iovec iov_in
[2] = {
1259 ssize_t nwritten
= iov_out
[0].iov_len
+ iov_out
[1].iov_len
;
1260 ssize_t nread
= iov_in
[0].iov_len
+ iov_in
[1].iov_len
;
1262 ASSERT_EQ(ceph_ll_writev(cmount
, fh
, iov_out
, 2, 0), nwritten
);
1263 ASSERT_EQ(ceph_ll_readv(cmount
, fh
, iov_in
, 2, 0), nread
);
1264 ASSERT_EQ(0, strncmp((const char*)iov_in
[0].iov_base
, (const char*)iov_out
[0].iov_base
, iov_out
[0].iov_len
));
1265 ASSERT_EQ(0, strncmp((const char*)iov_in
[1].iov_base
, (const char*)iov_out
[1].iov_base
, iov_out
[1].iov_len
));
1267 ceph_ll_close(cmount
, fh
);
1268 ceph_shutdown(cmount
);
1271 TEST(LibCephFS
, StripeUnitGran
) {
1272 struct ceph_mount_info
*cmount
;
1273 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1274 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1275 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1276 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1277 ASSERT_GT(ceph_get_stripe_unit_granularity(cmount
), 0);
1278 ceph_shutdown(cmount
);
1281 TEST(LibCephFS
, Rename
) {
1282 struct ceph_mount_info
*cmount
;
1283 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1284 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1285 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1286 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1288 int mypid
= getpid();
1292 /* make a source file */
1293 sprintf(path_src
, "test_rename_src%d", mypid
);
1294 int fd
= ceph_open(cmount
, path_src
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0777);
1296 ASSERT_EQ(0, ceph_close(cmount
, fd
));
1298 /* rename to a new dest path */
1299 sprintf(path_dst
, "test_rename_dst%d", mypid
);
1300 ASSERT_EQ(0, ceph_rename(cmount
, path_src
, path_dst
));
1302 /* test that dest path exists */
1303 struct ceph_statx stx
;
1304 ASSERT_EQ(0, ceph_statx(cmount
, path_dst
, &stx
, 0, 0));
1306 /* test that src path doesn't exist */
1307 ASSERT_EQ(-ENOENT
, ceph_statx(cmount
, path_src
, &stx
, 0, AT_SYMLINK_NOFOLLOW
));
1309 /* rename with non-existent source path */
1310 ASSERT_EQ(-ENOENT
, ceph_rename(cmount
, path_src
, path_dst
));
1312 ASSERT_EQ(0, ceph_unlink(cmount
, path_dst
));
1313 ceph_shutdown(cmount
);
1316 TEST(LibCephFS
, UseUnmounted
) {
1317 struct ceph_mount_info
*cmount
;
1318 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1319 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1320 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1322 struct statvfs stvfs
;
1323 EXPECT_EQ(-ENOTCONN
, ceph_statfs(cmount
, "/", &stvfs
));
1324 EXPECT_EQ(-ENOTCONN
, ceph_get_local_osd(cmount
));
1325 EXPECT_EQ(-ENOTCONN
, ceph_chdir(cmount
, "/"));
1327 struct ceph_dir_result
*dirp
;
1328 EXPECT_EQ(-ENOTCONN
, ceph_opendir(cmount
, "/", &dirp
));
1329 EXPECT_EQ(-ENOTCONN
, ceph_closedir(cmount
, dirp
));
1331 ceph_readdir(cmount
, dirp
);
1332 EXPECT_EQ(ENOTCONN
, errno
);
1334 struct dirent rdent
;
1335 EXPECT_EQ(-ENOTCONN
, ceph_readdir_r(cmount
, dirp
, &rdent
));
1337 struct ceph_statx stx
;
1338 EXPECT_EQ(-ENOTCONN
, ceph_readdirplus_r(cmount
, dirp
, &rdent
, &stx
, 0, 0, NULL
));
1339 EXPECT_EQ(-ENOTCONN
, ceph_getdents(cmount
, dirp
, NULL
, 0));
1340 EXPECT_EQ(-ENOTCONN
, ceph_getdnames(cmount
, dirp
, NULL
, 0));
1341 EXPECT_EQ(-ENOTCONN
, ceph_telldir(cmount
, dirp
));
1342 EXPECT_EQ(-ENOTCONN
, ceph_link(cmount
, "/", "/link"));
1343 EXPECT_EQ(-ENOTCONN
, ceph_unlink(cmount
, "/path"));
1344 EXPECT_EQ(-ENOTCONN
, ceph_rename(cmount
, "/path", "/path"));
1345 EXPECT_EQ(-ENOTCONN
, ceph_mkdir(cmount
, "/", 0655));
1346 EXPECT_EQ(-ENOTCONN
, ceph_mkdirs(cmount
, "/", 0655));
1347 EXPECT_EQ(-ENOTCONN
, ceph_rmdir(cmount
, "/path"));
1348 EXPECT_EQ(-ENOTCONN
, ceph_readlink(cmount
, "/path", NULL
, 0));
1349 EXPECT_EQ(-ENOTCONN
, ceph_symlink(cmount
, "/path", "/path"));
1350 EXPECT_EQ(-ENOTCONN
, ceph_statx(cmount
, "/path", &stx
, 0, 0));
1351 EXPECT_EQ(-ENOTCONN
, ceph_setattrx(cmount
, "/path", &stx
, 0, 0));
1352 EXPECT_EQ(-ENOTCONN
, ceph_getxattr(cmount
, "/path", "name", NULL
, 0));
1353 EXPECT_EQ(-ENOTCONN
, ceph_lgetxattr(cmount
, "/path", "name", NULL
, 0));
1354 EXPECT_EQ(-ENOTCONN
, ceph_listxattr(cmount
, "/path", NULL
, 0));
1355 EXPECT_EQ(-ENOTCONN
, ceph_llistxattr(cmount
, "/path", NULL
, 0));
1356 EXPECT_EQ(-ENOTCONN
, ceph_removexattr(cmount
, "/path", "name"));
1357 EXPECT_EQ(-ENOTCONN
, ceph_lremovexattr(cmount
, "/path", "name"));
1358 EXPECT_EQ(-ENOTCONN
, ceph_setxattr(cmount
, "/path", "name", NULL
, 0, 0));
1359 EXPECT_EQ(-ENOTCONN
, ceph_lsetxattr(cmount
, "/path", "name", NULL
, 0, 0));
1360 EXPECT_EQ(-ENOTCONN
, ceph_fsetattrx(cmount
, 0, &stx
, 0));
1361 EXPECT_EQ(-ENOTCONN
, ceph_chmod(cmount
, "/path", 0));
1362 EXPECT_EQ(-ENOTCONN
, ceph_fchmod(cmount
, 0, 0));
1363 EXPECT_EQ(-ENOTCONN
, ceph_chown(cmount
, "/path", 0, 0));
1364 EXPECT_EQ(-ENOTCONN
, ceph_lchown(cmount
, "/path", 0, 0));
1365 EXPECT_EQ(-ENOTCONN
, ceph_fchown(cmount
, 0, 0, 0));
1368 EXPECT_EQ(-ENOTCONN
, ceph_utime(cmount
, "/path", &utb
));
1369 EXPECT_EQ(-ENOTCONN
, ceph_truncate(cmount
, "/path", 0));
1370 EXPECT_EQ(-ENOTCONN
, ceph_mknod(cmount
, "/path", 0, 0));
1371 EXPECT_EQ(-ENOTCONN
, ceph_open(cmount
, "/path", 0, 0));
1372 EXPECT_EQ(-ENOTCONN
, ceph_open_layout(cmount
, "/path", 0, 0, 0, 0, 0, "pool"));
1373 EXPECT_EQ(-ENOTCONN
, ceph_close(cmount
, 0));
1374 EXPECT_EQ(-ENOTCONN
, ceph_lseek(cmount
, 0, 0, SEEK_SET
));
1375 EXPECT_EQ(-ENOTCONN
, ceph_read(cmount
, 0, NULL
, 0, 0));
1376 EXPECT_EQ(-ENOTCONN
, ceph_write(cmount
, 0, NULL
, 0, 0));
1377 EXPECT_EQ(-ENOTCONN
, ceph_ftruncate(cmount
, 0, 0));
1378 EXPECT_EQ(-ENOTCONN
, ceph_fsync(cmount
, 0, 0));
1379 EXPECT_EQ(-ENOTCONN
, ceph_fstatx(cmount
, 0, &stx
, 0, 0));
1380 EXPECT_EQ(-ENOTCONN
, ceph_sync_fs(cmount
));
1381 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_unit(cmount
, 0));
1382 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_count(cmount
, 0));
1383 EXPECT_EQ(-ENOTCONN
, ceph_get_file_layout(cmount
, 0, NULL
, NULL
,NULL
,NULL
));
1384 EXPECT_EQ(-ENOTCONN
, ceph_get_file_object_size(cmount
, 0));
1385 EXPECT_EQ(-ENOTCONN
, ceph_get_file_pool(cmount
, 0));
1386 EXPECT_EQ(-ENOTCONN
, ceph_get_file_pool_name(cmount
, 0, NULL
, 0));
1387 EXPECT_EQ(-ENOTCONN
, ceph_get_file_replication(cmount
, 0));
1388 EXPECT_EQ(-ENOTCONN
, ceph_get_path_replication(cmount
, "/path"));
1389 EXPECT_EQ(-ENOTCONN
, ceph_get_path_layout(cmount
, "/path", NULL
, NULL
, NULL
, NULL
));
1390 EXPECT_EQ(-ENOTCONN
, ceph_get_path_object_size(cmount
, "/path"));
1391 EXPECT_EQ(-ENOTCONN
, ceph_get_path_stripe_count(cmount
, "/path"));
1392 EXPECT_EQ(-ENOTCONN
, ceph_get_path_stripe_unit(cmount
, "/path"));
1393 EXPECT_EQ(-ENOTCONN
, ceph_get_path_pool(cmount
, "/path"));
1394 EXPECT_EQ(-ENOTCONN
, ceph_get_path_pool_name(cmount
, "/path", NULL
, 0));
1395 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_name(cmount
, 0, NULL
, 0));
1396 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_address(cmount
, 0, 0, NULL
, 0));
1397 EXPECT_EQ(-ENOTCONN
, ceph_localize_reads(cmount
, 0));
1398 EXPECT_EQ(-ENOTCONN
, ceph_debug_get_fd_caps(cmount
, 0));
1399 EXPECT_EQ(-ENOTCONN
, ceph_debug_get_file_caps(cmount
, "/path"));
1400 EXPECT_EQ(-ENOTCONN
, ceph_get_stripe_unit_granularity(cmount
));
1401 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_id(cmount
, "data"));
1402 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_replication(cmount
, 1));
1404 ceph_release(cmount
);
1407 TEST(LibCephFS
, GetPoolId
) {
1408 struct ceph_mount_info
*cmount
;
1409 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1410 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1411 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1412 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1415 memset(name
, 0, sizeof(name
));
1416 ASSERT_LE(0, ceph_get_path_pool_name(cmount
, "/", name
, sizeof(name
)));
1417 ASSERT_GE(ceph_get_pool_id(cmount
, name
), 0);
1418 ASSERT_EQ(ceph_get_pool_id(cmount
, "weflkjwelfjwlkejf"), -ENOENT
);
1420 ceph_shutdown(cmount
);
1423 TEST(LibCephFS
, GetPoolReplication
) {
1424 struct ceph_mount_info
*cmount
;
1425 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1426 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1427 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1428 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1430 /* negative pools */
1431 ASSERT_EQ(ceph_get_pool_replication(cmount
, -10), -ENOENT
);
1435 int stripe_unit
, stripe_count
, object_size
;
1436 ASSERT_EQ(0, ceph_get_path_layout(cmount
, "/", &stripe_unit
, &stripe_count
,
1437 &object_size
, &pool_id
));
1438 ASSERT_GE(pool_id
, 0);
1439 ASSERT_GT(ceph_get_pool_replication(cmount
, pool_id
), 0);
1441 ceph_shutdown(cmount
);
1444 TEST(LibCephFS
, GetExtentOsds
) {
1445 struct ceph_mount_info
*cmount
;
1446 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1448 EXPECT_EQ(-ENOTCONN
, ceph_get_file_extent_osds(cmount
, 0, 0, NULL
, NULL
, 0));
1450 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1451 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1452 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1454 int stripe_unit
= (1<<18);
1457 char test_file
[256];
1458 sprintf(test_file
, "test_extent_osds_%d", getpid());
1459 int fd
= ceph_open_layout(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666,
1460 stripe_unit
, 2, stripe_unit
*2, NULL
);
1463 /* get back how many osds > 0 */
1464 int ret
= ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, NULL
, 0);
1470 /* full stripe extent */
1471 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 0, &len
, osds
, ret
));
1472 EXPECT_EQ(len
, (int64_t)stripe_unit
);
1474 /* half stripe extent */
1475 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, stripe_unit
/2, &len
, osds
, ret
));
1476 EXPECT_EQ(len
, (int64_t)stripe_unit
/2);
1478 /* 1.5 stripe unit offset -1 byte */
1479 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 3*stripe_unit
/2-1, &len
, osds
, ret
));
1480 EXPECT_EQ(len
, (int64_t)stripe_unit
/2+1);
1482 /* 1.5 stripe unit offset +1 byte */
1483 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 3*stripe_unit
/2+1, &len
, osds
, ret
));
1484 EXPECT_EQ(len
, (int64_t)stripe_unit
/2-1);
1486 /* only when more than 1 osd */
1488 EXPECT_EQ(-ERANGE
, ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, osds
, 1));
1491 ceph_close(cmount
, fd
);
1493 ceph_shutdown(cmount
);
1496 TEST(LibCephFS
, GetOsdCrushLocation
) {
1497 struct ceph_mount_info
*cmount
;
1498 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1500 EXPECT_EQ(-ENOTCONN
, ceph_get_osd_crush_location(cmount
, 0, NULL
, 0));
1502 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1503 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1504 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1506 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 0, NULL
, 1), -EINVAL
);
1509 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 9999999, path
, 0), -ENOENT
);
1510 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, -1, path
, 0), -EINVAL
);
1512 char test_file
[256];
1513 sprintf(test_file
, "test_osds_loc_%d", getpid());
1514 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
1517 /* get back how many osds > 0 */
1518 int ret
= ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, NULL
, 0);
1521 /* full stripe extent */
1523 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, osds
, ret
));
1525 ASSERT_GT(ceph_get_osd_crush_location(cmount
, 0, path
, 0), 0);
1526 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 0, path
, 1), -ERANGE
);
1528 for (int i
= 0; i
< ret
; i
++) {
1529 int len
= ceph_get_osd_crush_location(cmount
, osds
[i
], path
, sizeof(path
));
1533 std::string
type(path
+ pos
);
1534 ASSERT_GT((int)type
.size(), 0);
1535 pos
+= type
.size() + 1;
1537 std::string
name(path
+ pos
);
1538 ASSERT_GT((int)name
.size(), 0);
1539 pos
+= name
.size() + 1;
1543 ceph_close(cmount
, fd
);
1544 ceph_shutdown(cmount
);
1547 TEST(LibCephFS
, GetOsdAddr
) {
1548 struct ceph_mount_info
*cmount
;
1549 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1551 EXPECT_EQ(-ENOTCONN
, ceph_get_osd_addr(cmount
, 0, NULL
));
1553 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1554 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1555 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1557 ASSERT_EQ(-EINVAL
, ceph_get_osd_addr(cmount
, 0, NULL
));
1559 struct sockaddr_storage addr
;
1560 ASSERT_EQ(-ENOENT
, ceph_get_osd_addr(cmount
, -1, &addr
));
1561 ASSERT_EQ(-ENOENT
, ceph_get_osd_addr(cmount
, 9999999, &addr
));
1563 ASSERT_EQ(0, ceph_get_osd_addr(cmount
, 0, &addr
));
1565 ceph_shutdown(cmount
);
1568 TEST(LibCephFS
, OpenNoClose
) {
1569 struct ceph_mount_info
*cmount
;
1570 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1571 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1572 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1573 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1575 pid_t mypid
= getpid();
1577 sprintf(str_buf
, "open_no_close_dir%d", mypid
);
1578 ASSERT_EQ(0, ceph_mkdirs(cmount
, str_buf
, 0777));
1580 struct ceph_dir_result
*ls_dir
= NULL
;
1581 ASSERT_EQ(ceph_opendir(cmount
, str_buf
, &ls_dir
), 0);
1583 sprintf(str_buf
, "open_no_close_file%d", mypid
);
1584 int fd
= ceph_open(cmount
, str_buf
, O_RDONLY
|O_CREAT
, 0666);
1587 // shutdown should force close opened file/dir
1588 ceph_shutdown(cmount
);
1591 TEST(LibCephFS
, Nlink
) {
1592 struct ceph_mount_info
*cmount
;
1593 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1594 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1595 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1596 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1598 Inode
*root
, *dir
, *file
;
1600 ASSERT_EQ(ceph_ll_lookup_root(cmount
, &root
), 0);
1602 char dirname
[32], filename
[32], linkname
[32];
1603 sprintf(dirname
, "nlinkdir%x", getpid());
1604 sprintf(filename
, "nlinkorig%x", getpid());
1605 sprintf(linkname
, "nlinklink%x", getpid());
1607 struct ceph_statx stx
;
1609 UserPerm
*perms
= ceph_mount_perms(cmount
);
1611 ASSERT_EQ(ceph_ll_mkdir(cmount
, root
, dirname
, 0755, &dir
, &stx
, 0, 0, perms
), 0);
1612 ASSERT_EQ(ceph_ll_create(cmount
, dir
, filename
, 0666, O_RDWR
|O_CREAT
|O_EXCL
,
1613 &file
, &fh
, &stx
, CEPH_STATX_NLINK
, 0, perms
), 0);
1614 ASSERT_EQ(ceph_ll_close(cmount
, fh
), 0);
1615 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)1);
1617 ASSERT_EQ(ceph_ll_link(cmount
, file
, dir
, linkname
, perms
), 0);
1618 ASSERT_EQ(ceph_ll_getattr(cmount
, file
, &stx
, CEPH_STATX_NLINK
, 0, perms
), 0);
1619 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)2);
1621 ASSERT_EQ(ceph_ll_unlink(cmount
, dir
, linkname
, perms
), 0);
1622 ASSERT_EQ(ceph_ll_lookup(cmount
, dir
, filename
, &file
, &stx
,
1623 CEPH_STATX_NLINK
, 0, perms
), 0);
1624 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)1);
1626 ceph_shutdown(cmount
);
1629 TEST(LibCephFS
, SlashDotDot
) {
1630 struct ceph_mount_info
*cmount
;
1631 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1632 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1633 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1634 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1636 struct ceph_statx stx
;
1637 ASSERT_EQ(ceph_statx(cmount
, "/.", &stx
, CEPH_STATX_INO
, 0), 0);
1639 ino_t ino
= stx
.stx_ino
;
1640 ASSERT_EQ(ceph_statx(cmount
, "/..", &stx
, CEPH_STATX_INO
, 0), 0);
1642 /* At root, "." and ".." should be the same inode */
1643 ASSERT_EQ(ino
, stx
.stx_ino
);
1645 /* Test accessing the parent of an unlinked directory */
1646 char dir1
[32], dir2
[56];
1647 sprintf(dir1
, "/sldotdot%x", getpid());
1648 sprintf(dir2
, "%s/sub%x", dir1
, getpid());
1650 ASSERT_EQ(ceph_mkdir(cmount
, dir1
, 0755), 0);
1651 ASSERT_EQ(ceph_mkdir(cmount
, dir2
, 0755), 0);
1653 ASSERT_EQ(ceph_chdir(cmount
, dir2
), 0);
1655 /* Test behavior when unlinking cwd */
1656 struct ceph_dir_result
*rdir
;
1657 ASSERT_EQ(ceph_opendir(cmount
, ".", &rdir
), 0);
1658 ASSERT_EQ(ceph_rmdir(cmount
, dir2
), 0);
1661 struct dirent
*result
= ceph_readdir(cmount
, rdir
);
1662 ino
= result
->d_ino
;
1664 /* get ".." entry */
1665 result
= ceph_readdir(cmount
, rdir
);
1666 ASSERT_EQ(ino
, result
->d_ino
);
1667 ceph_closedir(cmount
, rdir
);
1669 /* Make sure it works same way when mounting subtree */
1670 ASSERT_EQ(ceph_unmount(cmount
), 0);
1671 ASSERT_EQ(ceph_mount(cmount
, dir1
), 0);
1672 ASSERT_EQ(ceph_statx(cmount
, "/..", &stx
, CEPH_STATX_INO
, 0), 0);
1674 /* Test readdir behavior */
1675 ASSERT_EQ(ceph_opendir(cmount
, "/", &rdir
), 0);
1676 result
= ceph_readdir(cmount
, rdir
);
1677 ASSERT_TRUE(result
!= NULL
);
1678 ASSERT_STREQ(result
->d_name
, ".");
1679 ino
= result
->d_ino
;
1680 result
= ceph_readdir(cmount
, rdir
);
1681 ASSERT_TRUE(result
!= NULL
);
1682 ASSERT_STREQ(result
->d_name
, "..");
1683 ASSERT_EQ(ino
, result
->d_ino
);
1685 ceph_shutdown(cmount
);
1689 timespec_eq(timespec
const& lhs
, timespec
const& rhs
)
1691 return lhs
.tv_sec
== rhs
.tv_sec
&& lhs
.tv_nsec
== rhs
.tv_nsec
;
1694 TEST(LibCephFS
, Btime
) {
1695 struct ceph_mount_info
*cmount
;
1696 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1697 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1698 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1699 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1702 sprintf(filename
, "/getattrx%x", getpid());
1704 ceph_unlink(cmount
, filename
);
1705 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1708 /* make sure fstatx works */
1709 struct ceph_statx stx
;
1711 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1712 ASSERT_TRUE(stx
.stx_mask
& (CEPH_STATX_CTIME
|CEPH_STATX_BTIME
));
1713 ASSERT_TRUE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1714 ceph_close(cmount
, fd
);
1716 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1717 ASSERT_TRUE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1718 ASSERT_TRUE(stx
.stx_mask
& (CEPH_STATX_CTIME
|CEPH_STATX_BTIME
));
1720 struct timespec old_btime
= stx
.stx_btime
;
1722 /* Now sleep, do a chmod and verify that the ctime changed, but btime didn't */
1724 ASSERT_EQ(ceph_chmod(cmount
, filename
, 0644), 0);
1725 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1726 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_BTIME
);
1727 ASSERT_TRUE(timespec_eq(stx
.stx_btime
, old_btime
));
1728 ASSERT_FALSE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1730 ceph_shutdown(cmount
);
1733 TEST(LibCephFS
, SetBtime
) {
1734 struct ceph_mount_info
*cmount
;
1735 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1736 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1737 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1738 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1741 sprintf(filename
, "/setbtime%x", getpid());
1743 ceph_unlink(cmount
, filename
);
1744 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1746 ceph_close(cmount
, fd
);
1748 struct ceph_statx stx
;
1749 struct timespec old_btime
= { 1, 2 };
1751 stx
.stx_btime
= old_btime
;
1753 ASSERT_EQ(ceph_setattrx(cmount
, filename
, &stx
, CEPH_SETATTR_BTIME
, 0), 0);
1755 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_BTIME
, 0), 0);
1756 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_BTIME
);
1757 ASSERT_TRUE(timespec_eq(stx
.stx_btime
, old_btime
));
1759 ceph_shutdown(cmount
);
1762 TEST(LibCephFS
, LazyStatx
) {
1763 struct ceph_mount_info
*cmount1
, *cmount2
;
1764 ASSERT_EQ(ceph_create(&cmount1
, NULL
), 0);
1765 ASSERT_EQ(ceph_create(&cmount2
, NULL
), 0);
1766 ASSERT_EQ(ceph_conf_read_file(cmount1
, NULL
), 0);
1767 ASSERT_EQ(ceph_conf_read_file(cmount2
, NULL
), 0);
1768 ASSERT_EQ(0, ceph_conf_parse_env(cmount1
, NULL
));
1769 ASSERT_EQ(0, ceph_conf_parse_env(cmount2
, NULL
));
1770 ASSERT_EQ(ceph_mount(cmount1
, "/"), 0);
1771 ASSERT_EQ(ceph_mount(cmount2
, "/"), 0);
1774 sprintf(filename
, "lazystatx%x", getpid());
1776 Inode
*root1
, *file1
, *root2
, *file2
;
1777 struct ceph_statx stx
;
1779 UserPerm
*perms1
= ceph_mount_perms(cmount1
);
1780 UserPerm
*perms2
= ceph_mount_perms(cmount2
);
1782 ASSERT_EQ(ceph_ll_lookup_root(cmount1
, &root1
), 0);
1783 ceph_ll_unlink(cmount1
, root1
, filename
, perms1
);
1784 ASSERT_EQ(ceph_ll_create(cmount1
, root1
, filename
, 0666, O_RDWR
|O_CREAT
|O_EXCL
,
1785 &file1
, &fh
, &stx
, 0, 0, perms1
), 0);
1786 ASSERT_EQ(ceph_ll_close(cmount1
, fh
), 0);
1788 ASSERT_EQ(ceph_ll_lookup_root(cmount2
, &root2
), 0);
1790 ASSERT_EQ(ceph_ll_lookup(cmount2
, root2
, filename
, &file2
, &stx
, CEPH_STATX_CTIME
, 0, perms2
), 0);
1792 struct timespec old_ctime
= stx
.stx_ctime
;
1795 * Now sleep, do a chmod on the first client and the see whether we get a
1796 * different ctime with a statx that uses AT_NO_ATTR_SYNC
1799 stx
.stx_mode
= 0644;
1800 ASSERT_EQ(ceph_ll_setattr(cmount1
, file1
, &stx
, CEPH_SETATTR_MODE
, perms1
), 0);
1802 ASSERT_EQ(ceph_ll_getattr(cmount2
, file2
, &stx
, CEPH_STATX_CTIME
, AT_NO_ATTR_SYNC
, perms2
), 0);
1803 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_CTIME
);
1804 ASSERT_TRUE(stx
.stx_ctime
.tv_sec
== old_ctime
.tv_sec
&&
1805 stx
.stx_ctime
.tv_nsec
== old_ctime
.tv_nsec
);
1807 ceph_shutdown(cmount1
);
1808 ceph_shutdown(cmount2
);
1811 TEST(LibCephFS
, ChangeAttr
) {
1812 struct ceph_mount_info
*cmount
;
1813 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1814 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1815 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1816 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1819 sprintf(filename
, "/changeattr%x", getpid());
1821 ceph_unlink(cmount
, filename
);
1822 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1825 struct ceph_statx stx
;
1826 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1827 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1829 uint64_t old_change_attr
= stx
.stx_version
;
1831 /* do chmod, and check whether change_attr changed */
1832 ASSERT_EQ(ceph_chmod(cmount
, filename
, 0644), 0);
1833 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1834 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1835 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1836 old_change_attr
= stx
.stx_version
;
1838 /* now do a write and see if it changed again */
1839 ASSERT_EQ(3, ceph_write(cmount
, fd
, "foo", 3, 0));
1840 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1841 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1842 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1843 old_change_attr
= stx
.stx_version
;
1845 /* Now truncate and check again */
1846 ASSERT_EQ(0, ceph_ftruncate(cmount
, fd
, 0));
1847 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1848 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1849 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1851 ceph_close(cmount
, fd
);
1852 ceph_shutdown(cmount
);
1855 TEST(LibCephFS
, DirChangeAttr
) {
1856 struct ceph_mount_info
*cmount
;
1857 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1858 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1859 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1860 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1862 char dirname
[32], filename
[56];
1863 sprintf(dirname
, "/dirchange%x", getpid());
1864 sprintf(filename
, "%s/foo", dirname
);
1866 ASSERT_EQ(ceph_mkdir(cmount
, dirname
, 0755), 0);
1868 struct ceph_statx stx
;
1869 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1870 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1872 uint64_t old_change_attr
= stx
.stx_version
;
1874 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1876 ceph_close(cmount
, fd
);
1878 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1879 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1880 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1882 old_change_attr
= stx
.stx_version
;
1884 ASSERT_EQ(ceph_unlink(cmount
, filename
), 0);
1885 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1886 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1887 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1889 ceph_shutdown(cmount
);
1892 TEST(LibCephFS
, SetSize
) {
1893 struct ceph_mount_info
*cmount
;
1894 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1895 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1896 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1897 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1900 sprintf(filename
, "/setsize%x", getpid());
1902 ceph_unlink(cmount
, filename
);
1903 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1906 struct ceph_statx stx
;
1907 uint64_t size
= 8388608;
1908 stx
.stx_size
= size
;
1909 ASSERT_EQ(ceph_fsetattrx(cmount
, fd
, &stx
, CEPH_SETATTR_SIZE
), 0);
1910 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_SIZE
, 0), 0);
1911 ASSERT_EQ(stx
.stx_size
, size
);
1913 ceph_close(cmount
, fd
);
1914 ceph_shutdown(cmount
);
1917 TEST(LibCephFS
, ClearSetuid
) {
1918 struct ceph_mount_info
*cmount
;
1919 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1920 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1921 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1922 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1925 ASSERT_EQ(ceph_ll_lookup_root(cmount
, &root
), 0);
1928 sprintf(filename
, "clearsetuid%x", getpid());
1932 struct ceph_statx stx
;
1933 const mode_t after_mode
= S_IRWXU
;
1934 const mode_t before_mode
= S_IRWXU
| S_ISUID
| S_ISGID
;
1935 const unsigned want
= CEPH_STATX_UID
|CEPH_STATX_GID
|CEPH_STATX_MODE
;
1936 UserPerm
*usercred
= ceph_mount_perms(cmount
);
1938 ceph_ll_unlink(cmount
, root
, filename
, usercred
);
1939 ASSERT_EQ(ceph_ll_create(cmount
, root
, filename
, before_mode
,
1940 O_RDWR
|O_CREAT
|O_EXCL
, &in
, &fh
, &stx
, want
, 0,
1943 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1946 ASSERT_EQ(ceph_ll_write(cmount
, fh
, 0, 3, "foo"), 3);
1947 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1948 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1949 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1952 stx
.stx_mode
= before_mode
;
1953 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, usercred
), 0);
1954 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1955 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1956 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1960 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_SIZE
, usercred
), 0);
1961 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1962 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1963 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1966 stx
.stx_mode
= before_mode
;
1967 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, usercred
), 0);
1968 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1969 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1970 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1972 // chown -- for this we need to be "root"
1973 UserPerm
*rootcred
= ceph_userperm_new(0, 0, 0, NULL
);
1974 ASSERT_TRUE(rootcred
);
1977 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_UID
|CEPH_SETATTR_GID
, rootcred
), 0);
1978 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1979 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1980 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1982 /* test chown with supplementary groups, and chown with/without exe bit */
1985 gid_t gids
[] = {65533,65532};
1986 UserPerm
*altcred
= ceph_userperm_new(u
, g
, sizeof gids
/ sizeof gids
[0], gids
);
1989 mode_t m
= S_ISGID
|S_ISUID
|S_IRUSR
|S_IWUSR
;
1991 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
|CEPH_SETATTR_UID
|CEPH_SETATTR_GID
, rootcred
), 0);
1992 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1993 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
1994 /* not dropped without exe bit */
1995 stx
.stx_gid
= gids
[0];
1996 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_GID
, altcred
), 0);
1997 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1998 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
1999 /* now check dropped with exe bit */
2000 m
= S_ISGID
|S_ISUID
|S_IRWXU
;
2002 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, altcred
), 0);
2003 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
2004 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
2005 stx
.stx_gid
= gids
[1];
2006 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_GID
, altcred
), 0);
2007 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
2008 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
&(S_IRWXU
|S_IRWXG
|S_IRWXO
));
2009 ceph_userperm_destroy(altcred
);
2011 ASSERT_EQ(ceph_ll_close(cmount
, fh
), 0);
2012 ceph_shutdown(cmount
);
2015 TEST(LibCephFS
, OperationsOnRoot
)
2017 struct ceph_mount_info
*cmount
;
2018 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2019 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2020 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2021 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
2024 sprintf(dirname
, "/somedir%x", getpid());
2026 ASSERT_EQ(ceph_mkdir(cmount
, dirname
, 0755), 0);
2028 ASSERT_EQ(ceph_rmdir(cmount
, "/"), -EBUSY
);
2030 ASSERT_EQ(ceph_link(cmount
, "/", "/"), -EEXIST
);
2031 ASSERT_EQ(ceph_link(cmount
, dirname
, "/"), -EEXIST
);
2032 ASSERT_EQ(ceph_link(cmount
, "nonExisitingDir", "/"), -ENOENT
);
2034 ASSERT_EQ(ceph_unlink(cmount
, "/"), -EISDIR
);
2036 ASSERT_EQ(ceph_rename(cmount
, "/", "/"), -EBUSY
);
2037 ASSERT_EQ(ceph_rename(cmount
, dirname
, "/"), -EBUSY
);
2038 ASSERT_EQ(ceph_rename(cmount
, "nonExistingDir", "/"), -EBUSY
);
2039 ASSERT_EQ(ceph_rename(cmount
, "/", dirname
), -EBUSY
);
2040 ASSERT_EQ(ceph_rename(cmount
, "/", "nonExistingDir"), -EBUSY
);
2042 ASSERT_EQ(ceph_mkdir(cmount
, "/", 0777), -EEXIST
);
2044 ASSERT_EQ(ceph_mknod(cmount
, "/", 0, 0), -EEXIST
);
2046 ASSERT_EQ(ceph_symlink(cmount
, "/", "/"), -EEXIST
);
2047 ASSERT_EQ(ceph_symlink(cmount
, dirname
, "/"), -EEXIST
);
2048 ASSERT_EQ(ceph_symlink(cmount
, "nonExistingDir", "/"), -EEXIST
);
2050 ceph_shutdown(cmount
);
2053 static void shutdown_racer_func()
2055 const int niter
= 32;
2056 struct ceph_mount_info
*cmount
;
2059 for (i
= 0; i
< niter
; ++i
) {
2060 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2061 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2062 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2063 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
2064 ceph_shutdown(cmount
);
2068 // See tracker #20988
2069 TEST(LibCephFS
, ShutdownRace
)
2071 const int nthreads
= 32;
2072 std::thread threads
[nthreads
];
2074 // Need a bunch of fd's for this test
2075 struct rlimit rold
, rnew
;
2076 ASSERT_EQ(getrlimit(RLIMIT_NOFILE
, &rold
), 0);
2078 rnew
.rlim_cur
= rnew
.rlim_max
;
2079 ASSERT_EQ(setrlimit(RLIMIT_NOFILE
, &rnew
), 0);
2081 for (int i
= 0; i
< nthreads
; ++i
)
2082 threads
[i
] = std::thread(shutdown_racer_func
);
2084 for (int i
= 0; i
< nthreads
; ++i
)
2087 * Let's just ignore restoring the open files limit,
2088 * the kernel will defer releasing the file descriptors
2089 * and then the process will be possibly reachthe open
2090 * files limit. More detail, please see tracer#43039
2092 // ASSERT_EQ(setrlimit(RLIMIT_NOFILE, &rold), 0);
2095 static void get_current_time_utimbuf(struct utimbuf
*utb
)
2097 utime_t t
= ceph_clock_now();
2098 utb
->actime
= t
.sec();
2099 utb
->modtime
= t
.sec();
2102 static void get_current_time_timeval(struct timeval tv
[2])
2104 utime_t t
= ceph_clock_now();
2105 t
.copy_to_timeval(&tv
[0]);
2106 t
.copy_to_timeval(&tv
[1]);
2109 static void get_current_time_timespec(struct timespec ts
[2])
2111 utime_t t
= ceph_clock_now();
2112 t
.to_timespec(&ts
[0]);
2113 t
.to_timespec(&ts
[1]);
2116 TEST(LibCephFS
, TestUtime
) {
2117 struct ceph_mount_info
*cmount
;
2118 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2119 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2120 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2121 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2123 char test_file
[256];
2124 sprintf(test_file
, "test_utime_file_%d", getpid());
2125 int fd
= ceph_open(cmount
, test_file
, O_CREAT
, 0666);
2129 struct ceph_statx stx
;
2131 get_current_time_utimbuf(&utb
);
2134 EXPECT_EQ(0, ceph_utime(cmount
, test_file
, &utb
));
2135 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
,
2136 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2137 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(utb
.actime
, 0));
2138 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(utb
.modtime
, 0));
2140 get_current_time_utimbuf(&utb
);
2143 EXPECT_EQ(0, ceph_futime(cmount
, fd
, &utb
));
2144 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
,
2145 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2146 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(utb
.actime
, 0));
2147 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(utb
.modtime
, 0));
2149 ceph_close(cmount
, fd
);
2150 ceph_shutdown(cmount
);
2153 TEST(LibCephFS
, TestUtimes
) {
2154 struct ceph_mount_info
*cmount
;
2155 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2156 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2157 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2158 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2160 char test_file
[256];
2161 char test_symlink
[256];
2163 sprintf(test_file
, "test_utimes_file_%d", getpid());
2164 sprintf(test_symlink
, "test_utimes_symlink_%d", getpid());
2165 int fd
= ceph_open(cmount
, test_file
, O_CREAT
, 0666);
2168 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
2170 struct timeval times
[2];
2171 struct ceph_statx stx
;
2173 get_current_time_timeval(times
);
2175 // ceph_utimes() on symlink, validate target file time
2176 EXPECT_EQ(0, ceph_utimes(cmount
, test_symlink
, times
));
2177 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx
,
2178 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2179 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(times
[0]));
2180 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(times
[1]));
2182 get_current_time_timeval(times
);
2184 // ceph_lutimes() on symlink, validate symlink time
2185 EXPECT_EQ(0, ceph_lutimes(cmount
, test_symlink
, times
));
2186 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx
,
2187 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, AT_SYMLINK_NOFOLLOW
), 0);
2188 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(times
[0]));
2189 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(times
[1]));
2191 get_current_time_timeval(times
);
2194 EXPECT_EQ(0, ceph_futimes(cmount
, fd
, times
));
2195 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
,
2196 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2197 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(times
[0]));
2198 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(times
[1]));
2200 ceph_close(cmount
, fd
);
2201 ceph_shutdown(cmount
);
2204 TEST(LibCephFS
, TestFutimens
) {
2205 struct ceph_mount_info
*cmount
;
2206 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2207 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2208 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2209 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2211 char test_file
[256];
2213 sprintf(test_file
, "test_futimens_file_%d", getpid());
2214 int fd
= ceph_open(cmount
, test_file
, O_CREAT
, 0666);
2217 struct timespec times
[2];
2218 struct ceph_statx stx
;
2220 get_current_time_timespec(times
);
2223 EXPECT_EQ(0, ceph_futimens(cmount
, fd
, times
));
2224 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
,
2225 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2226 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(times
[0]));
2227 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(times
[1]));
2229 ceph_close(cmount
, fd
);
2230 ceph_shutdown(cmount
);
2233 TEST(LibCephFS
, OperationsOnDotDot
) {
2234 struct ceph_mount_info
*cmount
;
2235 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2236 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2237 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2238 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2240 char c_dir
[512], c_dir_dot
[1024], c_dir_dotdot
[1024];
2241 char c_non_existent_dir
[1024], c_non_existent_dirs
[1024];
2244 pid_t mypid
= getpid();
2245 sprintf(c_dir
, "/oodd_dir_%d", mypid
);
2246 sprintf(c_dir_dot
, "/%s/.", c_dir
);
2247 sprintf(c_dir_dotdot
, "/%s/..", c_dir
);
2248 sprintf(c_non_existent_dir
, "/%s/../oodd_nonexistent/..", c_dir
);
2249 sprintf(c_non_existent_dirs
,
2250 "/%s/../ood_nonexistent1_%d/oodd_nonexistent2_%d", c_dir
, mypid
, mypid
);
2251 sprintf(c_temp
, "/oodd_temp_%d", mypid
);
2253 ASSERT_EQ(0, ceph_mkdir(cmount
, c_dir
, 0777));
2254 ASSERT_EQ(-EEXIST
, ceph_mkdir(cmount
, c_dir_dot
, 0777));
2255 ASSERT_EQ(-EEXIST
, ceph_mkdir(cmount
, c_dir_dotdot
, 0777));
2256 ASSERT_EQ(0, ceph_mkdirs(cmount
, c_non_existent_dirs
, 0777));
2258 ASSERT_EQ(-ENOTEMPTY
, ceph_rmdir(cmount
, c_dir_dot
));
2259 ASSERT_EQ(-ENOTEMPTY
, ceph_rmdir(cmount
, c_dir_dotdot
));
2260 // non existent directory should return -ENOENT
2261 ASSERT_EQ(-ENOENT
, ceph_rmdir(cmount
, c_non_existent_dir
));
2263 ASSERT_EQ(-EBUSY
, ceph_rename(cmount
, c_dir_dot
, c_temp
));
2264 ASSERT_EQ(0, ceph_chdir(cmount
, c_dir
));
2265 ASSERT_EQ(0, ceph_mkdir(cmount
, c_temp
, 0777));
2266 ASSERT_EQ(-EBUSY
, ceph_rename(cmount
, c_temp
, ".."));
2268 ceph_shutdown(cmount
);
2271 TEST(LibCephFS
, SnapXattrs
) {
2272 struct ceph_mount_info
*cmount
;
2273 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2274 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2275 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2276 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2278 char test_snap_xattr_file
[256];
2279 char c_temp
[PATH_MAX
];
2282 int xbuflen
= sizeof(gxattrv
);
2283 pid_t mypid
= getpid();
2285 sprintf(test_snap_xattr_file
, "test_snap_xattr_%d", mypid
);
2286 int fd
= ceph_open(cmount
, test_snap_xattr_file
, O_CREAT
, 0666);
2288 ceph_close(cmount
, fd
);
2290 sprintf(c_temp
, "/.snap/test_snap_xattr_snap_%d", mypid
);
2291 ASSERT_EQ(0, ceph_mkdir(cmount
, c_temp
, 0777));
2293 int alen
= ceph_getxattr(cmount
, c_temp
, "ceph.snap.btime", (void *)gxattrv
, xbuflen
);
2294 // xattr value is secs.nsecs (don't assume zero-term)
2296 ASSERT_LT(alen
, xbuflen
);
2297 gxattrv
[alen
] = '\0';
2298 char *s
= strchrnul(gxattrv
, '.');
2299 ASSERT_LT(s
, gxattrv
+ alen
);
2302 utime_t btime
= utime_t(strtoull(gxattrv
, NULL
, 10), strtoull(s
+ 1, NULL
, 10));
2303 *s
= '.'; // restore for later strcmp
2305 // file within the snapshot should carry the same btime
2306 sprintf(c_temp
, "/.snap/test_snap_xattr_snap_%d/%s", mypid
, test_snap_xattr_file
);
2308 int alen2
= ceph_getxattr(cmount
, c_temp
, "ceph.snap.btime", (void *)gxattrv2
, xbuflen
);
2309 ASSERT_EQ(alen
, alen2
);
2310 ASSERT_EQ(0, strncmp(gxattrv
, gxattrv2
, alen
));
2312 // non-snap file shouldn't carry the xattr
2313 alen
= ceph_getxattr(cmount
, test_snap_xattr_file
, "ceph.snap.btime", (void *)gxattrv2
, xbuflen
);
2314 ASSERT_EQ(-ENODATA
, alen
);
2316 // create a second snapshot
2317 sprintf(c_temp
, "/.snap/test_snap_xattr_snap2_%d", mypid
);
2318 ASSERT_EQ(0, ceph_mkdir(cmount
, c_temp
, 0777));
2320 // check that the btime for the newer snapshot is > older
2321 alen
= ceph_getxattr(cmount
, c_temp
, "ceph.snap.btime", (void *)gxattrv2
, xbuflen
);
2323 ASSERT_LT(alen
, xbuflen
);
2324 gxattrv2
[alen
] = '\0';
2325 s
= strchrnul(gxattrv2
, '.');
2326 ASSERT_LT(s
, gxattrv2
+ alen
);
2329 utime_t new_btime
= utime_t(strtoull(gxattrv2
, NULL
, 10), strtoull(s
+ 1, NULL
, 10));
2330 ASSERT_LT(btime
, new_btime
);
2332 // listxattr() shouldn't return snap.btime vxattr
2333 char xattrlist
[512];
2334 int len
= ceph_listxattr(cmount
, test_snap_xattr_file
, xattrlist
, sizeof(xattrlist
));
2335 ASSERT_GE(sizeof(xattrlist
), (size_t)len
);
2336 char *p
= xattrlist
;
2339 if (strcmp(p
, "ceph.snap.btime") == 0)
2341 len
-= strlen(p
) + 1;
2344 ASSERT_EQ(found
, 0);
2346 ceph_shutdown(cmount
);
2349 TEST(LibCephFS
, SnapQuota
) {
2350 struct ceph_mount_info
*cmount
;
2351 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2352 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2353 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2354 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2356 char test_snap_dir_quota_xattr
[256];
2357 char test_snap_subdir_quota_xattr
[256];
2358 char test_snap_subdir_noquota_xattr
[256];
2361 char c_temp
[PATH_MAX
];
2363 int xbuflen
= sizeof(gxattrv
);
2364 pid_t mypid
= getpid();
2366 // create dir and set quota
2367 sprintf(test_snap_dir_quota_xattr
, "test_snap_dir_quota_xattr_%d", mypid
);
2368 ASSERT_EQ(0, ceph_mkdir(cmount
, test_snap_dir_quota_xattr
, 0777));
2370 sprintf(xattrk
, "ceph.quota.max_bytes");
2371 sprintf(xattrv
, "65536");
2372 ASSERT_EQ(0, ceph_setxattr(cmount
, test_snap_dir_quota_xattr
, xattrk
, (void *)xattrv
, 5, XATTR_CREATE
));
2374 // create subdir and set quota
2375 sprintf(test_snap_subdir_quota_xattr
, "test_snap_dir_quota_xattr_%d/subdir_quota", mypid
);
2376 ASSERT_EQ(0, ceph_mkdirs(cmount
, test_snap_subdir_quota_xattr
, 0777));
2378 sprintf(xattrk
, "ceph.quota.max_bytes");
2379 sprintf(xattrv
, "32768");
2380 ASSERT_EQ(0, ceph_setxattr(cmount
, test_snap_subdir_quota_xattr
, xattrk
, (void *)xattrv
, 5, XATTR_CREATE
));
2382 // create subdir with no quota
2383 sprintf(test_snap_subdir_noquota_xattr
, "test_snap_dir_quota_xattr_%d/subdir_noquota", mypid
);
2384 ASSERT_EQ(0, ceph_mkdirs(cmount
, test_snap_subdir_noquota_xattr
, 0777));
2387 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d", mypid
);
2388 ASSERT_EQ(0, ceph_mkdirs(cmount
, c_temp
, 0777));
2390 // check dir quota under snap
2391 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d", mypid
, mypid
);
2392 int alen
= ceph_getxattr(cmount
, c_temp
, "ceph.quota.max_bytes", (void *)gxattrv
, xbuflen
);
2394 ASSERT_LT(alen
, xbuflen
);
2395 gxattrv
[alen
] = '\0';
2396 ASSERT_STREQ(gxattrv
, "65536");
2398 // check subdir quota under snap
2399 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d/subdir_quota", mypid
, mypid
);
2400 alen
= ceph_getxattr(cmount
, c_temp
, "ceph.quota.max_bytes", (void *)gxattrv
, xbuflen
);
2402 ASSERT_LT(alen
, xbuflen
);
2403 gxattrv
[alen
] = '\0';
2404 ASSERT_STREQ(gxattrv
, "32768");
2406 // ensure subdir noquota xattr under snap
2407 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d/subdir_noquota", mypid
, mypid
);
2408 EXPECT_EQ(-ENODATA
, ceph_getxattr(cmount
, c_temp
, "ceph.quota.max_bytes", (void *)gxattrv
, xbuflen
));
2410 // listxattr() shouldn't return ceph.quota.max_bytes vxattr
2411 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d", mypid
, mypid
);
2412 char xattrlist
[512];
2413 int len
= ceph_listxattr(cmount
, c_temp
, xattrlist
, sizeof(xattrlist
));
2414 ASSERT_GE(sizeof(xattrlist
), (size_t)len
);
2415 char *p
= xattrlist
;
2418 if (strcmp(p
, "ceph.quota.max_bytes") == 0)
2420 len
-= strlen(p
) + 1;
2423 ASSERT_EQ(found
, 0);
2425 ceph_shutdown(cmount
);
2428 TEST(LibCephFS
, Lseek
) {
2429 struct ceph_mount_info
*cmount
;
2430 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
2431 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
2432 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2433 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
2436 sprintf(c_path
, "test_lseek_%d", getpid());
2437 int fd
= ceph_open(cmount
, c_path
, O_RDWR
|O_CREAT
|O_TRUNC
, 0666);
2440 const char *out_buf
= "hello world";
2441 size_t size
= strlen(out_buf
);
2442 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), (int)size
);
2444 /* basic SEEK_SET/END/CUR tests */
2445 ASSERT_EQ(0, ceph_lseek(cmount
, fd
, 0, SEEK_SET
));
2446 ASSERT_EQ(size
, ceph_lseek(cmount
, fd
, 0, SEEK_END
));
2447 ASSERT_EQ(0, ceph_lseek(cmount
, fd
, -size
, SEEK_CUR
));
2449 /* Test basic functionality and out of bounds conditions for SEEK_HOLE/DATA */
2451 ASSERT_EQ(size
, ceph_lseek(cmount
, fd
, 0, SEEK_HOLE
));
2452 ASSERT_EQ(-ENXIO
, ceph_lseek(cmount
, fd
, -1, SEEK_HOLE
));
2453 ASSERT_EQ(-ENXIO
, ceph_lseek(cmount
, fd
, size
+ 1, SEEK_HOLE
));
2456 ASSERT_EQ(0, ceph_lseek(cmount
, fd
, 0, SEEK_DATA
));
2457 ASSERT_EQ(-ENXIO
, ceph_lseek(cmount
, fd
, -1, SEEK_DATA
));
2458 ASSERT_EQ(-ENXIO
, ceph_lseek(cmount
, fd
, size
+ 1, SEEK_DATA
));
2461 ASSERT_EQ(0, ceph_close(cmount
, fd
));
2462 ceph_shutdown(cmount
);