1 /*
2 Copyright 2017 Skytechnology sp. z o.o..
3
4 This file is part of LizardFS.
5
6 LizardFS is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3.
9
10 LizardFS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with LizardFS If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "common/platform.h"
20
21 #include <cassert>
22 #include <system_error>
23
24 #include "lizardfs_c_api.h"
25 #include "common/lizardfs_error_codes.h"
26 #include "common/md5.h"
27 #include "common/small_vector.h"
28 #include "mount/client/iovec_traits.h"
29
30 #include "client.h"
31
32 using namespace lizardfs;
33
liz_set_default_init_params(struct liz_init_params * params,const char * host,const char * port,const char * mountpoint)34 void liz_set_default_init_params(struct liz_init_params *params,
35 const char *host, const char *port, const char *mountpoint) {
36 assert(params != nullptr);
37 params->bind_host = nullptr;
38 params->host = host;
39 params->port = port;
40 params->meta = false;
41 params->mountpoint = mountpoint;
42 params->subfolder = LizardClient::FsInitParams::kDefaultSubfolder;
43 params->password = nullptr;
44 params->md5_pass = nullptr;
45 params->do_not_remember_password = LizardClient::FsInitParams::kDefaultDoNotRememberPassword;
46 params->delayed_init = LizardClient::FsInitParams::kDefaultDelayedInit;
47 params->report_reserved_period = LizardClient::FsInitParams::kDefaultReportReservedPeriod;
48
49 params->io_retries = LizardClient::FsInitParams::kDefaultIoRetries;
50 params->chunkserver_round_time_ms = LizardClient::FsInitParams::kDefaultRoundTime;
51 params->chunkserver_connect_timeout_ms = LizardClient::FsInitParams::kDefaultChunkserverConnectTo;
52 params->chunkserver_wave_read_timeout_ms = LizardClient::FsInitParams::kDefaultChunkserverWaveReadTo;
53 params->total_read_timeout_ms = LizardClient::FsInitParams::kDefaultChunkserverTotalReadTo;
54 params->cache_expiration_time_ms = LizardClient::FsInitParams::kDefaultCacheExpirationTime;
55 params->readahead_max_window_size_kB = LizardClient::FsInitParams::kDefaultReadaheadMaxWindowSize;
56 params->prefetch_xor_stripes = LizardClient::FsInitParams::kDefaultPrefetchXorStripes;
57 params->bandwidth_overuse = LizardClient::FsInitParams::kDefaultBandwidthOveruse;
58
59 params->write_cache_size = LizardClient::FsInitParams::kDefaultWriteCacheSize;
60 params->write_workers = LizardClient::FsInitParams::kDefaultWriteWorkers;
61 params->write_window_size = LizardClient::FsInitParams::kDefaultWriteWindowSize;
62 params->chunkserver_write_timeout_ms = LizardClient::FsInitParams::kDefaultChunkserverWriteTo;
63 params->cache_per_inode_percentage = LizardClient::FsInitParams::kDefaultCachePerInodePercentage;
64 params->symlink_cache_timeout_s = LizardClient::FsInitParams::kDefaultSymlinkCacheTimeout;
65
66 params->debug_mode = LizardClient::FsInitParams::kDefaultDebugMode;
67 params->keep_cache = LizardClient::FsInitParams::kDefaultKeepCache;
68 params->direntry_cache_timeout = LizardClient::FsInitParams::kDefaultDirentryCacheTimeout;
69 params->direntry_cache_size = LizardClient::FsInitParams::kDefaultDirentryCacheSize;
70 params->entry_cache_timeout = LizardClient::FsInitParams::kDefaultEntryCacheTimeout;
71 params->attr_cache_timeout = LizardClient::FsInitParams::kDefaultAttrCacheTimeout;
72 params->mkdir_copy_sgid = LizardClient::FsInitParams::kDefaultMkdirCopySgid;
73 params->sugid_clear_mode = (liz_sugid_clear_mode)LizardClient::FsInitParams::kDefaultSugidClearMode;
74 params->use_rw_lock = LizardClient::FsInitParams::kDefaultUseRwLock;
75 params->acl_cache_timeout = LizardClient::FsInitParams::kDefaultAclCacheTimeout;
76 params->acl_cache_size = LizardClient::FsInitParams::kDefaultAclCacheSize;
77
78 params->verbose = LizardClient::FsInitParams::kDefaultVerbose;
79
80 params->io_limits_config_file = nullptr;
81
82 // statically assert that all SugidClearMode value are covered and consistent
83 static_assert(sizeof(liz_sugid_clear_mode) >= sizeof(SugidClearMode), "");
84 for (int dummy = LIZARDFS_SUGID_CLEAR_MODE_NEVER; dummy < LIZARDFS_SUGID_CLEAR_MODE_END_; ++dummy) {
85 switch (SugidClearMode(dummy)) { // exhaustive match check thanks to 'enum class'
86 #define STATIC_ASSERT_SUGID_CLEAR_MODE(KNAME,CENUM) \
87 case SugidClearMode::KNAME: \
88 static_assert((liz_sugid_clear_mode)SugidClearMode::KNAME == CENUM, \
89 "liz_sugid_clear_mode incompatible with SugidClearMode");
90 STATIC_ASSERT_SUGID_CLEAR_MODE(kNever, LIZARDFS_SUGID_CLEAR_MODE_NEVER);
91 STATIC_ASSERT_SUGID_CLEAR_MODE(kAlways, LIZARDFS_SUGID_CLEAR_MODE_ALWAYS);
92 STATIC_ASSERT_SUGID_CLEAR_MODE(kOsx, LIZARDFS_SUGID_CLEAR_MODE_OSX);
93 STATIC_ASSERT_SUGID_CLEAR_MODE(kBsd, LIZARDFS_SUGID_CLEAR_MODE_BSD);
94 STATIC_ASSERT_SUGID_CLEAR_MODE(kExt, LIZARDFS_SUGID_CLEAR_MODE_EXT);
95 STATIC_ASSERT_SUGID_CLEAR_MODE(kXfs, LIZARDFS_SUGID_CLEAR_MODE_XFS);
96 #undef STATIC_ASSERT_SUGID_CLEAR_MODE
97 }
98 }
99 }
100
101 static thread_local liz_err_t gLastErrorCode(LIZARDFS_STATUS_OK);
102
to_entry(const Client::EntryParam & param,liz_entry * entry)103 static void to_entry(const Client::EntryParam ¶m, liz_entry *entry) {
104 assert(entry);
105 entry->ino = param.ino;
106 entry->generation = param.generation;
107 entry->attr = param.attr;
108 entry->attr_timeout = param.attr_timeout;
109 entry->entry_timeout = param.entry_timeout;
110 }
111
to_attr_reply(const Client::AttrReply & attr_reply,liz_attr_reply * reply)112 static void to_attr_reply(const Client::AttrReply &attr_reply, liz_attr_reply *reply) {
113 assert(reply);
114 reply->attr = attr_reply.attr;
115 reply->attr_timeout = attr_reply.attrTimeout;
116 }
117
to_stat(const Client::Stats & stats,liz_stat_t * buf)118 static void to_stat(const Client::Stats &stats, liz_stat_t *buf) {
119 assert(buf);
120 buf->total_space = stats.total_space;
121 buf->avail_space = stats.avail_space;
122 buf->trash_space = stats.trash_space;
123 buf->reserved_space = stats.reserved_space;
124 buf->inodes = stats.inodes;
125 }
126
liz_last_err()127 liz_err_t liz_last_err() {
128 return gLastErrorCode;
129 }
130
liz_error_conv(liz_err_t lizardfs_error_code)131 liz_err_t liz_error_conv(liz_err_t lizardfs_error_code) {
132 if (lizardfs_error_code < 0) {
133 return EINVAL;
134 } else {
135 return lizardfs_error_conv(lizardfs_error_code);
136 }
137 }
138
liz_error_string(liz_err_t lizardfs_error_code)139 const char *liz_error_string(liz_err_t lizardfs_error_code) {
140 return lizardfs_error_string(lizardfs_error_code);
141 }
142
liz_create_context()143 liz_context_t *liz_create_context() {
144 try {
145 Client::Context *ret = new Client::Context(getuid(), getgid(), getpid(), 0);
146 return (liz_context_t *)ret;
147 } catch (...) {
148 gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
149 return nullptr;
150 }
151 }
152
liz_create_user_context(uid_t uid,gid_t gid,pid_t pid,mode_t umask)153 liz_context_t *liz_create_user_context(uid_t uid, gid_t gid, pid_t pid, mode_t umask) {
154 try {
155 Client::Context *ret = new Client::Context(uid, gid, pid, umask);
156 return (liz_context_t *)ret;
157 } catch (...) {
158 gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
159 return nullptr;
160 }
161 }
162
liz_destroy_context(liz_context_t * ctx)163 void liz_destroy_context(liz_context_t *ctx) {
164 Client::Context *client_ctx = (Client::Context *)ctx;
165 delete client_ctx;
166 }
167
liz_set_lock_owner(liz_fileinfo_t * fileinfo,uint64_t lock_owner)168 void liz_set_lock_owner(liz_fileinfo_t *fileinfo, uint64_t lock_owner) {
169 Client::FileInfo *fi = (Client::FileInfo *)fileinfo;
170 fi->lock_owner = lock_owner;
171 }
172
liz_init(const char * host,const char * port,const char * mountpoint)173 liz_t *liz_init(const char *host, const char *port, const char *mountpoint) {
174 try {
175 Client *ret = new Client(host, port, mountpoint);
176 gLastErrorCode = LIZARDFS_STATUS_OK;
177 return (liz_t *)ret;
178 } catch (...) {
179 gLastErrorCode = LIZARDFS_ERROR_CANTCONNECT;
180 return nullptr;
181 }
182 }
183
liz_init_with_params(struct liz_init_params * params)184 liz_t *liz_init_with_params(struct liz_init_params *params) {
185 assert(params != nullptr);
186 assert(params->host != nullptr);
187 assert(params->port != nullptr);
188 assert(params->mountpoint != nullptr);
189 assert(params->sugid_clear_mode >= 0);
190 assert(params->sugid_clear_mode < LIZARDFS_SUGID_CLEAR_MODE_END_);
191
192 Client::FsInitParams init_params(params->bind_host != nullptr ? params->bind_host : "",
193 params->host, params->port, params->mountpoint);
194
195 init_params.meta = params->meta;
196 if (params->subfolder != nullptr) {
197 init_params.subfolder = params->subfolder;
198 }
199 if (params->password != nullptr) {
200 md5ctx md5_ctx;
201 init_params.password_digest.resize(16);
202 md5_init(&md5_ctx);
203 md5_update(&md5_ctx,(uint8_t *)(params->password), strlen(params->password));
204 md5_final(init_params.password_digest.data(), &md5_ctx);
205 } else if (params->md5_pass) {
206 int ret = md5_parse(init_params.password_digest, params->md5_pass);
207 if (ret < 0) {
208 gLastErrorCode = LIZARDFS_ERROR_EINVAL;
209 return nullptr;
210 }
211 }
212
213 #define COPY_PARAM(PARAM) do { \
214 static_assert(std::is_same<decltype(init_params.PARAM), decltype(params->PARAM)>::value, \
215 "liz_init_params member incompatible with FsInitParams"); \
216 init_params.PARAM = params->PARAM; \
217 } while (0)
218 COPY_PARAM(do_not_remember_password);
219 COPY_PARAM(delayed_init);
220 COPY_PARAM(report_reserved_period);
221 COPY_PARAM(io_retries);
222 COPY_PARAM(chunkserver_round_time_ms);
223 COPY_PARAM(chunkserver_connect_timeout_ms);
224 COPY_PARAM(chunkserver_wave_read_timeout_ms);
225 COPY_PARAM(total_read_timeout_ms);
226 COPY_PARAM(cache_expiration_time_ms);
227 COPY_PARAM(readahead_max_window_size_kB);
228 COPY_PARAM(prefetch_xor_stripes);
229 COPY_PARAM(bandwidth_overuse);
230 COPY_PARAM(write_cache_size);
231 COPY_PARAM(write_workers);
232 COPY_PARAM(write_window_size);
233 COPY_PARAM(chunkserver_write_timeout_ms);
234 COPY_PARAM(cache_per_inode_percentage);
235 COPY_PARAM(symlink_cache_timeout_s);
236 COPY_PARAM(debug_mode);
237 COPY_PARAM(keep_cache);
238 COPY_PARAM(direntry_cache_timeout);
239 COPY_PARAM(direntry_cache_size);
240 COPY_PARAM(entry_cache_timeout);
241 COPY_PARAM(attr_cache_timeout);
242 COPY_PARAM(mkdir_copy_sgid);
243 init_params.sugid_clear_mode = (SugidClearMode)params->sugid_clear_mode;
244 COPY_PARAM(use_rw_lock);
245 COPY_PARAM(acl_cache_timeout);
246 COPY_PARAM(acl_cache_size);
247 COPY_PARAM(verbose);
248 #undef COPY_PARAM
249
250 if (params->io_limits_config_file != nullptr) {
251 init_params.io_limits_config_file = params->io_limits_config_file;
252 }
253
254 try {
255 Client *ret = new Client(init_params);
256 gLastErrorCode = LIZARDFS_STATUS_OK;
257 return (liz_t *)ret;
258 } catch (...) {
259 gLastErrorCode = LIZARDFS_ERROR_CANTCONNECT;
260 return nullptr;
261 }
262 }
263
liz_update_groups(liz_t * instance,liz_context_t * ctx,gid_t * gids,int gid_num)264 int liz_update_groups(liz_t *instance, liz_context_t *ctx, gid_t *gids, int gid_num) {
265 Client &client = *(Client *)instance;
266 Client::Context &client_ctx = *(Client::Context *)ctx;
267 Client::Context::GroupsContainer gids_backup(std::move(client_ctx.gids));
268 try {
269 client_ctx.gids.assign(gids, gids + gid_num);
270 std::error_code ec;
271 client.updateGroups(client_ctx, ec);
272 gLastErrorCode = ec.value();
273 if (ec) {
274 client_ctx.gids = std::move(gids_backup);
275 return -1;
276 }
277 } catch (...) {
278 client_ctx.gids = std::move(gids_backup);
279 gLastErrorCode = LIZARDFS_ERROR_GROUPNOTREGISTERED;
280 return -1;
281 }
282 return 0;
283 }
284
liz_lookup(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path,liz_entry * entry)285 int liz_lookup(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path,
286 liz_entry *entry) {
287 Client &client = *(Client *)instance;
288 Client::Context &context = *(Client::Context *)ctx;
289 Client::EntryParam entry_param;
290 std::error_code ec;
291 client.lookup(context, parent, path, entry_param, ec);
292 gLastErrorCode = ec.value();
293 if (ec) {
294 return -1;
295 } else {
296 to_entry(entry_param, entry);
297 }
298 return 0;
299 }
300
liz_mknod(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path,mode_t mode,dev_t rdev,liz_entry * entry)301 int liz_mknod(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path,
302 mode_t mode, dev_t rdev, liz_entry *entry) {
303 Client &client = *(Client *)instance;
304 Client::Context &context = *(Client::Context *)ctx;
305 Client::EntryParam entry_param;
306 std::error_code ec;
307 client.mknod(context, parent, path, mode, rdev, entry_param, ec);
308 gLastErrorCode = ec.value();
309 if (ec) {
310 return -1;
311 } else {
312 to_entry(entry_param, entry);
313 }
314 return 0;
315 }
316
liz_link(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,liz_inode_t parent,const char * name,struct liz_entry * entry)317 int liz_link(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, liz_inode_t parent,
318 const char *name, struct liz_entry *entry) {
319 Client &client = *(Client *)instance;
320 Client::Context &context = *(Client::Context *)ctx;
321 Client::EntryParam entry_param;
322 std::error_code ec;
323 client.link(context, inode, parent, name, entry_param, ec);
324 gLastErrorCode = ec.value();
325 if (ec) {
326 return -1;
327 }
328 to_entry(entry_param, entry);
329 return 0;
330 }
331
liz_symlink(liz_t * instance,liz_context_t * ctx,const char * link,liz_inode_t parent,const char * name,struct liz_entry * entry)332 int liz_symlink(liz_t *instance, liz_context_t *ctx, const char *link, liz_inode_t parent,
333 const char *name, struct liz_entry *entry) {
334 Client &client = *(Client *)instance;
335 Client::Context &context = *(Client::Context *)ctx;
336 Client::EntryParam entry_param;
337 std::error_code ec;
338 client.symlink(context, link, parent, name, entry_param, ec);
339 gLastErrorCode = ec.value();
340 if (ec) {
341 return -1;
342 }
343 to_entry(entry_param, entry);
344 return 0;
345 }
346
liz_open(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,int flags)347 liz_fileinfo *liz_open(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, int flags) {
348 Client &client = *(Client *)instance;
349 Client::Context &context = *(Client::Context *)ctx;
350 std::error_code ec;
351 liz_fileinfo *fi = (liz_fileinfo *)client.open(context, inode, flags, ec);
352 gLastErrorCode = ec.value();
353 return fi;
354 }
355
liz_read(liz_t * instance,liz_context_t * ctx,liz_fileinfo * fileinfo,off_t offset,size_t size,char * buffer)356 ssize_t liz_read(liz_t *instance, liz_context_t *ctx, liz_fileinfo *fileinfo, off_t offset,
357 size_t size, char *buffer) {
358 Client &client = *(Client *)instance;
359 Client::Context &context = *(Client::Context *)ctx;
360 std::error_code ec;
361 auto ret = client.read(context, (Client::FileInfo *)fileinfo, offset, size, ec);
362 if (ec) {
363 gLastErrorCode = ec.value();
364 return -1;
365 }
366 return ret.copyToBuffer((uint8_t *)buffer, offset, size);
367 }
368
liz_readv(liz_t * instance,liz_context_t * ctx,liz_fileinfo * fileinfo,off_t offset,size_t size,const struct iovec * iov,int iovcnt)369 ssize_t liz_readv(liz_t *instance, liz_context_t *ctx, liz_fileinfo *fileinfo, off_t offset,
370 size_t size, const struct iovec *iov, int iovcnt) {
371 Client &client = *(Client *)instance;
372 Client::Context &context = *(Client::Context *)ctx;
373 std::error_code ec;
374 auto ret = client.read(context, (Client::FileInfo *)fileinfo, offset, size, ec);
375 if (ec) {
376 gLastErrorCode = ec.value();
377 return -1;
378 }
379 small_vector<struct iovec, 8> reply;
380 ret.toIoVec(reply, offset, size);
381 return copyIoVec(iov, iovcnt, reply.data(), reply.size());
382 }
383
liz_write(liz_t * instance,liz_context_t * ctx,liz_fileinfo * fileinfo,off_t offset,size_t size,const char * buffer)384 ssize_t liz_write(liz_t *instance, liz_context_t *ctx, liz_fileinfo *fileinfo, off_t offset,
385 size_t size, const char *buffer){
386 Client &client = *(Client *)instance;
387 Client::Context &context = *(Client::Context *)ctx;
388 std::error_code ec;
389 std::size_t write_ret = client.write(context, (Client::FileInfo *)fileinfo, offset, size,
390 buffer, ec);
391 gLastErrorCode = ec.value();
392 return ec ? -1 : write_ret;
393 }
394
liz_release(liz_t * instance,liz_fileinfo * fileinfo)395 int liz_release(liz_t *instance, liz_fileinfo *fileinfo) {
396 Client &client = *(Client *)instance;
397 std::error_code ec;
398 client.release((Client::FileInfo *)fileinfo, ec);
399 gLastErrorCode = ec.value();
400 return ec ? -1 : 0;
401 }
402
liz_flush(liz_t * instance,liz_context_t * ctx,liz_fileinfo * fileinfo)403 int liz_flush(liz_t *instance, liz_context_t *ctx, liz_fileinfo *fileinfo) {
404 Client &client = *(Client *)instance;
405 Client::Context &context = *(Client::Context *)ctx;
406 std::error_code ec;
407 client.flush(context, (Client::FileInfo *)fileinfo, ec);
408 gLastErrorCode = ec.value();
409 return ec ? -1 : 0;
410 }
411
liz_getattr(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,liz_attr_reply * reply)412 int liz_getattr(liz_t *instance, liz_context_t *ctx, liz_inode_t inode,
413 liz_attr_reply *reply) {
414 Client &client = *(Client *)instance;
415 Client::Context &context = *(Client::Context *)ctx;
416 Client::AttrReply r;
417 std::error_code ec;
418 client.getattr(context, inode, r, ec);
419 gLastErrorCode = ec.value();
420 if (ec) {
421 return -1;
422 } else if (reply) {
423 to_attr_reply(r, reply);
424 }
425 return 0;
426 }
427
liz_destroy(liz_t * instance)428 void liz_destroy(liz_t *instance) {
429 Client *client = (Client *)instance;
430 delete client;
431 }
432
liz_opendir(liz_t * instance,liz_context_t * ctx,liz_inode_t inode)433 struct liz_fileinfo *liz_opendir(liz_t *instance, liz_context_t *ctx, liz_inode_t inode) {
434 Client &client = *(Client *)instance;
435 Client::Context &context = *(Client::Context *)ctx;
436 std::error_code ec;
437 liz_fileinfo *fi = (liz_fileinfo *)client.opendir(context, inode, ec);
438 gLastErrorCode = ec.value();
439 return fi;
440 }
441
liz_readdir(liz_t * instance,liz_context_t * ctx,struct liz_fileinfo * fileinfo,off_t offset,size_t max_entries,struct liz_direntry * buf,size_t * num_entries)442 int liz_readdir(liz_t *instance, liz_context_t *ctx, struct liz_fileinfo *fileinfo,
443 off_t offset, size_t max_entries, struct liz_direntry *buf, size_t *num_entries) {
444 Client &client = *(Client *)instance;
445 Client::Context &context = *(Client::Context *)ctx;
446 std::error_code ec;
447
448 if (max_entries > 0) {
449 buf->name = NULL;
450 } else {
451 gLastErrorCode = LIZARDFS_ERROR_EINVAL;
452 return -1;
453 }
454
455 Client::ReadDirReply reply = client.readdir(context, (Client::FileInfo *)fileinfo,
456 offset, max_entries, ec);
457 *num_entries = 0;
458 gLastErrorCode = ec.value();
459 if (ec) {
460 return -1;
461 }
462 if (reply.empty()) {
463 return 0;
464 }
465
466 size_t total_name_size = 0;
467 for (const auto &dir_entry : reply) {
468 total_name_size += dir_entry.name.size() + 1;
469 }
470
471 char *p_namebuf;
472 try {
473 p_namebuf = new char[total_name_size];
474 } catch (...) {
475 gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
476 return -1;
477 }
478
479 for (const auto &dir_entry : reply) {
480 buf->name = p_namebuf;
481 buf->attr = dir_entry.attr;
482 buf->next_entry_offset = dir_entry.nextEntryOffset;
483 buf++;
484
485 auto s = dir_entry.name.size();
486 dir_entry.name.copy(p_namebuf, s);
487 p_namebuf[s] = '\0';
488 p_namebuf += s + 1;
489 }
490
491 *num_entries = reply.size();
492 return 0;
493 }
494
liz_destroy_direntry(struct liz_direntry * buf,size_t)495 void liz_destroy_direntry(struct liz_direntry *buf, size_t /*num_entries*/) {
496 if (buf->name) {
497 delete[] buf->name;
498 }
499 }
500
liz_releasedir(liz_t * instance,struct liz_fileinfo * fileinfo)501 int liz_releasedir(liz_t *instance, struct liz_fileinfo *fileinfo) {
502 Client &client = *(Client *)instance;
503 std::error_code ec;
504 client.releasedir((Client::FileInfo *)fileinfo, ec);
505 gLastErrorCode = ec.value();
506 return ec ? -1 : 0;
507 }
508
convert_named_inodes(liz_namedinode_entry * out_entries,uint32_t * num_entries,const std::vector<NamedInodeEntry> & input)509 static int convert_named_inodes(liz_namedinode_entry *out_entries, uint32_t *num_entries,
510 const std::vector<NamedInodeEntry> &input) {
511 *num_entries = 0;
512 if (input.empty()) {
513 return 0;
514 }
515
516 size_t total_name_size = 0;
517 for (const auto &ni : input) {
518 total_name_size += ni.name.size() + 1;
519 }
520
521 char *p_namebuf;
522 try {
523 p_namebuf = new char[total_name_size];
524 } catch (...) {
525 gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
526 return -1;
527 }
528
529 for (const auto &ni : input) {
530 out_entries->ino = ni.inode;
531 out_entries->name = p_namebuf;
532 out_entries++;
533
534 auto s = ni.name.size();
535 ni.name.copy(p_namebuf, s);
536 p_namebuf[s] = '\0';
537 p_namebuf += s + 1;
538 }
539
540 *num_entries = input.size();
541 return 0;
542 }
543
liz_readreserved(liz_t * instance,liz_context_t * ctx,uint32_t offset,uint32_t max_entries,struct liz_namedinode_entry * out_entries,uint32_t * num_entries)544 int liz_readreserved(liz_t *instance, liz_context_t *ctx, uint32_t offset, uint32_t max_entries,
545 struct liz_namedinode_entry *out_entries, uint32_t *num_entries) {
546 Client &client = *(Client *)instance;
547 Client::Context &context = *(Client::Context *)ctx;
548 std::error_code ec;
549 auto named_inodes = client.readreserved(context, offset, max_entries, ec);
550 gLastErrorCode = ec.value();
551 if (ec) {
552 return -1;
553 }
554 return convert_named_inodes(out_entries, num_entries, named_inodes);
555 }
556
liz_readtrash(liz_t * instance,liz_context_t * ctx,uint32_t offset,uint32_t max_entries,struct liz_namedinode_entry * out_entries,uint32_t * num_entries)557 int liz_readtrash(liz_t *instance, liz_context_t *ctx, uint32_t offset, uint32_t max_entries,
558 struct liz_namedinode_entry *out_entries, uint32_t *num_entries) {
559 Client &client = *(Client *)instance;
560 Client::Context &context = *(Client::Context *)ctx;
561 std::error_code ec;
562 auto named_inodes = client.readtrash(context, offset, max_entries, ec);
563 gLastErrorCode = ec.value();
564 if (ec) {
565 return -1;
566 }
567 return convert_named_inodes(out_entries, num_entries, named_inodes);
568 }
569
liz_free_namedinode_entries(struct liz_namedinode_entry * entries,uint32_t num_entries)570 void liz_free_namedinode_entries(struct liz_namedinode_entry *entries, uint32_t num_entries) {
571 assert(num_entries > 0);
572 (void)num_entries;
573 delete[] entries->name;
574 }
575
liz_mkdir(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path,mode_t mode,struct liz_entry * entry)576 int liz_mkdir(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path,
577 mode_t mode, struct liz_entry *entry) {
578 Client &client = *(Client *)instance;
579 Client::Context &context = *(Client::Context *)ctx;
580 Client::EntryParam entry_param;
581 std::error_code ec;
582 client.mkdir(context, parent, path, mode, entry_param, ec);
583 if (!ec) {
584 to_entry(entry_param, entry);
585 }
586 gLastErrorCode = ec.value();
587 return ec ? -1 : 0;
588 }
589
liz_rmdir(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path)590 int liz_rmdir(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path) {
591 Client &client = *(Client *)instance;
592 Client::Context &context = *(Client::Context *)ctx;
593 std::error_code ec;
594 client.rmdir(context, parent, path, ec);
595 gLastErrorCode = ec.value();
596 return ec ? -1 : 0;
597 }
598
liz_makesnapshot(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,liz_inode_t dst_parent,const char * dst_name,int can_overwrite,uint32_t * job_id)599 int liz_makesnapshot(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, liz_inode_t dst_parent,
600 const char *dst_name, int can_overwrite, uint32_t *job_id) {
601 static_assert(sizeof(LizardClient::JobId) <= sizeof(uint32_t), "JobId type too large");
602 Client &client = *(Client *)instance;
603 Client::Context &context = *(Client::Context *)ctx;
604 std::error_code ec;
605 LizardClient::JobId ret = client.makesnapshot(context, inode, dst_parent, dst_name, can_overwrite, ec);
606 if (job_id) {
607 *job_id = ret;
608 }
609 gLastErrorCode = ec.value();
610 return ec ? -1 : 0;
611 }
612
liz_getgoal(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,char * goal_name)613 int liz_getgoal(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, char *goal_name) {
614 Client &client = *(Client *)instance;
615 Client::Context &context = *(Client::Context *)ctx;
616 std::error_code ec;
617 std::string goal = client.getgoal(context, inode, ec);
618 gLastErrorCode = ec.value();
619 if (ec) {
620 return -1;
621 }
622 size_t copied = goal.copy(goal_name, LIZARDFS_MAX_GOAL_NAME - 1);
623 goal_name[copied] = '\0';
624
625 return 0;
626 }
627
liz_setgoal(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,const char * goal_name,int is_recursive)628 int liz_setgoal(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, const char *goal_name,
629 int is_recursive) {
630 Client &client = *(Client *)instance;
631 Client::Context &context = *(Client::Context *)ctx;
632 std::error_code ec;
633 client.setgoal(context, inode, goal_name, is_recursive ? SMODE_RMASK : 0, ec);
634 gLastErrorCode = ec.value();
635 return ec ? -1 : 0;
636 }
637
liz_readlink(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,char * buf,size_t size)638 int liz_readlink(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, char *buf, size_t size) {
639 Client &client = *(Client *)instance;
640 Client::Context &context = *(Client::Context *)ctx;
641 std::error_code ec;
642 std::string link = client.readlink(context, inode, ec);
643 gLastErrorCode = ec.value();
644 if (ec) {
645 return -1;
646 }
647 link.copy(buf, size);
648 return link.size();
649 }
650
liz_unlink(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path)651 int liz_unlink(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path) {
652 Client &client = *(Client *)instance;
653 Client::Context &context = *(Client::Context *)ctx;
654 std::error_code ec;
655 client.unlink(context, parent, path, ec);
656 gLastErrorCode = ec.value();
657 return ec ? -1 : 0;
658 }
659
liz_undel(liz_t * instance,liz_context_t * ctx,liz_inode_t inode)660 int liz_undel(liz_t *instance, liz_context_t *ctx, liz_inode_t inode) {
661 Client &client = *(Client *)instance;
662 Client::Context &context = *(Client::Context *)ctx;
663 std::error_code ec;
664 client.undel(context, inode, ec);
665 gLastErrorCode = ec.value();
666 return ec ? -1 : 0;
667 }
668
liz_setattr(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,struct stat * stbuf,int to_set,struct liz_attr_reply * reply)669 int liz_setattr(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, struct stat *stbuf,
670 int to_set, struct liz_attr_reply *reply) {
671 Client &client = *(Client *)instance;
672 Client::Context &context = *(Client::Context *)ctx;
673 Client::AttrReply r;
674 std::error_code ec;
675 client.setattr(context, inode, stbuf, to_set, r, ec);
676 if (!ec) {
677 to_attr_reply(r, reply);
678 }
679 gLastErrorCode = ec.value();
680 return ec ? -1 : 0;
681 }
682
liz_fsync(liz_t * instance,liz_context_t * ctx,struct liz_fileinfo * fileinfo)683 int liz_fsync(liz_t *instance, liz_context_t *ctx, struct liz_fileinfo *fileinfo) {
684 Client &client = *(Client *)instance;
685 Client::Context &context = *(Client::Context *)ctx;
686 std::error_code ec;
687 client.fsync(context, (Client::FileInfo *)fileinfo, ec);
688 gLastErrorCode = ec.value();
689 return ec ? -1 : 0;
690 }
691
liz_rename(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path,liz_inode_t new_parent,const char * new_path)692 int liz_rename(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path,
693 liz_inode_t new_parent, const char *new_path) {
694 Client &client = *(Client *)instance;
695 Client::Context &context = *(Client::Context *)ctx;
696 std::error_code ec;
697 client.rename(context, parent, path, new_parent, new_path, ec);
698 gLastErrorCode = ec.value();
699 return ec ? -1 : 0;
700 }
701
liz_statfs(liz_t * instance,liz_stat_t * buf)702 int liz_statfs(liz_t *instance, liz_stat_t *buf) {
703 Client &client = *(Client *)instance;
704 Client::Stats stats;
705 std::error_code ec;
706 client.statfs(stats, ec);
707 gLastErrorCode = ec.value();
708 if (ec) {
709 return -1;
710 }
711 to_stat(stats, buf);
712 return 0;
713 }
714
liz_setxattr(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,const char * name,const uint8_t * value,size_t size,int flags)715 int liz_setxattr(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, const char *name,
716 const uint8_t *value, size_t size, int flags) {
717 Client &client = *(Client *)instance;
718 Client::Context &context = *(Client::Context *)ctx;
719 std::error_code ec;
720 client.setxattr(context, ino, name, std::vector<uint8_t>(value, value + size), flags, ec);
721 gLastErrorCode = ec.value();
722 return ec ? -1 : 0;
723 }
724
liz_getxattr(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,const char * name,size_t size,size_t * out_size,uint8_t * buf)725 int liz_getxattr(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, const char *name,
726 size_t size, size_t *out_size, uint8_t *buf) {
727 Client &client = *(Client *)instance;
728 Client::Context &context = *(Client::Context *)ctx;
729 std::error_code ec;
730 auto ret = client.getxattr(context, ino, name, ec);
731 gLastErrorCode = ec.value();
732 if (ec) {
733 return -1;
734 }
735 std::memcpy(buf, ret.data(), std::min(size, ret.size()));
736 if (out_size) {
737 *out_size = ret.size();
738 }
739 return 0;
740 }
741
liz_listxattr(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,size_t size,size_t * out_size,char * buf)742 int liz_listxattr(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, size_t size,
743 size_t *out_size, char *buf) {
744 Client &client = *(Client *)instance;
745 Client::Context &context = *(Client::Context *)ctx;
746 std::error_code ec;
747 auto ret = client.listxattr(context, ino, ec);
748 gLastErrorCode = ec.value();
749 if (ec) {
750 return -1;
751 }
752 std::memcpy(buf, ret.data(), std::min(size, ret.size()));
753 if (out_size) {
754 *out_size = ret.size();
755 }
756 return 0;
757 }
758
liz_removexattr(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,const char * name)759 int liz_removexattr(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, const char *name) {
760 Client &client = *(Client *)instance;
761 Client::Context &context = *(Client::Context *)ctx;
762 std::error_code ec;
763 client.removexattr(context, ino, name, ec);
764 gLastErrorCode = ec.value();
765 return ec ? -1 : 0;
766 }
767
liz_create_acl()768 liz_acl_t *liz_create_acl() {
769 try {
770 return (liz_acl_t *)new RichACL;
771 } catch (...) {
772 return nullptr;
773 }
774 }
775
liz_destroy_acl(liz_acl_t * acl)776 void liz_destroy_acl(liz_acl_t *acl) {
777 delete (RichACL *)acl;
778 }
779
liz_print_acl(liz_acl_t * acl,char * buf,size_t size,size_t * reply_size)780 int liz_print_acl(liz_acl_t *acl, char *buf, size_t size, size_t *reply_size) {
781 assert(acl);
782 assert(buf || size == 0);
783 RichACL &richacl = *(RichACL *)acl;
784 std::string repr = richacl.toString();
785 assert(reply_size);
786 *reply_size = repr.size();
787 if (size < repr.size()) {
788 gLastErrorCode = LIZARDFS_ERROR_WRONGSIZE;
789 return -1;
790 }
791 repr.copy(buf, size);
792
793 return 0;
794 }
795
liz_add_acl_entry(liz_acl_t * acl,const liz_acl_ace_t * ace)796 void liz_add_acl_entry(liz_acl_t *acl, const liz_acl_ace_t *ace) {
797 assert(acl);
798 assert(ace);
799 RichACL &richacl = *(RichACL *)acl;
800 richacl.insert(RichACL::Ace(ace->type, ace->flags, ace->mask, ace->id));
801 }
802
liz_get_acl_entry(const liz_acl_t * acl,int n,liz_acl_ace_t * ace)803 int liz_get_acl_entry(const liz_acl_t *acl, int n, liz_acl_ace_t *ace) {
804 assert(acl);
805 assert(ace);
806 const RichACL &richacl = *(RichACL *)acl;
807 if ((size_t)n > richacl.size()) {
808 gLastErrorCode = LIZARDFS_ERROR_WRONGSIZE;
809 return -1;
810 }
811 auto it = std::next(richacl.begin(), n);
812 ace->type = it->type;
813 ace->flags = it->flags;
814 ace->mask = it->mask;
815 ace->id = it->id;
816 return 0;
817 }
818
liz_get_acl_size(const liz_acl_t * acl)819 size_t liz_get_acl_size(const liz_acl_t *acl) {
820 assert(acl);
821 const RichACL &richacl = *(RichACL *)acl;
822 return richacl.size();
823 }
824
liz_setacl(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,const liz_acl_t * acl)825 int liz_setacl(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, const liz_acl_t *acl) {
826 assert(instance);
827 assert(ctx);
828 assert(acl);
829 Client &client = *(Client *)instance;
830 Client::Context &context = *(Client::Context *)ctx;
831 std::error_code ec;
832 try {
833 const RichACL &richacl = *(RichACL *)acl;
834 client.setacl(context, ino, richacl, ec);
835 gLastErrorCode = ec.value();
836 return ec ? -1 : 0;
837 } catch (...) {
838 gLastErrorCode = LIZARDFS_ERROR_ENOATTR;
839 return -1;
840 }
841 }
842
liz_getacl(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,liz_acl_t ** acl)843 int liz_getacl(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, liz_acl_t **acl) {
844 assert(instance);
845 assert(ctx);
846 assert(acl);
847 Client &client = *(Client *)instance;
848 Client::Context &context = *(Client::Context *)ctx;
849 std::error_code ec;
850 *acl = nullptr;
851 try {
852 RichACL richacl = client.getacl(context, ino, ec);
853 gLastErrorCode = ec.value();
854 if (ec) {
855 return -1;
856 }
857 *acl = (liz_acl_t *)new RichACL(std::move(richacl));
858 } catch (...) {
859 gLastErrorCode = LIZARDFS_ERROR_ENOATTR;
860 return -1;
861 }
862 return 0;
863 }
864
liz_get_chunks_info(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,uint32_t chunk_index,liz_chunk_info_t * buffer,uint32_t buffer_size,uint32_t * reply_size)865 int liz_get_chunks_info(liz_t *instance, liz_context_t *ctx, liz_inode_t inode,
866 uint32_t chunk_index, liz_chunk_info_t *buffer, uint32_t buffer_size,
867 uint32_t *reply_size) {
868 assert(instance && ctx && buffer && reply_size);
869
870 Client &client = *(Client *)instance;
871 Client::Context &context = *(Client::Context *)ctx;
872
873 if (buffer_size > 0) {
874 buffer->parts = NULL;
875 } else {
876 gLastErrorCode = LIZARDFS_ERROR_EINVAL;
877 return -1;
878 }
879
880 std::error_code ec;
881 auto chunks = client.getchunksinfo(context, inode, chunk_index, buffer_size, ec);
882 gLastErrorCode = ec.value();
883 if (ec) {
884 return -1;
885 }
886
887 *reply_size = chunks.size();
888 if (chunks.size() > buffer_size) {
889 gLastErrorCode = LIZARDFS_ERROR_WRONGSIZE;
890 return -1;
891 }
892
893 std::size_t strings_size = 0;
894 std::size_t parts_table_size = 0;
895 for(const auto &chunk : chunks) {
896 parts_table_size += chunk.chunk_parts.size() * sizeof(liz_chunk_part_info_t);
897 for(const auto &part : chunk.chunk_parts) {
898 strings_size += part.label.size() + 1;
899 }
900 }
901
902 uint8_t *data_buffer = (uint8_t *)std::malloc(parts_table_size + strings_size);
903 if (data_buffer == NULL) {
904 gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
905 return -1;
906 }
907
908 auto buf_part = (liz_chunk_part_info_t *)data_buffer;
909 auto buf_string = (char *)(data_buffer + parts_table_size);
910 auto buf_chunk = buffer;
911 for(const auto &chunk : chunks) {
912 buf_chunk->chunk_id = chunk.chunk_id;
913 buf_chunk->chunk_version = chunk.chunk_version;
914 buf_chunk->parts = buf_part;
915 buf_chunk->parts_size = chunk.chunk_parts.size();
916
917 for(const auto &part : chunk.chunk_parts) {
918 buf_part->addr = part.address.ip;
919 buf_part->port = part.address.port;
920 buf_part->part_type_id = part.chunkType.getId();
921 buf_part->label = buf_string;
922 std::strcpy(buf_string, part.label.c_str());
923
924 buf_string += part.label.size() + 1;
925 ++buf_part;
926 }
927 ++buf_chunk;
928 }
929
930 gLastErrorCode = LIZARDFS_STATUS_OK;
931 return 0;
932 }
933
liz_get_chunkservers_info(liz_t * instance,liz_chunkserver_info_t * servers,uint32_t size,uint32_t * reply_size)934 int liz_get_chunkservers_info(liz_t *instance, liz_chunkserver_info_t *servers, uint32_t size,
935 uint32_t *reply_size) {
936 Client &client = *(Client *)instance;
937 std::error_code ec;
938
939 if (size > 0) {
940 servers->label = nullptr;
941 } else {
942 gLastErrorCode = LIZARDFS_ERROR_EINVAL;
943 return -1;
944 }
945
946 std::vector<ChunkserverListEntry> entries = client.getchunkservers(ec);
947 gLastErrorCode = ec.value();
948 if (ec) {
949 return -1;
950 }
951 *reply_size = entries.size();
952 if (entries.size() > size) {
953 gLastErrorCode = LIZARDFS_ERROR_WRONGSIZE;
954 return -1;
955 }
956 size_t total_str_size = 0;
957 for (const ChunkserverListEntry &entry : entries) {
958 total_str_size += entry.label.size() + 1;
959 }
960
961 char *str_buf = (char *)malloc(total_str_size);
962 if (str_buf == nullptr) {
963 gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
964 return -1;
965 }
966 for (const ChunkserverListEntry &entry : entries) {
967 servers->version = entry.version;
968 servers->ip = entry.servip;
969 servers->port = entry.servport;
970 servers->used_space = entry.usedspace;
971 servers->total_space = entry.totalspace;
972 servers->error_counter = entry.errorcounter;
973 servers->label = strcpy(str_buf, entry.label.c_str());
974 str_buf += entry.label.size() + 1;
975 servers++;
976 }
977 gLastErrorCode = LIZARDFS_STATUS_OK;
978 return 0;
979 }
980
liz_destroy_chunkservers_info(liz_chunkserver_info_t * servers)981 void liz_destroy_chunkservers_info(liz_chunkserver_info_t *servers) {
982 if (servers) {
983 free(servers->label);
984 }
985 }
986
liz_destroy_chunks_info(liz_chunk_info_t * buffer)987 void liz_destroy_chunks_info(liz_chunk_info_t *buffer) {
988 if (buffer && buffer->parts) {
989 std::free(buffer->parts);
990 }
991 }
992
liz_setlk(liz_t * instance,liz_context_t * ctx,liz_fileinfo_t * fileinfo,const liz_lock_info * lock,liz_lock_register_interrupt_t handler,void * priv)993 int liz_setlk(liz_t *instance, liz_context_t *ctx, liz_fileinfo_t *fileinfo,
994 const liz_lock_info *lock, liz_lock_register_interrupt_t handler, void *priv) {
995 Client &client = *(Client *)instance;
996 Client::Context &context = *(Client::Context *)ctx;
997 Client::FileInfo *fi = (Client::FileInfo *)fileinfo;
998 gLastErrorCode = 0;
999
1000 lzfs_locks::FlockWrapper flock_wrapper;
1001 flock_wrapper.l_type = lock->l_type;
1002 flock_wrapper.l_start = lock->l_start;
1003 flock_wrapper.l_len = lock->l_len;
1004 flock_wrapper.l_pid = lock->l_pid;
1005 std::error_code ec;
1006 liz_lock_interrupt_info_t interrupt_info;
1007 std::function<int(const lzfs_locks::InterruptData &)> lambda;
1008 if (handler) {
1009 lambda = [&handler, &interrupt_info, priv](const lzfs_locks::InterruptData &data) {
1010 interrupt_info.owner = data.owner;
1011 interrupt_info.ino = data.ino;
1012 interrupt_info.reqid = data.reqid;
1013 return handler(&interrupt_info, priv);
1014 };
1015 }
1016 client.setlk(context, fi->inode, fi, flock_wrapper, lambda, ec);
1017 gLastErrorCode = ec.value();
1018 return ec ? -1 : 0;
1019 }
1020
liz_getlk(liz_t * instance,liz_context_t * ctx,liz_fileinfo_t * fileinfo,liz_lock_info * lock)1021 int liz_getlk(liz_t *instance, liz_context_t *ctx, liz_fileinfo_t *fileinfo, liz_lock_info *lock) {
1022 Client &client = *(Client *)instance;
1023 Client::Context &context = *(Client::Context *)ctx;
1024 Client::FileInfo *fi = (Client::FileInfo *)fileinfo;
1025 gLastErrorCode = 0;
1026
1027 lzfs_locks::FlockWrapper flock_wrapper;
1028 flock_wrapper.l_type = lock->l_type;
1029 flock_wrapper.l_start = lock->l_start;
1030 flock_wrapper.l_len = lock->l_len;
1031 flock_wrapper.l_pid = lock->l_pid;
1032 std::error_code ec;
1033 client.getlk(context, fi->inode, fi, flock_wrapper, ec);
1034 if (ec) {
1035 gLastErrorCode = ec.value();
1036 return -1;
1037 }
1038 lock->l_type = flock_wrapper.l_type;
1039 lock->l_start = flock_wrapper.l_start;
1040 lock->l_len = flock_wrapper.l_len;
1041 lock->l_pid = flock_wrapper.l_pid;
1042 return 0;
1043 }
1044
liz_setlk_interrupt(liz_t * instance,const liz_lock_interrupt_info_t * interrupt_info)1045 int liz_setlk_interrupt(liz_t *instance, const liz_lock_interrupt_info_t *interrupt_info) {
1046 if (interrupt_info == nullptr) {
1047 return 0;
1048 }
1049 Client &client = *(Client *)instance;
1050 lzfs_locks::InterruptData interrupt_data;
1051 interrupt_data.owner = interrupt_info->owner;
1052 interrupt_data.ino = interrupt_info->ino;
1053 interrupt_data.reqid = interrupt_info->reqid;
1054 std::error_code ec;
1055 client.setlk_interrupt(interrupt_data, ec);
1056 if (ec) {
1057 gLastErrorCode = ec.value();
1058 return -1;
1059 }
1060 return 0;
1061 }
1062