]> git.proxmox.com Git - ceph.git/blame - ceph/src/libcephfs.cc
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / libcephfs.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2009-2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include <fcntl.h>
16#include <iostream>
17#include <string.h>
18#include <string>
19
20#include "auth/Crypto.h"
21#include "client/Client.h"
aee94f69 22#include "client/Inode.h"
7c673cae 23#include "librados/RadosClient.h"
f67539c2 24#include "common/async/context_pool.h"
7c673cae
FG
25#include "common/ceph_argparse.h"
26#include "common/common_init.h"
27#include "common/config.h"
28#include "common/version.h"
29#include "mon/MonClient.h"
30#include "include/str_list.h"
b3b6e05e 31#include "include/stringify.h"
aee94f69 32#include "include/object.h"
7c673cae
FG
33#include "messages/MMonMap.h"
34#include "msg/Messenger.h"
11fdf7f2 35#include "include/ceph_assert.h"
b32b8144 36#include "mds/MDSMap.h"
7c673cae
FG
37
38#include "include/cephfs/libcephfs.h"
39
11fdf7f2
TL
40#define DEFAULT_UMASK 002
41
20effc67
TL
42using namespace std;
43
11fdf7f2 44static mode_t umask_cb(void *);
f67539c2
TL
45namespace {
46// Set things up this way so we don't start up threads until mount and
47// kill them off when the last mount goes away, but are tolerant to
48// multiple mounts of overlapping duration.
49std::shared_ptr<ceph::async::io_context_pool> get_icp(CephContext* cct)
50{
51 static std::mutex m;
52 static std::weak_ptr<ceph::async::io_context_pool> icwp;
53
54
55 std::unique_lock l(m);
56
57 auto icp = icwp.lock();
58 if (icp)
59 return icp;
60
61 icp = std::make_shared<ceph::async::io_context_pool>();
62 icwp = icp;
63 icp->start(cct->_conf.get_val<std::uint64_t>("client_asio_thread_count"));
64 return icp;
65}
66}
7c673cae
FG
67
68struct ceph_mount_info
69{
11fdf7f2 70 mode_t umask = DEFAULT_UMASK;
f67539c2 71 std::shared_ptr<ceph::async::io_context_pool> icp;
7c673cae
FG
72public:
73 explicit ceph_mount_info(CephContext *cct_)
74 : default_perms(),
75 mounted(false),
76 inited(false),
11fdf7f2
TL
77 client(nullptr),
78 monclient(nullptr),
79 messenger(nullptr),
7c673cae
FG
80 cct(cct_)
81 {
11fdf7f2 82 if (cct_) {
7c673cae
FG
83 cct->get();
84 }
85 }
86
87 ~ceph_mount_info()
88 {
89 try {
90 shutdown();
91 if (cct) {
92 cct->put();
11fdf7f2 93 cct = nullptr;
7c673cae
FG
94 }
95 }
96 catch (const std::exception& e) {
97 // we shouldn't get here, but if we do, we want to know about it.
98 lderr(cct) << "ceph_mount_info::~ceph_mount_info: caught exception: "
99 << e.what() << dendl;
100 }
101 catch (...) {
102 // ignore
103 }
104 }
105
106 int init()
107 {
7c673cae
FG
108 int ret;
109
f67539c2 110 if (!cct->_log->is_started()) {
11fdf7f2
TL
111 cct->_log->start();
112 }
f67539c2 113 icp = get_icp(cct);
11fdf7f2
TL
114
115 {
f67539c2 116 MonClient mc_bootstrap(cct, icp->get_io_context());
11fdf7f2
TL
117 ret = mc_bootstrap.get_monmap_and_config();
118 if (ret < 0)
119 return ret;
120 }
121
122 common_init_finish(cct);
123
7c673cae 124 //monmap
f67539c2 125 monclient = new MonClient(cct, icp->get_io_context());
7c673cae
FG
126 ret = -CEPHFS_ERROR_MON_MAP_BUILD; //defined in libcephfs.h;
127 if (monclient->build_initial_monmap() < 0)
128 goto fail;
129
130 //network connection
131 messenger = Messenger::create_client_messenger(cct, "client");
132
133 //at last the client
134 ret = -CEPHFS_ERROR_NEW_CLIENT; //defined in libcephfs.h;
f67539c2 135 client = new StandaloneClient(messenger, monclient, icp->get_io_context());
7c673cae
FG
136 if (!client)
137 goto fail;
138
139 ret = -CEPHFS_ERROR_MESSENGER_START; //defined in libcephfs.h;
140 if (messenger->start() != 0)
141 goto fail;
142
143 ret = client->init();
144 if (ret)
145 goto fail;
146
11fdf7f2 147 {
e306af50 148 ceph_client_callback_args args = {};
11fdf7f2
TL
149 args.handle = this;
150 args.umask_cb = umask_cb;
151 client->ll_register_callbacks(&args);
152 }
153
7c673cae
FG
154 default_perms = Client::pick_my_perms(cct);
155 inited = true;
156 return 0;
157
158 fail:
159 shutdown();
160 return ret;
161 }
162
11fdf7f2
TL
163 int select_filesystem(const std::string &fs_name_)
164 {
165 if (mounted) {
1e59de90 166 return -CEPHFS_EISCONN;
11fdf7f2
TL
167 }
168
169 fs_name = fs_name_;
170 return 0;
171 }
172
173 const std::string& get_filesystem(void)
174 {
175 return fs_name;
176 }
177
7c673cae
FG
178 int mount(const std::string &mount_root, const UserPerm& perms)
179 {
180 int ret;
181
182 if (mounted)
1e59de90 183 return -CEPHFS_EISCONN;
7c673cae
FG
184
185 if (!inited) {
186 ret = init();
187 if (ret != 0) {
188 return ret;
189 }
190 }
191
11fdf7f2 192 ret = client->mount(mount_root, perms, false, fs_name);
7c673cae
FG
193 if (ret) {
194 shutdown();
195 return ret;
196 } else {
197 mounted = true;
198 return 0;
199 }
200 }
201
202 int unmount()
203 {
204 if (!mounted)
1e59de90 205 return -CEPHFS_ENOTCONN;
7c673cae
FG
206 shutdown();
207 return 0;
208 }
11fdf7f2
TL
209 int abort_conn()
210 {
211 if (mounted) {
212 client->abort_conn();
213 mounted = false;
214 }
215 return 0;
216 }
7c673cae
FG
217
218 void shutdown()
219 {
220 if (mounted) {
221 client->unmount();
222 mounted = false;
223 }
224 if (inited) {
225 client->shutdown();
226 inited = false;
227 }
228 if (messenger) {
229 messenger->shutdown();
230 messenger->wait();
231 delete messenger;
11fdf7f2 232 messenger = nullptr;
7c673cae 233 }
f67539c2 234 icp.reset();
7c673cae
FG
235 if (monclient) {
236 delete monclient;
11fdf7f2 237 monclient = nullptr;
7c673cae
FG
238 }
239 if (client) {
240 delete client;
11fdf7f2 241 client = nullptr;
7c673cae
FG
242 }
243 }
244
245 bool is_initialized() const
246 {
247 return inited;
248 }
249
250 bool is_mounted()
251 {
252 return mounted;
253 }
254
11fdf7f2
TL
255 mode_t set_umask(mode_t umask)
256 {
257 this->umask = umask;
258 return umask;
259 }
260
9f95a23c
TL
261 std::string getaddrs()
262 {
263 CachedStackStringStream cos;
264 *cos << messenger->get_myaddrs();
265 return std::string(cos->strv());
266 }
267
7c673cae
FG
268 int conf_read_file(const char *path_list)
269 {
11fdf7f2 270 int ret = cct->_conf.parse_config_files(path_list, nullptr, 0);
7c673cae
FG
271 if (ret)
272 return ret;
11fdf7f2 273 cct->_conf.apply_changes(nullptr);
9f95a23c 274 cct->_conf.complain_about_parse_error(cct);
7c673cae
FG
275 return 0;
276 }
277
278 int conf_parse_argv(int argc, const char **argv)
279 {
20effc67
TL
280 auto args = argv_to_vec(argc, argv);
281 int ret = cct->_conf.parse_argv(args);
7c673cae
FG
282 if (ret)
283 return ret;
11fdf7f2 284 cct->_conf.apply_changes(nullptr);
7c673cae
FG
285 return 0;
286 }
287
288 int conf_parse_env(const char *name)
289 {
11fdf7f2
TL
290 auto& conf = cct->_conf;
291 conf.parse_env(cct->get_module_type(), name);
292 conf.apply_changes(nullptr);
7c673cae
FG
293 return 0;
294 }
295
296 int conf_set(const char *option, const char *value)
297 {
11fdf7f2 298 int ret = cct->_conf.set_val(option, value);
7c673cae
FG
299 if (ret)
300 return ret;
11fdf7f2 301 cct->_conf.apply_changes(nullptr);
7c673cae
FG
302 return 0;
303 }
304
305 int conf_get(const char *option, char *buf, size_t len)
306 {
307 char *tmp = buf;
11fdf7f2 308 return cct->_conf.get_val(option, &tmp, len);
7c673cae
FG
309 }
310
311 Client *get_client()
312 {
313 return client;
314 }
315
316 const char *get_cwd(const UserPerm& perms)
317 {
318 client->getcwd(cwd, perms);
319 return cwd.c_str();
320 }
321
322 int chdir(const char *to, const UserPerm& perms)
323 {
324 return client->chdir(to, cwd, perms);
325 }
326
327 CephContext *get_ceph_context() const {
328 return cct;
329 }
330
331 UserPerm default_perms;
332private:
333 bool mounted;
334 bool inited;
335 StandaloneClient *client;
336 MonClient *monclient;
337 Messenger *messenger;
338 CephContext *cct;
339 std::string cwd;
11fdf7f2 340 std::string fs_name;
7c673cae
FG
341};
342
11fdf7f2
TL
343static mode_t umask_cb(void *handle)
344{
345 return ((struct ceph_mount_info *)handle)->umask;
346}
347
7c673cae
FG
348static void do_out_buffer(bufferlist& outbl, char **outbuf, size_t *outbuflen)
349{
350 if (outbuf) {
351 if (outbl.length() > 0) {
352 *outbuf = (char *)malloc(outbl.length());
353 memcpy(*outbuf, outbl.c_str(), outbl.length());
354 } else {
11fdf7f2 355 *outbuf = nullptr;
7c673cae
FG
356 }
357 }
358 if (outbuflen)
359 *outbuflen = outbl.length();
360}
361
362static void do_out_buffer(string& outbl, char **outbuf, size_t *outbuflen)
363{
364 if (outbuf) {
365 if (outbl.length() > 0) {
366 *outbuf = (char *)malloc(outbl.length());
367 memcpy(*outbuf, outbl.c_str(), outbl.length());
368 } else {
11fdf7f2 369 *outbuf = nullptr;
7c673cae
FG
370 }
371 }
372 if (outbuflen)
373 *outbuflen = outbl.length();
374}
375
376extern "C" UserPerm *ceph_userperm_new(uid_t uid, gid_t gid, int ngids,
377 gid_t *gidlist)
378{
379 return new (std::nothrow) UserPerm(uid, gid, ngids, gidlist);
380}
381
382extern "C" void ceph_userperm_destroy(UserPerm *perm)
383{
384 delete perm;
385}
386
387extern "C" const char *ceph_version(int *pmajor, int *pminor, int *ppatch)
388{
389 int major, minor, patch;
390 const char *v = ceph_version_to_str();
391
392 int n = sscanf(v, "%d.%d.%d", &major, &minor, &patch);
393 if (pmajor)
394 *pmajor = (n >= 1) ? major : 0;
395 if (pminor)
396 *pminor = (n >= 2) ? minor : 0;
397 if (ppatch)
398 *ppatch = (n >= 3) ? patch : 0;
9f95a23c 399 return PROJECT_VERSION;
7c673cae
FG
400}
401
402extern "C" int ceph_create_with_context(struct ceph_mount_info **cmount, CephContext *cct)
403{
404 *cmount = new struct ceph_mount_info(cct);
405 return 0;
406}
407
408extern "C" int ceph_create_from_rados(struct ceph_mount_info **cmount,
409 rados_t cluster)
410{
411 auto rados = (librados::RadosClient *) cluster;
412 auto cct = rados->cct;
413 return ceph_create_with_context(cmount, cct);
414}
415
416extern "C" int ceph_create(struct ceph_mount_info **cmount, const char * const id)
417{
418 CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT);
419 if (id) {
420 iparams.name.set(CEPH_ENTITY_TYPE_CLIENT, id);
421 }
422
423 CephContext *cct = common_preinit(iparams, CODE_ENVIRONMENT_LIBRARY, 0);
11fdf7f2
TL
424 cct->_conf.parse_env(cct->get_module_type()); // environment variables coverride
425 cct->_conf.apply_changes(nullptr);
7c673cae
FG
426 int ret = ceph_create_with_context(cmount, cct);
427 cct->put();
11fdf7f2 428 cct = nullptr;
7c673cae
FG
429 return ret;
430}
431
432extern "C" int ceph_unmount(struct ceph_mount_info *cmount)
433{
434 return cmount->unmount();
435}
436
11fdf7f2
TL
437extern "C" int ceph_abort_conn(struct ceph_mount_info *cmount)
438{
439 return cmount->abort_conn();
440}
441
7c673cae
FG
442extern "C" int ceph_release(struct ceph_mount_info *cmount)
443{
444 if (cmount->is_mounted())
1e59de90 445 return -CEPHFS_EISCONN;
7c673cae 446 delete cmount;
11fdf7f2 447 cmount = nullptr;
7c673cae
FG
448 return 0;
449}
450
451extern "C" void ceph_shutdown(struct ceph_mount_info *cmount)
452{
453 cmount->shutdown();
454 delete cmount;
11fdf7f2
TL
455 cmount = nullptr;
456}
457
458extern "C" uint64_t ceph_get_instance_id(struct ceph_mount_info *cmount)
459{
460 if (cmount->is_initialized())
461 return cmount->get_client()->get_nodeid().v;
462 return 0;
7c673cae
FG
463}
464
9f95a23c
TL
465extern "C" int ceph_getaddrs(struct ceph_mount_info *cmount, char** addrs)
466{
467 if (!cmount->is_initialized())
1e59de90 468 return -CEPHFS_ENOTCONN;
9f95a23c
TL
469 auto s = cmount->getaddrs();
470 *addrs = strdup(s.c_str());
471 return 0;
472}
473
7c673cae
FG
474extern "C" int ceph_conf_read_file(struct ceph_mount_info *cmount, const char *path)
475{
476 return cmount->conf_read_file(path);
477}
478
11fdf7f2
TL
479extern "C" mode_t ceph_umask(struct ceph_mount_info *cmount, mode_t mode)
480{
481 return cmount->set_umask(mode);
482}
483
7c673cae
FG
484extern "C" int ceph_conf_parse_argv(struct ceph_mount_info *cmount, int argc,
485 const char **argv)
486{
487 return cmount->conf_parse_argv(argc, argv);
488}
489
490extern "C" int ceph_conf_parse_env(struct ceph_mount_info *cmount, const char *name)
491{
492 return cmount->conf_parse_env(name);
493}
494
495extern "C" int ceph_conf_set(struct ceph_mount_info *cmount, const char *option,
496 const char *value)
497{
498 return cmount->conf_set(option, value);
499}
500
501extern "C" int ceph_conf_get(struct ceph_mount_info *cmount, const char *option,
502 char *buf, size_t len)
503{
11fdf7f2 504 if (!buf) {
1e59de90 505 return -CEPHFS_EINVAL;
7c673cae
FG
506 }
507 return cmount->conf_get(option, buf, len);
508}
509
b3b6e05e
TL
510extern "C" int ceph_set_mount_timeout(struct ceph_mount_info *cmount, uint32_t timeout) {
511 if (cmount->is_mounted()) {
1e59de90 512 return -CEPHFS_EINVAL;
b3b6e05e
TL
513 }
514
515 auto timeout_str = stringify(timeout);
516 return ceph_conf_set(cmount, "client_mount_timeout", timeout_str.c_str());
517}
518
7c673cae
FG
519extern "C" int ceph_mds_command(struct ceph_mount_info *cmount,
520 const char *mds_spec,
521 const char **cmd,
522 size_t cmdlen,
523 const char *inbuf, size_t inbuflen,
524 char **outbuf, size_t *outbuflen,
525 char **outsbuf, size_t *outsbuflen)
526{
527 bufferlist inbl;
528 bufferlist outbl;
529 std::vector<string> cmdv;
530 std::string outs;
531
532 if (!cmount->is_initialized()) {
1e59de90 533 return -CEPHFS_ENOTCONN;
7c673cae
FG
534 }
535
536 // Construct inputs
537 for (size_t i = 0; i < cmdlen; ++i) {
538 cmdv.push_back(cmd[i]);
539 }
540 inbl.append(inbuf, inbuflen);
541
542 // Issue remote command
543 C_SaferCond cond;
544 int r = cmount->get_client()->mds_command(
545 mds_spec,
546 cmdv, inbl,
547 &outbl, &outs,
548 &cond);
549
550 if (r != 0) {
551 goto out;
552 }
553
554 // Wait for completion
555 r = cond.wait();
556
557 // Construct outputs
558 do_out_buffer(outbl, outbuf, outbuflen);
559 do_out_buffer(outs, outsbuf, outsbuflen);
560
561out:
562 return r;
563}
564
565extern "C" int ceph_init(struct ceph_mount_info *cmount)
566{
567 return cmount->init();
568}
569
11fdf7f2
TL
570extern "C" int ceph_select_filesystem(struct ceph_mount_info *cmount,
571 const char *fs_name)
572{
573 if (fs_name == nullptr) {
1e59de90 574 return -CEPHFS_EINVAL;
11fdf7f2
TL
575 }
576
577 return cmount->select_filesystem(fs_name);
578}
579
7c673cae
FG
580extern "C" int ceph_mount(struct ceph_mount_info *cmount, const char *root)
581{
582 std::string mount_root;
583 if (root)
584 mount_root = root;
585 return cmount->mount(mount_root, cmount->default_perms);
586}
587
588extern "C" int ceph_is_mounted(struct ceph_mount_info *cmount)
589{
590 return cmount->is_mounted() ? 1 : 0;
591}
592
593extern "C" struct UserPerm *ceph_mount_perms(struct ceph_mount_info *cmount)
594{
595 return &cmount->default_perms;
596}
597
11fdf7f2
TL
598extern "C" int64_t ceph_get_fs_cid(struct ceph_mount_info *cmount)
599{
600 if (!cmount->is_mounted())
1e59de90 601 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
602 return cmount->get_client()->get_fs_cid();
603}
604
605extern "C" int ceph_mount_perms_set(struct ceph_mount_info *cmount,
606 struct UserPerm *perms)
607{
608 if (cmount->is_mounted())
1e59de90 609 return -CEPHFS_EISCONN;
11fdf7f2
TL
610 cmount->default_perms = *perms;
611 return 0;
612}
613
7c673cae
FG
614extern "C" int ceph_statfs(struct ceph_mount_info *cmount, const char *path,
615 struct statvfs *stbuf)
616{
617 if (!cmount->is_mounted())
1e59de90 618 return -CEPHFS_ENOTCONN;
7c673cae
FG
619 return cmount->get_client()->statfs(path, stbuf, cmount->default_perms);
620}
621
622extern "C" int ceph_get_local_osd(struct ceph_mount_info *cmount)
623{
624 if (!cmount->is_mounted())
1e59de90 625 return -CEPHFS_ENOTCONN;
7c673cae
FG
626 return cmount->get_client()->get_local_osd();
627}
628
629extern "C" const char* ceph_getcwd(struct ceph_mount_info *cmount)
630{
631 return cmount->get_cwd(cmount->default_perms);
632}
633
634extern "C" int ceph_chdir (struct ceph_mount_info *cmount, const char *s)
635{
636 if (!cmount->is_mounted())
1e59de90 637 return -CEPHFS_ENOTCONN;
7c673cae
FG
638 return cmount->chdir(s, cmount->default_perms);
639}
640
641extern "C" int ceph_opendir(struct ceph_mount_info *cmount,
642 const char *name, struct ceph_dir_result **dirpp)
643{
644 if (!cmount->is_mounted())
1e59de90 645 return -CEPHFS_ENOTCONN;
7c673cae
FG
646 return cmount->get_client()->opendir(name, (dir_result_t **)dirpp, cmount->default_perms);
647}
648
b3b6e05e
TL
649extern "C" int ceph_fdopendir(struct ceph_mount_info *cmount, int dirfd,
650 struct ceph_dir_result **dirpp)
651{
652 if (!cmount->is_mounted())
1e59de90 653 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
654 return cmount->get_client()->fdopendir(dirfd, (dir_result_t **)dirpp, cmount->default_perms);
655}
656
7c673cae
FG
657extern "C" int ceph_closedir(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp)
658{
659 if (!cmount->is_mounted())
1e59de90 660 return -CEPHFS_ENOTCONN;
7c673cae
FG
661 return cmount->get_client()->closedir(reinterpret_cast<dir_result_t*>(dirp));
662}
663
664extern "C" struct dirent * ceph_readdir(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp)
665{
666 if (!cmount->is_mounted()) {
667 /* Client::readdir also sets errno to signal errors. */
1e59de90 668 errno = CEPHFS_ENOTCONN;
11fdf7f2 669 return nullptr;
7c673cae
FG
670 }
671 return cmount->get_client()->readdir(reinterpret_cast<dir_result_t*>(dirp));
672}
673
674extern "C" int ceph_readdir_r(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp, struct dirent *de)
675{
676 if (!cmount->is_mounted())
1e59de90 677 return -CEPHFS_ENOTCONN;
7c673cae
FG
678 return cmount->get_client()->readdir_r(reinterpret_cast<dir_result_t*>(dirp), de);
679}
680
681extern "C" int ceph_readdirplus_r(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp,
682 struct dirent *de, struct ceph_statx *stx, unsigned want,
683 unsigned flags, struct Inode **out)
684{
685 if (!cmount->is_mounted())
1e59de90 686 return -CEPHFS_ENOTCONN;
7c673cae 687 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 688 return -CEPHFS_EINVAL;
7c673cae
FG
689 return cmount->get_client()->readdirplus_r(reinterpret_cast<dir_result_t*>(dirp), de, stx, want, flags, out);
690}
691
aee94f69
TL
692extern "C" int ceph_open_snapdiff(struct ceph_mount_info* cmount,
693 const char* root_path,
694 const char* rel_path,
695 const char* snap1,
696 const char* snap2,
697 struct ceph_snapdiff_info* out)
698{
699 if (!cmount->is_mounted()) {
700 /* we set errno to signal errors. */
701 errno = ENOTCONN;
702 return -errno;
703 }
704 if (!out || !root_path || !rel_path ||
705 !snap1 || !*snap1 || !snap2 || !*snap2) {
706 errno = EINVAL;
707 return -errno;
708 }
709 out->cmount = cmount;
710 out->dir1 = out->dir_aux = nullptr;
711
712 char full_path1[PATH_MAX];
713 char snapdir[PATH_MAX];
714 cmount->conf_get("client_snapdir", snapdir, sizeof(snapdir) - 1);
715 int n = snprintf(full_path1, PATH_MAX,
716 "%s/%s/%s/%s", root_path, snapdir, snap1, rel_path);
717 if (n < 0 || n == PATH_MAX) {
718 errno = ENAMETOOLONG;
719 return -errno;
720 }
721 char full_path2[PATH_MAX];
722 n = snprintf(full_path2, PATH_MAX,
723 "%s/%s/%s/%s", root_path, snapdir, snap2, rel_path);
724 if (n < 0 || n == PATH_MAX) {
725 errno = ENAMETOOLONG;
726 return -errno;
727 }
728
729 int r = ceph_opendir(cmount, full_path1, &(out->dir1));
730 if (r != 0) {
731 //it's OK to have one of the snap paths absent - attempting another one
732 r = ceph_opendir(cmount, full_path2, &(out->dir1));
733 if (r != 0) {
734 // both snaps are absent, giving up
735 errno = ENOENT;
736 return -errno;
737 }
738 std::swap(snap1, snap2); // will use snap1 to learn snap_other below
739 } else {
740 // trying to open second snapshot to learn snapid and
741 // get the entry loaded into the client cache if any.
742 r = ceph_opendir(cmount, full_path2, &(out->dir_aux));
743 //paranoic, rely on this value below
744 out->dir_aux = r == 0 ? out->dir_aux : nullptr;
745 }
746 if (!out->dir_aux) {
747 // now trying to learn the second snapshot's id by using snapshot's root
748 n = snprintf(full_path2, PATH_MAX,
749 "%s/%s/%s", root_path, snapdir, snap2);
750 ceph_assert(n > 0 && n < PATH_MAX); //we've already checked above
751 //that longer string fits.
752 // Hence unlikely to assert
753 r = ceph_opendir(cmount, full_path2, &(out->dir_aux));
754 if (r != 0) {
755 goto close_err;
756 }
757 }
758 return 0;
759
760close_err:
761 ceph_close_snapdiff(out);
762 return r;
763}
764
765extern "C" int ceph_readdir_snapdiff(struct ceph_snapdiff_info* snapdiff,
766 struct ceph_snapdiff_entry_t* out)
767{
768 if (!snapdiff->cmount->is_mounted()) {
769 /* also sets errno to signal errors. */
770 errno = ENOTCONN;
771 return -errno;
772 }
773 dir_result_t* d1 = reinterpret_cast<dir_result_t*>(snapdiff->dir1);
774 dir_result_t* d2 = reinterpret_cast<dir_result_t*>(snapdiff->dir_aux);
775 if (!d1 || !d2 || !d1->inode || !d2->inode) {
776 errno = EINVAL;
777 return -errno;
778 }
779 snapid_t snapid;
780 int r = snapdiff->cmount->get_client()->readdir_snapdiff(
781 d1,
782 d2->inode->snapid,
783 &(out->dir_entry),
784 &snapid);
785 if (r >= 0) {
786 // converting snapid_t to uint64_t to avoid snapid_t exposure
787 out->snapid = snapid;
788 }
789 return r;
790}
791
792extern "C" int ceph_close_snapdiff(struct ceph_snapdiff_info* snapdiff)
793{
794 if (!snapdiff->cmount || !snapdiff->cmount->is_mounted()) {
795 /* also sets errno to signal errors. */
796 errno = ENOTCONN;
797 return -errno;
798 }
799 if (snapdiff->dir_aux) {
800 ceph_closedir(snapdiff->cmount, snapdiff->dir_aux);
801 }
802 if (snapdiff->dir1) {
803 ceph_closedir(snapdiff->cmount, snapdiff->dir1);
804 }
805 snapdiff->cmount = nullptr;
806 snapdiff->dir1 = snapdiff->dir_aux = nullptr;
807 return 0;
808}
809
7c673cae
FG
810extern "C" int ceph_getdents(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp,
811 char *buf, int buflen)
812{
813 if (!cmount->is_mounted())
1e59de90 814 return -CEPHFS_ENOTCONN;
7c673cae
FG
815 return cmount->get_client()->getdents(reinterpret_cast<dir_result_t*>(dirp), buf, buflen);
816}
817
818extern "C" int ceph_getdnames(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp,
819 char *buf, int buflen)
820{
821 if (!cmount->is_mounted())
1e59de90 822 return -CEPHFS_ENOTCONN;
7c673cae
FG
823 return cmount->get_client()->getdnames(reinterpret_cast<dir_result_t*>(dirp), buf, buflen);
824}
825
826extern "C" void ceph_rewinddir(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp)
827{
828 if (!cmount->is_mounted())
829 return;
830 cmount->get_client()->rewinddir(reinterpret_cast<dir_result_t*>(dirp));
831}
832
833extern "C" int64_t ceph_telldir(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp)
834{
835 if (!cmount->is_mounted())
1e59de90 836 return -CEPHFS_ENOTCONN;
7c673cae
FG
837 return cmount->get_client()->telldir(reinterpret_cast<dir_result_t*>(dirp));
838}
839
840extern "C" void ceph_seekdir(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp, int64_t offset)
841{
842 if (!cmount->is_mounted())
843 return;
844 cmount->get_client()->seekdir(reinterpret_cast<dir_result_t*>(dirp), offset);
845}
846
f67539c2
TL
847extern "C" int ceph_may_delete(struct ceph_mount_info *cmount, const char *path)
848{
849 if (!cmount->is_mounted())
1e59de90 850 return -CEPHFS_ENOTCONN;
f67539c2
TL
851 return cmount->get_client()->may_delete(path, cmount->default_perms);
852}
853
7c673cae
FG
854extern "C" int ceph_link (struct ceph_mount_info *cmount, const char *existing,
855 const char *newname)
856{
857 if (!cmount->is_mounted())
1e59de90 858 return -CEPHFS_ENOTCONN;
7c673cae
FG
859 return cmount->get_client()->link(existing, newname, cmount->default_perms);
860}
861
862extern "C" int ceph_unlink(struct ceph_mount_info *cmount, const char *path)
863{
864 if (!cmount->is_mounted())
1e59de90 865 return -CEPHFS_ENOTCONN;
7c673cae
FG
866 return cmount->get_client()->unlink(path, cmount->default_perms);
867}
868
b3b6e05e
TL
869extern "C" int ceph_unlinkat(struct ceph_mount_info *cmount, int dirfd, const char *relpath, int flags)
870{
871 if (!cmount->is_mounted())
1e59de90 872 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
873 return cmount->get_client()->unlinkat(dirfd, relpath, flags, cmount->default_perms);
874}
875
7c673cae
FG
876extern "C" int ceph_rename(struct ceph_mount_info *cmount, const char *from,
877 const char *to)
878{
879 if (!cmount->is_mounted())
1e59de90 880 return -CEPHFS_ENOTCONN;
7c673cae
FG
881 return cmount->get_client()->rename(from, to, cmount->default_perms);
882}
883
884// dirs
885extern "C" int ceph_mkdir(struct ceph_mount_info *cmount, const char *path, mode_t mode)
886{
887 if (!cmount->is_mounted())
1e59de90 888 return -CEPHFS_ENOTCONN;
7c673cae
FG
889 return cmount->get_client()->mkdir(path, mode, cmount->default_perms);
890}
891
b3b6e05e
TL
892extern "C" int ceph_mkdirat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
893 mode_t mode)
894{
895 if (!cmount->is_mounted())
1e59de90 896 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
897 return cmount->get_client()->mkdirat(dirfd, relpath, mode, cmount->default_perms);
898}
899
f67539c2
TL
900extern "C" int ceph_mksnap(struct ceph_mount_info *cmount, const char *path, const char *name,
901 mode_t mode, struct snap_metadata *snap_metadata, size_t nr_snap_metadata)
902{
903 if (!cmount->is_mounted())
1e59de90 904 return -CEPHFS_ENOTCONN;
f67539c2
TL
905 size_t i = 0;
906 std::map<std::string, std::string> metadata;
907 while (i < nr_snap_metadata) {
908 metadata.emplace(snap_metadata[i].key, snap_metadata[i].value);
909 ++i;
910 }
911 return cmount->get_client()->mksnap(path, name, cmount->default_perms, mode, metadata);
912}
913
914extern "C" int ceph_rmsnap(struct ceph_mount_info *cmount, const char *path, const char *name)
915{
916 if (!cmount->is_mounted())
1e59de90 917 return -CEPHFS_ENOTCONN;
f67539c2
TL
918 return cmount->get_client()->rmsnap(path, name, cmount->default_perms, true);
919}
920
7c673cae
FG
921extern "C" int ceph_mkdirs(struct ceph_mount_info *cmount, const char *path, mode_t mode)
922{
923 if (!cmount->is_mounted())
1e59de90 924 return -CEPHFS_ENOTCONN;
7c673cae
FG
925 return cmount->get_client()->mkdirs(path, mode, cmount->default_perms);
926}
927
928extern "C" int ceph_rmdir(struct ceph_mount_info *cmount, const char *path)
929{
930 if (!cmount->is_mounted())
1e59de90 931 return -CEPHFS_ENOTCONN;
7c673cae
FG
932 return cmount->get_client()->rmdir(path, cmount->default_perms);
933}
934
935// symlinks
936extern "C" int ceph_readlink(struct ceph_mount_info *cmount, const char *path,
937 char *buf, int64_t size)
938{
939 if (!cmount->is_mounted())
1e59de90 940 return -CEPHFS_ENOTCONN;
7c673cae
FG
941 return cmount->get_client()->readlink(path, buf, size, cmount->default_perms);
942}
943
b3b6e05e
TL
944extern "C" int ceph_readlinkat(struct ceph_mount_info *cmount, int dirfd,
945 const char *relpath, char *buf, int64_t size)
946{
947 if (!cmount->is_mounted())
1e59de90 948 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
949 return cmount->get_client()->readlinkat(dirfd, relpath, buf, size, cmount->default_perms);
950}
951
7c673cae
FG
952extern "C" int ceph_symlink(struct ceph_mount_info *cmount, const char *existing,
953 const char *newname)
954{
955 if (!cmount->is_mounted())
1e59de90 956 return -CEPHFS_ENOTCONN;
7c673cae
FG
957 return cmount->get_client()->symlink(existing, newname, cmount->default_perms);
958}
959
b3b6e05e
TL
960extern "C" int ceph_symlinkat(struct ceph_mount_info *cmount, const char *existing, int dirfd,
961 const char *newname)
962{
963 if (!cmount->is_mounted())
1e59de90 964 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
965 return cmount->get_client()->symlinkat(existing, dirfd, newname, cmount->default_perms);
966}
967
7c673cae
FG
968extern "C" int ceph_fstatx(struct ceph_mount_info *cmount, int fd, struct ceph_statx *stx,
969 unsigned int want, unsigned int flags)
970{
971 if (!cmount->is_mounted())
1e59de90 972 return -CEPHFS_ENOTCONN;
7c673cae 973 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 974 return -CEPHFS_EINVAL;
7c673cae
FG
975 return cmount->get_client()->fstatx(fd, stx, cmount->default_perms,
976 want, flags);
977}
978
b3b6e05e
TL
979extern "C" int ceph_statxat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
980 struct ceph_statx *stx, unsigned int want, unsigned int flags)
981{
982 if (!cmount->is_mounted())
1e59de90 983 return -CEPHFS_ENOTCONN;
b3b6e05e 984 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 985 return -CEPHFS_EINVAL;
b3b6e05e
TL
986 return cmount->get_client()->statxat(dirfd, relpath, stx, cmount->default_perms,
987 want, flags);
988}
989
7c673cae
FG
990extern "C" int ceph_statx(struct ceph_mount_info *cmount, const char *path,
991 struct ceph_statx *stx, unsigned int want, unsigned int flags)
992{
993 if (!cmount->is_mounted())
1e59de90 994 return -CEPHFS_ENOTCONN;
7c673cae 995 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 996 return -CEPHFS_EINVAL;
7c673cae
FG
997 return cmount->get_client()->statx(path, stx, cmount->default_perms,
998 want, flags);
999}
1000
1001extern "C" int ceph_fsetattrx(struct ceph_mount_info *cmount, int fd,
1002 struct ceph_statx *stx, int mask)
1003{
1004 if (!cmount->is_mounted())
1e59de90 1005 return -CEPHFS_ENOTCONN;
7c673cae
FG
1006 return cmount->get_client()->fsetattrx(fd, stx, mask, cmount->default_perms);
1007}
1008
1009extern "C" int ceph_setattrx(struct ceph_mount_info *cmount, const char *relpath,
1010 struct ceph_statx *stx, int mask, int flags)
1011{
1012 if (!cmount->is_mounted())
1e59de90 1013 return -CEPHFS_ENOTCONN;
7c673cae 1014 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 1015 return -CEPHFS_EINVAL;
7c673cae
FG
1016 return cmount->get_client()->setattrx(relpath, stx, mask,
1017 cmount->default_perms, flags);
1018}
1019
1020// *xattr() calls supporting samba/vfs
1021extern "C" int ceph_getxattr(struct ceph_mount_info *cmount, const char *path, const char *name, void *value, size_t size)
1022{
1023 if (!cmount->is_mounted())
1e59de90 1024 return -CEPHFS_ENOTCONN;
7c673cae
FG
1025
1026 return cmount->get_client()->getxattr(path, name, value, size, cmount->default_perms);
1027}
1028
1029extern "C" int ceph_lgetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, void *value, size_t size)
1030{
1031 if (!cmount->is_mounted())
1e59de90 1032 return -CEPHFS_ENOTCONN;
7c673cae
FG
1033 return cmount->get_client()->lgetxattr(path, name, value, size, cmount->default_perms);
1034}
1035
1036extern "C" int ceph_fgetxattr(struct ceph_mount_info *cmount, int fd, const char *name, void *value, size_t size)
1037{
1038 if (!cmount->is_mounted())
1e59de90 1039 return -CEPHFS_ENOTCONN;
7c673cae
FG
1040 return cmount->get_client()->fgetxattr(fd, name, value, size, cmount->default_perms);
1041}
1042
1043
1044extern "C" int ceph_listxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size)
1045{
1046 if (!cmount->is_mounted())
1e59de90 1047 return -CEPHFS_ENOTCONN;
7c673cae
FG
1048 return cmount->get_client()->listxattr(path, list, size, cmount->default_perms);
1049}
1050
1051extern "C" int ceph_llistxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size)
1052{
1053 if (!cmount->is_mounted())
1e59de90 1054 return -CEPHFS_ENOTCONN;
7c673cae
FG
1055 return cmount->get_client()->llistxattr(path, list, size, cmount->default_perms);
1056}
1057
1058extern "C" int ceph_flistxattr(struct ceph_mount_info *cmount, int fd, char *list, size_t size)
1059{
1060 if (!cmount->is_mounted())
1e59de90 1061 return -CEPHFS_ENOTCONN;
7c673cae
FG
1062 return cmount->get_client()->flistxattr(fd, list, size, cmount->default_perms);
1063}
1064
1065extern "C" int ceph_removexattr(struct ceph_mount_info *cmount, const char *path, const char *name)
1066{
1067 if (!cmount->is_mounted())
1e59de90 1068 return -CEPHFS_ENOTCONN;
7c673cae
FG
1069 return cmount->get_client()->removexattr(path, name, cmount->default_perms);
1070}
1071
1072extern "C" int ceph_lremovexattr(struct ceph_mount_info *cmount, const char *path, const char *name)
1073{
1074 if (!cmount->is_mounted())
1e59de90 1075 return -CEPHFS_ENOTCONN;
7c673cae
FG
1076 return cmount->get_client()->lremovexattr(path, name, cmount->default_perms);
1077}
1078
1079extern "C" int ceph_fremovexattr(struct ceph_mount_info *cmount, int fd, const char *name)
1080{
1081 if (!cmount->is_mounted())
1e59de90 1082 return -CEPHFS_ENOTCONN;
7c673cae
FG
1083 return cmount->get_client()->fremovexattr(fd, name, cmount->default_perms);
1084}
1085
1086extern "C" int ceph_setxattr(struct ceph_mount_info *cmount, const char *path, const char *name, const void *value, size_t size, int flags)
1087{
1088 if (!cmount->is_mounted())
1e59de90 1089 return -CEPHFS_ENOTCONN;
7c673cae
FG
1090 return cmount->get_client()->setxattr(path, name, value, size, flags, cmount->default_perms);
1091}
1092
1093extern "C" int ceph_lsetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, const void *value, size_t size, int flags)
1094{
1095 if (!cmount->is_mounted())
1e59de90 1096 return -CEPHFS_ENOTCONN;
7c673cae
FG
1097 return cmount->get_client()->lsetxattr(path, name, value, size, flags, cmount->default_perms);
1098}
1099
1100extern "C" int ceph_fsetxattr(struct ceph_mount_info *cmount, int fd, const char *name, const void *value, size_t size, int flags)
1101{
1102 if (!cmount->is_mounted())
1e59de90 1103 return -CEPHFS_ENOTCONN;
7c673cae
FG
1104 return cmount->get_client()->fsetxattr(fd, name, value, size, flags, cmount->default_perms);
1105}
1106/* end xattr support */
1107
11fdf7f2
TL
1108extern "C" int ceph_stat(struct ceph_mount_info *cmount, const char *path, struct stat *stbuf)
1109{
1110 if (!cmount->is_mounted())
1e59de90 1111 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
1112 return cmount->get_client()->stat(path, stbuf, cmount->default_perms);
1113}
1114
1115extern "C" int ceph_fstat(struct ceph_mount_info *cmount, int fd, struct stat *stbuf)
1116{
1117 if (!cmount->is_mounted())
1e59de90 1118 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
1119 return cmount->get_client()->fstat(fd, stbuf, cmount->default_perms);
1120}
1121
1122extern int ceph_lstat(struct ceph_mount_info *cmount, const char *path, struct stat *stbuf)
1123{
1124 if (!cmount->is_mounted())
1e59de90 1125 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
1126 return cmount->get_client()->lstat(path, stbuf, cmount->default_perms);
1127}
1128
7c673cae
FG
1129extern "C" int ceph_chmod(struct ceph_mount_info *cmount, const char *path, mode_t mode)
1130{
1131 if (!cmount->is_mounted())
1e59de90 1132 return -CEPHFS_ENOTCONN;
7c673cae
FG
1133 return cmount->get_client()->chmod(path, mode, cmount->default_perms);
1134}
f67539c2
TL
1135extern "C" int ceph_lchmod(struct ceph_mount_info *cmount, const char *path, mode_t mode)
1136{
1137 if (!cmount->is_mounted())
1e59de90 1138 return -CEPHFS_ENOTCONN;
f67539c2
TL
1139 return cmount->get_client()->lchmod(path, mode, cmount->default_perms);
1140}
7c673cae
FG
1141extern "C" int ceph_fchmod(struct ceph_mount_info *cmount, int fd, mode_t mode)
1142{
1143 if (!cmount->is_mounted())
1e59de90 1144 return -CEPHFS_ENOTCONN;
7c673cae
FG
1145 return cmount->get_client()->fchmod(fd, mode, cmount->default_perms);
1146}
b3b6e05e
TL
1147
1148extern "C" int ceph_chmodat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
1149 mode_t mode, int flags) {
1150 if (!cmount->is_mounted())
1e59de90 1151 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
1152 return cmount->get_client()->chmodat(dirfd, relpath, mode, flags, cmount->default_perms);
1153}
1154
7c673cae
FG
1155extern "C" int ceph_chown(struct ceph_mount_info *cmount, const char *path,
1156 int uid, int gid)
1157{
1158 if (!cmount->is_mounted())
1e59de90 1159 return -CEPHFS_ENOTCONN;
7c673cae
FG
1160 return cmount->get_client()->chown(path, uid, gid, cmount->default_perms);
1161}
1162extern "C" int ceph_fchown(struct ceph_mount_info *cmount, int fd,
1163 int uid, int gid)
1164{
1165 if (!cmount->is_mounted())
1e59de90 1166 return -CEPHFS_ENOTCONN;
7c673cae
FG
1167 return cmount->get_client()->fchown(fd, uid, gid, cmount->default_perms);
1168}
1169extern "C" int ceph_lchown(struct ceph_mount_info *cmount, const char *path,
1170 int uid, int gid)
1171{
1172 if (!cmount->is_mounted())
1e59de90 1173 return -CEPHFS_ENOTCONN;
7c673cae
FG
1174 return cmount->get_client()->lchown(path, uid, gid, cmount->default_perms);
1175}
1176
b3b6e05e
TL
1177extern "C" int ceph_chownat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
1178 uid_t uid, gid_t gid, int flags) {
1179 if (!cmount->is_mounted())
1e59de90 1180 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
1181 return cmount->get_client()->chownat(dirfd, relpath, uid, gid, flags, cmount->default_perms);
1182}
7c673cae
FG
1183
1184extern "C" int ceph_utime(struct ceph_mount_info *cmount, const char *path,
1185 struct utimbuf *buf)
1186{
1187 if (!cmount->is_mounted())
1e59de90 1188 return -CEPHFS_ENOTCONN;
7c673cae
FG
1189 return cmount->get_client()->utime(path, buf, cmount->default_perms);
1190}
1191
11fdf7f2
TL
1192extern "C" int ceph_futime(struct ceph_mount_info *cmount, int fd,
1193 struct utimbuf *buf)
1194{
1195 if (!cmount->is_mounted())
1e59de90 1196 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
1197 return cmount->get_client()->futime(fd, buf, cmount->default_perms);
1198}
1199
1200extern "C" int ceph_utimes(struct ceph_mount_info *cmount, const char *path,
1201 struct timeval times[2])
1202{
1203 if (!cmount->is_mounted())
1e59de90 1204 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
1205 return cmount->get_client()->utimes(path, times, cmount->default_perms);
1206}
1207
1208extern "C" int ceph_lutimes(struct ceph_mount_info *cmount, const char *path,
1209 struct timeval times[2])
1210{
1211 if (!cmount->is_mounted())
1e59de90 1212 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
1213 return cmount->get_client()->lutimes(path, times, cmount->default_perms);
1214}
1215
1216extern "C" int ceph_futimes(struct ceph_mount_info *cmount, int fd,
1217 struct timeval times[2])
1218{
1219 if (!cmount->is_mounted())
1e59de90 1220 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
1221 return cmount->get_client()->futimes(fd, times, cmount->default_perms);
1222}
1223
1224extern "C" int ceph_futimens(struct ceph_mount_info *cmount, int fd,
1225 struct timespec times[2])
1226{
1227 if (!cmount->is_mounted())
1e59de90 1228 return -CEPHFS_ENOTCONN;
11fdf7f2
TL
1229 return cmount->get_client()->futimens(fd, times, cmount->default_perms);
1230}
1231
b3b6e05e
TL
1232extern "C" int ceph_utimensat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
1233 struct timespec times[2], int flags) {
1234 if (!cmount->is_mounted())
1e59de90 1235 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
1236 return cmount->get_client()->utimensat(dirfd, relpath, times, flags, cmount->default_perms);
1237}
1238
7c673cae
FG
1239extern "C" int ceph_flock(struct ceph_mount_info *cmount, int fd, int operation,
1240 uint64_t owner)
1241{
1242 if (!cmount->is_mounted())
1e59de90 1243 return -CEPHFS_ENOTCONN;
7c673cae
FG
1244 return cmount->get_client()->flock(fd, operation, owner);
1245}
1246
1247extern "C" int ceph_truncate(struct ceph_mount_info *cmount, const char *path,
1248 int64_t size)
1249{
1250 if (!cmount->is_mounted())
1e59de90 1251 return -CEPHFS_ENOTCONN;
7c673cae
FG
1252 return cmount->get_client()->truncate(path, size, cmount->default_perms);
1253}
1254
1255// file ops
1256extern "C" int ceph_mknod(struct ceph_mount_info *cmount, const char *path,
1257 mode_t mode, dev_t rdev)
1258{
1259 if (!cmount->is_mounted())
1e59de90 1260 return -CEPHFS_ENOTCONN;
7c673cae
FG
1261 return cmount->get_client()->mknod(path, mode, cmount->default_perms, rdev);
1262}
1263
1264extern "C" int ceph_open(struct ceph_mount_info *cmount, const char *path,
1265 int flags, mode_t mode)
1266{
1267 if (!cmount->is_mounted())
1e59de90 1268 return -CEPHFS_ENOTCONN;
7c673cae
FG
1269 return cmount->get_client()->open(path, flags, cmount->default_perms, mode);
1270}
1271
b3b6e05e
TL
1272extern "C" int ceph_openat(struct ceph_mount_info *cmount, int dirfd, const char *relpath,
1273 int flags, mode_t mode)
1274{
1275 if (!cmount->is_mounted())
1e59de90 1276 return -CEPHFS_ENOTCONN;
b3b6e05e
TL
1277 return cmount->get_client()->openat(dirfd, relpath, flags, cmount->default_perms, mode);
1278}
1279
7c673cae
FG
1280extern "C" int ceph_open_layout(struct ceph_mount_info *cmount, const char *path, int flags,
1281 mode_t mode, int stripe_unit, int stripe_count, int object_size, const char *data_pool)
1282{
1283 if (!cmount->is_mounted())
1e59de90 1284 return -CEPHFS_ENOTCONN;
7c673cae
FG
1285 return cmount->get_client()->open(path, flags, cmount->default_perms, mode,
1286 stripe_unit, stripe_count,
1287 object_size, data_pool);
1288}
1289
1290extern "C" int ceph_close(struct ceph_mount_info *cmount, int fd)
1291{
1292 if (!cmount->is_mounted())
1e59de90 1293 return -CEPHFS_ENOTCONN;
7c673cae
FG
1294 return cmount->get_client()->close(fd);
1295}
1296
1297extern "C" int64_t ceph_lseek(struct ceph_mount_info *cmount, int fd,
1298 int64_t offset, int whence)
1299{
1300 if (!cmount->is_mounted())
1e59de90 1301 return -CEPHFS_ENOTCONN;
7c673cae
FG
1302 return cmount->get_client()->lseek(fd, offset, whence);
1303}
1304
1305extern "C" int ceph_read(struct ceph_mount_info *cmount, int fd, char *buf,
1306 int64_t size, int64_t offset)
1307{
1308 if (!cmount->is_mounted())
1e59de90 1309 return -CEPHFS_ENOTCONN;
7c673cae
FG
1310 return cmount->get_client()->read(fd, buf, size, offset);
1311}
1312
1313extern "C" int ceph_preadv(struct ceph_mount_info *cmount, int fd,
1314 const struct iovec *iov, int iovcnt, int64_t offset)
1315{
1316 if (!cmount->is_mounted())
1e59de90 1317 return -CEPHFS_ENOTCONN;
7c673cae
FG
1318 return cmount->get_client()->preadv(fd, iov, iovcnt, offset);
1319}
1320
1321extern "C" int ceph_write(struct ceph_mount_info *cmount, int fd, const char *buf,
1322 int64_t size, int64_t offset)
1323{
1324 if (!cmount->is_mounted())
1e59de90 1325 return -CEPHFS_ENOTCONN;
7c673cae
FG
1326 return cmount->get_client()->write(fd, buf, size, offset);
1327}
1328
1329extern "C" int ceph_pwritev(struct ceph_mount_info *cmount, int fd,
1330 const struct iovec *iov, int iovcnt, int64_t offset)
1331{
1332 if (!cmount->is_mounted())
1e59de90 1333 return -CEPHFS_ENOTCONN;
7c673cae
FG
1334 return cmount->get_client()->pwritev(fd, iov, iovcnt, offset);
1335}
1336
1337extern "C" int ceph_ftruncate(struct ceph_mount_info *cmount, int fd, int64_t size)
1338{
1339 if (!cmount->is_mounted())
1e59de90 1340 return -CEPHFS_ENOTCONN;
7c673cae
FG
1341 return cmount->get_client()->ftruncate(fd, size, cmount->default_perms);
1342}
1343
1344extern "C" int ceph_fsync(struct ceph_mount_info *cmount, int fd, int syncdataonly)
1345{
1346 if (!cmount->is_mounted())
1e59de90 1347 return -CEPHFS_ENOTCONN;
7c673cae
FG
1348 return cmount->get_client()->fsync(fd, syncdataonly);
1349}
1350
1351extern "C" int ceph_fallocate(struct ceph_mount_info *cmount, int fd, int mode,
1352 int64_t offset, int64_t length)
1353{
1354 if (!cmount->is_mounted())
1e59de90 1355 return -CEPHFS_ENOTCONN;
7c673cae
FG
1356 return cmount->get_client()->fallocate(fd, mode, offset, length);
1357}
1358
11fdf7f2
TL
1359extern "C" int ceph_lazyio(class ceph_mount_info *cmount,
1360 int fd, int enable)
1361{
1362 return (cmount->get_client()->lazyio(fd, enable));
1363}
1364
92f5a8d4
TL
1365extern "C" int ceph_lazyio_propagate(class ceph_mount_info *cmount,
1366 int fd, int64_t offset, size_t count)
1367{
1368 if (!cmount->is_mounted())
1e59de90 1369 return -CEPHFS_ENOTCONN;
92f5a8d4
TL
1370 return (cmount->get_client()->lazyio_propagate(fd, offset, count));
1371}
1372
1373extern "C" int ceph_lazyio_synchronize(class ceph_mount_info *cmount,
1374 int fd, int64_t offset, size_t count)
1375{
1376 if (!cmount->is_mounted())
1e59de90 1377 return -CEPHFS_ENOTCONN;
92f5a8d4
TL
1378 return (cmount->get_client()->lazyio_synchronize(fd, offset, count));
1379}
1380
1381
7c673cae
FG
1382extern "C" int ceph_sync_fs(struct ceph_mount_info *cmount)
1383{
1384 if (!cmount->is_mounted())
1e59de90 1385 return -CEPHFS_ENOTCONN;
7c673cae
FG
1386 return cmount->get_client()->sync_fs();
1387}
1388
7c673cae
FG
1389extern "C" int ceph_get_file_stripe_unit(struct ceph_mount_info *cmount, int fh)
1390{
1391 file_layout_t l;
1392 int r;
1393
1394 if (!cmount->is_mounted())
1e59de90 1395 return -CEPHFS_ENOTCONN;
7c673cae
FG
1396 r = cmount->get_client()->fdescribe_layout(fh, &l);
1397 if (r < 0)
1398 return r;
1399 return l.stripe_unit;
1400}
1401
1402extern "C" int ceph_get_path_stripe_unit(struct ceph_mount_info *cmount, const char *path)
1403{
1404 file_layout_t l;
1405 int r;
1406
1407 if (!cmount->is_mounted())
1e59de90 1408 return -CEPHFS_ENOTCONN;
7c673cae
FG
1409 r = cmount->get_client()->describe_layout(path, &l, cmount->default_perms);
1410 if (r < 0)
1411 return r;
1412 return l.stripe_unit;
1413}
1414
1415extern "C" int ceph_get_file_stripe_count(struct ceph_mount_info *cmount, int fh)
1416{
1417 file_layout_t l;
1418 int r;
1419
1420 if (!cmount->is_mounted())
1e59de90 1421 return -CEPHFS_ENOTCONN;
7c673cae
FG
1422 r = cmount->get_client()->fdescribe_layout(fh, &l);
1423 if (r < 0)
1424 return r;
1425 return l.stripe_count;
1426}
1427
1428extern "C" int ceph_get_path_stripe_count(struct ceph_mount_info *cmount, const char *path)
1429{
1430 file_layout_t l;
1431 int r;
1432
1433 if (!cmount->is_mounted())
1e59de90 1434 return -CEPHFS_ENOTCONN;
7c673cae
FG
1435 r = cmount->get_client()->describe_layout(path, &l, cmount->default_perms);
1436 if (r < 0)
1437 return r;
1438 return l.stripe_count;
1439}
1440
1441extern "C" int ceph_get_file_object_size(struct ceph_mount_info *cmount, int fh)
1442{
1443 file_layout_t l;
1444 int r;
1445
1446 if (!cmount->is_mounted())
1e59de90 1447 return -CEPHFS_ENOTCONN;
7c673cae
FG
1448 r = cmount->get_client()->fdescribe_layout(fh, &l);
1449 if (r < 0)
1450 return r;
1451 return l.object_size;
1452}
1453
1454extern "C" int ceph_get_path_object_size(struct ceph_mount_info *cmount, const char *path)
1455{
1456 file_layout_t l;
1457 int r;
1458
1459 if (!cmount->is_mounted())
1e59de90 1460 return -CEPHFS_ENOTCONN;
7c673cae
FG
1461 r = cmount->get_client()->describe_layout(path, &l, cmount->default_perms);
1462 if (r < 0)
1463 return r;
1464 return l.object_size;
1465}
1466
1467extern "C" int ceph_get_file_pool(struct ceph_mount_info *cmount, int fh)
1468{
1469 file_layout_t l;
1470 int r;
1471
1472 if (!cmount->is_mounted())
1e59de90 1473 return -CEPHFS_ENOTCONN;
7c673cae
FG
1474 r = cmount->get_client()->fdescribe_layout(fh, &l);
1475 if (r < 0)
1476 return r;
1477 return l.pool_id;
1478}
1479
1480extern "C" int ceph_get_path_pool(struct ceph_mount_info *cmount, const char *path)
1481{
1482 file_layout_t l;
1483 int r;
1484
1485 if (!cmount->is_mounted())
1e59de90 1486 return -CEPHFS_ENOTCONN;
7c673cae
FG
1487 r = cmount->get_client()->describe_layout(path, &l, cmount->default_perms);
1488 if (r < 0)
1489 return r;
1490 return l.pool_id;
1491}
1492
1493extern "C" int ceph_get_file_pool_name(struct ceph_mount_info *cmount, int fh, char *buf, size_t len)
1494{
1495 file_layout_t l;
1496 int r;
1497
1498 if (!cmount->is_mounted())
1e59de90 1499 return -CEPHFS_ENOTCONN;
7c673cae
FG
1500 r = cmount->get_client()->fdescribe_layout(fh, &l);
1501 if (r < 0)
1502 return r;
1503 string name = cmount->get_client()->get_pool_name(l.pool_id);
1504 if (len == 0)
1505 return name.length();
1506 if (name.length() > len)
1e59de90 1507 return -CEPHFS_ERANGE;
7c673cae
FG
1508 strncpy(buf, name.c_str(), len);
1509 return name.length();
1510}
1511
1512extern "C" int ceph_get_pool_name(struct ceph_mount_info *cmount, int pool, char *buf, size_t len)
1513{
1514 if (!cmount->is_mounted())
1e59de90 1515 return -CEPHFS_ENOTCONN;
7c673cae
FG
1516 string name = cmount->get_client()->get_pool_name(pool);
1517 if (len == 0)
1518 return name.length();
1519 if (name.length() > len)
1e59de90 1520 return -CEPHFS_ERANGE;
7c673cae
FG
1521 strncpy(buf, name.c_str(), len);
1522 return name.length();
1523}
1524
1525extern "C" int ceph_get_path_pool_name(struct ceph_mount_info *cmount, const char *path, char *buf, size_t len)
1526{
1527 file_layout_t l;
1528 int r;
1529
1530 if (!cmount->is_mounted())
1e59de90 1531 return -CEPHFS_ENOTCONN;
7c673cae
FG
1532 r = cmount->get_client()->describe_layout(path, &l, cmount->default_perms);
1533 if (r < 0)
1534 return r;
1535 string name = cmount->get_client()->get_pool_name(l.pool_id);
1536 if (len == 0)
1537 return name.length();
1538 if (name.length() > len)
1e59de90 1539 return -CEPHFS_ERANGE;
7c673cae
FG
1540 strncpy(buf, name.c_str(), len);
1541 return name.length();
1542}
1543
d2e6a577
FG
1544extern "C" int ceph_get_default_data_pool_name(struct ceph_mount_info *cmount, char *buf, size_t len)
1545{
1546 if (!cmount->is_mounted())
1e59de90 1547 return -CEPHFS_ENOTCONN;
d2e6a577
FG
1548 int64_t pool_id = cmount->get_client()->get_default_pool_id();
1549
1550 string name = cmount->get_client()->get_pool_name(pool_id);
1551 if (len == 0)
1552 return name.length();
1553 if (name.length() > len)
1e59de90 1554 return -CEPHFS_ERANGE;
d2e6a577
FG
1555 strncpy(buf, name.c_str(), len);
1556 return name.length();
1557}
1558
7c673cae
FG
1559extern "C" int ceph_get_file_layout(struct ceph_mount_info *cmount, int fh, int *stripe_unit, int *stripe_count, int *object_size, int *pg_pool)
1560{
1561 file_layout_t l;
1562 int r;
1563
1564 if (!cmount->is_mounted())
1e59de90 1565 return -CEPHFS_ENOTCONN;
7c673cae
FG
1566 r = cmount->get_client()->fdescribe_layout(fh, &l);
1567 if (r < 0)
1568 return r;
1569 if (stripe_unit)
1570 *stripe_unit = l.stripe_unit;
1571 if (stripe_count)
1572 *stripe_count = l.stripe_count;
1573 if (object_size)
1574 *object_size = l.object_size;
1575 if (pg_pool)
1576 *pg_pool = l.pool_id;
1577 return 0;
1578}
1579
1580extern "C" int ceph_get_path_layout(struct ceph_mount_info *cmount, const char *path, int *stripe_unit, int *stripe_count, int *object_size, int *pg_pool)
1581{
1582 file_layout_t l;
1583 int r;
1584
1585 if (!cmount->is_mounted())
1e59de90 1586 return -CEPHFS_ENOTCONN;
7c673cae
FG
1587 r = cmount->get_client()->describe_layout(path, &l, cmount->default_perms);
1588 if (r < 0)
1589 return r;
1590 if (stripe_unit)
1591 *stripe_unit = l.stripe_unit;
1592 if (stripe_count)
1593 *stripe_count = l.stripe_count;
1594 if (object_size)
1595 *object_size = l.object_size;
1596 if (pg_pool)
1597 *pg_pool = l.pool_id;
1598 return 0;
1599}
1600
1601extern "C" int ceph_get_file_replication(struct ceph_mount_info *cmount, int fh)
1602{
1603 file_layout_t l;
1604 int r;
1605
1606 if (!cmount->is_mounted())
1e59de90 1607 return -CEPHFS_ENOTCONN;
7c673cae
FG
1608 r = cmount->get_client()->fdescribe_layout(fh, &l);
1609 if (r < 0)
1610 return r;
1611 int rep = cmount->get_client()->get_pool_replication(l.pool_id);
1612 return rep;
1613}
1614
1615extern "C" int ceph_get_path_replication(struct ceph_mount_info *cmount, const char *path)
1616{
1617 file_layout_t l;
1618 int r;
1619
1620 if (!cmount->is_mounted())
1e59de90 1621 return -CEPHFS_ENOTCONN;
7c673cae
FG
1622 r = cmount->get_client()->describe_layout(path, &l, cmount->default_perms);
1623 if (r < 0)
1624 return r;
1625 int rep = cmount->get_client()->get_pool_replication(l.pool_id);
1626 return rep;
1627}
1628
1629extern "C" int ceph_set_default_file_stripe_unit(struct ceph_mount_info *cmount,
1630 int stripe)
1631{
1632 // this option no longer exists
1e59de90 1633 return -CEPHFS_EOPNOTSUPP;
7c673cae
FG
1634}
1635
1636extern "C" int ceph_set_default_file_stripe_count(struct ceph_mount_info *cmount,
1637 int count)
1638{
1639 // this option no longer exists
1e59de90 1640 return -CEPHFS_EOPNOTSUPP;
7c673cae
FG
1641}
1642
1643extern "C" int ceph_set_default_object_size(struct ceph_mount_info *cmount, int size)
1644{
1645 // this option no longer exists
1e59de90 1646 return -CEPHFS_EOPNOTSUPP;
7c673cae
FG
1647}
1648
1649extern "C" int ceph_set_default_file_replication(struct ceph_mount_info *cmount,
1650 int replication)
1651{
1652 // this option no longer exists
1e59de90 1653 return -CEPHFS_EOPNOTSUPP;
7c673cae
FG
1654}
1655
1656extern "C" int ceph_set_default_preferred_pg(struct ceph_mount_info *cmount, int osd)
1657{
1658 // this option no longer exists
1e59de90 1659 return -CEPHFS_EOPNOTSUPP;
7c673cae
FG
1660}
1661
1662extern "C" int ceph_get_file_extent_osds(struct ceph_mount_info *cmount, int fh,
1663 int64_t offset, int64_t *length, int *osds, int nosds)
1664{
1665 if (nosds < 0)
1e59de90 1666 return -CEPHFS_EINVAL;
7c673cae
FG
1667
1668 if (!cmount->is_mounted())
1e59de90 1669 return -CEPHFS_ENOTCONN;
7c673cae
FG
1670
1671 vector<int> vosds;
1672 int ret = cmount->get_client()->get_file_extent_osds(fh, offset, length, vosds);
1673 if (ret < 0)
1674 return ret;
1675
1676 if (!nosds)
1677 return vosds.size();
1678
1679 if ((int)vosds.size() > nosds)
1e59de90 1680 return -CEPHFS_ERANGE;
7c673cae
FG
1681
1682 for (int i = 0; i < (int)vosds.size(); i++)
1683 osds[i] = vosds[i];
1684
1685 return vosds.size();
1686}
1687
1688extern "C" int ceph_get_osd_crush_location(struct ceph_mount_info *cmount,
1689 int osd, char *path, size_t len)
1690{
1691 if (!cmount->is_mounted())
1e59de90 1692 return -CEPHFS_ENOTCONN;
7c673cae
FG
1693
1694 if (!path && len)
1e59de90 1695 return -CEPHFS_EINVAL;
7c673cae
FG
1696
1697 vector<pair<string, string> > loc;
1698 int ret = cmount->get_client()->get_osd_crush_location(osd, loc);
1699 if (ret)
1700 return ret;
1701
1702 size_t needed = 0;
1703 size_t cur = 0;
1704 vector<pair<string, string> >::iterator it;
1705 for (it = loc.begin(); it != loc.end(); ++it) {
1706 string& type = it->first;
1707 string& name = it->second;
1708 needed += type.size() + name.size() + 2;
1709 if (needed <= len) {
1710 if (path)
1711 strcpy(path + cur, type.c_str());
1712 cur += type.size() + 1;
1713 if (path)
1714 strcpy(path + cur, name.c_str());
1715 cur += name.size() + 1;
1716 }
1717 }
1718
1719 if (len == 0)
1720 return needed;
1721
1722 if (needed > len)
1e59de90 1723 return -CEPHFS_ERANGE;
7c673cae
FG
1724
1725 return needed;
1726}
1727
1728extern "C" int ceph_get_osd_addr(struct ceph_mount_info *cmount, int osd,
1729 struct sockaddr_storage *addr)
1730{
1731 if (!cmount->is_mounted())
1e59de90 1732 return -CEPHFS_ENOTCONN;
7c673cae
FG
1733
1734 if (!addr)
1e59de90 1735 return -CEPHFS_EINVAL;
7c673cae
FG
1736
1737 entity_addr_t address;
1738 int ret = cmount->get_client()->get_osd_addr(osd, address);
1739 if (ret < 0)
1740 return ret;
1741
1742 *addr = address.get_sockaddr_storage();
1743
1744 return 0;
1745}
1746
1747extern "C" int ceph_get_file_stripe_address(struct ceph_mount_info *cmount, int fh,
1748 int64_t offset, struct sockaddr_storage *addr, int naddr)
1749{
1750 vector<entity_addr_t> address;
1751 unsigned i;
1752 int r;
1753
1754 if (naddr < 0)
1e59de90 1755 return -CEPHFS_EINVAL;
7c673cae
FG
1756
1757 if (!cmount->is_mounted())
1e59de90 1758 return -CEPHFS_ENOTCONN;
7c673cae
FG
1759
1760 r = cmount->get_client()->get_file_stripe_address(fh, offset, address);
1761 if (r < 0)
1762 return r;
1763
1764 for (i = 0; i < (unsigned)naddr && i < address.size(); i++)
1765 addr[i] = address[i].get_sockaddr_storage();
1766
1767 /* naddr == 0: drop through and return actual size */
1768 if (naddr && (address.size() > (unsigned)naddr))
1e59de90 1769 return -CEPHFS_ERANGE;
7c673cae
FG
1770
1771 return address.size();
1772}
1773
1774extern "C" int ceph_localize_reads(struct ceph_mount_info *cmount, int val)
1775{
1776 if (!cmount->is_mounted())
1e59de90 1777 return -CEPHFS_ENOTCONN;
7c673cae
FG
1778 if (!val)
1779 cmount->get_client()->clear_filer_flags(CEPH_OSD_FLAG_LOCALIZE_READS);
1780 else
1781 cmount->get_client()->set_filer_flags(CEPH_OSD_FLAG_LOCALIZE_READS);
1782 return 0;
1783}
1784
1785extern "C" CephContext *ceph_get_mount_context(struct ceph_mount_info *cmount)
1786{
1787 return cmount->get_ceph_context();
1788}
1789
1790extern "C" int ceph_debug_get_fd_caps(struct ceph_mount_info *cmount, int fd)
1791{
1792 if (!cmount->is_mounted())
1e59de90 1793 return -CEPHFS_ENOTCONN;
7c673cae
FG
1794 return cmount->get_client()->get_caps_issued(fd);
1795}
1796
1797extern "C" int ceph_debug_get_file_caps(struct ceph_mount_info *cmount, const char *path)
1798{
1799 if (!cmount->is_mounted())
1e59de90 1800 return -CEPHFS_ENOTCONN;
7c673cae
FG
1801 return cmount->get_client()->get_caps_issued(path, cmount->default_perms);
1802}
1803
1804extern "C" int ceph_get_stripe_unit_granularity(struct ceph_mount_info *cmount)
1805{
1806 if (!cmount->is_mounted())
1e59de90 1807 return -CEPHFS_ENOTCONN;
7c673cae
FG
1808 return CEPH_MIN_STRIPE_UNIT;
1809}
1810
1811extern "C" int ceph_get_pool_id(struct ceph_mount_info *cmount, const char *pool_name)
1812{
1813 if (!cmount->is_mounted())
1e59de90 1814 return -CEPHFS_ENOTCONN;
7c673cae
FG
1815
1816 if (!pool_name || !pool_name[0])
1e59de90 1817 return -CEPHFS_EINVAL;
7c673cae
FG
1818
1819 /* negative range reserved for errors */
1820 int64_t pool_id = cmount->get_client()->get_pool_id(pool_name);
1821 if (pool_id > 0x7fffffff)
1e59de90 1822 return -CEPHFS_ERANGE;
7c673cae
FG
1823
1824 /* get_pool_id error codes fit in int */
1825 return (int)pool_id;
1826}
1827
1828extern "C" int ceph_get_pool_replication(struct ceph_mount_info *cmount,
1829 int pool_id)
1830{
1831 if (!cmount->is_mounted())
1e59de90 1832 return -CEPHFS_ENOTCONN;
7c673cae
FG
1833 return cmount->get_client()->get_pool_replication(pool_id);
1834}
1835/* Low-level exports */
1836
1837extern "C" int ceph_ll_lookup_root(struct ceph_mount_info *cmount,
1838 Inode **parent)
1839{
1840 *parent = cmount->get_client()->get_root();
1841 if (*parent)
1842 return 0;
1e59de90 1843 return -CEPHFS_EFAULT;
7c673cae
FG
1844}
1845
1846extern "C" struct Inode *ceph_ll_get_inode(class ceph_mount_info *cmount,
1847 vinodeno_t vino)
1848{
1849 return (cmount->get_client())->ll_get_inode(vino);
1850}
1851
1852
f67539c2
TL
1853extern "C" int ceph_ll_lookup_vino(
1854 struct ceph_mount_info *cmount,
1855 vinodeno_t vino,
1856 Inode **inode)
1857{
1858 return (cmount->get_client())->ll_lookup_vino(vino, cmount->default_perms, inode);
1859}
1860
7c673cae
FG
1861/**
1862 * Populates the client cache with the requested inode, and its
1863 * parent dentry.
1864 */
1865extern "C" int ceph_ll_lookup_inode(
1866 struct ceph_mount_info *cmount,
1867 struct inodeno_t ino,
1868 Inode **inode)
1869{
1adf2230 1870 return (cmount->get_client())->ll_lookup_inode(ino, cmount->default_perms, inode);
7c673cae
FG
1871}
1872
1873extern "C" int ceph_ll_lookup(struct ceph_mount_info *cmount,
1874 Inode *parent, const char *name, Inode **out,
1875 struct ceph_statx *stx, unsigned want,
1876 unsigned flags, const UserPerm *perms)
1877{
1878 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 1879 return -CEPHFS_EINVAL;
7c673cae
FG
1880 return (cmount->get_client())->ll_lookupx(parent, name, out, stx, want,
1881 flags, *perms);
1882}
1883
1884extern "C" int ceph_ll_put(class ceph_mount_info *cmount, Inode *in)
1885{
1886 return (cmount->get_client()->ll_put(in));
1887}
1888
1889extern "C" int ceph_ll_forget(class ceph_mount_info *cmount, Inode *in,
1890 int count)
1891{
1892 return (cmount->get_client()->ll_forget(in, count));
1893}
1894
1895extern "C" int ceph_ll_walk(struct ceph_mount_info *cmount, const char* name, Inode **i,
1896 struct ceph_statx *stx, unsigned int want, unsigned int flags,
1897 const UserPerm *perms)
1898{
1899 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 1900 return -CEPHFS_EINVAL;
7c673cae
FG
1901 return(cmount->get_client()->ll_walk(name, i, stx, want, flags, *perms));
1902}
1903
1904extern "C" int ceph_ll_getattr(class ceph_mount_info *cmount,
1905 Inode *in, struct ceph_statx *stx,
1906 unsigned int want, unsigned int flags,
1907 const UserPerm *perms)
1908{
1909 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 1910 return -CEPHFS_EINVAL;
7c673cae
FG
1911 return (cmount->get_client()->ll_getattrx(in, stx, want, flags, *perms));
1912}
1913
1914extern "C" int ceph_ll_setattr(class ceph_mount_info *cmount,
1915 Inode *in, struct ceph_statx *stx,
1916 int mask, const UserPerm *perms)
1917{
1918 return (cmount->get_client()->ll_setattrx(in, stx, mask, *perms));
1919}
1920
1921extern "C" int ceph_ll_open(class ceph_mount_info *cmount, Inode *in,
1922 int flags, Fh **fh, const UserPerm *perms)
1923{
1924 return (cmount->get_client()->ll_open(in, flags, fh, *perms));
1925}
1926
1927extern "C" int ceph_ll_read(class ceph_mount_info *cmount, Fh* filehandle,
1928 int64_t off, uint64_t len, char* buf)
1929{
1930 bufferlist bl;
1931 int r = 0;
1932
1933 r = cmount->get_client()->ll_read(filehandle, off, len, &bl);
1934 if (r >= 0)
1935 {
9f95a23c 1936 bl.begin().copy(bl.length(), buf);
7c673cae
FG
1937 r = bl.length();
1938 }
1939 return r;
1940}
1941
1942extern "C" int ceph_ll_read_block(class ceph_mount_info *cmount,
1943 Inode *in, uint64_t blockid,
1944 char* buf, uint64_t offset,
1945 uint64_t length,
1946 struct ceph_file_layout* layout)
1947{
1948 file_layout_t l;
1949 int r = (cmount->get_client()->ll_read_block(in, blockid, buf, offset,
1950 length, &l));
1951 l.to_legacy(layout);
1952 return r;
1953}
1954
1955extern "C" int ceph_ll_write_block(class ceph_mount_info *cmount,
1956 Inode *in, uint64_t blockid,
1957 char *buf, uint64_t offset,
1958 uint64_t length,
1959 struct ceph_file_layout *layout,
1960 uint64_t snapseq, uint32_t sync)
1961{
1962 file_layout_t l;
1963 int r = (cmount->get_client()->ll_write_block(in, blockid, buf, offset,
1964 length, &l, snapseq, sync));
1965 l.to_legacy(layout);
1966 return r;
1967}
1968
1969extern "C" int ceph_ll_commit_blocks(class ceph_mount_info *cmount,
1970 Inode *in, uint64_t offset,
1971 uint64_t range)
1972{
1973 return (cmount->get_client()->ll_commit_blocks(in, offset, range));
1974}
1975
1976extern "C" int ceph_ll_fsync(class ceph_mount_info *cmount,
1977 Fh *fh, int syncdataonly)
1978{
1979 return (cmount->get_client()->ll_fsync(fh, syncdataonly));
1980}
1981
28e407b8
AA
1982extern "C" int ceph_ll_sync_inode(class ceph_mount_info *cmount,
1983 Inode *in, int syncdataonly)
1984{
1985 return (cmount->get_client()->ll_sync_inode(in, syncdataonly));
1986}
1987
11fdf7f2
TL
1988extern "C" int ceph_ll_fallocate(class ceph_mount_info *cmount, Fh *fh,
1989 int mode, int64_t offset, int64_t length)
1990{
1991 return cmount->get_client()->ll_fallocate(fh, mode, offset, length);
1992}
1993
7c673cae
FG
1994extern "C" off_t ceph_ll_lseek(class ceph_mount_info *cmount,
1995 Fh *fh, off_t offset, int whence)
1996{
1997 return (cmount->get_client()->ll_lseek(fh, offset, whence));
1998}
1999
2000extern "C" int ceph_ll_write(class ceph_mount_info *cmount,
2001 Fh *fh, int64_t off, uint64_t len,
2002 const char *data)
2003{
2004 return (cmount->get_client()->ll_write(fh, off, len, data));
2005}
2006
2007extern "C" int64_t ceph_ll_readv(class ceph_mount_info *cmount,
2008 struct Fh *fh, const struct iovec *iov,
2009 int iovcnt, int64_t off)
2010{
11fdf7f2 2011 return (cmount->get_client()->ll_readv(fh, iov, iovcnt, off));
7c673cae
FG
2012}
2013
2014extern "C" int64_t ceph_ll_writev(class ceph_mount_info *cmount,
2015 struct Fh *fh, const struct iovec *iov,
2016 int iovcnt, int64_t off)
2017{
11fdf7f2 2018 return (cmount->get_client()->ll_writev(fh, iov, iovcnt, off));
7c673cae
FG
2019}
2020
2021extern "C" int ceph_ll_close(class ceph_mount_info *cmount, Fh* fh)
2022{
2023 return (cmount->get_client()->ll_release(fh));
2024}
2025
2026extern "C" int ceph_ll_create(class ceph_mount_info *cmount,
2027 Inode *parent, const char *name, mode_t mode,
2028 int oflags, Inode **outp, Fh **fhp,
2029 struct ceph_statx *stx, unsigned want,
2030 unsigned lflags, const UserPerm *perms)
2031{
2032 if (lflags & ~CEPH_REQ_FLAG_MASK)
1e59de90 2033 return -CEPHFS_EINVAL;
7c673cae
FG
2034 return (cmount->get_client())->ll_createx(parent, name, mode, oflags, outp,
2035 fhp, stx, want, lflags, *perms);
2036}
2037
2038extern "C" int ceph_ll_mknod(class ceph_mount_info *cmount, Inode *parent,
2039 const char *name, mode_t mode, dev_t rdev,
2040 Inode **out, struct ceph_statx *stx,
2041 unsigned want, unsigned flags,
2042 const UserPerm *perms)
2043{
2044 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 2045 return -CEPHFS_EINVAL;
7c673cae
FG
2046 return (cmount->get_client())->ll_mknodx(parent, name, mode, rdev,
2047 out, stx, want, flags, *perms);
2048}
2049
2050extern "C" int ceph_ll_mkdir(class ceph_mount_info *cmount, Inode *parent,
2051 const char *name, mode_t mode, Inode **out,
2052 struct ceph_statx *stx, unsigned want,
2053 unsigned flags, const UserPerm *perms)
2054{
2055 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 2056 return -CEPHFS_EINVAL;
7c673cae
FG
2057 return cmount->get_client()->ll_mkdirx(parent, name, mode, out, stx, want,
2058 flags, *perms);
2059}
2060
2061extern "C" int ceph_ll_link(class ceph_mount_info *cmount,
2062 Inode *in, Inode *newparent,
2063 const char *name, const UserPerm *perms)
2064{
2065 return cmount->get_client()->ll_link(in, newparent, name, *perms);
2066}
2067
2068extern "C" int ceph_ll_opendir(class ceph_mount_info *cmount,
2069 Inode *in,
2070 struct ceph_dir_result **dirpp,
2071 const UserPerm *perms)
2072{
2073 return (cmount->get_client()->ll_opendir(in, O_RDONLY, (dir_result_t**) dirpp,
2074 *perms));
2075}
2076
2077extern "C" int ceph_ll_releasedir(class ceph_mount_info *cmount,
2078 ceph_dir_result *dir)
2079{
9f95a23c 2080 return cmount->get_client()->ll_releasedir(reinterpret_cast<dir_result_t*>(dir));
7c673cae
FG
2081}
2082
2083extern "C" int ceph_ll_rename(class ceph_mount_info *cmount,
2084 Inode *parent, const char *name,
2085 Inode *newparent, const char *newname,
2086 const UserPerm *perms)
2087{
2088 return cmount->get_client()->ll_rename(parent, name, newparent,
2089 newname, *perms);
2090}
2091
2092extern "C" int ceph_ll_unlink(class ceph_mount_info *cmount, Inode *in,
2093 const char *name, const UserPerm *perms)
2094{
2095 return cmount->get_client()->ll_unlink(in, name, *perms);
2096}
2097
2098extern "C" int ceph_ll_statfs(class ceph_mount_info *cmount,
2099 Inode *in, struct statvfs *stbuf)
2100{
2101 return (cmount->get_client()->ll_statfs(in, stbuf, cmount->default_perms));
2102}
2103
2104extern "C" int ceph_ll_readlink(class ceph_mount_info *cmount, Inode *in,
2105 char *buf, size_t bufsiz,
2106 const UserPerm *perms)
2107{
2108 return cmount->get_client()->ll_readlink(in, buf, bufsiz, *perms);
2109}
2110
2111extern "C" int ceph_ll_symlink(class ceph_mount_info *cmount,
2112 Inode *in, const char *name,
2113 const char *value, Inode **out,
2114 struct ceph_statx *stx, unsigned want,
2115 unsigned flags, const UserPerm *perms)
2116{
2117 if (flags & ~CEPH_REQ_FLAG_MASK)
1e59de90 2118 return -CEPHFS_EINVAL;
7c673cae
FG
2119 return (cmount->get_client()->ll_symlinkx(in, name, value, out, stx, want,
2120 flags, *perms));
2121}
2122
2123extern "C" int ceph_ll_rmdir(class ceph_mount_info *cmount,
2124 Inode *in, const char *name,
2125 const UserPerm *perms)
2126{
2127 return cmount->get_client()->ll_rmdir(in, name, *perms);
2128}
2129
2130extern "C" int ceph_ll_getxattr(class ceph_mount_info *cmount,
2131 Inode *in, const char *name, void *value,
2132 size_t size, const UserPerm *perms)
2133{
2134 return (cmount->get_client()->ll_getxattr(in, name, value, size, *perms));
2135}
2136
2137extern "C" int ceph_ll_listxattr(struct ceph_mount_info *cmount,
2138 Inode *in, char *list,
2139 size_t buf_size, size_t *list_size,
2140 const UserPerm *perms)
2141{
2142 int res = cmount->get_client()->ll_listxattr(in, list, buf_size, *perms);
2143 if (res >= 0) {
2144 *list_size = (size_t)res;
2145 return 0;
2146 }
2147 return res;
2148}
2149
2150extern "C" int ceph_ll_setxattr(class ceph_mount_info *cmount,
2151 Inode *in, const char *name,
2152 const void *value, size_t size,
2153 int flags, const UserPerm *perms)
2154{
2155 return (cmount->get_client()->ll_setxattr(in, name, value, size, flags, *perms));
2156}
2157
2158extern "C" int ceph_ll_removexattr(class ceph_mount_info *cmount,
2159 Inode *in, const char *name,
2160 const UserPerm *perms)
2161{
2162 return (cmount->get_client()->ll_removexattr(in, name, *perms));
2163}
2164
2165extern "C" int ceph_ll_getlk(struct ceph_mount_info *cmount,
2166 Fh *fh, struct flock *fl, uint64_t owner)
2167{
2168 return (cmount->get_client()->ll_getlk(fh, fl, owner));
2169}
2170
2171extern "C" int ceph_ll_setlk(struct ceph_mount_info *cmount,
2172 Fh *fh, struct flock *fl, uint64_t owner,
2173 int sleep)
2174{
2175 return (cmount->get_client()->ll_setlk(fh, fl, owner, sleep));
2176}
2177
11fdf7f2
TL
2178extern "C" int ceph_ll_lazyio(class ceph_mount_info *cmount,
2179 Fh *fh, int enable)
2180{
2181 return (cmount->get_client()->ll_lazyio(fh, enable));
2182}
2183
b32b8144
FG
2184extern "C" int ceph_ll_delegation(struct ceph_mount_info *cmount, Fh *fh,
2185 unsigned cmd, ceph_deleg_cb_t cb, void *priv)
2186{
2187 return (cmount->get_client()->ll_delegation(fh, cmd, cb, priv));
2188}
2189
7c673cae
FG
2190extern "C" uint32_t ceph_ll_stripe_unit(class ceph_mount_info *cmount,
2191 Inode *in)
2192{
2193 return (cmount->get_client()->ll_stripe_unit(in));
2194}
2195
2196extern "C" uint32_t ceph_ll_file_layout(class ceph_mount_info *cmount,
2197 Inode *in,
2198 struct ceph_file_layout *layout)
2199{
2200 file_layout_t l;
2201 int r = (cmount->get_client()->ll_file_layout(in, &l));
2202 l.to_legacy(layout);
2203 return r;
2204}
2205
2206uint64_t ceph_ll_snap_seq(class ceph_mount_info *cmount, Inode *in)
2207{
2208 return (cmount->get_client()->ll_snap_seq(in));
2209}
2210
2211extern "C" int ceph_ll_get_stripe_osd(class ceph_mount_info *cmount,
2212 Inode *in, uint64_t blockno,
2213 struct ceph_file_layout* layout)
2214{
2215 file_layout_t l;
2216 int r = (cmount->get_client()->ll_get_stripe_osd(in, blockno, &l));
2217 l.to_legacy(layout);
2218 return r;
2219}
2220
2221extern "C" int ceph_ll_num_osds(class ceph_mount_info *cmount)
2222{
2223 return (cmount->get_client()->ll_num_osds());
2224}
2225
2226extern "C" int ceph_ll_osdaddr(class ceph_mount_info *cmount,
2227 int osd, uint32_t *addr)
2228{
2229 return (cmount->get_client()->ll_osdaddr(osd, addr));
2230}
2231
2232extern "C" uint64_t ceph_ll_get_internal_offset(class ceph_mount_info *cmount,
2233 Inode *in,
2234 uint64_t blockno)
2235{
2236 return (cmount->get_client()->ll_get_internal_offset(in, blockno));
2237}
2238
2239extern "C" void ceph_buffer_free(char *buf)
2240{
2241 if (buf) {
2242 free(buf);
2243 }
2244}
b32b8144
FG
2245
2246extern "C" uint32_t ceph_get_cap_return_timeout(class ceph_mount_info *cmount)
2247{
2248 if (!cmount->is_mounted())
2249 return 0;
2250 return cmount->get_client()->mdsmap->get_session_autoclose().sec();
2251}
2252
2253extern "C" int ceph_set_deleg_timeout(class ceph_mount_info *cmount, uint32_t timeout)
2254{
2255 if (!cmount->is_mounted())
1e59de90 2256 return -CEPHFS_ENOTCONN;
b32b8144
FG
2257 return cmount->get_client()->set_deleg_timeout(timeout);
2258}
11fdf7f2
TL
2259
2260extern "C" void ceph_set_session_timeout(class ceph_mount_info *cmount, unsigned timeout)
2261{
2262 cmount->get_client()->set_session_timeout(timeout);
2263}
2264
2265extern "C" void ceph_set_uuid(class ceph_mount_info *cmount, const char *uuid)
2266{
2267 cmount->get_client()->set_uuid(std::string(uuid));
2268}
2269
2270extern "C" int ceph_start_reclaim(class ceph_mount_info *cmount,
2271 const char *uuid, unsigned flags)
2272{
2273 if (!cmount->is_initialized()) {
2274 int ret = cmount->init();
2275 if (ret != 0)
2276 return ret;
2277 }
2278 return cmount->get_client()->start_reclaim(std::string(uuid), flags,
2279 cmount->get_filesystem());
2280}
2281
2282extern "C" void ceph_finish_reclaim(class ceph_mount_info *cmount)
2283{
2284 cmount->get_client()->finish_reclaim();
2285}
e306af50 2286
20effc67 2287// This is deprecated, use ceph_ll_register_callbacks2 instead.
e306af50
TL
2288extern "C" void ceph_ll_register_callbacks(class ceph_mount_info *cmount,
2289 struct ceph_client_callback_args *args)
2290{
2291 cmount->get_client()->ll_register_callbacks(args);
20effc67 2292}
f67539c2 2293
20effc67
TL
2294extern "C" int ceph_ll_register_callbacks2(class ceph_mount_info *cmount,
2295 struct ceph_client_callback_args *args)
2296{
2297 return cmount->get_client()->ll_register_callbacks2(args);
f67539c2
TL
2298}
2299
2300
2301extern "C" int ceph_get_snap_info(struct ceph_mount_info *cmount,
2302 const char *path, struct snap_info *snap_info) {
2303 Client::SnapInfo info;
2304 int r = cmount->get_client()->get_snap_info(path, cmount->default_perms, &info);
2305 if (r < 0) {
2306 return r;
2307 }
2308
2309 size_t i = 0;
2310 auto nr_metadata = info.metadata.size();
2311
2312 snap_info->id = info.id.val;
2313 snap_info->nr_snap_metadata = nr_metadata;
2314 if (nr_metadata) {
2315 snap_info->snap_metadata = (struct snap_metadata *)calloc(nr_metadata, sizeof(struct snap_metadata));
2316 if (!snap_info->snap_metadata) {
1e59de90 2317 return -CEPHFS_ENOMEM;
f67539c2
TL
2318 }
2319
2320 // fill with key, value pairs
2321 for (auto &[key, value] : info.metadata) {
2322 // len(key) + '\0' + len(value) + '\0'
2323 char *kvp = (char *)malloc(key.size() + value.size() + 2);
2324 if (!kvp) {
2325 break;
2326 }
2327 char *_key = kvp;
2328 char *_value = kvp + key.size() + 1;
2329
2330 memcpy(_key, key.c_str(), key.size());
2331 _key[key.size()] = '\0';
2332 memcpy(_value, value.c_str(), value.size());
2333 _value[value.size()] = '\0';
2334
2335 snap_info->snap_metadata[i].key = _key;
2336 snap_info->snap_metadata[i].value = _value;
2337 ++i;
2338 }
2339 }
2340
2341 if (nr_metadata && i != nr_metadata) {
2342 ceph_free_snap_info_buffer(snap_info);
1e59de90 2343 return -CEPHFS_ENOMEM;
f67539c2
TL
2344 }
2345
2346 return 0;
2347}
2348
2349extern "C" void ceph_free_snap_info_buffer(struct snap_info *snap_info) {
2350 for (size_t i = 0; i < snap_info->nr_snap_metadata; ++i) {
2351 free((void *)snap_info->snap_metadata[i].key); // malloc'd memory is key+value composite
2352 }
2353 free(snap_info->snap_metadata);
e306af50 2354}