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>
41 #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
44 TEST(LibCephFS
, OpenEmptyComponent
) {
46 pid_t mypid
= getpid();
47 struct ceph_mount_info
*cmount
;
48 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
49 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
50 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
51 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
54 sprintf(c_dir
, "/open_test_%d", mypid
);
55 struct ceph_dir_result
*dirp
;
57 ASSERT_EQ(0, ceph_mkdirs(cmount
, c_dir
, 0777));
59 ASSERT_EQ(0, ceph_opendir(cmount
, c_dir
, &dirp
));
62 sprintf(c_path
, "/open_test_%d//created_file_%d", mypid
, mypid
);
63 int fd
= ceph_open(cmount
, c_path
, O_RDONLY
|O_CREAT
, 0666);
66 ASSERT_EQ(0, ceph_close(cmount
, fd
));
67 ASSERT_EQ(0, ceph_closedir(cmount
, dirp
));
68 ceph_shutdown(cmount
);
70 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
71 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
72 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
74 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
76 fd
= ceph_open(cmount
, c_path
, O_RDONLY
, 0666);
79 ASSERT_EQ(0, ceph_close(cmount
, fd
));
80 ceph_shutdown(cmount
);
83 TEST(LibCephFS
, OpenReadWrite
) {
84 struct ceph_mount_info
*cmount
;
85 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
86 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
87 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
88 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
91 sprintf(c_path
, "test_open_rdwr_%d", getpid());
92 int fd
= ceph_open(cmount
, c_path
, O_WRONLY
|O_CREAT
, 0666);
95 const char *out_buf
= "hello world";
96 size_t size
= strlen(out_buf
);
98 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), (int)size
);
99 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), -EBADF
);
100 ASSERT_EQ(0, ceph_close(cmount
, fd
));
102 fd
= ceph_open(cmount
, c_path
, O_RDONLY
, 0);
104 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), -EBADF
);
105 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), (int)size
);
106 ASSERT_EQ(0, ceph_close(cmount
, fd
));
108 fd
= ceph_open(cmount
, c_path
, O_RDWR
, 0);
110 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), (int)size
);
111 ASSERT_EQ(ceph_read(cmount
, fd
, in_buf
, sizeof(in_buf
), 0), (int)size
);
112 ASSERT_EQ(0, ceph_close(cmount
, fd
));
114 ceph_shutdown(cmount
);
117 TEST(LibCephFS
, MountNonExist
) {
119 struct ceph_mount_info
*cmount
;
121 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
122 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
123 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
124 ASSERT_NE(0, ceph_mount(cmount
, "/non-exist"));
125 ceph_shutdown(cmount
);
128 TEST(LibCephFS
, MountDouble
) {
130 struct ceph_mount_info
*cmount
;
132 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
133 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
134 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
135 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
136 ASSERT_EQ(-EISCONN
, ceph_mount(cmount
, "/"));
137 ceph_shutdown(cmount
);
140 TEST(LibCephFS
, MountRemount
) {
142 struct ceph_mount_info
*cmount
;
144 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
145 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
146 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
148 CephContext
*cct
= ceph_get_mount_context(cmount
);
149 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
150 ASSERT_EQ(0, ceph_unmount(cmount
));
152 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
153 ASSERT_EQ(cct
, ceph_get_mount_context(cmount
));
155 ceph_shutdown(cmount
);
158 TEST(LibCephFS
, UnmountUnmounted
) {
160 struct ceph_mount_info
*cmount
;
162 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
163 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
164 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
165 ASSERT_EQ(-ENOTCONN
, ceph_unmount(cmount
));
166 ceph_shutdown(cmount
);
169 TEST(LibCephFS
, ReleaseUnmounted
) {
171 struct ceph_mount_info
*cmount
;
173 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
174 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
175 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
176 ASSERT_EQ(0, ceph_release(cmount
));
179 TEST(LibCephFS
, ReleaseMounted
) {
181 struct ceph_mount_info
*cmount
;
183 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
184 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
185 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
186 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
187 ASSERT_EQ(-EISCONN
, ceph_release(cmount
));
188 ASSERT_EQ(0, ceph_unmount(cmount
));
189 ASSERT_EQ(0, ceph_release(cmount
));
192 TEST(LibCephFS
, UnmountRelease
) {
194 struct ceph_mount_info
*cmount
;
196 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
197 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
198 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
199 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
200 ASSERT_EQ(0, ceph_unmount(cmount
));
201 ASSERT_EQ(0, ceph_release(cmount
));
204 TEST(LibCephFS
, Mount
) {
205 struct ceph_mount_info
*cmount
;
206 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
207 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
208 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
209 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
210 ceph_shutdown(cmount
);
212 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
213 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
214 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
215 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
216 ceph_shutdown(cmount
);
219 TEST(LibCephFS
, OpenLayout
) {
220 struct ceph_mount_info
*cmount
;
221 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
222 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
223 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
224 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
227 char test_layout_file
[256];
228 sprintf(test_layout_file
, "test_layout_%d_b", getpid());
229 int fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
|O_WRONLY
, 0666, (1<<20), 7, (1<<20), NULL
);
232 ASSERT_LT(0, ceph_get_file_pool_name(cmount
, fd
, poolname
, sizeof(poolname
)));
233 ASSERT_LT(0, ceph_get_file_pool_name(cmount
, fd
, poolname
, 0));
235 /* on already-written file (ENOTEMPTY) */
236 ceph_write(cmount
, fd
, "hello world", 11, 0);
237 ceph_close(cmount
, fd
);
241 sprintf(xattrk
, "ceph.file.layout.stripe_unit");
242 sprintf(xattrv
, "65536");
243 ASSERT_EQ(-ENOTEMPTY
, ceph_setxattr(cmount
, test_layout_file
, xattrk
, (void *)xattrv
, 5, 0));
246 sprintf(test_layout_file
, "test_layout_%d_c", getpid());
247 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 1, 19, NULL
);
248 ASSERT_EQ(fd
, -EINVAL
);
251 sprintf(test_layout_file
, "test_layout_%d_d", getpid());
252 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), poolname
);
254 ceph_close(cmount
, fd
);
256 /* with metadata pool (invalid) */
257 sprintf(test_layout_file
, "test_layout_%d_e", getpid());
258 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), "metadata");
259 ASSERT_EQ(fd
, -EINVAL
);
261 /* with metadata pool (does not exist) */
262 sprintf(test_layout_file
, "test_layout_%d_f", getpid());
263 fd
= ceph_open_layout(cmount
, test_layout_file
, O_CREAT
, 0666, (1<<20), 7, (1<<20), "asdfjasdfjasdf");
264 ASSERT_EQ(fd
, -EINVAL
);
266 ceph_shutdown(cmount
);
269 TEST(LibCephFS
, DirLs
) {
271 pid_t mypid
= getpid();
273 struct ceph_mount_info
*cmount
;
274 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
275 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
276 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
277 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
279 struct ceph_dir_result
*ls_dir
= NULL
;
281 sprintf(foostr
, "dir_ls%d", mypid
);
282 ASSERT_EQ(ceph_opendir(cmount
, foostr
, &ls_dir
), -ENOENT
);
284 ASSERT_EQ(ceph_mkdir(cmount
, foostr
, 0777), 0);
285 struct ceph_statx stx
;
286 ASSERT_EQ(ceph_statx(cmount
, foostr
, &stx
, 0, 0), 0);
287 ASSERT_NE(S_ISDIR(stx
.stx_mode
), 0);
290 sprintf(barstr
, "dir_ls2%d", mypid
);
291 ASSERT_EQ(ceph_statx(cmount
, barstr
, &stx
, 0, AT_SYMLINK_NOFOLLOW
), -ENOENT
);
293 // insert files into directory and test open
295 int i
= 0, r
= rand() % 4096;
296 if (getenv("LIBCEPHFS_RAND")) {
297 r
= atoi(getenv("LIBCEPHFS_RAND"));
299 printf("rand: %d\n", r
);
302 sprintf(bazstr
, "dir_ls%d/dirf%d", mypid
, i
);
303 int fd
= ceph_open(cmount
, bazstr
, O_CREAT
|O_RDONLY
, 0666);
305 ASSERT_EQ(ceph_close(cmount
, fd
), 0);
307 // set file sizes for readdirplus
308 ceph_truncate(cmount
, bazstr
, i
);
311 ASSERT_EQ(ceph_opendir(cmount
, foostr
, &ls_dir
), 0);
313 // not guaranteed to get . and .. first, but its a safe assumption in this case
314 struct dirent
*result
= ceph_readdir(cmount
, ls_dir
);
315 ASSERT_TRUE(result
!= NULL
);
316 ASSERT_STREQ(result
->d_name
, ".");
317 result
= ceph_readdir(cmount
, ls_dir
);
318 ASSERT_TRUE(result
!= NULL
);
319 ASSERT_STREQ(result
->d_name
, "..");
321 std::vector
<std::string
> entries
;
322 std::map
<std::string
, int64_t> offset_map
;
323 int64_t offset
= ceph_telldir(cmount
, ls_dir
);
324 for(i
= 0; i
< r
; ++i
) {
325 result
= ceph_readdir(cmount
, ls_dir
);
326 ASSERT_TRUE(result
!= NULL
);
327 entries
.push_back(result
->d_name
);
328 offset_map
[result
->d_name
] = offset
;
329 offset
= ceph_telldir(cmount
, ls_dir
);
332 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) == NULL
);
333 offset
= ceph_telldir(cmount
, ls_dir
);
335 ASSERT_EQ(offset_map
.size(), entries
.size());
336 for(i
= 0; i
< r
; ++i
) {
337 sprintf(bazstr
, "dirf%d", i
);
338 ASSERT_TRUE(offset_map
.count(bazstr
) == 1);
342 ceph_seekdir(cmount
, ls_dir
, offset
);
343 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) == NULL
);
345 for (auto p
= offset_map
.begin(); p
!= offset_map
.end(); ++p
) {
346 ceph_seekdir(cmount
, ls_dir
, p
->second
);
347 result
= ceph_readdir(cmount
, ls_dir
);
348 ASSERT_TRUE(result
!= NULL
);
349 std::string
d_name(result
->d_name
);
350 ASSERT_EQ(p
->first
, d_name
);
354 ceph_rewinddir(cmount
, ls_dir
);
356 result
= ceph_readdir(cmount
, ls_dir
);
357 ASSERT_TRUE(result
!= NULL
);
358 ASSERT_STREQ(result
->d_name
, ".");
359 result
= ceph_readdir(cmount
, ls_dir
);
360 ASSERT_TRUE(result
!= NULL
);
361 ASSERT_STREQ(result
->d_name
, "..");
363 ceph_rewinddir(cmount
, ls_dir
);
365 int t
= ceph_telldir(cmount
, ls_dir
);
368 ASSERT_TRUE(ceph_readdir(cmount
, ls_dir
) != NULL
);
370 // test seekdir - move back to the beginning
371 ceph_seekdir(cmount
, ls_dir
, t
);
374 struct dirent
*getdents_entries
;
375 size_t getdents_entries_len
= (r
+ 2) * sizeof(*getdents_entries
);
376 getdents_entries
= (struct dirent
*)malloc(getdents_entries_len
);
379 std::vector
<std::string
> found
;
381 int len
= ceph_getdents(cmount
, ls_dir
, (char *)getdents_entries
, getdents_entries_len
);
385 ASSERT_TRUE((len
% sizeof(*getdents_entries
)) == 0);
386 int n
= len
/ sizeof(*getdents_entries
);
389 ASSERT_STREQ(getdents_entries
[0].d_name
, ".");
390 ASSERT_STREQ(getdents_entries
[1].d_name
, "..");
396 for(; j
< n
; ++i
, ++j
) {
397 const char *name
= getdents_entries
[j
].d_name
;
398 found
.push_back(name
);
401 ASSERT_EQ(found
, entries
);
402 free(getdents_entries
);
405 ceph_rewinddir(cmount
, ls_dir
);
407 result
= ceph_readdir(cmount
, ls_dir
);
408 ASSERT_TRUE(result
!= NULL
);
409 ASSERT_STREQ(result
->d_name
, ".");
410 result
= ceph_readdir(cmount
, ls_dir
);
411 ASSERT_TRUE(result
!= NULL
);
412 ASSERT_STREQ(result
->d_name
, "..");
417 int len
= ceph_readdir_r(cmount
, ls_dir
, &rdent
);
421 found
.push_back(rdent
.d_name
);
423 ASSERT_EQ(found
, entries
);
426 ceph_rewinddir(cmount
, ls_dir
);
428 result
= ceph_readdir(cmount
, ls_dir
);
429 ASSERT_TRUE(result
!= NULL
);
430 ASSERT_STREQ(result
->d_name
, ".");
431 result
= ceph_readdir(cmount
, ls_dir
);
432 ASSERT_TRUE(result
!= NULL
);
433 ASSERT_STREQ(result
->d_name
, "..");
438 struct ceph_statx stx
;
439 int len
= ceph_readdirplus_r(cmount
, ls_dir
, &rdent
, &stx
,
440 CEPH_STATX_SIZE
, AT_NO_ATTR_SYNC
, NULL
);
444 const char *name
= rdent
.d_name
;
445 found
.push_back(name
);
447 sscanf(name
, "dirf%d", &size
);
448 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_SIZE
);
449 ASSERT_EQ(stx
.stx_size
, (size_t)size
);
450 ASSERT_EQ(stx
.stx_ino
, rdent
.d_ino
);
451 //ASSERT_EQ(st.st_mode, (mode_t)0666);
453 ASSERT_EQ(found
, entries
);
455 ASSERT_EQ(ceph_closedir(cmount
, ls_dir
), 0);
457 ceph_shutdown(cmount
);
460 TEST(LibCephFS
, ManyNestedDirs
) {
461 struct ceph_mount_info
*cmount
;
462 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
463 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
464 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
465 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
467 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";
468 ASSERT_EQ(ceph_mkdirs(cmount
, many_path
, 0755), 0);
473 ASSERT_EQ(ceph_chdir(cmount
, "a"), 0);
475 struct ceph_dir_result
*dirp
;
476 ASSERT_EQ(ceph_opendir(cmount
, "a", &dirp
), 0);
477 struct dirent
*dent
= ceph_readdir(cmount
, dirp
);
478 ASSERT_TRUE(dent
!= NULL
);
479 ASSERT_STREQ(dent
->d_name
, ".");
480 dent
= ceph_readdir(cmount
, dirp
);
481 ASSERT_TRUE(dent
!= NULL
);
482 ASSERT_STREQ(dent
->d_name
, "..");
483 dent
= ceph_readdir(cmount
, dirp
);
484 ASSERT_TRUE(dent
!= NULL
);
485 ASSERT_STREQ(dent
->d_name
, "a");
486 ASSERT_EQ(ceph_closedir(cmount
, dirp
), 0);
489 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");
491 ASSERT_EQ(ceph_chdir(cmount
, "a/a/a"), 0);
493 for(i
= 0; i
< 39; ++i
) {
494 ASSERT_EQ(ceph_chdir(cmount
, ".."), 0);
495 ASSERT_EQ(ceph_rmdir(cmount
, "a"), 0);
498 ASSERT_EQ(ceph_chdir(cmount
, "/"), 0);
500 ASSERT_EQ(ceph_rmdir(cmount
, "a/a/a"), 0);
502 ceph_shutdown(cmount
);
505 TEST(LibCephFS
, Xattrs
) {
506 struct ceph_mount_info
*cmount
;
507 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
508 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
509 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
510 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
512 char test_xattr_file
[256];
513 sprintf(test_xattr_file
, "test_xattr_%d", getpid());
514 int fd
= ceph_open(cmount
, test_xattr_file
, O_CREAT
, 0666);
520 for(; i
< 'a'+26; ++i
) {
521 sprintf(xattrk
, "user.test_xattr_%c", i
);
522 int len
= sprintf(xattrv
, "testxattr%c", i
);
523 ASSERT_EQ(ceph_setxattr(cmount
, test_xattr_file
, xattrk
, (void *) xattrv
, len
, XATTR_CREATE
), 0);
526 // zero size should return required buffer length
527 int len_needed
= ceph_listxattr(cmount
, test_xattr_file
, NULL
, 0);
528 ASSERT_GT(len_needed
, 0);
530 // buffer size smaller than needed should fail
531 char xattrlist
[128*26];
532 ASSERT_GT(sizeof(xattrlist
), (size_t)len_needed
);
533 int len
= ceph_listxattr(cmount
, test_xattr_file
, xattrlist
, len_needed
- 1);
534 ASSERT_EQ(-ERANGE
, len
);
536 len
= ceph_listxattr(cmount
, test_xattr_file
, xattrlist
, sizeof(xattrlist
));
537 ASSERT_EQ(len
, len_needed
);
542 // ceph.* xattrs should not be listed
543 ASSERT_NE(strncmp(p
, "ceph.", 5), 0);
545 sprintf(xattrk
, "user.test_xattr_%c", i
);
546 ASSERT_STREQ(p
, xattrk
);
549 std::cout
<< "getting attr " << p
<< std::endl
;
550 int alen
= ceph_getxattr(cmount
, test_xattr_file
, p
, (void *) gxattrv
, 128);
552 sprintf(xattrv
, "testxattr%c", i
);
553 ASSERT_TRUE(!strncmp(xattrv
, gxattrv
, alen
));
563 for(i
= 'a'; i
< 'a'+26; ++i
) {
564 sprintf(xattrk
, "user.test_xattr_%c", i
);
565 ASSERT_EQ(ceph_removexattr(cmount
, test_xattr_file
, xattrk
), 0);
568 ceph_close(cmount
, fd
);
569 ceph_shutdown(cmount
);
573 TEST(LibCephFS
, Xattrs_ll
) {
574 struct ceph_mount_info
*cmount
;
575 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
576 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
577 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
578 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
580 char test_xattr_file
[256];
581 sprintf(test_xattr_file
, "test_xattr_%d", getpid());
582 int fd
= ceph_open(cmount
, test_xattr_file
, O_CREAT
, 0666);
584 ceph_close(cmount
, fd
);
587 Inode
*existent_file_handle
= NULL
;
589 int res
= ceph_ll_lookup_root(cmount
, &root
);
592 UserPerm
*perms
= ceph_mount_perms(cmount
);
593 struct ceph_statx stx
;
595 res
= ceph_ll_lookup(cmount
, root
, test_xattr_file
, &existent_file_handle
,
599 const char *valid_name
= "user.attrname";
600 const char *value
= "attrvalue";
601 char value_buf
[256] = { 0 };
603 res
= ceph_ll_setxattr(cmount
, existent_file_handle
, valid_name
, value
, strlen(value
), 0, perms
);
606 res
= ceph_ll_getxattr(cmount
, existent_file_handle
, valid_name
, value_buf
, 256, perms
);
607 ASSERT_EQ(res
, (int)strlen(value
));
609 value_buf
[res
] = '\0';
610 ASSERT_STREQ(value_buf
, value
);
612 ceph_shutdown(cmount
);
615 TEST(LibCephFS
, LstatSlashdot
) {
616 struct ceph_mount_info
*cmount
;
617 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
618 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
619 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
620 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
622 struct ceph_statx stx
;
623 ASSERT_EQ(ceph_statx(cmount
, "/.", &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
624 ASSERT_EQ(ceph_statx(cmount
, ".", &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
626 ceph_shutdown(cmount
);
629 TEST(LibCephFS
, StatDirNlink
) {
630 struct ceph_mount_info
*cmount
;
631 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
632 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
633 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
634 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
637 sprintf(test_dir1
, "dir1_symlinks_%d", getpid());
638 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
640 int fd
= ceph_open(cmount
, test_dir1
, O_DIRECTORY
|O_RDONLY
, 0);
642 struct ceph_statx stx
;
643 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
644 ASSERT_EQ(stx
.stx_nlink
, 2u);
648 sprintf(test_dir2
, "%s/.", test_dir1
);
649 ASSERT_EQ(ceph_statx(cmount
, test_dir2
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
650 ASSERT_EQ(stx
.stx_nlink
, 2u);
655 sprintf(test_dir2
, "%s/1", test_dir1
);
656 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
657 ASSERT_EQ(ceph_statx(cmount
, test_dir2
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
658 ASSERT_EQ(stx
.stx_nlink
, 2u);
659 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
660 ASSERT_EQ(stx
.stx_nlink
, 3u);
661 sprintf(test_dir2
, "%s/2", test_dir1
);
662 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
663 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
664 ASSERT_EQ(stx
.stx_nlink
, 4u);
665 sprintf(test_dir2
, "%s/1/1", test_dir1
);
666 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
667 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
668 ASSERT_EQ(stx
.stx_nlink
, 4u);
669 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
670 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
671 ASSERT_EQ(stx
.stx_nlink
, 4u);
672 sprintf(test_dir2
, "%s/1", test_dir1
);
673 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
674 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
675 ASSERT_EQ(stx
.stx_nlink
, 3u);
676 sprintf(test_dir2
, "%s/2", test_dir1
);
677 ASSERT_EQ(ceph_rmdir(cmount
, test_dir2
), 0);
678 ASSERT_EQ(ceph_statx(cmount
, test_dir1
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
679 ASSERT_EQ(stx
.stx_nlink
, 2u);
682 ASSERT_EQ(ceph_rmdir(cmount
, test_dir1
), 0);
683 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_NLINK
, AT_SYMLINK_NOFOLLOW
), 0);
684 ASSERT_EQ(stx
.stx_nlink
, 0u);
686 ceph_close(cmount
, fd
);
688 ceph_shutdown(cmount
);
691 TEST(LibCephFS
, DoubleChmod
) {
693 struct ceph_mount_info
*cmount
;
694 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
695 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
696 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
697 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
700 sprintf(test_file
, "test_perms_%d", getpid());
702 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
706 const char *bytes
= "foobarbaz";
707 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
709 ceph_close(cmount
, fd
);
711 // set perms to read but can't write
712 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0400), 0);
714 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
715 ASSERT_EQ(fd
, -EACCES
);
717 fd
= ceph_open(cmount
, test_file
, O_RDONLY
, 0);
721 int ret
= ceph_read(cmount
, fd
, buf
, 100, 0);
722 ASSERT_EQ(ret
, (int)strlen(bytes
));
724 ASSERT_STREQ(buf
, bytes
);
726 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), -EBADF
);
728 ceph_close(cmount
, fd
);
730 // reset back to writeable
731 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0600), 0);
733 // ensure perms are correct
734 struct ceph_statx stx
;
735 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
, CEPH_STATX_MODE
, AT_SYMLINK_NOFOLLOW
), 0);
736 ASSERT_EQ(stx
.stx_mode
, 0100600U);
738 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
741 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
742 ceph_close(cmount
, fd
);
744 ceph_shutdown(cmount
);
747 TEST(LibCephFS
, Fchmod
) {
748 struct ceph_mount_info
*cmount
;
749 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
750 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
751 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
752 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
755 sprintf(test_file
, "test_perms_%d", getpid());
757 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
761 const char *bytes
= "foobarbaz";
762 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
764 // set perms to read but can't write
765 ASSERT_EQ(ceph_fchmod(cmount
, fd
, 0400), 0);
768 int ret
= ceph_read(cmount
, fd
, buf
, 100, 0);
769 ASSERT_EQ(ret
, (int)strlen(bytes
));
771 ASSERT_STREQ(buf
, bytes
);
773 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
775 ceph_close(cmount
, fd
);
777 ASSERT_EQ(ceph_open(cmount
, test_file
, O_RDWR
, 0), -EACCES
);
779 // reset back to writeable
780 ASSERT_EQ(ceph_chmod(cmount
, test_file
, 0600), 0);
782 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
785 ASSERT_EQ(ceph_write(cmount
, fd
, bytes
, strlen(bytes
), 0), (int)strlen(bytes
));
786 ceph_close(cmount
, fd
);
788 ceph_shutdown(cmount
);
791 TEST(LibCephFS
, Fchown
) {
792 struct ceph_mount_info
*cmount
;
793 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
794 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
795 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
796 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
799 sprintf(test_file
, "test_fchown_%d", getpid());
801 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
804 // set perms to readable and writeable only by owner
805 ASSERT_EQ(ceph_fchmod(cmount
, fd
, 0600), 0);
807 // change ownership to nobody -- we assume nobody exists and id is always 65534
808 ASSERT_EQ(ceph_conf_set(cmount
, "client_permissions", "0"), 0);
809 ASSERT_EQ(ceph_fchown(cmount
, fd
, 65534, 65534), 0);
810 ASSERT_EQ(ceph_conf_set(cmount
, "client_permissions", "1"), 0);
812 ceph_close(cmount
, fd
);
814 fd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
815 ASSERT_EQ(fd
, -EACCES
);
817 ceph_shutdown(cmount
);
820 #if defined(__linux__) && defined(O_PATH)
821 TEST(LibCephFS
, FlagO_PATH
) {
822 struct ceph_mount_info
*cmount
;
824 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
825 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
826 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
827 ASSERT_EQ(0, ceph_mount(cmount
, NULL
));
829 char test_file
[PATH_MAX
];
830 sprintf(test_file
, "test_oflag_%d", getpid());
832 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
|O_PATH
, 0666);
833 ASSERT_EQ(-ENOENT
, fd
);
835 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
837 ASSERT_EQ(0, ceph_close(cmount
, fd
));
839 // ok, the file has been created. perform real checks now
840 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
|O_PATH
, 0666);
844 ASSERT_EQ(-EBADF
, ceph_read(cmount
, fd
, buf
, sizeof(buf
), 0));
845 ASSERT_EQ(-EBADF
, ceph_write(cmount
, fd
, buf
, sizeof(buf
), 0));
847 // set perms to readable and writeable only by owner
848 ASSERT_EQ(-EBADF
, ceph_fchmod(cmount
, fd
, 0600));
850 // change ownership to nobody -- we assume nobody exists and id is always 65534
851 ASSERT_EQ(-EBADF
, ceph_fchown(cmount
, fd
, 65534, 65534));
854 ASSERT_EQ(-EBADF
, ceph_fsync(cmount
, fd
, false));
856 struct ceph_statx stx
;
857 ASSERT_EQ(0, ceph_fstatx(cmount
, fd
, &stx
, 0, 0));
859 ASSERT_EQ(0, ceph_close(cmount
, fd
));
860 ceph_shutdown(cmount
);
864 TEST(LibCephFS
, Symlinks
) {
865 struct ceph_mount_info
*cmount
;
866 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
867 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
868 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
869 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
872 sprintf(test_file
, "test_symlinks_%d", getpid());
874 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
877 ceph_close(cmount
, fd
);
879 char test_symlink
[256];
880 sprintf(test_symlink
, "test_symlinks_sym_%d", getpid());
882 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
884 // test the O_NOFOLLOW case
885 fd
= ceph_open(cmount
, test_symlink
, O_NOFOLLOW
, 0);
886 ASSERT_EQ(fd
, -ELOOP
);
888 // stat the original file
889 struct ceph_statx stx_orig
;
890 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
892 struct ceph_statx stx_symlink_orig
;
893 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_symlink_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
894 // ensure the statx bufs are equal
895 ASSERT_EQ(memcmp(&stx_orig
, &stx_symlink_orig
, sizeof(stx_orig
)), 0);
897 sprintf(test_file
, "/test_symlinks_abs_%d", getpid());
899 fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
902 ceph_close(cmount
, fd
);
904 sprintf(test_symlink
, "/test_symlinks_abs_sym_%d", getpid());
906 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
908 // stat the original file
909 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
911 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_symlink_orig
, CEPH_STATX_ALL_STATS
, 0), 0);
912 // ensure the statx bufs are equal
913 ASSERT_TRUE(!memcmp(&stx_orig
, &stx_symlink_orig
, sizeof(stx_orig
)));
916 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx_orig
, CEPH_STATX_ALL_STATS
, AT_SYMLINK_NOFOLLOW
), 0);
917 ASSERT_TRUE(S_ISLNK(stx_orig
.stx_mode
));
919 ceph_shutdown(cmount
);
922 TEST(LibCephFS
, DirSyms
) {
923 struct ceph_mount_info
*cmount
;
924 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
925 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
926 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
927 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
930 sprintf(test_dir1
, "dir1_symlinks_%d", getpid());
932 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
934 char test_symdir
[256];
935 sprintf(test_symdir
, "symdir_symlinks_%d", getpid());
937 ASSERT_EQ(ceph_symlink(cmount
, test_dir1
, test_symdir
), 0);
940 sprintf(test_file
, "/symdir_symlinks_%d/test_symdir_file", getpid());
941 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0600);
943 ceph_close(cmount
, fd
);
945 struct ceph_statx stx
;
946 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
, 0, AT_SYMLINK_NOFOLLOW
), 0);
948 // ensure that its a file not a directory we get back
949 ASSERT_TRUE(S_ISREG(stx
.stx_mode
));
951 ceph_shutdown(cmount
);
954 TEST(LibCephFS
, LoopSyms
) {
955 struct ceph_mount_info
*cmount
;
956 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
957 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
958 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
959 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
962 sprintf(test_dir1
, "dir1_loopsym_%d", getpid());
964 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0700), 0);
967 sprintf(test_dir2
, "/dir1_loopsym_%d/loop_dir", getpid());
969 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0700), 0);
971 // symlink it itself: /path/to/mysym -> /path/to/mysym
972 char test_symdir
[256];
973 sprintf(test_symdir
, "/dir1_loopsym_%d/loop_dir/symdir", getpid());
975 ASSERT_EQ(ceph_symlink(cmount
, test_symdir
, test_symdir
), 0);
978 sprintf(test_file
, "/dir1_loopsym_%d/loop_dir/symdir/test_loopsym_file", getpid());
979 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0600);
980 ASSERT_EQ(fd
, -ELOOP
);
982 // loop: /a -> /b, /b -> /c, /c -> /a
983 char a
[264], b
[264], c
[264];
984 sprintf(a
, "/%s/a", test_dir1
);
985 sprintf(b
, "/%s/b", test_dir1
);
986 sprintf(c
, "/%s/c", test_dir1
);
987 ASSERT_EQ(ceph_symlink(cmount
, a
, b
), 0);
988 ASSERT_EQ(ceph_symlink(cmount
, b
, c
), 0);
989 ASSERT_EQ(ceph_symlink(cmount
, c
, a
), 0);
990 ASSERT_EQ(ceph_open(cmount
, a
, O_RDWR
, 0), -ELOOP
);
992 ceph_shutdown(cmount
);
995 TEST(LibCephFS
, HardlinkNoOriginal
) {
997 int mypid
= getpid();
999 struct ceph_mount_info
*cmount
;
1000 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1001 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1002 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1003 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1006 sprintf(dir
, "/test_rmdirfail%d", mypid
);
1007 ASSERT_EQ(ceph_mkdir(cmount
, dir
, 0777), 0);
1009 ASSERT_EQ(ceph_chdir(cmount
, dir
), 0);
1011 int fd
= ceph_open(cmount
, "f1", O_CREAT
, 0644);
1014 ceph_close(cmount
, fd
);
1017 ASSERT_EQ(ceph_link(cmount
, "f1", "hardl1"), 0);
1019 // remove file link points to
1020 ASSERT_EQ(ceph_unlink(cmount
, "f1"), 0);
1022 ceph_shutdown(cmount
);
1025 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1026 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1027 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1028 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1029 ASSERT_EQ(ceph_chdir(cmount
, dir
), 0);
1030 ASSERT_EQ(ceph_unlink(cmount
, "hardl1"), 0);
1031 ASSERT_EQ(ceph_rmdir(cmount
, dir
), 0);
1033 ceph_shutdown(cmount
);
1036 TEST(LibCephFS
, BadArgument
) {
1037 struct ceph_mount_info
*cmount
;
1038 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1039 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1040 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1041 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1043 int fd
= ceph_open(cmount
, "test_file", O_CREAT
|O_RDWR
, 0666);
1046 ASSERT_EQ(ceph_write(cmount
, fd
, buf
, sizeof(buf
), 0), (int)sizeof(buf
));
1047 ASSERT_EQ(ceph_read(cmount
, fd
, buf
, 0, 5), 0);
1048 ceph_close(cmount
, fd
);
1049 ASSERT_EQ(ceph_unlink(cmount
, "test_file"), 0);
1051 ceph_shutdown(cmount
);
1054 TEST(LibCephFS
, BadFileDesc
) {
1055 struct ceph_mount_info
*cmount
;
1056 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1057 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1058 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1059 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1061 ASSERT_EQ(ceph_fchmod(cmount
, -1, 0655), -EBADF
);
1062 ASSERT_EQ(ceph_close(cmount
, -1), -EBADF
);
1063 ASSERT_EQ(ceph_lseek(cmount
, -1, 0, SEEK_SET
), -EBADF
);
1066 ASSERT_EQ(ceph_read(cmount
, -1, buf
, 0, 0), -EBADF
);
1067 ASSERT_EQ(ceph_write(cmount
, -1, buf
, 0, 0), -EBADF
);
1069 ASSERT_EQ(ceph_ftruncate(cmount
, -1, 0), -EBADF
);
1070 ASSERT_EQ(ceph_fsync(cmount
, -1, 0), -EBADF
);
1072 struct ceph_statx stx
;
1073 ASSERT_EQ(ceph_fstatx(cmount
, -1, &stx
, 0, 0), -EBADF
);
1075 struct sockaddr_storage addr
;
1076 ASSERT_EQ(ceph_get_file_stripe_address(cmount
, -1, 0, &addr
, 1), -EBADF
);
1078 ASSERT_EQ(ceph_get_file_stripe_unit(cmount
, -1), -EBADF
);
1079 ASSERT_EQ(ceph_get_file_pool(cmount
, -1), -EBADF
);
1081 ASSERT_EQ(ceph_get_file_pool_name(cmount
, -1, poolname
, sizeof(poolname
)), -EBADF
);
1082 ASSERT_EQ(ceph_get_file_replication(cmount
, -1), -EBADF
);
1083 ASSERT_EQ(ceph_get_file_object_size(cmount
, -1), -EBADF
);
1084 int stripe_unit
, stripe_count
, object_size
, pg_pool
;
1085 ASSERT_EQ(ceph_get_file_layout(cmount
, -1, &stripe_unit
, &stripe_count
, &object_size
, &pg_pool
), -EBADF
);
1086 ASSERT_EQ(ceph_get_file_stripe_count(cmount
, -1), -EBADF
);
1088 ceph_shutdown(cmount
);
1091 TEST(LibCephFS
, ReadEmptyFile
) {
1092 struct ceph_mount_info
*cmount
;
1093 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1094 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1095 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1096 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1098 // test the read_sync path in the client for zero files
1099 ASSERT_EQ(ceph_conf_set(cmount
, "client_debug_force_sync_read", "true"), 0);
1101 int mypid
= getpid();
1104 sprintf(testf
, "test_reademptyfile%d", mypid
);
1105 int fd
= ceph_open(cmount
, testf
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644);
1108 ceph_close(cmount
, fd
);
1110 fd
= ceph_open(cmount
, testf
, O_RDONLY
, 0);
1114 ASSERT_EQ(ceph_read(cmount
, fd
, buf
, 4096, 0), 0);
1116 ceph_close(cmount
, fd
);
1117 ceph_shutdown(cmount
);
1120 TEST(LibCephFS
, PreadvPwritev
) {
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 int mypid
= getpid();
1130 sprintf(testf
, "test_preadvpwritevfile%d", mypid
);
1131 int fd
= ceph_open(cmount
, testf
, O_CREAT
|O_RDWR
, 0666);
1134 char out0
[] = "hello ";
1135 char out1
[] = "world\n";
1136 struct iovec iov_out
[2] = {
1137 {out0
, sizeof(out0
)},
1138 {out1
, sizeof(out1
)},
1140 char in0
[sizeof(out0
)];
1141 char in1
[sizeof(out1
)];
1142 struct iovec iov_in
[2] = {
1146 ssize_t nwritten
= iov_out
[0].iov_len
+ iov_out
[1].iov_len
;
1147 ssize_t nread
= iov_in
[0].iov_len
+ iov_in
[1].iov_len
;
1149 ASSERT_EQ(ceph_pwritev(cmount
, fd
, iov_out
, 2, 0), nwritten
);
1150 ASSERT_EQ(ceph_preadv(cmount
, fd
, iov_in
, 2, 0), nread
);
1151 ASSERT_EQ(0, strncmp((const char*)iov_in
[0].iov_base
, (const char*)iov_out
[0].iov_base
, iov_out
[0].iov_len
));
1152 ASSERT_EQ(0, strncmp((const char*)iov_in
[1].iov_base
, (const char*)iov_out
[1].iov_base
, iov_out
[1].iov_len
));
1154 ceph_close(cmount
, fd
);
1155 ceph_shutdown(cmount
);
1158 TEST(LibCephFS
, LlreadvLlwritev
) {
1159 struct ceph_mount_info
*cmount
;
1160 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1161 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1162 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1163 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1165 int mypid
= getpid();
1168 sprintf(filename
, "test_llreadvllwritevfile%u", mypid
);
1171 ASSERT_EQ(ceph_ll_lookup_root(cmount
, &root
), 0);
1174 struct ceph_statx stx
;
1175 UserPerm
*perms
= ceph_mount_perms(cmount
);
1177 ASSERT_EQ(ceph_ll_create(cmount
, root
, filename
, 0666,
1178 O_RDWR
|O_CREAT
|O_TRUNC
, &file
, &fh
, &stx
, 0, 0, perms
), 0);
1180 /* Reopen read-only */
1181 char out0
[] = "hello ";
1182 char out1
[] = "world\n";
1183 struct iovec iov_out
[2] = {
1184 {out0
, sizeof(out0
)},
1185 {out1
, sizeof(out1
)},
1187 char in0
[sizeof(out0
)];
1188 char in1
[sizeof(out1
)];
1189 struct iovec iov_in
[2] = {
1193 ssize_t nwritten
= iov_out
[0].iov_len
+ iov_out
[1].iov_len
;
1194 ssize_t nread
= iov_in
[0].iov_len
+ iov_in
[1].iov_len
;
1196 ASSERT_EQ(ceph_ll_writev(cmount
, fh
, iov_out
, 2, 0), nwritten
);
1197 ASSERT_EQ(ceph_ll_readv(cmount
, fh
, iov_in
, 2, 0), nread
);
1198 ASSERT_EQ(0, strncmp((const char*)iov_in
[0].iov_base
, (const char*)iov_out
[0].iov_base
, iov_out
[0].iov_len
));
1199 ASSERT_EQ(0, strncmp((const char*)iov_in
[1].iov_base
, (const char*)iov_out
[1].iov_base
, iov_out
[1].iov_len
));
1201 ceph_ll_close(cmount
, fh
);
1202 ceph_shutdown(cmount
);
1205 TEST(LibCephFS
, StripeUnitGran
) {
1206 struct ceph_mount_info
*cmount
;
1207 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1208 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1209 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1210 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1211 ASSERT_GT(ceph_get_stripe_unit_granularity(cmount
), 0);
1212 ceph_shutdown(cmount
);
1215 TEST(LibCephFS
, Rename
) {
1216 struct ceph_mount_info
*cmount
;
1217 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1218 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1219 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1220 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1222 int mypid
= getpid();
1226 /* make a source file */
1227 sprintf(path_src
, "test_rename_src%d", mypid
);
1228 int fd
= ceph_open(cmount
, path_src
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0777);
1230 ASSERT_EQ(0, ceph_close(cmount
, fd
));
1232 /* rename to a new dest path */
1233 sprintf(path_dst
, "test_rename_dst%d", mypid
);
1234 ASSERT_EQ(0, ceph_rename(cmount
, path_src
, path_dst
));
1236 /* test that dest path exists */
1237 struct ceph_statx stx
;
1238 ASSERT_EQ(0, ceph_statx(cmount
, path_dst
, &stx
, 0, 0));
1240 /* test that src path doesn't exist */
1241 ASSERT_EQ(-ENOENT
, ceph_statx(cmount
, path_src
, &stx
, 0, AT_SYMLINK_NOFOLLOW
));
1243 /* rename with non-existent source path */
1244 ASSERT_EQ(-ENOENT
, ceph_rename(cmount
, path_src
, path_dst
));
1246 ASSERT_EQ(0, ceph_unlink(cmount
, path_dst
));
1247 ceph_shutdown(cmount
);
1250 TEST(LibCephFS
, UseUnmounted
) {
1251 struct ceph_mount_info
*cmount
;
1252 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1253 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1254 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1256 struct statvfs stvfs
;
1257 EXPECT_EQ(-ENOTCONN
, ceph_statfs(cmount
, "/", &stvfs
));
1258 EXPECT_EQ(-ENOTCONN
, ceph_get_local_osd(cmount
));
1259 EXPECT_EQ(-ENOTCONN
, ceph_chdir(cmount
, "/"));
1261 struct ceph_dir_result
*dirp
;
1262 EXPECT_EQ(-ENOTCONN
, ceph_opendir(cmount
, "/", &dirp
));
1263 EXPECT_EQ(-ENOTCONN
, ceph_closedir(cmount
, dirp
));
1265 ceph_readdir(cmount
, dirp
);
1266 EXPECT_EQ(ENOTCONN
, errno
);
1268 struct dirent rdent
;
1269 EXPECT_EQ(-ENOTCONN
, ceph_readdir_r(cmount
, dirp
, &rdent
));
1271 struct ceph_statx stx
;
1272 EXPECT_EQ(-ENOTCONN
, ceph_readdirplus_r(cmount
, dirp
, &rdent
, &stx
, 0, 0, NULL
));
1273 EXPECT_EQ(-ENOTCONN
, ceph_getdents(cmount
, dirp
, NULL
, 0));
1274 EXPECT_EQ(-ENOTCONN
, ceph_getdnames(cmount
, dirp
, NULL
, 0));
1275 EXPECT_EQ(-ENOTCONN
, ceph_telldir(cmount
, dirp
));
1276 EXPECT_EQ(-ENOTCONN
, ceph_link(cmount
, "/", "/link"));
1277 EXPECT_EQ(-ENOTCONN
, ceph_unlink(cmount
, "/path"));
1278 EXPECT_EQ(-ENOTCONN
, ceph_rename(cmount
, "/path", "/path"));
1279 EXPECT_EQ(-ENOTCONN
, ceph_mkdir(cmount
, "/", 0655));
1280 EXPECT_EQ(-ENOTCONN
, ceph_mkdirs(cmount
, "/", 0655));
1281 EXPECT_EQ(-ENOTCONN
, ceph_rmdir(cmount
, "/path"));
1282 EXPECT_EQ(-ENOTCONN
, ceph_readlink(cmount
, "/path", NULL
, 0));
1283 EXPECT_EQ(-ENOTCONN
, ceph_symlink(cmount
, "/path", "/path"));
1284 EXPECT_EQ(-ENOTCONN
, ceph_statx(cmount
, "/path", &stx
, 0, 0));
1285 EXPECT_EQ(-ENOTCONN
, ceph_setattrx(cmount
, "/path", &stx
, 0, 0));
1286 EXPECT_EQ(-ENOTCONN
, ceph_getxattr(cmount
, "/path", "name", NULL
, 0));
1287 EXPECT_EQ(-ENOTCONN
, ceph_lgetxattr(cmount
, "/path", "name", NULL
, 0));
1288 EXPECT_EQ(-ENOTCONN
, ceph_listxattr(cmount
, "/path", NULL
, 0));
1289 EXPECT_EQ(-ENOTCONN
, ceph_llistxattr(cmount
, "/path", NULL
, 0));
1290 EXPECT_EQ(-ENOTCONN
, ceph_removexattr(cmount
, "/path", "name"));
1291 EXPECT_EQ(-ENOTCONN
, ceph_lremovexattr(cmount
, "/path", "name"));
1292 EXPECT_EQ(-ENOTCONN
, ceph_setxattr(cmount
, "/path", "name", NULL
, 0, 0));
1293 EXPECT_EQ(-ENOTCONN
, ceph_lsetxattr(cmount
, "/path", "name", NULL
, 0, 0));
1294 EXPECT_EQ(-ENOTCONN
, ceph_fsetattrx(cmount
, 0, &stx
, 0));
1295 EXPECT_EQ(-ENOTCONN
, ceph_chmod(cmount
, "/path", 0));
1296 EXPECT_EQ(-ENOTCONN
, ceph_fchmod(cmount
, 0, 0));
1297 EXPECT_EQ(-ENOTCONN
, ceph_chown(cmount
, "/path", 0, 0));
1298 EXPECT_EQ(-ENOTCONN
, ceph_lchown(cmount
, "/path", 0, 0));
1299 EXPECT_EQ(-ENOTCONN
, ceph_fchown(cmount
, 0, 0, 0));
1302 EXPECT_EQ(-ENOTCONN
, ceph_utime(cmount
, "/path", &utb
));
1303 EXPECT_EQ(-ENOTCONN
, ceph_truncate(cmount
, "/path", 0));
1304 EXPECT_EQ(-ENOTCONN
, ceph_mknod(cmount
, "/path", 0, 0));
1305 EXPECT_EQ(-ENOTCONN
, ceph_open(cmount
, "/path", 0, 0));
1306 EXPECT_EQ(-ENOTCONN
, ceph_open_layout(cmount
, "/path", 0, 0, 0, 0, 0, "pool"));
1307 EXPECT_EQ(-ENOTCONN
, ceph_close(cmount
, 0));
1308 EXPECT_EQ(-ENOTCONN
, ceph_lseek(cmount
, 0, 0, SEEK_SET
));
1309 EXPECT_EQ(-ENOTCONN
, ceph_read(cmount
, 0, NULL
, 0, 0));
1310 EXPECT_EQ(-ENOTCONN
, ceph_write(cmount
, 0, NULL
, 0, 0));
1311 EXPECT_EQ(-ENOTCONN
, ceph_ftruncate(cmount
, 0, 0));
1312 EXPECT_EQ(-ENOTCONN
, ceph_fsync(cmount
, 0, 0));
1313 EXPECT_EQ(-ENOTCONN
, ceph_fstatx(cmount
, 0, &stx
, 0, 0));
1314 EXPECT_EQ(-ENOTCONN
, ceph_sync_fs(cmount
));
1315 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_unit(cmount
, 0));
1316 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_count(cmount
, 0));
1317 EXPECT_EQ(-ENOTCONN
, ceph_get_file_layout(cmount
, 0, NULL
, NULL
,NULL
,NULL
));
1318 EXPECT_EQ(-ENOTCONN
, ceph_get_file_object_size(cmount
, 0));
1319 EXPECT_EQ(-ENOTCONN
, ceph_get_file_pool(cmount
, 0));
1320 EXPECT_EQ(-ENOTCONN
, ceph_get_file_pool_name(cmount
, 0, NULL
, 0));
1321 EXPECT_EQ(-ENOTCONN
, ceph_get_file_replication(cmount
, 0));
1322 EXPECT_EQ(-ENOTCONN
, ceph_get_path_replication(cmount
, "/path"));
1323 EXPECT_EQ(-ENOTCONN
, ceph_get_path_layout(cmount
, "/path", NULL
, NULL
, NULL
, NULL
));
1324 EXPECT_EQ(-ENOTCONN
, ceph_get_path_object_size(cmount
, "/path"));
1325 EXPECT_EQ(-ENOTCONN
, ceph_get_path_stripe_count(cmount
, "/path"));
1326 EXPECT_EQ(-ENOTCONN
, ceph_get_path_stripe_unit(cmount
, "/path"));
1327 EXPECT_EQ(-ENOTCONN
, ceph_get_path_pool(cmount
, "/path"));
1328 EXPECT_EQ(-ENOTCONN
, ceph_get_path_pool_name(cmount
, "/path", NULL
, 0));
1329 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_name(cmount
, 0, NULL
, 0));
1330 EXPECT_EQ(-ENOTCONN
, ceph_get_file_stripe_address(cmount
, 0, 0, NULL
, 0));
1331 EXPECT_EQ(-ENOTCONN
, ceph_localize_reads(cmount
, 0));
1332 EXPECT_EQ(-ENOTCONN
, ceph_debug_get_fd_caps(cmount
, 0));
1333 EXPECT_EQ(-ENOTCONN
, ceph_debug_get_file_caps(cmount
, "/path"));
1334 EXPECT_EQ(-ENOTCONN
, ceph_get_stripe_unit_granularity(cmount
));
1335 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_id(cmount
, "data"));
1336 EXPECT_EQ(-ENOTCONN
, ceph_get_pool_replication(cmount
, 1));
1338 ceph_release(cmount
);
1341 TEST(LibCephFS
, GetPoolId
) {
1342 struct ceph_mount_info
*cmount
;
1343 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1344 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1345 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1346 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1349 memset(name
, 0, sizeof(name
));
1350 ASSERT_LE(0, ceph_get_path_pool_name(cmount
, "/", name
, sizeof(name
)));
1351 ASSERT_GE(ceph_get_pool_id(cmount
, name
), 0);
1352 ASSERT_EQ(ceph_get_pool_id(cmount
, "weflkjwelfjwlkejf"), -ENOENT
);
1354 ceph_shutdown(cmount
);
1357 TEST(LibCephFS
, GetPoolReplication
) {
1358 struct ceph_mount_info
*cmount
;
1359 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1360 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1361 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1362 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1364 /* negative pools */
1365 ASSERT_EQ(ceph_get_pool_replication(cmount
, -10), -ENOENT
);
1369 int stripe_unit
, stripe_count
, object_size
;
1370 ASSERT_EQ(0, ceph_get_path_layout(cmount
, "/", &stripe_unit
, &stripe_count
,
1371 &object_size
, &pool_id
));
1372 ASSERT_GE(pool_id
, 0);
1373 ASSERT_GT(ceph_get_pool_replication(cmount
, pool_id
), 0);
1375 ceph_shutdown(cmount
);
1378 TEST(LibCephFS
, GetExtentOsds
) {
1379 struct ceph_mount_info
*cmount
;
1380 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1382 EXPECT_EQ(-ENOTCONN
, ceph_get_file_extent_osds(cmount
, 0, 0, NULL
, NULL
, 0));
1384 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1385 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1386 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1388 int stripe_unit
= (1<<18);
1391 char test_file
[256];
1392 sprintf(test_file
, "test_extent_osds_%d", getpid());
1393 int fd
= ceph_open_layout(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666,
1394 stripe_unit
, 2, stripe_unit
*2, NULL
);
1397 /* get back how many osds > 0 */
1398 int ret
= ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, NULL
, 0);
1404 /* full stripe extent */
1405 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 0, &len
, osds
, ret
));
1406 EXPECT_EQ(len
, (int64_t)stripe_unit
);
1408 /* half stripe extent */
1409 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, stripe_unit
/2, &len
, osds
, ret
));
1410 EXPECT_EQ(len
, (int64_t)stripe_unit
/2);
1412 /* 1.5 stripe unit offset -1 byte */
1413 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 3*stripe_unit
/2-1, &len
, osds
, ret
));
1414 EXPECT_EQ(len
, (int64_t)stripe_unit
/2+1);
1416 /* 1.5 stripe unit offset +1 byte */
1417 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 3*stripe_unit
/2+1, &len
, osds
, ret
));
1418 EXPECT_EQ(len
, (int64_t)stripe_unit
/2-1);
1420 /* only when more than 1 osd */
1422 EXPECT_EQ(-ERANGE
, ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, osds
, 1));
1425 ceph_close(cmount
, fd
);
1427 ceph_shutdown(cmount
);
1430 TEST(LibCephFS
, GetOsdCrushLocation
) {
1431 struct ceph_mount_info
*cmount
;
1432 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1434 EXPECT_EQ(-ENOTCONN
, ceph_get_osd_crush_location(cmount
, 0, NULL
, 0));
1436 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1437 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1438 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1440 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 0, NULL
, 1), -EINVAL
);
1443 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 9999999, path
, 0), -ENOENT
);
1444 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, -1, path
, 0), -EINVAL
);
1446 char test_file
[256];
1447 sprintf(test_file
, "test_osds_loc_%d", getpid());
1448 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0666);
1451 /* get back how many osds > 0 */
1452 int ret
= ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, NULL
, 0);
1455 /* full stripe extent */
1457 EXPECT_EQ(ret
, ceph_get_file_extent_osds(cmount
, fd
, 0, NULL
, osds
, ret
));
1459 ASSERT_GT(ceph_get_osd_crush_location(cmount
, 0, path
, 0), 0);
1460 ASSERT_EQ(ceph_get_osd_crush_location(cmount
, 0, path
, 1), -ERANGE
);
1462 for (int i
= 0; i
< ret
; i
++) {
1463 int len
= ceph_get_osd_crush_location(cmount
, osds
[i
], path
, sizeof(path
));
1467 std::string
type(path
+ pos
);
1468 ASSERT_GT((int)type
.size(), 0);
1469 pos
+= type
.size() + 1;
1471 std::string
name(path
+ pos
);
1472 ASSERT_GT((int)name
.size(), 0);
1473 pos
+= name
.size() + 1;
1477 ceph_close(cmount
, fd
);
1478 ceph_shutdown(cmount
);
1481 TEST(LibCephFS
, GetOsdAddr
) {
1482 struct ceph_mount_info
*cmount
;
1483 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1485 EXPECT_EQ(-ENOTCONN
, ceph_get_osd_addr(cmount
, 0, NULL
));
1487 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1488 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1489 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
1491 ASSERT_EQ(-EINVAL
, ceph_get_osd_addr(cmount
, 0, NULL
));
1493 struct sockaddr_storage addr
;
1494 ASSERT_EQ(-ENOENT
, ceph_get_osd_addr(cmount
, -1, &addr
));
1495 ASSERT_EQ(-ENOENT
, ceph_get_osd_addr(cmount
, 9999999, &addr
));
1497 ASSERT_EQ(0, ceph_get_osd_addr(cmount
, 0, &addr
));
1499 ceph_shutdown(cmount
);
1502 TEST(LibCephFS
, OpenNoClose
) {
1503 struct ceph_mount_info
*cmount
;
1504 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1505 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1506 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1507 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1509 pid_t mypid
= getpid();
1511 sprintf(str_buf
, "open_no_close_dir%d", mypid
);
1512 ASSERT_EQ(0, ceph_mkdirs(cmount
, str_buf
, 0777));
1514 struct ceph_dir_result
*ls_dir
= NULL
;
1515 ASSERT_EQ(ceph_opendir(cmount
, str_buf
, &ls_dir
), 0);
1517 sprintf(str_buf
, "open_no_close_file%d", mypid
);
1518 int fd
= ceph_open(cmount
, str_buf
, O_RDONLY
|O_CREAT
, 0666);
1521 // shutdown should force close opened file/dir
1522 ceph_shutdown(cmount
);
1525 TEST(LibCephFS
, Nlink
) {
1526 struct ceph_mount_info
*cmount
;
1527 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1528 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1529 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1530 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1532 Inode
*root
, *dir
, *file
;
1534 ASSERT_EQ(ceph_ll_lookup_root(cmount
, &root
), 0);
1536 char dirname
[32], filename
[32], linkname
[32];
1537 sprintf(dirname
, "nlinkdir%x", getpid());
1538 sprintf(filename
, "nlinkorig%x", getpid());
1539 sprintf(linkname
, "nlinklink%x", getpid());
1541 struct ceph_statx stx
;
1543 UserPerm
*perms
= ceph_mount_perms(cmount
);
1545 ASSERT_EQ(ceph_ll_mkdir(cmount
, root
, dirname
, 0755, &dir
, &stx
, 0, 0, perms
), 0);
1546 ASSERT_EQ(ceph_ll_create(cmount
, dir
, filename
, 0666, O_RDWR
|O_CREAT
|O_EXCL
,
1547 &file
, &fh
, &stx
, CEPH_STATX_NLINK
, 0, perms
), 0);
1548 ASSERT_EQ(ceph_ll_close(cmount
, fh
), 0);
1549 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)1);
1551 ASSERT_EQ(ceph_ll_link(cmount
, file
, dir
, linkname
, perms
), 0);
1552 ASSERT_EQ(ceph_ll_getattr(cmount
, file
, &stx
, CEPH_STATX_NLINK
, 0, perms
), 0);
1553 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)2);
1555 ASSERT_EQ(ceph_ll_unlink(cmount
, dir
, linkname
, perms
), 0);
1556 ASSERT_EQ(ceph_ll_lookup(cmount
, dir
, filename
, &file
, &stx
,
1557 CEPH_STATX_NLINK
, 0, perms
), 0);
1558 ASSERT_EQ(stx
.stx_nlink
, (nlink_t
)1);
1560 ceph_shutdown(cmount
);
1563 TEST(LibCephFS
, SlashDotDot
) {
1564 struct ceph_mount_info
*cmount
;
1565 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1566 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1567 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1568 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1570 struct ceph_statx stx
;
1571 ASSERT_EQ(ceph_statx(cmount
, "/.", &stx
, CEPH_STATX_INO
, 0), 0);
1573 ino_t ino
= stx
.stx_ino
;
1574 ASSERT_EQ(ceph_statx(cmount
, "/..", &stx
, CEPH_STATX_INO
, 0), 0);
1576 /* At root, "." and ".." should be the same inode */
1577 ASSERT_EQ(ino
, stx
.stx_ino
);
1579 /* Test accessing the parent of an unlinked directory */
1580 char dir1
[32], dir2
[56];
1581 sprintf(dir1
, "/sldotdot%x", getpid());
1582 sprintf(dir2
, "%s/sub%x", dir1
, getpid());
1584 ASSERT_EQ(ceph_mkdir(cmount
, dir1
, 0755), 0);
1585 ASSERT_EQ(ceph_mkdir(cmount
, dir2
, 0755), 0);
1587 ASSERT_EQ(ceph_chdir(cmount
, dir2
), 0);
1589 /* Test behavior when unlinking cwd */
1590 struct ceph_dir_result
*rdir
;
1591 ASSERT_EQ(ceph_opendir(cmount
, ".", &rdir
), 0);
1592 ASSERT_EQ(ceph_rmdir(cmount
, dir2
), 0);
1595 struct dirent
*result
= ceph_readdir(cmount
, rdir
);
1596 ino
= result
->d_ino
;
1598 /* get ".." entry */
1599 result
= ceph_readdir(cmount
, rdir
);
1600 ASSERT_EQ(ino
, result
->d_ino
);
1601 ceph_closedir(cmount
, rdir
);
1603 /* Make sure it works same way when mounting subtree */
1604 ASSERT_EQ(ceph_unmount(cmount
), 0);
1605 ASSERT_EQ(ceph_mount(cmount
, dir1
), 0);
1606 ASSERT_EQ(ceph_statx(cmount
, "/..", &stx
, CEPH_STATX_INO
, 0), 0);
1608 /* Test readdir behavior */
1609 ASSERT_EQ(ceph_opendir(cmount
, "/", &rdir
), 0);
1610 result
= ceph_readdir(cmount
, rdir
);
1611 ASSERT_TRUE(result
!= NULL
);
1612 ASSERT_STREQ(result
->d_name
, ".");
1613 ino
= result
->d_ino
;
1614 result
= ceph_readdir(cmount
, rdir
);
1615 ASSERT_TRUE(result
!= NULL
);
1616 ASSERT_STREQ(result
->d_name
, "..");
1617 ASSERT_EQ(ino
, result
->d_ino
);
1619 ceph_shutdown(cmount
);
1623 timespec_eq(timespec
const& lhs
, timespec
const& rhs
)
1625 return lhs
.tv_sec
== rhs
.tv_sec
&& lhs
.tv_nsec
== rhs
.tv_nsec
;
1628 TEST(LibCephFS
, Btime
) {
1629 struct ceph_mount_info
*cmount
;
1630 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1631 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1632 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1633 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1636 sprintf(filename
, "/getattrx%x", getpid());
1638 ceph_unlink(cmount
, filename
);
1639 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1642 /* make sure fstatx works */
1643 struct ceph_statx stx
;
1645 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1646 ASSERT_TRUE(stx
.stx_mask
& (CEPH_STATX_CTIME
|CEPH_STATX_BTIME
));
1647 ASSERT_TRUE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1648 ceph_close(cmount
, fd
);
1650 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1651 ASSERT_TRUE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1652 ASSERT_TRUE(stx
.stx_mask
& (CEPH_STATX_CTIME
|CEPH_STATX_BTIME
));
1654 struct timespec old_btime
= stx
.stx_btime
;
1656 /* Now sleep, do a chmod and verify that the ctime changed, but btime didn't */
1658 ASSERT_EQ(ceph_chmod(cmount
, filename
, 0644), 0);
1659 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_CTIME
|CEPH_STATX_BTIME
, 0), 0);
1660 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_BTIME
);
1661 ASSERT_TRUE(timespec_eq(stx
.stx_btime
, old_btime
));
1662 ASSERT_FALSE(timespec_eq(stx
.stx_ctime
, stx
.stx_btime
));
1664 ceph_shutdown(cmount
);
1667 TEST(LibCephFS
, SetBtime
) {
1668 struct ceph_mount_info
*cmount
;
1669 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1670 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1671 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1672 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1675 sprintf(filename
, "/setbtime%x", getpid());
1677 ceph_unlink(cmount
, filename
);
1678 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1680 ceph_close(cmount
, fd
);
1682 struct ceph_statx stx
;
1683 struct timespec old_btime
= { 1, 2 };
1685 stx
.stx_btime
= old_btime
;
1687 ASSERT_EQ(ceph_setattrx(cmount
, filename
, &stx
, CEPH_SETATTR_BTIME
, 0), 0);
1689 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_BTIME
, 0), 0);
1690 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_BTIME
);
1691 ASSERT_TRUE(timespec_eq(stx
.stx_btime
, old_btime
));
1693 ceph_shutdown(cmount
);
1696 TEST(LibCephFS
, LazyStatx
) {
1697 struct ceph_mount_info
*cmount1
, *cmount2
;
1698 ASSERT_EQ(ceph_create(&cmount1
, NULL
), 0);
1699 ASSERT_EQ(ceph_create(&cmount2
, NULL
), 0);
1700 ASSERT_EQ(ceph_conf_read_file(cmount1
, NULL
), 0);
1701 ASSERT_EQ(ceph_conf_read_file(cmount2
, NULL
), 0);
1702 ASSERT_EQ(0, ceph_conf_parse_env(cmount1
, NULL
));
1703 ASSERT_EQ(0, ceph_conf_parse_env(cmount2
, NULL
));
1704 ASSERT_EQ(ceph_mount(cmount1
, "/"), 0);
1705 ASSERT_EQ(ceph_mount(cmount2
, "/"), 0);
1708 sprintf(filename
, "lazystatx%x", getpid());
1710 Inode
*root1
, *file1
, *root2
, *file2
;
1711 struct ceph_statx stx
;
1713 UserPerm
*perms1
= ceph_mount_perms(cmount1
);
1714 UserPerm
*perms2
= ceph_mount_perms(cmount2
);
1716 ASSERT_EQ(ceph_ll_lookup_root(cmount1
, &root1
), 0);
1717 ceph_ll_unlink(cmount1
, root1
, filename
, perms1
);
1718 ASSERT_EQ(ceph_ll_create(cmount1
, root1
, filename
, 0666, O_RDWR
|O_CREAT
|O_EXCL
,
1719 &file1
, &fh
, &stx
, 0, 0, perms1
), 0);
1720 ASSERT_EQ(ceph_ll_close(cmount1
, fh
), 0);
1722 ASSERT_EQ(ceph_ll_lookup_root(cmount2
, &root2
), 0);
1724 ASSERT_EQ(ceph_ll_lookup(cmount2
, root2
, filename
, &file2
, &stx
, CEPH_STATX_CTIME
, 0, perms2
), 0);
1726 struct timespec old_ctime
= stx
.stx_ctime
;
1729 * Now sleep, do a chmod on the first client and the see whether we get a
1730 * different ctime with a statx that uses AT_NO_ATTR_SYNC
1733 stx
.stx_mode
= 0644;
1734 ASSERT_EQ(ceph_ll_setattr(cmount1
, file1
, &stx
, CEPH_SETATTR_MODE
, perms1
), 0);
1736 ASSERT_EQ(ceph_ll_getattr(cmount2
, file2
, &stx
, CEPH_STATX_CTIME
, AT_NO_ATTR_SYNC
, perms2
), 0);
1737 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_CTIME
);
1738 ASSERT_TRUE(stx
.stx_ctime
.tv_sec
== old_ctime
.tv_sec
&&
1739 stx
.stx_ctime
.tv_nsec
== old_ctime
.tv_nsec
);
1741 ceph_shutdown(cmount1
);
1742 ceph_shutdown(cmount2
);
1745 TEST(LibCephFS
, ChangeAttr
) {
1746 struct ceph_mount_info
*cmount
;
1747 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1748 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1749 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1750 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1753 sprintf(filename
, "/changeattr%x", getpid());
1755 ceph_unlink(cmount
, filename
);
1756 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1759 struct ceph_statx stx
;
1760 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1761 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1763 uint64_t old_change_attr
= stx
.stx_version
;
1765 /* do chmod, and check whether change_attr changed */
1766 ASSERT_EQ(ceph_chmod(cmount
, filename
, 0644), 0);
1767 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1768 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1769 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1770 old_change_attr
= stx
.stx_version
;
1772 /* now do a write and see if it changed again */
1773 ASSERT_EQ(3, ceph_write(cmount
, fd
, "foo", 3, 0));
1774 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1775 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1776 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1777 old_change_attr
= stx
.stx_version
;
1779 /* Now truncate and check again */
1780 ASSERT_EQ(0, ceph_ftruncate(cmount
, fd
, 0));
1781 ASSERT_EQ(ceph_statx(cmount
, filename
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1782 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1783 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1785 ceph_close(cmount
, fd
);
1786 ceph_shutdown(cmount
);
1789 TEST(LibCephFS
, DirChangeAttr
) {
1790 struct ceph_mount_info
*cmount
;
1791 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1792 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1793 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1794 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1796 char dirname
[32], filename
[56];
1797 sprintf(dirname
, "/dirchange%x", getpid());
1798 sprintf(filename
, "%s/foo", dirname
);
1800 ASSERT_EQ(ceph_mkdir(cmount
, dirname
, 0755), 0);
1802 struct ceph_statx stx
;
1803 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1804 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1806 uint64_t old_change_attr
= stx
.stx_version
;
1808 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1810 ceph_close(cmount
, fd
);
1812 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1813 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1814 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1816 old_change_attr
= stx
.stx_version
;
1818 ASSERT_EQ(ceph_unlink(cmount
, filename
), 0);
1819 ASSERT_EQ(ceph_statx(cmount
, dirname
, &stx
, CEPH_STATX_VERSION
, 0), 0);
1820 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_VERSION
);
1821 ASSERT_NE(stx
.stx_version
, old_change_attr
);
1823 ceph_shutdown(cmount
);
1826 TEST(LibCephFS
, SetSize
) {
1827 struct ceph_mount_info
*cmount
;
1828 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1829 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1830 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1831 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1834 sprintf(filename
, "/setsize%x", getpid());
1836 ceph_unlink(cmount
, filename
);
1837 int fd
= ceph_open(cmount
, filename
, O_RDWR
|O_CREAT
|O_EXCL
, 0666);
1840 struct ceph_statx stx
;
1841 uint64_t size
= 8388608;
1842 stx
.stx_size
= size
;
1843 ASSERT_EQ(ceph_fsetattrx(cmount
, fd
, &stx
, CEPH_SETATTR_SIZE
), 0);
1844 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_SIZE
, 0), 0);
1845 ASSERT_EQ(stx
.stx_size
, size
);
1847 ceph_close(cmount
, fd
);
1848 ceph_shutdown(cmount
);
1851 TEST(LibCephFS
, ClearSetuid
) {
1852 struct ceph_mount_info
*cmount
;
1853 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1854 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1855 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1856 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1859 ASSERT_EQ(ceph_ll_lookup_root(cmount
, &root
), 0);
1862 sprintf(filename
, "clearsetuid%x", getpid());
1866 struct ceph_statx stx
;
1867 const mode_t after_mode
= S_IRWXU
;
1868 const mode_t before_mode
= S_IRWXU
| S_ISUID
| S_ISGID
;
1869 const unsigned want
= CEPH_STATX_UID
|CEPH_STATX_GID
|CEPH_STATX_MODE
;
1870 UserPerm
*usercred
= ceph_mount_perms(cmount
);
1872 ceph_ll_unlink(cmount
, root
, filename
, usercred
);
1873 ASSERT_EQ(ceph_ll_create(cmount
, root
, filename
, before_mode
,
1874 O_RDWR
|O_CREAT
|O_EXCL
, &in
, &fh
, &stx
, want
, 0,
1877 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1880 ASSERT_EQ(ceph_ll_write(cmount
, fh
, 0, 3, "foo"), 3);
1881 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1882 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1883 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1886 stx
.stx_mode
= before_mode
;
1887 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, usercred
), 0);
1888 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1889 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1890 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1894 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_SIZE
, usercred
), 0);
1895 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1896 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1897 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1900 stx
.stx_mode
= before_mode
;
1901 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, usercred
), 0);
1902 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1903 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1904 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, before_mode
);
1906 // chown -- for this we need to be "root"
1907 UserPerm
*rootcred
= ceph_userperm_new(0, 0, 0, NULL
);
1908 ASSERT_TRUE(rootcred
);
1911 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_UID
|CEPH_SETATTR_GID
, rootcred
), 0);
1912 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, usercred
), 0);
1913 ASSERT_TRUE(stx
.stx_mask
& CEPH_STATX_MODE
);
1914 ASSERT_EQ(stx
.stx_mode
& (mode_t
)ALLPERMS
, after_mode
);
1916 /* test chown with supplementary groups, and chown with/without exe bit */
1919 gid_t gids
[] = {65533,65532};
1920 UserPerm
*altcred
= ceph_userperm_new(u
, g
, sizeof gids
/ sizeof gids
[0], gids
);
1923 mode_t m
= S_ISGID
|S_ISUID
|S_IRUSR
|S_IWUSR
;
1925 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
|CEPH_SETATTR_UID
|CEPH_SETATTR_GID
, rootcred
), 0);
1926 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1927 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
1928 /* not dropped without exe bit */
1929 stx
.stx_gid
= gids
[0];
1930 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_GID
, altcred
), 0);
1931 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1932 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
1933 /* now check dropped with exe bit */
1934 m
= S_ISGID
|S_ISUID
|S_IRWXU
;
1936 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, altcred
), 0);
1937 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1938 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
);
1939 stx
.stx_gid
= gids
[1];
1940 ASSERT_EQ(ceph_ll_setattr(cmount
, in
, &stx
, CEPH_SETATTR_GID
, altcred
), 0);
1941 ASSERT_EQ(ceph_ll_getattr(cmount
, in
, &stx
, CEPH_STATX_MODE
, 0, altcred
), 0);
1942 ASSERT_EQ(stx
.stx_mode
&(mode_t
)ALLPERMS
, m
&(S_IRWXU
|S_IRWXG
|S_IRWXO
));
1943 ceph_userperm_destroy(altcred
);
1945 ASSERT_EQ(ceph_ll_close(cmount
, fh
), 0);
1946 ceph_shutdown(cmount
);
1949 TEST(LibCephFS
, OperationsOnRoot
)
1951 struct ceph_mount_info
*cmount
;
1952 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1953 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1954 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1955 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1958 sprintf(dirname
, "/somedir%x", getpid());
1960 ASSERT_EQ(ceph_mkdir(cmount
, dirname
, 0755), 0);
1962 ASSERT_EQ(ceph_rmdir(cmount
, "/"), -EBUSY
);
1964 ASSERT_EQ(ceph_link(cmount
, "/", "/"), -EEXIST
);
1965 ASSERT_EQ(ceph_link(cmount
, dirname
, "/"), -EEXIST
);
1966 ASSERT_EQ(ceph_link(cmount
, "nonExisitingDir", "/"), -ENOENT
);
1968 ASSERT_EQ(ceph_unlink(cmount
, "/"), -EISDIR
);
1970 ASSERT_EQ(ceph_rename(cmount
, "/", "/"), -EBUSY
);
1971 ASSERT_EQ(ceph_rename(cmount
, dirname
, "/"), -EBUSY
);
1972 ASSERT_EQ(ceph_rename(cmount
, "nonExistingDir", "/"), -EBUSY
);
1973 ASSERT_EQ(ceph_rename(cmount
, "/", dirname
), -EBUSY
);
1974 ASSERT_EQ(ceph_rename(cmount
, "/", "nonExistingDir"), -EBUSY
);
1976 ASSERT_EQ(ceph_mkdir(cmount
, "/", 0777), -EEXIST
);
1978 ASSERT_EQ(ceph_mknod(cmount
, "/", 0, 0), -EEXIST
);
1980 ASSERT_EQ(ceph_symlink(cmount
, "/", "/"), -EEXIST
);
1981 ASSERT_EQ(ceph_symlink(cmount
, dirname
, "/"), -EEXIST
);
1982 ASSERT_EQ(ceph_symlink(cmount
, "nonExistingDir", "/"), -EEXIST
);
1984 ceph_shutdown(cmount
);
1987 static void shutdown_racer_func()
1989 const int niter
= 32;
1990 struct ceph_mount_info
*cmount
;
1993 for (i
= 0; i
< niter
; ++i
) {
1994 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
1995 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
1996 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
1997 ASSERT_EQ(ceph_mount(cmount
, "/"), 0);
1998 ceph_shutdown(cmount
);
2002 // See tracker #20988
2003 TEST(LibCephFS
, ShutdownRace
)
2005 const int nthreads
= 128;
2006 std::thread threads
[nthreads
];
2008 // Need a bunch of fd's for this test
2009 struct rlimit rold
, rnew
;
2010 ASSERT_EQ(getrlimit(RLIMIT_NOFILE
, &rold
), 0);
2012 rnew
.rlim_cur
= rnew
.rlim_max
;
2013 ASSERT_EQ(setrlimit(RLIMIT_NOFILE
, &rnew
), 0);
2015 for (int i
= 0; i
< nthreads
; ++i
)
2016 threads
[i
] = std::thread(shutdown_racer_func
);
2018 for (int i
= 0; i
< nthreads
; ++i
)
2020 ASSERT_EQ(setrlimit(RLIMIT_NOFILE
, &rold
), 0);
2023 static void get_current_time_utimbuf(struct utimbuf
*utb
)
2025 utime_t t
= ceph_clock_now();
2026 utb
->actime
= t
.sec();
2027 utb
->modtime
= t
.sec();
2030 static void get_current_time_timeval(struct timeval tv
[2])
2032 utime_t t
= ceph_clock_now();
2033 t
.copy_to_timeval(&tv
[0]);
2034 t
.copy_to_timeval(&tv
[1]);
2037 static void get_current_time_timespec(struct timespec ts
[2])
2039 utime_t t
= ceph_clock_now();
2040 t
.to_timespec(&ts
[0]);
2041 t
.to_timespec(&ts
[1]);
2044 TEST(LibCephFS
, TestUtime
) {
2045 struct ceph_mount_info
*cmount
;
2046 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2047 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2048 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2049 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2051 char test_file
[256];
2052 sprintf(test_file
, "test_utime_file_%d", getpid());
2053 int fd
= ceph_open(cmount
, test_file
, O_CREAT
, 0666);
2057 struct ceph_statx stx
;
2059 get_current_time_utimbuf(&utb
);
2062 EXPECT_EQ(0, ceph_utime(cmount
, test_file
, &utb
));
2063 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
,
2064 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2065 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(utb
.actime
, 0));
2066 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(utb
.modtime
, 0));
2068 get_current_time_utimbuf(&utb
);
2071 EXPECT_EQ(0, ceph_futime(cmount
, fd
, &utb
));
2072 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
,
2073 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2074 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(utb
.actime
, 0));
2075 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(utb
.modtime
, 0));
2077 ceph_close(cmount
, fd
);
2078 ceph_shutdown(cmount
);
2081 TEST(LibCephFS
, TestUtimes
) {
2082 struct ceph_mount_info
*cmount
;
2083 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2084 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2085 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2086 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2088 char test_file
[256];
2089 char test_symlink
[256];
2091 sprintf(test_file
, "test_utimes_file_%d", getpid());
2092 sprintf(test_symlink
, "test_utimes_symlink_%d", getpid());
2093 int fd
= ceph_open(cmount
, test_file
, O_CREAT
, 0666);
2096 ASSERT_EQ(ceph_symlink(cmount
, test_file
, test_symlink
), 0);
2098 struct timeval times
[2];
2099 struct ceph_statx stx
;
2101 get_current_time_timeval(times
);
2103 // ceph_utimes() on symlink, validate target file time
2104 EXPECT_EQ(0, ceph_utimes(cmount
, test_symlink
, times
));
2105 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx
,
2106 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2107 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(times
[0]));
2108 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(times
[1]));
2110 get_current_time_timeval(times
);
2112 // ceph_lutimes() on symlink, validate symlink time
2113 EXPECT_EQ(0, ceph_lutimes(cmount
, test_symlink
, times
));
2114 ASSERT_EQ(ceph_statx(cmount
, test_symlink
, &stx
,
2115 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, AT_SYMLINK_NOFOLLOW
), 0);
2116 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(times
[0]));
2117 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(times
[1]));
2119 get_current_time_timeval(times
);
2122 EXPECT_EQ(0, ceph_futimes(cmount
, fd
, times
));
2123 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
,
2124 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2125 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(times
[0]));
2126 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(times
[1]));
2128 ceph_close(cmount
, fd
);
2129 ceph_shutdown(cmount
);
2132 TEST(LibCephFS
, TestFutimens
) {
2133 struct ceph_mount_info
*cmount
;
2134 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2135 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2136 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2137 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2139 char test_file
[256];
2141 sprintf(test_file
, "test_futimens_file_%d", getpid());
2142 int fd
= ceph_open(cmount
, test_file
, O_CREAT
, 0666);
2145 struct timespec times
[2];
2146 struct ceph_statx stx
;
2148 get_current_time_timespec(times
);
2151 EXPECT_EQ(0, ceph_futimens(cmount
, fd
, times
));
2152 ASSERT_EQ(ceph_statx(cmount
, test_file
, &stx
,
2153 CEPH_STATX_MTIME
|CEPH_STATX_ATIME
, 0), 0);
2154 ASSERT_EQ(utime_t(stx
.stx_atime
), utime_t(times
[0]));
2155 ASSERT_EQ(utime_t(stx
.stx_mtime
), utime_t(times
[1]));
2157 ceph_close(cmount
, fd
);
2158 ceph_shutdown(cmount
);
2161 TEST(LibCephFS
, OperationsOnDotDot
) {
2162 struct ceph_mount_info
*cmount
;
2163 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2164 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2165 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2166 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2168 char c_dir
[512], c_dir_dot
[1024], c_dir_dotdot
[1024];
2169 char c_non_existent_dir
[1024], c_non_existent_dirs
[1024];
2172 pid_t mypid
= getpid();
2173 sprintf(c_dir
, "/oodd_dir_%d", mypid
);
2174 sprintf(c_dir_dot
, "/%s/.", c_dir
);
2175 sprintf(c_dir_dotdot
, "/%s/..", c_dir
);
2176 sprintf(c_non_existent_dir
, "/%s/../oodd_nonexistent/..", c_dir
);
2177 sprintf(c_non_existent_dirs
,
2178 "/%s/../ood_nonexistent1_%d/oodd_nonexistent2_%d", c_dir
, mypid
, mypid
);
2179 sprintf(c_temp
, "/oodd_temp_%d", mypid
);
2181 ASSERT_EQ(0, ceph_mkdir(cmount
, c_dir
, 0777));
2182 ASSERT_EQ(-EEXIST
, ceph_mkdir(cmount
, c_dir_dot
, 0777));
2183 ASSERT_EQ(-EEXIST
, ceph_mkdir(cmount
, c_dir_dotdot
, 0777));
2184 ASSERT_EQ(0, ceph_mkdirs(cmount
, c_non_existent_dirs
, 0777));
2186 ASSERT_EQ(-ENOTEMPTY
, ceph_rmdir(cmount
, c_dir_dot
));
2187 ASSERT_EQ(-ENOTEMPTY
, ceph_rmdir(cmount
, c_dir_dotdot
));
2188 // non existent directory should return -ENOENT
2189 ASSERT_EQ(-ENOENT
, ceph_rmdir(cmount
, c_non_existent_dir
));
2191 ASSERT_EQ(-EBUSY
, ceph_rename(cmount
, c_dir_dot
, c_temp
));
2192 ASSERT_EQ(0, ceph_chdir(cmount
, c_dir
));
2193 ASSERT_EQ(0, ceph_mkdir(cmount
, c_temp
, 0777));
2194 ASSERT_EQ(-EBUSY
, ceph_rename(cmount
, c_temp
, ".."));
2196 ceph_shutdown(cmount
);
2199 TEST(LibCephFS
, SnapXattrs
) {
2200 struct ceph_mount_info
*cmount
;
2201 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2202 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2203 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2204 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2206 char test_snap_xattr_file
[256];
2207 char c_temp
[PATH_MAX
];
2210 int xbuflen
= sizeof(gxattrv
);
2211 pid_t mypid
= getpid();
2213 sprintf(test_snap_xattr_file
, "test_snap_xattr_%d", mypid
);
2214 int fd
= ceph_open(cmount
, test_snap_xattr_file
, O_CREAT
, 0666);
2216 ceph_close(cmount
, fd
);
2218 sprintf(c_temp
, "/.snap/test_snap_xattr_snap_%d", mypid
);
2219 ASSERT_EQ(0, ceph_mkdir(cmount
, c_temp
, 0777));
2221 int alen
= ceph_getxattr(cmount
, c_temp
, "ceph.snap.btime", (void *)gxattrv
, xbuflen
);
2222 // xattr value is secs.nsecs (don't assume zero-term)
2224 ASSERT_LT(alen
, xbuflen
);
2225 gxattrv
[alen
] = '\0';
2226 char *s
= strchrnul(gxattrv
, '.');
2227 ASSERT_LT(s
, gxattrv
+ alen
);
2230 utime_t btime
= utime_t(strtoull(gxattrv
, NULL
, 10), strtoull(s
+ 1, NULL
, 10));
2231 *s
= '.'; // restore for later strcmp
2233 // file within the snapshot should carry the same btime
2234 sprintf(c_temp
, "/.snap/test_snap_xattr_snap_%d/%s", mypid
, test_snap_xattr_file
);
2236 int alen2
= ceph_getxattr(cmount
, c_temp
, "ceph.snap.btime", (void *)gxattrv2
, xbuflen
);
2237 ASSERT_EQ(alen
, alen2
);
2238 ASSERT_EQ(0, strncmp(gxattrv
, gxattrv2
, alen
));
2240 // non-snap file shouldn't carry the xattr
2241 alen
= ceph_getxattr(cmount
, test_snap_xattr_file
, "ceph.snap.btime", (void *)gxattrv2
, xbuflen
);
2242 ASSERT_EQ(-ENODATA
, alen
);
2244 // create a second snapshot
2245 sprintf(c_temp
, "/.snap/test_snap_xattr_snap2_%d", mypid
);
2246 ASSERT_EQ(0, ceph_mkdir(cmount
, c_temp
, 0777));
2248 // check that the btime for the newer snapshot is > older
2249 alen
= ceph_getxattr(cmount
, c_temp
, "ceph.snap.btime", (void *)gxattrv2
, xbuflen
);
2251 ASSERT_LT(alen
, xbuflen
);
2252 gxattrv2
[alen
] = '\0';
2253 s
= strchrnul(gxattrv2
, '.');
2254 ASSERT_LT(s
, gxattrv2
+ alen
);
2257 utime_t new_btime
= utime_t(strtoull(gxattrv2
, NULL
, 10), strtoull(s
+ 1, NULL
, 10));
2258 ASSERT_LT(btime
, new_btime
);
2260 // listxattr() shouldn't return snap.btime vxattr
2261 char xattrlist
[512];
2262 int len
= ceph_listxattr(cmount
, test_snap_xattr_file
, xattrlist
, sizeof(xattrlist
));
2263 ASSERT_GE(sizeof(xattrlist
), (size_t)len
);
2264 char *p
= xattrlist
;
2267 if (strcmp(p
, "ceph.snap.btime") == 0)
2269 len
-= strlen(p
) + 1;
2272 ASSERT_EQ(found
, 0);
2274 ceph_shutdown(cmount
);
2277 TEST(LibCephFS
, SnapQuota
) {
2278 struct ceph_mount_info
*cmount
;
2279 ASSERT_EQ(ceph_create(&cmount
, NULL
), 0);
2280 ASSERT_EQ(ceph_conf_read_file(cmount
, NULL
), 0);
2281 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2282 ASSERT_EQ(ceph_mount(cmount
, NULL
), 0);
2284 char test_snap_dir_quota_xattr
[256];
2285 char test_snap_subdir_quota_xattr
[256];
2286 char test_snap_subdir_noquota_xattr
[256];
2289 char c_temp
[PATH_MAX
];
2291 int xbuflen
= sizeof(gxattrv
);
2292 pid_t mypid
= getpid();
2294 // create dir and set quota
2295 sprintf(test_snap_dir_quota_xattr
, "test_snap_dir_quota_xattr_%d", mypid
);
2296 ASSERT_EQ(0, ceph_mkdir(cmount
, test_snap_dir_quota_xattr
, 0777));
2298 sprintf(xattrk
, "ceph.quota.max_bytes");
2299 sprintf(xattrv
, "65536");
2300 ASSERT_EQ(0, ceph_setxattr(cmount
, test_snap_dir_quota_xattr
, xattrk
, (void *)xattrv
, 5, XATTR_CREATE
));
2302 // create subdir and set quota
2303 sprintf(test_snap_subdir_quota_xattr
, "test_snap_dir_quota_xattr_%d/subdir_quota", mypid
);
2304 ASSERT_EQ(0, ceph_mkdirs(cmount
, test_snap_subdir_quota_xattr
, 0777));
2306 sprintf(xattrk
, "ceph.quota.max_bytes");
2307 sprintf(xattrv
, "32768");
2308 ASSERT_EQ(0, ceph_setxattr(cmount
, test_snap_subdir_quota_xattr
, xattrk
, (void *)xattrv
, 5, XATTR_CREATE
));
2310 // create subdir with no quota
2311 sprintf(test_snap_subdir_noquota_xattr
, "test_snap_dir_quota_xattr_%d/subdir_noquota", mypid
);
2312 ASSERT_EQ(0, ceph_mkdirs(cmount
, test_snap_subdir_noquota_xattr
, 0777));
2315 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d", mypid
);
2316 ASSERT_EQ(0, ceph_mkdirs(cmount
, c_temp
, 0777));
2318 // check dir quota under snap
2319 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d", mypid
, mypid
);
2320 int alen
= ceph_getxattr(cmount
, c_temp
, "ceph.quota.max_bytes", (void *)gxattrv
, xbuflen
);
2322 ASSERT_LT(alen
, xbuflen
);
2323 gxattrv
[alen
] = '\0';
2324 ASSERT_STREQ(gxattrv
, "65536");
2326 // check subdir quota under snap
2327 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d/subdir_quota", mypid
, mypid
);
2328 alen
= ceph_getxattr(cmount
, c_temp
, "ceph.quota.max_bytes", (void *)gxattrv
, xbuflen
);
2330 ASSERT_LT(alen
, xbuflen
);
2331 gxattrv
[alen
] = '\0';
2332 ASSERT_STREQ(gxattrv
, "32768");
2334 // ensure subdir noquota xattr under snap
2335 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d/subdir_noquota", mypid
, mypid
);
2336 EXPECT_EQ(-ENODATA
, ceph_getxattr(cmount
, c_temp
, "ceph.quota.max_bytes", (void *)gxattrv
, xbuflen
));
2338 // listxattr() shouldn't return ceph.quota.max_bytes vxattr
2339 sprintf(c_temp
, "/.snap/test_snap_dir_quota_xattr_snap_%d/test_snap_dir_quota_xattr_%d", mypid
, mypid
);
2340 char xattrlist
[512];
2341 int len
= ceph_listxattr(cmount
, c_temp
, xattrlist
, sizeof(xattrlist
));
2342 ASSERT_GE(sizeof(xattrlist
), (size_t)len
);
2343 char *p
= xattrlist
;
2346 if (strcmp(p
, "ceph.quota.max_bytes") == 0)
2348 len
-= strlen(p
) + 1;
2351 ASSERT_EQ(found
, 0);
2353 ceph_shutdown(cmount
);
2356 TEST(LibCephFS
, Lseek
) {
2357 struct ceph_mount_info
*cmount
;
2358 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
2359 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
2360 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
2361 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
2364 sprintf(c_path
, "test_lseek_%d", getpid());
2365 int fd
= ceph_open(cmount
, c_path
, O_RDWR
|O_CREAT
|O_TRUNC
, 0666);
2368 const char *out_buf
= "hello world";
2369 size_t size
= strlen(out_buf
);
2370 ASSERT_EQ(ceph_write(cmount
, fd
, out_buf
, size
, 0), (int)size
);
2372 /* basic SEEK_SET/END/CUR tests */
2373 ASSERT_EQ(0, ceph_lseek(cmount
, fd
, 0, SEEK_SET
));
2374 ASSERT_EQ(size
, ceph_lseek(cmount
, fd
, 0, SEEK_END
));
2375 ASSERT_EQ(0, ceph_lseek(cmount
, fd
, -size
, SEEK_CUR
));
2377 /* Test basic functionality and out of bounds conditions for SEEK_HOLE/DATA */
2379 ASSERT_EQ(size
, ceph_lseek(cmount
, fd
, 0, SEEK_HOLE
));
2380 ASSERT_EQ(-ENXIO
, ceph_lseek(cmount
, fd
, -1, SEEK_HOLE
));
2381 ASSERT_EQ(-ENXIO
, ceph_lseek(cmount
, fd
, size
+ 1, SEEK_HOLE
));
2384 ASSERT_EQ(0, ceph_lseek(cmount
, fd
, 0, SEEK_DATA
));
2385 ASSERT_EQ(-ENXIO
, ceph_lseek(cmount
, fd
, -1, SEEK_DATA
));
2386 ASSERT_EQ(-ENXIO
, ceph_lseek(cmount
, fd
, size
+ 1, SEEK_DATA
));
2389 ASSERT_EQ(0, ceph_close(cmount
, fd
));
2390 ceph_shutdown(cmount
);