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 "gtest/gtest.h"
16 #include "include/cephfs/libcephfs.h"
17 #include "include/stat.h"
21 #include <sys/types.h>
24 #include <sys/xattr.h>
27 #include <sys/resource.h>
37 TEST(LibCephFS
, OpenEmptyComponent
) {
39 pid_t mypid
= getpid();
40 struct ceph_mount_info
*cmount
;
41 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
42 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
43 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
44 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
47 sprintf(c_dir
, "/open_test_%d", mypid
);
48 struct ceph_dir_result
*dirp
;
50 ASSERT_EQ(0, ceph_mkdirs(cmount
, c_dir
, 0777));
52 ASSERT_EQ(0, ceph_opendir(cmount
, c_dir
, &dirp
));
55 sprintf(c_path
, "/open_test_%d//created_file_%d", mypid
, mypid
);
56 int fd
= ceph_open(cmount
, c_path
, O_RDONLY
|O_CREAT
, 0666);
59 ASSERT_EQ(0, ceph_close(cmount
, fd
));
60 ASSERT_EQ(0, ceph_closedir(cmount
, dirp
));
61 ceph_shutdown(cmount
);
63 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
64 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
65 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
67 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
69 fd
= ceph_open(cmount
, c_path
, O_RDONLY
, 0666);
72 ASSERT_EQ(0, ceph_close(cmount
, fd
));
73 ceph_shutdown(cmount
);
76 TEST(LibCephFS
, OpenReadWrite
) {
77 struct ceph_mount_info
*cmount
;
78 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
79 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
80 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
81 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
84 sprintf(c_path
, "test_open_rdwr_%d", getpid());
85 int fd
= ceph_open(cmount
, c_path
, O_WRONLY
|O_CREAT
, 0666);
88 const char *out_buf
= "hello world";
89 size_t size
= strlen(out_buf
);
91 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), (int)size
);
92 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), -EBADF
);
93 ASSERT_EQ(0, ceph_close(cmount
, fd
));
95 fd
= ceph_open(cmount
, c_path
, O_RDONLY
, 0);
97 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), -EBADF
);
98 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), (int)size
);
99 ASSERT_EQ(0, ceph_close(cmount
, fd
));
101 fd
= ceph_open(cmount
, c_path
, O_RDWR
, 0);
103 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), (int)size
);
104 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), (int)size
);
105 ASSERT_EQ(0, ceph_close(cmount
, fd
));
107 ceph_shutdown(cmount
);
110 TEST(LibCephFS
, MountNonExist
) {
112 struct ceph_mount_info
*cmount
;
114 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
115 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
116 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
117 ASSERT_NE(0, ceph_mount(cmount
, "/non-exist"));
118 ceph_shutdown(cmount
);
121 TEST(LibCephFS
, MountDouble
) {
123 struct ceph_mount_info
*cmount
;
125 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
126 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
127 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
128 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
129 ASSERT_EQ(-EISCONN
, ceph_mount(cmount
, "/"));
130 ceph_shutdown(cmount
);
133 TEST(LibCephFS
, MountRemount
) {
135 struct ceph_mount_info
*cmount
;
137 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
138 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
139 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
141 CephContext
*cct
= ceph_get_mount_context(cmount
);
142 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
143 ASSERT_EQ(0, ceph_unmount(cmount
));
145 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
146 ASSERT_EQ(cct
, ceph_get_mount_context(cmount
));
148 ceph_shutdown(cmount
);
151 TEST(LibCephFS
, UnmountUnmounted
) {
153 struct ceph_mount_info
*cmount
;
155 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
156 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
157 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
158 ASSERT_EQ(-ENOTCONN
, ceph_unmount(cmount
));
159 ceph_shutdown(cmount
);
162 TEST(LibCephFS
, ReleaseUnmounted
) {
164 struct ceph_mount_info
*cmount
;
166 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
167 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
168 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
169 ASSERT_EQ(0, ceph_release(cmount
));
172 TEST(LibCephFS
, ReleaseMounted
) {
174 struct ceph_mount_info
*cmount
;
176 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
177 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
178 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
179 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
180 ASSERT_EQ(-EISCONN
, ceph_release(cmount
));
181 ASSERT_EQ(0, ceph_unmount(cmount
));
182 ASSERT_EQ(0, ceph_release(cmount
));
185 TEST(LibCephFS
, UnmountRelease
) {
187 struct ceph_mount_info
*cmount
;
189 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
190 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
191 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
192 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
193 ASSERT_EQ(0, ceph_unmount(cmount
));
194 ASSERT_EQ(0, ceph_release(cmount
));
197 TEST(LibCephFS
, Mount
) {
198 struct ceph_mount_info
*cmount
;
199 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
200 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
201 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
202 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
203 ceph_shutdown(cmount
);
205 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
206 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
207 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
208 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
209 ceph_shutdown(cmount
);
212 TEST(LibCephFS
, OpenLayout
) {
213 struct ceph_mount_info
*cmount
;
214 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
215 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
216 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
217 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
220 char test_layout_file
[256];
221 sprintf(test_layout_file
, "test_layout_%d_b", getpid());
222 int fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
|O_WRONLY
, 0666, (1<<20), 7, (1<<20), NULL
);
225 ASSERT_LT(0, ceph_get_file_pool_name(cmount
, fd
, poolname
, sizeof(poolname
)));
226 ASSERT_LT(0, ceph_get_file_pool_name(cmount
, fd
, poolname
, 0));
228 /* on already-written file (ENOTEMPTY) */
229 ceph_write(cmount
, fd
, "hello world", 11, 0);
230 ceph_close(cmount
, fd
);
234 sprintf(xattrk
, "ceph.file.layout.stripe_unit");
235 sprintf(xattrv
, "65536");
236 ASSERT_EQ(-ENOTEMPTY
, ceph_setxattr(cmount
, test_layout_file
, xattrk
, (void *)xattrv
, 5, 0));
239 sprintf(test_layout_file
, "test_layout_%d_c", getpid());
240 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 1, 19, NULL
);
241 ASSERT_EQ(fd
, -EINVAL
);
244 sprintf(test_layout_file
, "test_layout_%d_d", getpid());
245 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), poolname
);
247 ceph_close(cmount
, fd
);
249 /* with metadata pool (invalid) */
250 sprintf(test_layout_file
, "test_layout_%d_e", getpid());
251 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), "metadata");
252 ASSERT_EQ(fd
, -EINVAL
);
254 /* with metadata pool (does not exist) */
255 sprintf(test_layout_file
, "test_layout_%d_f", getpid());
256 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), "asdfjasdfjasdf");
257 ASSERT_EQ(fd
, -EINVAL
);
259 ceph_shutdown(cmount
);
262 TEST(LibCephFS
, DirLs
) {
264 pid_t mypid
= getpid();
266 struct ceph_mount_info
*cmount
;
267 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
268 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
269 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
270 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
272 struct ceph_dir_result
*ls_dir
= NULL
;
274 sprintf(foostr
, "dir_ls%d", mypid
);
275 ASSERT_EQ(ceph_opendir(cmount
, foostr
, &ls_dir
), -ENOENT
);
277 ASSERT_EQ(ceph_mkdir(cmount
, foostr
, 0777), 0);
278 struct ceph_statx stx
;
279 ASSERT_EQ(ceph_statx(cmount
, foostr
, &stx
, 0, 0), 0);
280 ASSERT_NE(S_ISDIR(stx
.stx_mode
), 0);
283 sprintf(barstr
, "dir_ls2%d", mypid
);
284 ASSERT_EQ(ceph_statx(cmount
, barstr
, &stx
, 0, AT_SYMLINK_NOFOLLOW
), -ENOENT
);
286 // insert files into directory and test open
288 int i
= 0, r
= rand() % 4096;
289 if (getenv("LIBCEPHFS_RAND")) {
290 r
= atoi(getenv("LIBCEPHFS_RAND"));
292 printf("rand: %d\n", r
);
295 sprintf(bazstr
, "dir_ls%d/dirf%d", mypid
, i
);
296 int fd
= ceph_open(cmount
, bazstr
, O_CREAT
|O_RDONLY
, 0666);
298 ASSERT_EQ(ceph_close(cmount
, fd
), 0);
300 // set file sizes for readdirplus
301 ceph_truncate(cmount
, bazstr
, i
);
304 ASSERT_EQ(ceph_opendir(cmount
, foostr
, &ls_dir
), 0);
306 // not guaranteed to get . and .. first, but its a safe assumption in this case
307 struct dirent
*result
= ceph_readdir(cmount
, ls_dir
);
308 ASSERT_TRUE(result
!= NULL
);
309 ASSERT_STREQ(result
->d_name
, ".");
310 result
= ceph_readdir(cmount
, ls_dir
);
311 ASSERT_TRUE(result
!= NULL
);
312 ASSERT_STREQ(result
->d_name
, "..");
314 std::vector
<std::string
> entries
;
315 std::map
<std::string
, int64_t> offset_map
;
316 int64_t offset
= ceph_telldir(cmount
, ls_dir
);
317 for(i
= 0; i
< r
; ++i
) {
318 result
= ceph_readdir(cmount
, ls_dir
);
319 ASSERT_TRUE(result
!= NULL
);
320 entries
.push_back(result
->d_name
);
321 offset_map
[result
->d_name
] = offset
;
322 offset
= ceph_telldir(cmount
, ls_dir
);
325 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) == NULL
);
326 offset
= ceph_telldir(cmount
, ls_dir
);
328 ASSERT_EQ(offset_map
.size(), entries
.size());
329 for(i
= 0; i
< r
; ++i
) {
330 sprintf(bazstr
, "dirf%d", i
);
331 ASSERT_TRUE(offset_map
.count(bazstr
) == 1);
335 ceph_seekdir(cmount
, ls_dir
, offset
);
336 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) == NULL
);
338 for (auto p
= offset_map
.begin(); p
!= offset_map
.end(); ++p
) {
339 ceph_seekdir(cmount
, ls_dir
, p
->second
);
340 result
= ceph_readdir(cmount
, ls_dir
);
341 ASSERT_TRUE(result
!= NULL
);
342 std::string
d_name(result
->d_name
);
343 ASSERT_EQ(p
->first
, d_name
);
347 ceph_rewinddir(cmount
, ls_dir
);
349 result
= ceph_readdir(cmount
, ls_dir
);
350 ASSERT_TRUE(result
!= NULL
);
351 ASSERT_STREQ(result
->d_name
, ".");
352 result
= ceph_readdir(cmount
, ls_dir
);
353 ASSERT_TRUE(result
!= NULL
);
354 ASSERT_STREQ(result
->d_name
, "..");
356 ceph_rewinddir(cmount
, ls_dir
);
358 int t
= ceph_telldir(cmount
, ls_dir
);
361 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) != NULL
);
363 // test seekdir - move back to the beginning
364 ceph_seekdir(cmount
, ls_dir
, t
);
367 struct dirent
*getdents_entries
;
368 size_t getdents_entries_len
= (r
+ 2) * sizeof(*getdents_entries
);
369 getdents_entries
= (struct dirent
*)malloc(getdents_entries_len
);
372 std::vector
<std::string
> found
;
374 int len
= ceph_getdents(cmount
, ls_dir
, (char *)getdents_entries
, getdents_entries_len
);
378 ASSERT_TRUE((len
% sizeof(*getdents_entries
)) == 0);
379 int n
= len
/ sizeof(*getdents_entries
);
382 ASSERT_STREQ(getdents_entries
[0].d_name
, ".");
383 ASSERT_STREQ(getdents_entries
[1].d_name
, "..");
389 for(; j
< n
; ++i
, ++j
) {
390 const char *name
= getdents_entries
[j
].d_name
;
391 found
.push_back(name
);
394 ASSERT_EQ(found
, entries
);
395 free(getdents_entries
);
398 ceph_rewinddir(cmount
, ls_dir
);
400 result
= ceph_readdir(cmount
, ls_dir
);
401 ASSERT_TRUE(result
!= NULL
);
402 ASSERT_STREQ(result
->d_name
, ".");
403 result
= ceph_readdir(cmount
, ls_dir
);
404 ASSERT_TRUE(result
!= NULL
);
405 ASSERT_STREQ(result
->d_name
, "..");
410 int len
= ceph_readdir_r(cmount
, ls_dir
, &rdent
);
414 found
.push_back(rdent
.d_name
);
416 ASSERT_EQ(found
, entries
);
419 ceph_rewinddir(cmount
, ls_dir
);
421 result
= ceph_readdir(cmount
, ls_dir
);
422 ASSERT_TRUE(result
!= NULL
);
423 ASSERT_STREQ(result
->d_name
, ".");
424 result
= ceph_readdir(cmount
, ls_dir
);
425 ASSERT_TRUE(result
!= NULL
);
426 ASSERT_STREQ(result
->d_name
, "..");
431 struct ceph_statx stx
;
432 int len
= ceph_readdirplus_r(cmount
, ls_dir
, &rdent
, &stx
,
433 CEPH_STATX_SIZE
, AT_NO_ATTR_SYNC
, NULL
);
437 const char *name
= rdent
.d_name
;
438 found
.push_back(name
);
440 sscanf(name
, "dirf%d", &size
);
441 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_SIZE
);
442 ASSERT_EQ(stx
.stx_size
, (size_t)size
);
443 ASSERT_EQ(stx
.stx_ino
, rdent
.d_ino
);
444 //ASSERT_EQ(st.st_mode, (mode_t)0666);
446 ASSERT_EQ(found
, entries
);
448 ASSERT_EQ(ceph_closedir(cmount
, ls_dir
), 0);
450 ceph_shutdown(cmount
);
453 TEST(LibCephFS
, ManyNestedDirs
) {
454 struct ceph_mount_info
*cmount
;
455 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
456 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
457 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
458 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
460 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";
461 ASSERT_EQ(ceph_mkdirs(cmount
, many_path
, 0755), 0);
466 ASSERT_EQ(ceph_chdir(cmount
, "a"), 0);
468 struct ceph_dir_result
*dirp
;
469 ASSERT_EQ(ceph_opendir(cmount
, "a", &dirp
), 0);
470 struct dirent
*dent
= ceph_readdir(cmount
, dirp
);
471 ASSERT_TRUE(dent
!= NULL
);
472 ASSERT_STREQ(dent
->d_name
, ".");
473 dent
= ceph_readdir(cmount
, dirp
);
474 ASSERT_TRUE(dent
!= NULL
);
475 ASSERT_STREQ(dent
->d_name
, "..");
476 dent
= ceph_readdir(cmount
, dirp
);
477 ASSERT_TRUE(dent
!= NULL
);
478 ASSERT_STREQ(dent
->d_name
, "a");
479 ASSERT_EQ(ceph_closedir(cmount
, dirp
), 0);
482 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");
484 ASSERT_EQ(ceph_chdir(cmount
, "a/a/a"), 0);
486 for(i
= 0; i
< 39; ++i
) {
487 ASSERT_EQ(ceph_chdir(cmount
, ".."), 0);
488 ASSERT_EQ(ceph_rmdir(cmount
, "a"), 0);
491 ASSERT_EQ(ceph_chdir(cmount
, "/"), 0);
493 ASSERT_EQ(ceph_rmdir(cmount
, "a/a/a"), 0);
495 ceph_shutdown(cmount
);
498 TEST(LibCephFS
, Xattrs
) {
499 struct ceph_mount_info
*cmount
;
500 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
501 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
502 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
503 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
505 char test_xattr_file
[256];
506 sprintf(test_xattr_file
, "test_xattr_%d", getpid());
507 int fd
= ceph_open(cmount
, test_xattr_file
, O_CREAT
, 0666);
513 for(; i
< 'a'+26; ++i
) {
514 sprintf(xattrk
, "user.test_xattr_%c", i
);
515 int len
= sprintf(xattrv
, "testxattr%c", i
);
516 ASSERT_EQ(ceph_setxattr(cmount
, test_xattr_file
, xattrk
, (void *) xattrv
, len
, XATTR_CREATE
), 0);
519 char xattrlist
[128*26];
520 int len
= ceph_listxattr(cmount
, test_xattr_file
, xattrlist
, sizeof(xattrlist
));
525 // skip/ignore the dir layout
526 if (strcmp(p
, "ceph.dir.layout") == 0 ||
527 strcmp(p
, "ceph.file.layout") == 0) {
528 len
-= strlen(p
) + 1;
533 sprintf(xattrk
, "user.test_xattr_%c", i
);
534 ASSERT_STREQ(p
, xattrk
);
537 std::cout
<< "getting attr " << p
<< std::endl
;
538 int alen
= ceph_getxattr(cmount
, test_xattr_file
, p
, (void *) gxattrv
, 128);
540 sprintf(xattrv
, "testxattr%c", i
);
541 ASSERT_TRUE(!strncmp(xattrv
, gxattrv
, alen
));
551 for(i
= 'a'; i
< 'a'+26; ++i
) {
552 sprintf(xattrk
, "user.test_xattr_%c", i
);
553 ASSERT_EQ(ceph_removexattr(cmount
, test_xattr_file
, xattrk
), 0);
556 ceph_close(cmount
, fd
);
557 ceph_shutdown(cmount
);
561 TEST(LibCephFS
, Xattrs_ll
) {
562 struct ceph_mount_info
*cmount
;
563 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
564 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
565 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
566 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
568 char test_xattr_file
[256];
569 sprintf(test_xattr_file
, "test_xattr_%d", getpid());
570 int fd
= ceph_open(cmount
, test_xattr_file
, O_CREAT
, 0666);
572 ceph_close(cmount
, fd
);
575 Inode
*existent_file_handle
= NULL
;
577 int res
= ceph_ll_lookup_root(cmount
, &root
);
580 UserPerm
*perms
= ceph_mount_perms(cmount
);
581 struct ceph_statx stx
;
583 res
= ceph_ll_lookup(cmount
, root
, test_xattr_file
, &existent_file_handle
,
587 const char *valid_name
= "user.attrname";
588 const char *value
= "attrvalue";
589 char value_buf
[256] = { 0 };
591 res
= ceph_ll_setxattr(cmount
, existent_file_handle
, valid_name
, value
, strlen(value
), 0, perms
);
594 res
= ceph_ll_getxattr(cmount
, existent_file_handle
, valid_name
, value_buf
, 256, perms
);
595 ASSERT_EQ(res
, (int)strlen(value
));
597 value_buf
[res
] = '\0';
598 ASSERT_STREQ(value_buf
, value
);
600 ceph_shutdown(cmount
);
603 TEST(LibCephFS
, LstatSlashdot
) {
604 struct ceph_mount_info
*cmount
;
605 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
606 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
607 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
608 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
610 struct ceph_statx stx
;
611 ASSERT_EQ(ceph_statx(cmount
, "/.", &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
612 ASSERT_EQ(ceph_statx(cmount
, ".", &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
614 ceph_shutdown(cmount
);
617 TEST(LibCephFS
, StatDirNlink
) {
618 struct ceph_mount_info
*cmount
;
619 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
620 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
621 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
622 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
625 sprintf(test_dir1
, "dir1_symlinks_%d", getpid());
626 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
628 int fd
= ceph_open(cmount
, test_dir1
, O_DIRECTORY
|O_RDONLY
, 0);
630 struct ceph_statx stx
;
631 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
632 ASSERT_EQ(stx
.stx_nlink
, 2);
636 sprintf(test_dir2
, "%s/.", test_dir1
);
637 ASSERT_EQ(ceph_statx(cmount
, test_dir2
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
638 ASSERT_EQ(stx
.stx_nlink
, 2);
643 sprintf(test_dir2
, "%s/1", test_dir1
);
644 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
645 ASSERT_EQ(ceph_statx(cmount
, test_dir2
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
646 ASSERT_EQ(stx
.stx_nlink
, 2);
647 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
648 ASSERT_EQ(stx
.stx_nlink
, 3);
649 sprintf(test_dir2
, "%s/2", test_dir1
);
650 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
651 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
652 ASSERT_EQ(stx
.stx_nlink
, 4);
653 sprintf(test_dir2
, "%s/1/1", test_dir1
);
654 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
655 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
656 ASSERT_EQ(stx
.stx_nlink
, 4);
657 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
658 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
659 ASSERT_EQ(stx
.stx_nlink
, 4);
660 sprintf(test_dir2
, "%s/1", test_dir1
);
661 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
662 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
663 ASSERT_EQ(stx
.stx_nlink
, 3);
664 sprintf(test_dir2
, "%s/2", test_dir1
);
665 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
666 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
667 ASSERT_EQ(stx
.stx_nlink
, 2);
670 ASSERT_EQ(ceph_rmdir(cmount
, test_dir1
), 0);
671 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
672 ASSERT_EQ(stx
.stx_nlink
, 0);
674 ceph_close(cmount
, fd
);
676 ceph_shutdown(cmount
);
679 TEST(LibCephFS
, DoubleChmod
) {
681 struct ceph_mount_info
*cmount
;
682 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
683 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
684 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
685 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
688 sprintf(test_file
, "test_perms_%d", getpid());
690 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
694 const char *bytes
= "foobarbaz";
695 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
697 ceph_close(cmount
, fd
);
699 // set perms to read but can't write
700 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0400), 0);
702 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
703 ASSERT_EQ(fd
, -EACCES
);
705 fd
= ceph_open(cmount
, test_file
, O_RDONLY
, 0);
709 int ret
= ceph_read(cmount
, fd
, buf
, 100, 0);
710 ASSERT_EQ(ret
, (int)strlen(bytes
));
712 ASSERT_STREQ(buf
, bytes
);
714 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), -EBADF
);
716 ceph_close(cmount
, fd
);
718 // reset back to writeable
719 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0600), 0);
721 // ensure perms are correct
722 struct ceph_statx stx
;
723 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
, CEPH_STATX_MODE
, AT_SYMLINK_NOFOLLOW
), 0);
724 ASSERT_EQ(stx
.stx_mode
, 0100600U);
726 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
729 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
730 ceph_close(cmount
, fd
);
732 ceph_shutdown(cmount
);
735 TEST(LibCephFS
, Fchmod
) {
736 struct ceph_mount_info
*cmount
;
737 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
738 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
739 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
740 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
743 sprintf(test_file
, "test_perms_%d", getpid());
745 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
749 const char *bytes
= "foobarbaz";
750 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
752 // set perms to read but can't write
753 ASSERT_EQ(ceph_fchmod(cmount
, fd
, 0400), 0);
756 int ret
= ceph_read(cmount
, fd
, buf
, 100, 0);
757 ASSERT_EQ(ret
, (int)strlen(bytes
));
759 ASSERT_STREQ(buf
, bytes
);
761 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
763 ceph_close(cmount
, fd
);
765 ASSERT_EQ(ceph_open(cmount
, test_file
, O_RDWR
, 0), -EACCES
);
767 // reset back to writeable
768 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0600), 0);
770 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
773 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
774 ceph_close(cmount
, fd
);
776 ceph_shutdown(cmount
);
779 TEST(LibCephFS
, Fchown
) {
780 struct ceph_mount_info
*cmount
;
781 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
782 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
783 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
784 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
787 sprintf(test_file
, "test_fchown_%d", getpid());
789 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
792 // set perms to readable and writeable only by owner
793 ASSERT_EQ(ceph_fchmod(cmount
, fd
, 0600), 0);
795 // change ownership to nobody -- we assume nobody exists and id is always 65534
796 ASSERT_EQ(ceph_conf_set(cmount
, "client_permissions", "0"), 0);
797 ASSERT_EQ(ceph_fchown(cmount
, fd
, 65534, 65534), 0);
798 ASSERT_EQ(ceph_conf_set(cmount
, "client_permissions", "1"), 0);
800 ceph_close(cmount
, fd
);
802 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
803 ASSERT_EQ(fd
, -EACCES
);
805 ceph_shutdown(cmount
);
808 #if defined(__linux__) && defined(O_PATH)
809 TEST(LibCephFS
, FlagO_PATH
) {
810 struct ceph_mount_info
*cmount
;
812 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
813 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
814 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
815 ASSERT_EQ(0, ceph_mount(cmount
, NULL
));
817 char test_file
[PATH_MAX
];
818 sprintf(test_file
, "test_oflag_%d", getpid());
820 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
|O_PATH
, 0666);
821 ASSERT_EQ(-ENOENT
, fd
);
823 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
825 ASSERT_EQ(0, ceph_close(cmount
, fd
));
827 // ok, the file has been created. perform real checks now
828 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
|O_PATH
, 0666);
832 ASSERT_EQ(-EBADF
, ceph_read(cmount
, fd
, buf
, sizeof(buf
), 0));
833 ASSERT_EQ(-EBADF
, ceph_write(cmount
, fd
, buf
, sizeof(buf
), 0));
835 // set perms to readable and writeable only by owner
836 ASSERT_EQ(-EBADF
, ceph_fchmod(cmount
, fd
, 0600));
838 // change ownership to nobody -- we assume nobody exists and id is always 65534
839 ASSERT_EQ(-EBADF
, ceph_fchown(cmount
, fd
, 65534, 65534));
842 ASSERT_EQ(-EBADF
, ceph_fsync(cmount
, fd
, false));
844 struct ceph_statx stx
;
845 ASSERT_EQ(0, ceph_fstatx(cmount
, fd
, &stx
, 0, 0));
847 ASSERT_EQ(0, ceph_close(cmount
, fd
));
848 ceph_shutdown(cmount
);
852 TEST(LibCephFS
, Symlinks
) {
853 struct ceph_mount_info
*cmount
;
854 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
855 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
856 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
857 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
860 sprintf(test_file
, "test_symlinks_%d", getpid());
862 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
865 ceph_close(cmount
, fd
);
867 char test_symlink
[256];
868 sprintf(test_symlink
, "test_symlinks_sym_%d", getpid());
870 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
872 // test the O_NOFOLLOW case
873 fd
= ceph_open(cmount
, test_symlink
, O_NOFOLLOW
, 0);
874 ASSERT_EQ(fd
, -ELOOP
);
876 // stat the original file
877 struct ceph_statx stx_orig
;
878 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
880 struct ceph_statx stx_symlink_orig
;
881 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_symlink_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
882 // ensure the statx bufs are equal
883 ASSERT_EQ(memcmp(&stx_orig
, &stx_symlink_orig
, sizeof(stx_orig
)), 0);
885 sprintf(test_file
, "/test_symlinks_abs_%d", getpid());
887 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
890 ceph_close(cmount
, fd
);
892 sprintf(test_symlink
, "/test_symlinks_abs_sym_%d", getpid());
894 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
896 // stat the original file
897 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
899 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_symlink_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
900 // ensure the statx bufs are equal
901 ASSERT_TRUE(!memcmp(&stx_orig
, &stx_symlink_orig
, sizeof(stx_orig
)));
904 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_orig
, CEPH_STATX_ALL_STATS
, AT_SYMLINK_NOFOLLOW
), 0);
905 ASSERT_TRUE(S_ISLNK(stx_orig
.stx_mode
));
907 ceph_shutdown(cmount
);
910 TEST(LibCephFS
, DirSyms
) {
911 struct ceph_mount_info
*cmount
;
912 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
913 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
914 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
915 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
918 sprintf(test_dir1
, "dir1_symlinks_%d", getpid());
920 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
922 char test_symdir
[256];
923 sprintf(test_symdir
, "symdir_symlinks_%d", getpid());
925 ASSERT_EQ(ceph_symlink(cmount
, test_dir1
, test_symdir
), 0);
928 sprintf(test_file
, "/symdir_symlinks_%d/test_symdir_file", getpid());
929 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0600);
931 ceph_close(cmount
, fd
);
933 struct ceph_statx stx
;
934 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
936 // ensure that its a file not a directory we get back
937 ASSERT_TRUE(S_ISREG(stx
.stx_mode
));
939 ceph_shutdown(cmount
);
942 TEST(LibCephFS
, LoopSyms
) {
943 struct ceph_mount_info
*cmount
;
944 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
945 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
946 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
947 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
950 sprintf(test_dir1
, "dir1_loopsym_%d", getpid());
952 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
955 sprintf(test_dir2
, "/dir1_loopsym_%d/loop_dir", getpid());
957 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
959 // symlink it itself: /path/to/mysym -> /path/to/mysym
960 char test_symdir
[256];
961 sprintf(test_symdir
, "/dir1_loopsym_%d/loop_dir/symdir", getpid());
963 ASSERT_EQ(ceph_symlink(cmount
, test_symdir
, test_symdir
), 0);
966 sprintf(test_file
, "/dir1_loopsym_%d/loop_dir/symdir/test_loopsym_file", getpid());
967 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0600);
968 ASSERT_EQ(fd
, -ELOOP
);
970 // loop: /a -> /b, /b -> /c, /c -> /a
971 char a
[256], b
[256], c
[256];
972 sprintf(a
, "/%s/a", test_dir1
);
973 sprintf(b
, "/%s/b", test_dir1
);
974 sprintf(c
, "/%s/c", test_dir1
);
975 ASSERT_EQ(ceph_symlink(cmount
, a
, b
), 0);
976 ASSERT_EQ(ceph_symlink(cmount
, b
, c
), 0);
977 ASSERT_EQ(ceph_symlink(cmount
, c
, a
), 0);
978 ASSERT_EQ(ceph_open(cmount
, a
, O_RDWR
, 0), -ELOOP
);
980 ceph_shutdown(cmount
);
983 TEST(LibCephFS
, HardlinkNoOriginal
) {
985 int mypid
= getpid();
987 struct ceph_mount_info
*cmount
;
988 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
989 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
990 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
991 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
994 sprintf(dir
, "/test_rmdirfail%d", mypid
);
995 ASSERT_EQ(ceph_mkdir(cmount
, dir
, 0777), 0);
997 ASSERT_EQ(ceph_chdir(cmount
, dir
), 0);
999 int fd
= ceph_open(cmount
, "f1", O_CREAT
, 0644);
1002 ceph_close(cmount
, fd
);
1005 ASSERT_EQ(ceph_link(cmount
, "f1", "hardl1"), 0);
1007 // remove file link points to
1008 ASSERT_EQ(ceph_unlink(cmount
, "f1"), 0);
1010 ceph_shutdown(cmount
);
1013 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1014 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1015 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1016 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1017 ASSERT_EQ(ceph_chdir(cmount
, dir
), 0);
1018 ASSERT_EQ(ceph_unlink(cmount
, "hardl1"), 0);
1019 ASSERT_EQ(ceph_rmdir(cmount
, dir
), 0);
1021 ceph_shutdown(cmount
);
1024 TEST(LibCephFS
, BadArgument
) {
1025 struct ceph_mount_info
*cmount
;
1026 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1027 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1028 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1029 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1031 int fd
= ceph_open(cmount
, "test_file", O_CREAT
|O_RDWR
, 0666);
1034 ASSERT_EQ(ceph_write(cmount
, fd
, buf
, sizeof(buf
), 0), (int)sizeof(buf
));
1035 ASSERT_EQ(ceph_read(cmount
, fd
, buf
, 0, 5), 0);
1036 ceph_close(cmount
, fd
);
1037 ASSERT_EQ(ceph_unlink(cmount
, "test_file"), 0);
1039 ceph_shutdown(cmount
);
1042 TEST(LibCephFS
, BadFileDesc
) {
1043 struct ceph_mount_info
*cmount
;
1044 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1045 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1046 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1047 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1049 ASSERT_EQ(ceph_fchmod(cmount
, -1, 0655), -EBADF
);
1050 ASSERT_EQ(ceph_close(cmount
, -1), -EBADF
);
1051 ASSERT_EQ(ceph_lseek(cmount
, -1, 0, SEEK_SET
), -EBADF
);
1054 ASSERT_EQ(ceph_read(cmount
, -1, buf
, 0, 0), -EBADF
);
1055 ASSERT_EQ(ceph_write(cmount
, -1, buf
, 0, 0), -EBADF
);
1057 ASSERT_EQ(ceph_ftruncate(cmount
, -1, 0), -EBADF
);
1058 ASSERT_EQ(ceph_fsync(cmount
, -1, 0), -EBADF
);
1060 struct ceph_statx stx
;
1061 ASSERT_EQ(ceph_fstatx(cmount
, -1, &stx
, 0, 0), -EBADF
);
1063 struct sockaddr_storage addr
;
1064 ASSERT_EQ(ceph_get_file_stripe_address(cmount
, -1, 0, &addr
, 1), -EBADF
);
1066 ASSERT_EQ(ceph_get_file_stripe_unit(cmount
, -1), -EBADF
);
1067 ASSERT_EQ(ceph_get_file_pool(cmount
, -1), -EBADF
);
1069 ASSERT_EQ(ceph_get_file_pool_name(cmount
, -1, poolname
, sizeof(poolname
)), -EBADF
);
1070 ASSERT_EQ(ceph_get_file_replication(cmount
, -1), -EBADF
);
1071 ASSERT_EQ(ceph_get_file_object_size(cmount
, -1), -EBADF
);
1072 int stripe_unit
, stripe_count
, object_size
, pg_pool
;
1073 ASSERT_EQ(ceph_get_file_layout(cmount
, -1, &stripe_unit
, &stripe_count
, &object_size
, &pg_pool
), -EBADF
);
1074 ASSERT_EQ(ceph_get_file_stripe_count(cmount
, -1), -EBADF
);
1076 ceph_shutdown(cmount
);
1079 TEST(LibCephFS
, ReadEmptyFile
) {
1080 struct ceph_mount_info
*cmount
;
1081 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1082 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1083 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1084 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1086 // test the read_sync path in the client for zero files
1087 ASSERT_EQ(ceph_conf_set(cmount
, "client_debug_force_sync_read", "true"), 0);
1089 int mypid
= getpid();
1092 sprintf(testf
, "test_reademptyfile%d", mypid
);
1093 int fd
= ceph_open(cmount
, testf
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644);
1096 ceph_close(cmount
, fd
);
1098 fd
= ceph_open(cmount
, testf
, O_RDONLY
, 0);
1102 ASSERT_EQ(ceph_read(cmount
, fd
, buf
, 4096, 0), 0);
1104 ceph_close(cmount
, fd
);
1105 ceph_shutdown(cmount
);
1108 TEST(LibCephFS
, PreadvPwritev
) {
1109 struct ceph_mount_info
*cmount
;
1110 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1111 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1112 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1113 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1115 int mypid
= getpid();
1118 sprintf(testf
, "test_preadvpwritevfile%d", mypid
);
1119 int fd
= ceph_open(cmount
, testf
, O_CREAT
|O_RDWR
, 0666);
1122 char out0
[] = "hello ";
1123 char out1
[] = "world\n";
1124 struct iovec iov_out
[2] = {
1125 {out0
, sizeof(out0
)},
1126 {out1
, sizeof(out1
)},
1128 char in0
[sizeof(out0
)];
1129 char in1
[sizeof(out1
)];
1130 struct iovec iov_in
[2] = {
1134 ssize_t nwritten
= iov_out
[0].iov_len
+ iov_out
[1].iov_len
;
1135 ssize_t nread
= iov_in
[0].iov_len
+ iov_in
[1].iov_len
;
1137 ASSERT_EQ(ceph_pwritev(cmount
, fd
, iov_out
, 2, 0), nwritten
);
1138 ASSERT_EQ(ceph_preadv(cmount
, fd
, iov_in
, 2, 0), nread
);
1139 ASSERT_EQ(0, strncmp((const char*)iov_in
[0].iov_base
, (const char*)iov_out
[0].iov_base
, iov_out
[0].iov_len
));
1140 ASSERT_EQ(0, strncmp((const char*)iov_in
[1].iov_base
, (const char*)iov_out
[1].iov_base
, iov_out
[1].iov_len
));
1142 ceph_close(cmount
, fd
);
1143 ceph_shutdown(cmount
);
1146 TEST(LibCephFS
, StripeUnitGran
) {
1147 struct ceph_mount_info
*cmount
;
1148 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1149 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1150 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1151 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1152 ASSERT_GT(ceph_get_stripe_unit_granularity(cmount
), 0);
1153 ceph_shutdown(cmount
);
1156 TEST(LibCephFS
, Rename
) {
1157 struct ceph_mount_info
*cmount
;
1158 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1159 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1160 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1161 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1163 int mypid
= getpid();
1167 /* make a source file */
1168 sprintf(path_src
, "test_rename_src%d", mypid
);
1169 int fd
= ceph_open(cmount
, path_src
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0777);
1171 ASSERT_EQ(0, ceph_close(cmount
, fd
));
1173 /* rename to a new dest path */
1174 sprintf(path_dst
, "test_rename_dst%d", mypid
);
1175 ASSERT_EQ(0, ceph_rename(cmount
, path_src
, path_dst
));
1177 /* test that dest path exists */
1178 struct ceph_statx stx
;
1179 ASSERT_EQ(0, ceph_statx(cmount
, path_dst
, &stx
, 0, 0));
1181 /* test that src path doesn't exist */
1182 ASSERT_EQ(-ENOENT
, ceph_statx(cmount
, path_src
, &stx
, 0, AT_SYMLINK_NOFOLLOW
));
1184 /* rename with non-existent source path */
1185 ASSERT_EQ(-ENOENT
, ceph_rename(cmount
, path_src
, path_dst
));
1187 ASSERT_EQ(0, ceph_unlink(cmount
, path_dst
));
1188 ceph_shutdown(cmount
);
1191 TEST(LibCephFS
, UseUnmounted
) {
1192 struct ceph_mount_info
*cmount
;
1193 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1194 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1195 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1197 struct statvfs stvfs
;
1198 EXPECT_EQ(-ENOTCONN
, ceph_statfs(cmount
, "/", &stvfs
));
1199 EXPECT_EQ(-ENOTCONN
, ceph_get_local_osd(cmount
));
1200 EXPECT_EQ(-ENOTCONN
, ceph_chdir(cmount
, "/"));
1202 struct ceph_dir_result
*dirp
;
1203 EXPECT_EQ(-ENOTCONN
, ceph_opendir(cmount
, "/", &dirp
));
1204 EXPECT_EQ(-ENOTCONN
, ceph_closedir(cmount
, dirp
));
1206 ceph_readdir(cmount
, dirp
);
1207 EXPECT_EQ(ENOTCONN
, errno
);
1209 struct dirent rdent
;
1210 EXPECT_EQ(-ENOTCONN
, ceph_readdir_r(cmount
, dirp
, &rdent
));
1212 struct ceph_statx stx
;
1213 EXPECT_EQ(-ENOTCONN
, ceph_readdirplus_r(cmount
, dirp
, &rdent
, &stx
, 0, 0, NULL
));
1214 EXPECT_EQ(-ENOTCONN
, ceph_getdents(cmount
, dirp
, NULL
, 0));
1215 EXPECT_EQ(-ENOTCONN
, ceph_getdnames(cmount
, dirp
, NULL
, 0));
1216 EXPECT_EQ(-ENOTCONN
, ceph_telldir(cmount
, dirp
));
1217 EXPECT_EQ(-ENOTCONN
, ceph_link(cmount
, "/", "/link"));
1218 EXPECT_EQ(-ENOTCONN
, ceph_unlink(cmount
, "/path"));
1219 EXPECT_EQ(-ENOTCONN
, ceph_rename(cmount
, "/path", "/path"));
1220 EXPECT_EQ(-ENOTCONN
, ceph_mkdir(cmount
, "/", 0655));
1221 EXPECT_EQ(-ENOTCONN
, ceph_mkdirs(cmount
, "/", 0655));
1222 EXPECT_EQ(-ENOTCONN
, ceph_rmdir(cmount
, "/path"));
1223 EXPECT_EQ(-ENOTCONN
, ceph_readlink(cmount
, "/path", NULL
, 0));
1224 EXPECT_EQ(-ENOTCONN
, ceph_symlink(cmount
, "/path", "/path"));
1225 EXPECT_EQ(-ENOTCONN
, ceph_statx(cmount
, "/path", &stx
, 0, 0));
1226 EXPECT_EQ(-ENOTCONN
, ceph_setattrx(cmount
, "/path", &stx
, 0, 0));
1227 EXPECT_EQ(-ENOTCONN
, ceph_getxattr(cmount
, "/path", "name", NULL
, 0));
1228 EXPECT_EQ(-ENOTCONN
, ceph_lgetxattr(cmount
, "/path", "name", NULL
, 0));
1229 EXPECT_EQ(-ENOTCONN
, ceph_listxattr(cmount
, "/path", NULL
, 0));
1230 EXPECT_EQ(-ENOTCONN
, ceph_llistxattr(cmount
, "/path", NULL
, 0));
1231 EXPECT_EQ(-ENOTCONN
, ceph_removexattr(cmount
, "/path", "name"));
1232 EXPECT_EQ(-ENOTCONN
, ceph_lremovexattr(cmount
, "/path", "name"));
1233 EXPECT_EQ(-ENOTCONN
, ceph_setxattr(cmount
, "/path", "name", NULL
, 0, 0));
1234 EXPECT_EQ(-ENOTCONN
, ceph_lsetxattr(cmount
, "/path", "name", NULL
, 0, 0));
1235 EXPECT_EQ(-ENOTCONN
, ceph_fsetattrx(cmount
, 0, &stx
, 0));
1236 EXPECT_EQ(-ENOTCONN
, ceph_chmod(cmount
, "/path", 0));
1237 EXPECT_EQ(-ENOTCONN
, ceph_fchmod(cmount
, 0, 0));
1238 EXPECT_EQ(-ENOTCONN
, ceph_chown(cmount
, "/path", 0, 0));
1239 EXPECT_EQ(-ENOTCONN
, ceph_lchown(cmount
, "/path", 0, 0));
1240 EXPECT_EQ(-ENOTCONN
, ceph_fchown(cmount
, 0, 0, 0));
1243 EXPECT_EQ(-ENOTCONN
, ceph_utime(cmount
, "/path", &utb
));
1244 EXPECT_EQ(-ENOTCONN
, ceph_truncate(cmount
, "/path", 0));
1245 EXPECT_EQ(-ENOTCONN
, ceph_mknod(cmount
, "/path", 0, 0));
1246 EXPECT_EQ(-ENOTCONN
, ceph_open(cmount
, "/path", 0, 0));
1247 EXPECT_EQ(-ENOTCONN
, ceph_open_layout(cmount
, "/path", 0, 0, 0, 0, 0, "pool"));
1248 EXPECT_EQ(-ENOTCONN
, ceph_close(cmount
, 0));
1249 EXPECT_EQ(-ENOTCONN
, ceph_lseek(cmount
, 0, 0, SEEK_SET
));
1250 EXPECT_EQ(-ENOTCONN
, ceph_read(cmount
, 0, NULL
, 0, 0));
1251 EXPECT_EQ(-ENOTCONN
, ceph_write(cmount
, 0, NULL
, 0, 0));
1252 EXPECT_EQ(-ENOTCONN
, ceph_ftruncate(cmount
, 0, 0));
1253 EXPECT_EQ(-ENOTCONN
, ceph_fsync(cmount
, 0, 0));
1254 EXPECT_EQ(-ENOTCONN
, ceph_fstatx(cmount
, 0, &stx
, 0, 0));
1255 EXPECT_EQ(-ENOTCONN
, ceph_sync_fs(cmount
));
1256 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_unit(cmount
, 0));
1257 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_count(cmount
, 0));
1258 EXPECT_EQ(-ENOTCONN
, ceph_get_file_layout(cmount
, 0, NULL
, NULL
,NULL
,NULL
));
1259 EXPECT_EQ(-ENOTCONN
, ceph_get_file_object_size(cmount
, 0));
1260 EXPECT_EQ(-ENOTCONN
, ceph_get_file_pool(cmount
, 0));
1261 EXPECT_EQ(-ENOTCONN
, ceph_get_file_pool_name(cmount
, 0, NULL
, 0));
1262 EXPECT_EQ(-ENOTCONN
, ceph_get_file_replication(cmount
, 0));
1263 EXPECT_EQ(-ENOTCONN
, ceph_get_path_replication(cmount
, "/path"));
1264 EXPECT_EQ(-ENOTCONN
, ceph_get_path_layout(cmount
, "/path", NULL
, NULL
, NULL
, NULL
));
1265 EXPECT_EQ(-ENOTCONN
, ceph_get_path_object_size(cmount
, "/path"));
1266 EXPECT_EQ(-ENOTCONN
, ceph_get_path_stripe_count(cmount
, "/path"));
1267 EXPECT_EQ(-ENOTCONN
, ceph_get_path_stripe_unit(cmount
, "/path"));
1268 EXPECT_EQ(-ENOTCONN
, ceph_get_path_pool(cmount
, "/path"));
1269 EXPECT_EQ(-ENOTCONN
, ceph_get_path_pool_name(cmount
, "/path", NULL
, 0));
1270 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_name(cmount
, 0, NULL
, 0));
1271 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_address(cmount
, 0, 0, NULL
, 0));
1272 EXPECT_EQ(-ENOTCONN
, ceph_localize_reads(cmount
, 0));
1273 EXPECT_EQ(-ENOTCONN
, ceph_debug_get_fd_caps(cmount
, 0));
1274 EXPECT_EQ(-ENOTCONN
, ceph_debug_get_file_caps(cmount
, "/path"));
1275 EXPECT_EQ(-ENOTCONN
, ceph_get_stripe_unit_granularity(cmount
));
1276 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_id(cmount
, "data"));
1277 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_replication(cmount
, 1));
1279 ceph_release(cmount
);
1282 TEST(LibCephFS
, GetPoolId
) {
1283 struct ceph_mount_info
*cmount
;
1284 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1285 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1286 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1287 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1290 memset(name
, 0, sizeof(name
));
1291 ASSERT_LE(0, ceph_get_path_pool_name(cmount
, "/", name
, sizeof(name
)));
1292 ASSERT_GE(ceph_get_pool_id(cmount
, name
), 0);
1293 ASSERT_EQ(ceph_get_pool_id(cmount
, "weflkjwelfjwlkejf"), -ENOENT
);
1295 ceph_shutdown(cmount
);
1298 TEST(LibCephFS
, GetPoolReplication
) {
1299 struct ceph_mount_info
*cmount
;
1300 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1301 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1302 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1303 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1305 /* negative pools */
1306 ASSERT_EQ(ceph_get_pool_replication(cmount
, -10), -ENOENT
);
1310 int stripe_unit
, stripe_count
, object_size
;
1311 ASSERT_EQ(0, ceph_get_path_layout(cmount
, "/", &stripe_unit
, &stripe_count
,
1312 &object_size
, &pool_id
));
1313 ASSERT_GE(pool_id
, 0);
1314 ASSERT_GT(ceph_get_pool_replication(cmount
, pool_id
), 0);
1316 ceph_shutdown(cmount
);
1319 TEST(LibCephFS
, GetExtentOsds
) {
1320 struct ceph_mount_info
*cmount
;
1321 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1323 EXPECT_EQ(-ENOTCONN
, ceph_get_file_extent_osds(cmount
, 0, 0, NULL
, NULL
, 0));
1325 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1326 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1327 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1329 int stripe_unit
= (1<<18);
1332 char test_file
[256];
1333 sprintf(test_file
, "test_extent_osds_%d", getpid());
1334 int fd
= ceph_open_layout(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666,
1335 stripe_unit
, 2, stripe_unit
*2, NULL
);
1338 /* get back how many osds > 0 */
1339 int ret
= ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, NULL
, 0);
1345 /* full stripe extent */
1346 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 0, &len
, osds
, ret
));
1347 EXPECT_EQ(len
, (int64_t)stripe_unit
);
1349 /* half stripe extent */
1350 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, stripe_unit
/2, &len
, osds
, ret
));
1351 EXPECT_EQ(len
, (int64_t)stripe_unit
/2);
1353 /* 1.5 stripe unit offset -1 byte */
1354 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 3*stripe_unit
/2-1, &len
, osds
, ret
));
1355 EXPECT_EQ(len
, (int64_t)stripe_unit
/2+1);
1357 /* 1.5 stripe unit offset +1 byte */
1358 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 3*stripe_unit
/2+1, &len
, osds
, ret
));
1359 EXPECT_EQ(len
, (int64_t)stripe_unit
/2-1);
1361 /* only when more than 1 osd */
1363 EXPECT_EQ(-ERANGE
, ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, osds
, 1));
1366 ceph_close(cmount
, fd
);
1368 ceph_shutdown(cmount
);
1371 TEST(LibCephFS
, GetOsdCrushLocation
) {
1372 struct ceph_mount_info
*cmount
;
1373 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1375 EXPECT_EQ(-ENOTCONN
, ceph_get_osd_crush_location(cmount
, 0, NULL
, 0));
1377 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1378 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1379 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1381 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 0, NULL
, 1), -EINVAL
);
1384 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 9999999, path
, 0), -ENOENT
);
1385 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, -1, path
, 0), -EINVAL
);
1387 char test_file
[256];
1388 sprintf(test_file
, "test_osds_loc_%d", getpid());
1389 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
1392 /* get back how many osds > 0 */
1393 int ret
= ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, NULL
, 0);
1396 /* full stripe extent */
1398 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, osds
, ret
));
1400 ASSERT_GT(ceph_get_osd_crush_location(cmount
, 0, path
, 0), 0);
1401 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 0, path
, 1), -ERANGE
);
1403 for (int i
= 0; i
< ret
; i
++) {
1404 int len
= ceph_get_osd_crush_location(cmount
, osds
[i
], path
, sizeof(path
));
1408 std::string
type(path
+ pos
);
1409 ASSERT_GT((int)type
.size(), 0);
1410 pos
+= type
.size() + 1;
1412 std::string
name(path
+ pos
);
1413 ASSERT_GT((int)name
.size(), 0);
1414 pos
+= name
.size() + 1;
1418 ceph_close(cmount
, fd
);
1419 ceph_shutdown(cmount
);
1422 TEST(LibCephFS
, GetOsdAddr
) {
1423 struct ceph_mount_info
*cmount
;
1424 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1426 EXPECT_EQ(-ENOTCONN
, ceph_get_osd_addr(cmount
, 0, NULL
));
1428 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1429 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1430 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1432 ASSERT_EQ(-EINVAL
, ceph_get_osd_addr(cmount
, 0, NULL
));
1434 struct sockaddr_storage addr
;
1435 ASSERT_EQ(-ENOENT
, ceph_get_osd_addr(cmount
, -1, &addr
));
1436 ASSERT_EQ(-ENOENT
, ceph_get_osd_addr(cmount
, 9999999, &addr
));
1438 ASSERT_EQ(0, ceph_get_osd_addr(cmount
, 0, &addr
));
1440 ceph_shutdown(cmount
);
1443 TEST(LibCephFS
, OpenNoClose
) {
1444 struct ceph_mount_info
*cmount
;
1445 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1446 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1447 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1448 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1450 pid_t mypid
= getpid();
1452 sprintf(str_buf
, "open_no_close_dir%d", mypid
);
1453 ASSERT_EQ(0, ceph_mkdirs(cmount
, str_buf
, 0777));
1455 struct ceph_dir_result
*ls_dir
= NULL
;
1456 ASSERT_EQ(ceph_opendir(cmount
, str_buf
, &ls_dir
), 0);
1458 sprintf(str_buf
, "open_no_close_file%d", mypid
);
1459 int fd
= ceph_open(cmount
, str_buf
, O_RDONLY
|O_CREAT
, 0666);
1462 // shutdown should force close opened file/dir
1463 ceph_shutdown(cmount
);
1466 TEST(LibCephFS
, Nlink
) {
1467 struct ceph_mount_info
*cmount
;
1468 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1469 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1470 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1471 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1473 Inode
*root
, *dir
, *file
;
1475 ASSERT_EQ(ceph_ll_lookup_root(cmount
, &root
), 0);
1477 char dirname
[32], filename
[32], linkname
[32];
1478 sprintf(dirname
, "nlinkdir%x", getpid());
1479 sprintf(filename
, "nlinkorig%x", getpid());
1480 sprintf(linkname
, "nlinklink%x", getpid());
1482 struct ceph_statx stx
;
1484 UserPerm
*perms
= ceph_mount_perms(cmount
);
1486 ASSERT_EQ(ceph_ll_mkdir(cmount
, root
, dirname
, 0755, &dir
, &stx
, 0, 0, perms
), 0);
1487 ASSERT_EQ(ceph_ll_create(cmount
, dir
, filename
, 0666, O_RDWR
|O_CREAT
|O_EXCL
,
1488 &file
, &fh
, &stx
, CEPH_STATX_NLINK
, 0, perms
), 0);
1489 ASSERT_EQ(ceph_ll_close(cmount
, fh
), 0);
1490 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)1);
1492 ASSERT_EQ(ceph_ll_link(cmount
, file
, dir
, linkname
, perms
), 0);
1493 ASSERT_EQ(ceph_ll_getattr(cmount
, file
, &stx
, CEPH_STATX_NLINK
, 0, perms
), 0);
1494 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)2);
1496 ASSERT_EQ(ceph_ll_unlink(cmount
, dir
, linkname
, perms
), 0);
1497 ASSERT_EQ(ceph_ll_lookup(cmount
, dir
, filename
, &file
, &stx
,
1498 CEPH_STATX_NLINK
, 0, perms
), 0);
1499 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)1);
1501 ceph_shutdown(cmount
);
1504 TEST(LibCephFS
, SlashDotDot
) {
1505 struct ceph_mount_info
*cmount
;
1506 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1507 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1508 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1509 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1511 struct ceph_statx stx
;
1512 ASSERT_EQ(ceph_statx(cmount
, "/.", &stx
, CEPH_STATX_INO
, 0), 0);
1514 ino_t ino
= stx
.stx_ino
;
1515 ASSERT_EQ(ceph_statx(cmount
, "/..", &stx
, CEPH_STATX_INO
, 0), 0);
1517 /* At root, "." and ".." should be the same inode */
1518 ASSERT_EQ(ino
, stx
.stx_ino
);
1520 /* Test accessing the parent of an unlinked directory */
1521 char dir1
[32], dir2
[32];
1522 sprintf(dir1
, "/sldotdot%x", getpid());
1523 sprintf(dir2
, "%s/sub%x", dir1
, getpid());
1525 ASSERT_EQ(ceph_mkdir(cmount
, dir1
, 0755), 0);
1526 ASSERT_EQ(ceph_mkdir(cmount
, dir2
, 0755), 0);
1528 ASSERT_EQ(ceph_chdir(cmount
, dir2
), 0);
1530 /* Test behavior when unlinking cwd */
1531 struct ceph_dir_result
*rdir
;
1532 ASSERT_EQ(ceph_opendir(cmount
, ".", &rdir
), 0);
1533 ASSERT_EQ(ceph_rmdir(cmount
, dir2
), 0);
1536 struct dirent
*result
= ceph_readdir(cmount
, rdir
);
1537 ino
= result
->d_ino
;
1539 /* get ".." entry */
1540 result
= ceph_readdir(cmount
, rdir
);
1541 ASSERT_EQ(ino
, result
->d_ino
);
1542 ceph_closedir(cmount
, rdir
);
1544 /* Make sure it works same way when mounting subtree */
1545 ASSERT_EQ(ceph_unmount(cmount
), 0);
1546 ASSERT_EQ(ceph_mount(cmount
, dir1
), 0);
1547 ASSERT_EQ(ceph_statx(cmount
, "/..", &stx
, CEPH_STATX_INO
, 0), 0);
1549 /* Test readdir behavior */
1550 ASSERT_EQ(ceph_opendir(cmount
, "/", &rdir
), 0);
1551 result
= ceph_readdir(cmount
, rdir
);
1552 ASSERT_TRUE(result
!= NULL
);
1553 ASSERT_STREQ(result
->d_name
, ".");
1554 ino
= result
->d_ino
;
1555 result
= ceph_readdir(cmount
, rdir
);
1556 ASSERT_TRUE(result
!= NULL
);
1557 ASSERT_STREQ(result
->d_name
, "..");
1558 ASSERT_EQ(ino
, result
->d_ino
);
1560 ceph_shutdown(cmount
);
1564 timespec_eq(timespec
const& lhs
, timespec
const& rhs
)
1566 return lhs
.tv_sec
== rhs
.tv_sec
&& lhs
.tv_nsec
== rhs
.tv_nsec
;
1569 TEST(LibCephFS
, Btime
) {
1570 struct ceph_mount_info
*cmount
;
1571 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1572 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1573 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1574 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1577 sprintf(filename
, "/getattrx%x", getpid());
1579 ceph_unlink(cmount
, filename
);
1580 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1583 /* make sure fstatx works */
1584 struct ceph_statx stx
;
1586 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1587 ASSERT_TRUE(stx
.stx_mask
& (CEPH_STATX_CTIME
|CEPH_STATX_BTIME
));
1588 ASSERT_TRUE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1589 ceph_close(cmount
, fd
);
1591 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1592 ASSERT_TRUE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1593 ASSERT_TRUE(stx
.stx_mask
& (CEPH_STATX_CTIME
|CEPH_STATX_BTIME
));
1595 struct timespec old_btime
= stx
.stx_btime
;
1597 /* Now sleep, do a chmod and verify that the ctime changed, but btime didn't */
1599 ASSERT_EQ(ceph_chmod(cmount
, filename
, 0644), 0);
1600 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1601 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_BTIME
);
1602 ASSERT_TRUE(timespec_eq(stx
.stx_btime
, old_btime
));
1603 ASSERT_FALSE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1605 ceph_shutdown(cmount
);
1608 TEST(LibCephFS
, SetBtime
) {
1609 struct ceph_mount_info
*cmount
;
1610 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1611 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1612 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1613 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1616 sprintf(filename
, "/setbtime%x", getpid());
1618 ceph_unlink(cmount
, filename
);
1619 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1621 ceph_close(cmount
, fd
);
1623 struct ceph_statx stx
;
1624 struct timespec old_btime
= { 1, 2 };
1626 stx
.stx_btime
= old_btime
;
1628 ASSERT_EQ(ceph_setattrx(cmount
, filename
, &stx
, CEPH_SETATTR_BTIME
, 0), 0);
1630 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_BTIME
, 0), 0);
1631 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_BTIME
);
1632 ASSERT_TRUE(timespec_eq(stx
.stx_btime
, old_btime
));
1634 ceph_shutdown(cmount
);
1637 TEST(LibCephFS
, LazyStatx
) {
1638 struct ceph_mount_info
*cmount1
, *cmount2
;
1639 ASSERT_EQ(ceph_create(&cmount1
, NULL
), 0);
1640 ASSERT_EQ(ceph_create(&cmount2
, NULL
), 0);
1641 ASSERT_EQ(ceph_conf_read_file(cmount1
, NULL
), 0);
1642 ASSERT_EQ(ceph_conf_read_file(cmount2
, NULL
), 0);
1643 ASSERT_EQ(0, ceph_conf_parse_env(cmount1
, NULL
));
1644 ASSERT_EQ(0, ceph_conf_parse_env(cmount2
, NULL
));
1645 ASSERT_EQ(ceph_mount(cmount1
, "/"), 0);
1646 ASSERT_EQ(ceph_mount(cmount2
, "/"), 0);
1649 sprintf(filename
, "lazystatx%x", getpid());
1651 Inode
*root1
, *file1
, *root2
, *file2
;
1652 struct ceph_statx stx
;
1654 UserPerm
*perms1
= ceph_mount_perms(cmount1
);
1655 UserPerm
*perms2
= ceph_mount_perms(cmount2
);
1657 ASSERT_EQ(ceph_ll_lookup_root(cmount1
, &root1
), 0);
1658 ceph_ll_unlink(cmount1
, root1
, filename
, perms1
);
1659 ASSERT_EQ(ceph_ll_create(cmount1
, root1
, filename
, 0666, O_RDWR
|O_CREAT
|O_EXCL
,
1660 &file1
, &fh
, &stx
, 0, 0, perms1
), 0);
1661 ASSERT_EQ(ceph_ll_close(cmount1
, fh
), 0);
1663 ASSERT_EQ(ceph_ll_lookup_root(cmount2
, &root2
), 0);
1665 ASSERT_EQ(ceph_ll_lookup(cmount2
, root2
, filename
, &file2
, &stx
, CEPH_STATX_CTIME
, 0, perms2
), 0);
1667 struct timespec old_ctime
= stx
.stx_ctime
;
1670 * Now sleep, do a chmod on the first client and the see whether we get a
1671 * different ctime with a statx that uses AT_NO_ATTR_SYNC
1674 stx
.stx_mode
= 0644;
1675 ASSERT_EQ(ceph_ll_setattr(cmount1
, file1
, &stx
, CEPH_SETATTR_MODE
, perms1
), 0);
1677 ASSERT_EQ(ceph_ll_getattr(cmount2
, file2
, &stx
, CEPH_STATX_CTIME
, AT_NO_ATTR_SYNC
, perms2
), 0);
1678 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_CTIME
);
1679 ASSERT_TRUE(stx
.stx_ctime
.tv_sec
== old_ctime
.tv_sec
&&
1680 stx
.stx_ctime
.tv_nsec
== old_ctime
.tv_nsec
);
1682 ceph_shutdown(cmount1
);
1683 ceph_shutdown(cmount2
);
1686 TEST(LibCephFS
, ChangeAttr
) {
1687 struct ceph_mount_info
*cmount
;
1688 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1689 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1690 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1691 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1694 sprintf(filename
, "/changeattr%x", getpid());
1696 ceph_unlink(cmount
, filename
);
1697 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1700 struct ceph_statx stx
;
1701 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1702 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1704 uint64_t old_change_attr
= stx
.stx_version
;
1706 /* do chmod, and check whether change_attr changed */
1707 ASSERT_EQ(ceph_chmod(cmount
, filename
, 0644), 0);
1708 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1709 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1710 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1711 old_change_attr
= stx
.stx_version
;
1713 /* now do a write and see if it changed again */
1714 ASSERT_EQ(3, ceph_write(cmount
, fd
, "foo", 3, 0));
1715 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1716 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1717 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1718 old_change_attr
= stx
.stx_version
;
1720 /* Now truncate and check again */
1721 ASSERT_EQ(0, ceph_ftruncate(cmount
, fd
, 0));
1722 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1723 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1724 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1726 ceph_close(cmount
, fd
);
1727 ceph_shutdown(cmount
);
1730 TEST(LibCephFS
, DirChangeAttr
) {
1731 struct ceph_mount_info
*cmount
;
1732 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1733 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1734 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1735 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1737 char dirname
[32], filename
[32];
1738 sprintf(dirname
, "/dirchange%x", getpid());
1739 sprintf(filename
, "%s/foo", dirname
);
1741 ASSERT_EQ(ceph_mkdir(cmount
, dirname
, 0755), 0);
1743 struct ceph_statx stx
;
1744 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1745 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1747 uint64_t old_change_attr
= stx
.stx_version
;
1749 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1751 ceph_close(cmount
, fd
);
1753 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1754 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1755 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1757 old_change_attr
= stx
.stx_version
;
1759 ASSERT_EQ(ceph_unlink(cmount
, filename
), 0);
1760 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1761 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1762 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1764 ceph_shutdown(cmount
);
1767 TEST(LibCephFS
, SetSize
) {
1768 struct ceph_mount_info
*cmount
;
1769 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1770 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1771 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1772 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1775 sprintf(filename
, "/setsize%x", getpid());
1777 ceph_unlink(cmount
, filename
);
1778 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1781 struct ceph_statx stx
;
1782 uint64_t size
= 8388608;
1783 stx
.stx_size
= size
;
1784 ASSERT_EQ(ceph_fsetattrx(cmount
, fd
, &stx
, CEPH_SETATTR_SIZE
), 0);
1785 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_SIZE
, 0), 0);
1786 ASSERT_EQ(stx
.stx_size
, size
);
1788 ceph_close(cmount
, fd
);
1789 ceph_shutdown(cmount
);
1792 TEST(LibCephFS
, ClearSetuid
) {
1793 struct ceph_mount_info
*cmount
;
1794 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1795 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1796 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1797 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1800 ASSERT_EQ(ceph_ll_lookup_root(cmount
, &root
), 0);
1803 sprintf(filename
, "clearsetuid%x", getpid());
1807 struct ceph_statx stx
;
1808 const mode_t after_mode
= S_IRWXU
;
1809 const mode_t before_mode
= S_IRWXU
| S_ISUID
| S_ISGID
;
1810 const unsigned want
= CEPH_STATX_UID
|CEPH_STATX_GID
|CEPH_STATX_MODE
;
1811 UserPerm
*usercred
= ceph_mount_perms(cmount
);
1813 ceph_ll_unlink(cmount
, root
, filename
, usercred
);
1814 ASSERT_EQ(ceph_ll_create(cmount
, root
, filename
, before_mode
,
1815 O_RDWR
|O_CREAT
|O_EXCL
, &in
, &fh
, &stx
, want
, 0,
1818 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1821 ASSERT_EQ(ceph_ll_write(cmount
, fh
, 0, 3, "foo"), 3);
1822 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1823 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1824 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1827 stx
.stx_mode
= before_mode
;
1828 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, usercred
), 0);
1829 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1830 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1831 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1835 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_SIZE
, usercred
), 0);
1836 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1837 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1838 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1841 stx
.stx_mode
= before_mode
;
1842 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, usercred
), 0);
1843 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1844 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1845 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1847 // chown -- for this we need to be "root"
1848 UserPerm
*rootcred
= ceph_userperm_new(0, 0, 0, NULL
);
1849 ASSERT_TRUE(rootcred
);
1852 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_UID
|CEPH_SETATTR_GID
, rootcred
), 0);
1853 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1854 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1855 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1857 /* test chown with supplementary groups, and chown with/without exe bit */
1860 gid_t gids
[] = {65533,65532};
1861 UserPerm
*altcred
= ceph_userperm_new(u
, g
, sizeof gids
/ sizeof gids
[0], gids
);
1864 mode_t m
= S_ISGID
|S_ISUID
|S_IRUSR
|S_IWUSR
;
1866 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
|CEPH_SETATTR_UID
|CEPH_SETATTR_GID
, rootcred
), 0);
1867 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1868 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
1869 /* not dropped without exe bit */
1870 stx
.stx_gid
= gids
[0];
1871 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_GID
, altcred
), 0);
1872 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1873 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
1874 /* now check dropped with exe bit */
1875 m
= S_ISGID
|S_ISUID
|S_IRWXU
;
1877 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, altcred
), 0);
1878 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1879 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
1880 stx
.stx_gid
= gids
[1];
1881 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_GID
, altcred
), 0);
1882 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1883 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
&(S_IRWXU
|S_IRWXG
|S_IRWXO
));
1884 ceph_userperm_destroy(altcred
);
1886 ASSERT_EQ(ceph_ll_close(cmount
, fh
), 0);
1887 ceph_shutdown(cmount
);
1890 TEST(LibCephFS
, OperationsOnRoot
)
1892 struct ceph_mount_info
*cmount
;
1893 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1894 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1895 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1896 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1899 sprintf(dirname
, "/somedir%x", getpid());
1901 ASSERT_EQ(ceph_mkdir(cmount
, dirname
, 0755), 0);
1903 ASSERT_EQ(ceph_rmdir(cmount
, "/"), -EBUSY
);
1905 ASSERT_EQ(ceph_link(cmount
, "/", "/"), -EEXIST
);
1906 ASSERT_EQ(ceph_link(cmount
, dirname
, "/"), -EEXIST
);
1907 ASSERT_EQ(ceph_link(cmount
, "nonExisitingDir", "/"), -ENOENT
);
1909 ASSERT_EQ(ceph_unlink(cmount
, "/"), -EISDIR
);
1911 ASSERT_EQ(ceph_rename(cmount
, "/", "/"), -EBUSY
);
1912 ASSERT_EQ(ceph_rename(cmount
, dirname
, "/"), -EBUSY
);
1913 ASSERT_EQ(ceph_rename(cmount
, "nonExistingDir", "/"), -EBUSY
);
1914 ASSERT_EQ(ceph_rename(cmount
, "/", dirname
), -EBUSY
);
1915 ASSERT_EQ(ceph_rename(cmount
, "/", "nonExistingDir"), -EBUSY
);
1917 ASSERT_EQ(ceph_mkdir(cmount
, "/", 0777), -EEXIST
);
1919 ASSERT_EQ(ceph_mknod(cmount
, "/", 0, 0), -EEXIST
);
1921 ASSERT_EQ(ceph_symlink(cmount
, "/", "/"), -EEXIST
);
1922 ASSERT_EQ(ceph_symlink(cmount
, dirname
, "/"), -EEXIST
);
1923 ASSERT_EQ(ceph_symlink(cmount
, "nonExistingDir", "/"), -EEXIST
);
1925 ceph_shutdown(cmount
);
1928 static void shutdown_racer_func()
1930 const int niter
= 32;
1931 struct ceph_mount_info
*cmount
;
1934 for (i
= 0; i
< niter
; ++i
) {
1935 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1936 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1937 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1938 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1939 ceph_shutdown(cmount
);
1943 // See tracker #20988
1944 TEST(LibCephFS
, ShutdownRace
)
1946 const int nthreads
= 128;
1947 std::thread threads
[nthreads
];
1949 // Need a bunch of fd's for this test
1950 struct rlimit rold
, rnew
;
1951 ASSERT_EQ(getrlimit(RLIMIT_NOFILE
, &rold
), 0);
1953 rnew
.rlim_cur
= rnew
.rlim_max
;
1954 ASSERT_EQ(setrlimit(RLIMIT_NOFILE
, &rnew
), 0);
1956 for (int i
= 0; i
< nthreads
; ++i
)
1957 threads
[i
] = std::thread(shutdown_racer_func
);
1959 for (int i
= 0; i
< nthreads
; ++i
)
1961 ASSERT_EQ(setrlimit(RLIMIT_NOFILE
, &rold
), 0);