2
* Copyright (c) 2018 Red Hat, Inc. <http://www.redhat.com>
3
* This file is part of GlusterFS.
5
* This file is licensed to you under your choice of the GNU Lesser
6
* General Public License, version 3 or any later version (LGPLv3 or
7
* later), or the GNU General Public License, version 2 (GPLv2), in all
8
* cases as published by the Free Software Foundation.
12
#include "cloudsync-common.h"
13
#include <glusterfs/call-stub.h>
14
#include "cloudsync-autogen-fops.h"
20
cs_cleanup_private(cs_private_t *priv)
24
priv->stores->fini(priv->stores->config);
25
GF_FREE(priv->stores);
28
pthread_spin_destroy(&priv->lock);
35
static struct cs_plugin plugins[] = {
36
{.name = "cloudsyncs3",
37
.library = "cloudsyncs3.so",
38
.description = "cloudsync s3 store."},
41
.library = "cloudsynccvlt.so",
42
.description = "Commvault content store."},
48
cs_init(xlator_t *this)
50
cs_private_t *priv = NULL;
51
gf_boolean_t per_vol = _gf_false;
54
store_methods_t *store_methods = NULL;
56
char *temp_str = NULL;
60
priv = GF_CALLOC(1, sizeof(*priv), gf_cs_mt_cs_private_t);
62
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insufficient memory");
68
this->local_pool = mem_pool_new(cs_local_t, 512);
69
if (!this->local_pool) {
70
gf_msg(this->name, GF_LOG_ERROR, 0, ENOMEM, "initialisation failed.");
77
GF_OPTION_INIT("cloudsync-remote-read", priv->remote_read, bool, out);
79
/* temp workaround. Should be configurable through glusterd*/
83
if (dict_get_str_sizen(this->options, "cloudsync-storetype",
85
for (index = 0; plugins[index].name; index++) {
86
if (!strcmp(temp_str, plugins[index].name)) {
87
libname = plugins[index].library;
96
gf_msg(this->name, GF_LOG_WARNING, 0, 0, "no plugin enabled");
101
ret = gf_asprintf(&libpath, "%s/%s", CS_PLUGINDIR, libname);
106
handle = dlopen(libpath, RTLD_NOW);
108
gf_msg(this->name, GF_LOG_WARNING, 0, 0,
110
"load the required library. %s",
115
gf_msg(this->name, GF_LOG_INFO, 0, 0,
116
"loading library:%s successful", libname);
119
priv->stores = GF_CALLOC(1, sizeof(struct cs_remote_stores),
120
gf_cs_mt_cs_remote_stores_t);
122
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
124
"allocate memory for priv->stores");
129
(void)dlerror(); /* clear out previous error string */
131
/* load library methods */
132
store_methods = (store_methods_t *)dlsym(handle, "store_ops");
133
if (!store_methods) {
134
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "null store_methods %s",
142
if (priv->remote_read) {
143
priv->stores->rdfop = store_methods->fop_remote_read;
144
if (!priv->stores->rdfop) {
145
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
154
priv->stores->dlfop = store_methods->fop_download;
155
if (!priv->stores->dlfop) {
156
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
165
priv->stores->init = store_methods->fop_init;
166
if (!priv->stores->init) {
167
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
176
priv->stores->reconfigure = store_methods->fop_reconfigure;
177
if (!priv->stores->reconfigure) {
178
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
180
" reconfigure fop %s",
186
priv->stores->handle = handle;
188
priv->stores->config = (void *)((priv->stores->init)(this));
189
if (!priv->stores->config) {
190
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "null config");
200
if (this->local_pool) {
201
mem_pool_destroy(this->local_pool);
202
this->local_pool = NULL;
205
cs_cleanup_private(priv);
218
cs_forget(xlator_t *this, inode_t *inode)
220
uint64_t ctx_int = 0;
221
cs_inode_ctx_t *ctx = NULL;
223
inode_ctx_del(inode, this, &ctx_int);
227
ctx = (cs_inode_ctx_t *)(uintptr_t)ctx_int;
234
cs_fini(xlator_t *this)
236
cs_private_t *priv = NULL;
237
priv = this->private;
239
cs_cleanup_private(priv);
243
cs_reconfigure(xlator_t *this, dict_t *options)
245
cs_private_t *priv = NULL;
248
priv = this->private;
254
GF_OPTION_RECONF("cloudsync-remote-read", priv->remote_read, options, bool,
257
/* needed only for per volume configuration*/
258
ret = priv->stores->reconfigure(this, options);
265
cs_mem_acct_init(xlator_t *this)
269
GF_VALIDATE_OR_GOTO("cloudsync", this, out);
271
ret = xlator_mem_acct_init(this, gf_cs_mt_end);
274
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "Memory accounting init failed");
282
cs_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
283
off_t off, dict_t *xdata)
286
int op_errno = ENOMEM;
291
gf_msg(this->name, GF_LOG_ERROR, 0, ENOMEM,
300
ret = dict_set_uint32(xdata, GF_CS_OBJECT_STATUS, 1);
302
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
303
"dict_set failed key:"
305
GF_CS_OBJECT_STATUS);
309
STACK_WIND(frame, default_readdirp_cbk, FIRST_CHILD(this),
310
FIRST_CHILD(this)->fops->readdirp, fd, size, off, xdata);
314
STACK_UNWIND_STRICT(readdirp, frame, -1, op_errno, NULL, NULL);
322
cs_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
323
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
324
struct iatt *postbuf, dict_t *xdata)
326
cs_local_t *local = NULL;
330
local = frame->local;
335
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "truncate failed");
336
ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val);
338
if (val == GF_CS_ERROR) {
339
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
340
"could not get file state, unwinding");
345
__cs_inode_ctx_update(this, local->loc.inode, val);
346
gf_msg(this->name, GF_LOG_INFO, 0, 0, " state = %" PRIu64, val);
348
if (local->call_cnt == 1 &&
349
(val == GF_CS_REMOTE || val == GF_CS_DOWNLOADING)) {
350
gf_msg(this->name, GF_LOG_WARNING, 0, 0,
351
"will repair and download "
352
"the file, current state : %" PRIu64,
356
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
357
"second truncate, Unwinding");
362
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
364
"could not be figured, unwinding");
368
/* successful write => file is local */
369
__cs_inode_ctx_update(this, local->loc.inode, GF_CS_LOCAL);
370
gf_msg(this->name, GF_LOG_INFO, 0, 0,
371
"state : GF_CS_LOCAL"
372
", truncate successful");
378
ret = locate_and_execute(frame);
386
CS_STACK_UNWIND(truncate, frame, op_ret, op_errno, prebuf, postbuf, xdata);
391
cs_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,
394
cs_local_t *local = NULL;
396
cs_inode_ctx_t *ctx = NULL;
397
gf_cs_obj_state state = -1;
399
VALIDATE_OR_GOTO(frame, err);
400
VALIDATE_OR_GOTO(this, err);
401
VALIDATE_OR_GOTO(loc, err);
403
local = cs_local_init(this, frame, loc, NULL, GF_FOP_TRUNCATE);
405
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "local init failed");
409
__cs_inode_ctx_get(this, loc->inode, &ctx);
412
state = __cs_get_file_state(loc->inode, ctx);
416
local->xattr_req = xdata ? dict_ref(xdata) : (xdata = dict_new());
418
ret = dict_set_uint32(local->xattr_req, GF_CS_OBJECT_STATUS, 1);
420
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
421
"dict_set failed key:"
423
GF_CS_OBJECT_STATUS);
427
local->stub = fop_truncate_stub(frame, cs_resume_truncate, loc, offset,
430
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insufficient memory");
434
if (state == GF_CS_LOCAL) {
435
STACK_WIND(frame, cs_truncate_cbk, FIRST_CHILD(this),
436
FIRST_CHILD(this)->fops->truncate, loc, offset, xdata);
440
ret = locate_and_execute(frame);
448
CS_STACK_UNWIND(truncate, frame, -1, ENOMEM, NULL, NULL, NULL);
453
cs_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
454
int32_t op_errno, struct statvfs *buf, dict_t *xdata)
456
STACK_UNWIND_STRICT(statfs, frame, op_ret, op_errno, buf, xdata);
461
cs_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
463
STACK_WIND(frame, cs_statfs_cbk, FIRST_CHILD(this),
464
FIRST_CHILD(this)->fops->statfs, loc, xdata);
469
cs_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
470
int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata)
472
STACK_UNWIND_STRICT(getxattr, frame, op_ret, op_errno, dict, xdata);
477
cs_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
480
STACK_WIND(frame, cs_getxattr_cbk, FIRST_CHILD(this),
481
FIRST_CHILD(this)->fops->getxattr, loc, name, xattr_req);
486
cs_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
487
int32_t op_ret, int32_t op_errno, dict_t *xdata)
489
cs_local_t *local = NULL;
491
local = frame->local;
494
cs_inodelk_unlock(frame);
496
CS_STACK_UNWIND(setxattr, frame, op_ret, op_errno, xdata);
502
cs_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
503
int32_t flags, dict_t *xdata)
506
cs_local_t *local = NULL;
509
VALIDATE_OR_GOTO(frame, err);
510
VALIDATE_OR_GOTO(this, err);
512
local = cs_local_init(this, frame, loc, NULL, GF_FOP_SETXATTR);
518
local->xattr_req = xdata ? dict_ref(xdata) : (xdata = dict_new());
520
tmp = dict_get_sizen(dict, GF_CS_OBJECT_UPLOAD_COMPLETE);
522
/* Value of key should be the atime */
523
local->stub = fop_setxattr_stub(frame, cs_resume_setxattr, loc, dict,
529
ret = locate_and_execute(frame);
537
STACK_WIND(frame, cs_setxattr_cbk, FIRST_CHILD(this),
538
FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata);
541
CS_STACK_UNWIND(setxattr, frame, -1, errno, NULL);
546
cs_fgetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
547
int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata)
549
STACK_UNWIND_STRICT(fgetxattr, frame, op_ret, op_errno, dict, xdata);
554
cs_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name,
557
STACK_WIND(frame, cs_fgetxattr_cbk, FIRST_CHILD(this),
558
FIRST_CHILD(this)->fops->fgetxattr, fd, name, xdata);
563
cs_fsetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
564
int32_t op_ret, int32_t op_errno, dict_t *xdata)
566
STACK_UNWIND_STRICT(fsetxattr, frame, op_ret, op_errno, xdata);
571
cs_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict,
572
int32_t flags, dict_t *xdata)
574
STACK_WIND(frame, cs_fsetxattr_cbk, FIRST_CHILD(this),
575
FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata);
580
cs_unlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
581
int32_t op_errno, struct iatt *preparent, struct iatt *postparent,
584
STACK_UNWIND_STRICT(unlink, frame, op_ret, op_errno, preparent, postparent,
590
cs_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
593
cs_local_t *local = NULL;
596
local = cs_local_init(this, frame, loc, NULL, GF_FOP_UNLINK);
600
local->xattr_req = xattr_req ? dict_ref(xattr_req) : dict_new();
602
ret = dict_set_uint32(local->xattr_req, GF_CS_OBJECT_STATUS, 1);
604
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
605
"dict_set failed key:"
607
GF_CS_OBJECT_STATUS);
610
STACK_WIND(frame, cs_unlink_cbk, FIRST_CHILD(this),
611
FIRST_CHILD(this)->fops->unlink, loc, flags, local->xattr_req);
614
CS_STACK_UNWIND(unlink, frame, -1, errno, NULL, NULL, NULL);
619
cs_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
620
int32_t op_errno, fd_t *fd, dict_t *xdata)
626
ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val);
628
ret = __cs_inode_ctx_update(this, fd->inode, val);
630
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "ctx update failed");
634
cs_inode_ctx_reset(this, fd->inode);
637
CS_STACK_UNWIND(open, frame, op_ret, op_errno, fd, xdata);
642
cs_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
643
fd_t *fd, dict_t *xattr_req)
645
cs_local_t *local = NULL;
648
local = cs_local_init(this, frame, NULL, fd, GF_FOP_OPEN);
652
local->xattr_req = xattr_req ? dict_ref(xattr_req) : dict_new();
654
ret = dict_set_uint32(local->xattr_req, GF_CS_OBJECT_STATUS, 1);
656
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
657
"dict_set failed key:"
659
GF_CS_OBJECT_STATUS);
663
STACK_WIND(frame, cs_open_cbk, FIRST_CHILD(this),
664
FIRST_CHILD(this)->fops->open, loc, flags, fd, local->xattr_req);
667
CS_STACK_UNWIND(open, frame, -1, errno, NULL, NULL);
672
cs_fstat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
673
int32_t op_errno, struct iatt *buf, dict_t *xdata)
678
cs_local_t *local = NULL;
680
local = frame->local;
685
ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val);
687
gf_msg_debug(this->name, 0, "state %" PRIu64, val);
688
ret = __cs_inode_ctx_update(this, fd->inode, val);
690
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "ctx update failed");
694
cs_inode_ctx_reset(this, fd->inode);
697
CS_STACK_UNWIND(fstat, frame, op_ret, op_errno, buf, xdata);
703
cs_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xattr_req)
705
cs_local_t *local = NULL;
708
local = cs_local_init(this, frame, NULL, fd, GF_FOP_FSTAT);
712
if (fd->inode->ia_type == IA_IFDIR)
715
local->xattr_req = xattr_req ? dict_ref(xattr_req) : dict_new();
717
ret = dict_set_uint32(local->xattr_req, GF_CS_OBJECT_STATUS, 1);
719
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
720
"dict_set failed key:"
722
GF_CS_OBJECT_STATUS);
727
STACK_WIND(frame, cs_fstat_cbk, FIRST_CHILD(this),
728
FIRST_CHILD(this)->fops->fstat, fd, local->xattr_req);
731
CS_STACK_UNWIND(fstat, frame, -1, errno, NULL, NULL);
736
cs_local_init(xlator_t *this, call_frame_t *frame, loc_t *loc, fd_t *fd,
739
cs_local_t *local = NULL;
742
local = mem_get0(this->local_pool);
747
ret = loc_copy(&local->loc, loc);
753
local->fd = fd_ref(fd);
757
local->op_errno = EUCLEAN;
760
frame->local = local;
761
local->locked = _gf_false;
774
cs_lock_frame(call_frame_t *parent_frame)
776
call_frame_t *lock_frame = NULL;
778
lock_frame = copy_frame(parent_frame);
780
if (lock_frame == NULL)
783
set_lk_owner_from_ptr(&lock_frame->root->lk_owner, parent_frame->root);
790
cs_lock_wipe(call_frame_t *lock_frame)
792
CS_STACK_DESTROY(lock_frame);
796
cs_inodelk_unlock_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
797
int32_t op_ret, int32_t op_errno, dict_t *xdata)
805
cs_inodelk_unlock(call_frame_t *main_frame)
807
xlator_t *this = NULL;
808
struct gf_flock flock = {
811
call_frame_t *lock_frame = NULL;
812
cs_local_t *lock_local = NULL;
813
cs_local_t *main_local = NULL;
816
this = main_frame->this;
817
main_local = main_frame->local;
819
lock_frame = cs_lock_frame(main_frame);
823
lock_local = cs_local_init(this, lock_frame, NULL, NULL, 0);
827
ret = cs_build_loc(&lock_local->loc, main_frame);
832
flock.l_type = F_UNLCK;
834
main_local->locked = _gf_false;
836
STACK_WIND(lock_frame, cs_inodelk_unlock_cbk, FIRST_CHILD(this),
837
FIRST_CHILD(this)->fops->inodelk, CS_LOCK_DOMAIN,
838
&lock_local->loc, F_SETLKW, &flock, NULL);
843
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
844
"Stale lock would be found on"
848
cs_lock_wipe(lock_frame);
854
cs_download_task(void *arg)
856
call_frame_t *frame = NULL;
857
xlator_t *this = NULL;
858
cs_private_t *priv = NULL;
860
char *sign_req = NULL;
862
cs_local_t *local = NULL;
865
frame = (call_frame_t *)arg;
869
priv = this->private;
872
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
879
local = frame->local;
882
fd = fd_anonymous(local->fd->inode);
884
fd = fd_anonymous(local->loc.inode);
887
gf_msg("CS", GF_LOG_ERROR, 0, 0, "fd creation failed");
897
gf_msg(this->name, GF_LOG_ERROR, 0, ENOMEM,
904
ret = dict_set_uint32(dict, GF_CS_OBJECT_DOWNLOADING, 1);
906
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "dict_set failed");
911
ret = syncop_fsetxattr(this, local->fd, dict, 0, NULL, NULL);
913
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
916
GF_CS_OBJECT_DOWNLOADING);
920
/*this calling method is for per volume setting */
921
ret = priv->stores->dlfop(frame, priv->stores->config);
923
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
928
/*using dlfd as it is anonymous and have RDWR flag*/
929
ret = syncop_ftruncate(FIRST_CHILD(this), local->dlfd, 0, NULL, NULL,
932
gf_msg(this->name, GF_LOG_ERROR, 0, -ret, "ftruncate failed");
934
gf_msg_debug(this->name, 0, "ftruncate succeed");
940
gf_msg(this->name, GF_LOG_INFO, 0, 0,
941
"download success, path"
945
ret = syncop_fremovexattr(this, local->fd, GF_CS_OBJECT_REMOTE, NULL,
948
gf_msg(this->name, GF_LOG_ERROR, 0, -ret,
949
"removexattr failed, remotexattr");
953
gf_msg_debug(this->name, 0,
954
"fremovexattr success, "
959
ret = syncop_fremovexattr(this, local->fd, GF_CS_OBJECT_DOWNLOADING,
962
gf_msg(this->name, GF_LOG_ERROR, 0, -ret,
963
"removexattr failed, downloading xattr, path %s",
968
gf_msg_debug(this->name, 0,
969
"fremovexattr success"
990
cs_download(call_frame_t *frame)
993
cs_local_t *local = NULL;
994
xlator_t *this = NULL;
996
local = frame->local;
999
if (!local->remotepath) {
1001
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1003
" available. Check posix logs to resolve");
1007
ret = cs_download_task((void *)frame);
1013
cs_set_xattr_req(call_frame_t *frame)
1015
cs_local_t *local = NULL;
1016
GF_UNUSED int ret = 0;
1018
local = frame->local;
1020
/* When remote reads are performed (i.e. reads on remote store),
1021
* there needs to be a way to associate a file on gluster volume
1022
* with its correspnding file on the remote store. In order to do
1023
* that, a unique key can be maintained as an xattr
1024
* (GF_CS_XATTR_ARCHIVE_UUID)on the stub file on gluster bricks.
1025
* This xattr should be provided to the plugin to
1026
* perform the read fop on the correct file. This assumes that the file
1027
* hierarchy and name need not be the same on remote store as that of
1028
* the gluster volume.
1030
ret = dict_set_sizen_str_sizen(local->xattr_req, GF_CS_XATTR_ARCHIVE_UUID,
1037
cs_update_xattrs(call_frame_t *frame, dict_t *xdata)
1039
cs_local_t *local = NULL;
1040
xlator_t *this = NULL;
1042
GF_UNUSED int ret = 0;
1044
local = frame->local;
1047
local->xattrinfo.lxattr = GF_CALLOC(1, sizeof(cs_loc_xattr_t),
1048
gf_cs_mt_cs_lxattr_t);
1049
if (!local->xattrinfo.lxattr) {
1051
local->op_errno = ENOMEM;
1055
gf_uuid_copy(local->xattrinfo.lxattr->gfid, local->loc.gfid);
1057
if (local->remotepath) {
1058
local->xattrinfo.lxattr->file_path = gf_strdup(local->remotepath);
1059
if (!local->xattrinfo.lxattr->file_path) {
1061
local->op_errno = ENOMEM;
1066
ret = dict_get_gfuuid(xdata, GF_CS_XATTR_ARCHIVE_UUID,
1067
&(local->xattrinfo.lxattr->uuid));
1070
gf_uuid_clear(local->xattrinfo.lxattr->uuid);
1072
size = strlen(this->name) - strlen("-cloudsync") + 1;
1073
local->xattrinfo.lxattr->volname = GF_CALLOC(1, size, gf_common_mt_char);
1074
if (!local->xattrinfo.lxattr->volname) {
1076
local->op_errno = ENOMEM;
1079
strncpy(local->xattrinfo.lxattr->volname, this->name, size - 1);
1080
local->xattrinfo.lxattr->volname[size - 1] = '\0';
1084
cs_xattrinfo_wipe(local);
1089
cs_serve_readv(call_frame_t *frame, off_t offset, size_t size, uint32_t flags)
1091
xlator_t *this = NULL;
1092
cs_private_t *priv = NULL;
1095
cs_local_t *local = NULL;
1097
local = frame->local;
1099
priv = this->private;
1101
if (!local->remotepath) {
1103
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1105
" available. Check posix logs to resolve");
1109
if (!priv->stores) {
1110
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1118
fd = fd_anonymous(local->fd->inode);
1120
fd = fd_anonymous(local->loc.inode);
1123
local->xattrinfo.size = size;
1124
local->xattrinfo.offset = offset;
1125
local->xattrinfo.flags = flags;
1128
gf_msg("CS", GF_LOG_ERROR, 0, 0, "fd creation failed");
1134
local->dloffset = offset;
1136
/*this calling method is for per volume setting */
1137
ret = priv->stores->rdfop(frame, priv->stores->config);
1139
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1146
gf_msg(this->name, GF_LOG_INFO, 0, 0,
1147
"read success, path"
1161
cs_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
1162
int32_t op_errno, struct iovec *vector, int32_t count,
1163
struct iatt *stbuf, struct iobref *iobref, dict_t *xdata)
1165
cs_local_t *local = NULL;
1170
local = frame->local;
1176
ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val);
1178
if (val == GF_CS_ERROR) {
1179
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1180
"could not get file state, unwinding");
1185
__cs_inode_ctx_update(this, fd->inode, val);
1186
gf_msg(this->name, GF_LOG_INFO, 0, 0, " state = %" PRIu64, val);
1188
if (local->call_cnt == 1 &&
1189
(val == GF_CS_REMOTE || val == GF_CS_DOWNLOADING)) {
1190
gf_msg(this->name, GF_LOG_INFO, 0, 0,
1191
" will read from remote : %" PRIu64, val);
1194
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1195
"second readv, Unwinding");
1200
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1202
"could not be figured, unwinding");
1206
/* successful readv => file is local */
1207
__cs_inode_ctx_update(this, fd->inode, GF_CS_LOCAL);
1208
gf_msg(this->name, GF_LOG_INFO, 0, 0,
1209
"state : GF_CS_LOCAL"
1210
", readv successful");
1216
ret = locate_and_execute(frame);
1224
CS_STACK_UNWIND(readv, frame, op_ret, op_errno, vector, count, stbuf,
1231
cs_resume_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
1232
off_t offset, uint32_t flags, dict_t *xdata)
1236
ret = cs_resume_postprocess(this, frame, fd->inode);
1241
cs_inodelk_unlock(frame);
1243
STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this),
1244
FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata);
1249
cs_inodelk_unlock(frame);
1251
cs_common_cbk(frame);
1257
cs_resume_remote_readv(call_frame_t *frame, xlator_t *this, fd_t *fd,
1258
size_t size, off_t offset, uint32_t flags, dict_t *xdata)
1261
cs_local_t *local = NULL;
1262
gf_cs_obj_state state = -1;
1263
cs_inode_ctx_t *ctx = NULL;
1265
cs_inodelk_unlock(frame);
1267
local = frame->local;
1273
__cs_inode_ctx_get(this, fd->inode, &ctx);
1275
state = __cs_get_file_state(fd->inode, ctx);
1276
if (state == GF_CS_ERROR) {
1277
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1278
"status is GF_CS_ERROR."
1281
local->op_errno = EREMOTE;
1286
/* Serve readv from remote store only if it is remote. */
1287
gf_msg_debug(this->name, 0, "status of file %s is %d",
1288
local->remotepath ? local->remotepath : "", state);
1290
/* We will reach this condition if local inode ctx had REMOTE
1291
* state when the control was in cs_readv but after stat
1292
* we got an updated state saying that the file is LOCAL.
1294
if (state == GF_CS_LOCAL) {
1295
STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this),
1296
FIRST_CHILD(this)->fops->readv, fd, size, offset, flags,
1298
} else if (state == GF_CS_REMOTE) {
1299
ret = cs_resume_remote_readv_postprocess(this, frame, fd->inode, offset,
1301
/* Failed to submit the remote readv fop to plugin */
1304
local->op_errno = EREMOTE;
1307
/* When the file is in any other intermediate state,
1308
* we should not perform remote reads.
1312
local->op_errno = EINVAL;
1319
cs_common_cbk(frame);
1325
cs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
1326
off_t offset, uint32_t flags, dict_t *xdata)
1328
int op_errno = ENOMEM;
1329
cs_local_t *local = NULL;
1331
cs_inode_ctx_t *ctx = NULL;
1332
gf_cs_obj_state state = -1;
1333
cs_private_t *priv = NULL;
1335
VALIDATE_OR_GOTO(frame, err);
1336
VALIDATE_OR_GOTO(this, err);
1337
VALIDATE_OR_GOTO(fd, err);
1339
priv = this->private;
1341
local = cs_local_init(this, frame, NULL, fd, GF_FOP_READ);
1343
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "local init failed");
1347
__cs_inode_ctx_get(this, fd->inode, &ctx);
1350
state = __cs_get_file_state(fd->inode, ctx);
1352
state = GF_CS_LOCAL;
1354
local->xattr_req = xdata ? dict_ref(xdata) : (xdata = dict_new());
1356
ret = dict_set_uint32(local->xattr_req, GF_CS_OBJECT_STATUS, 1);
1358
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1359
"dict_set failed key:"
1361
GF_CS_OBJECT_STATUS);
1365
if (priv->remote_read) {
1366
local->stub = fop_readv_stub(frame, cs_resume_remote_readv, fd, size,
1367
offset, flags, xdata);
1369
local->stub = fop_readv_stub(frame, cs_resume_readv, fd, size, offset,
1373
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insufficient memory");
1377
if (state == GF_CS_LOCAL) {
1378
STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this),
1379
FIRST_CHILD(this)->fops->readv, fd, size, offset, flags,
1383
ret = locate_and_execute(frame);
1392
CS_STACK_UNWIND(readv, frame, -1, op_errno, NULL, -1, NULL, NULL, NULL);
1398
cs_resume_remote_readv_postprocess(xlator_t *this, call_frame_t *frame,
1399
inode_t *inode, off_t offset, size_t size,
1404
ret = cs_serve_readv(frame, offset, size, flags);
1410
cs_stat_check_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
1411
int op_errno, struct iatt *stbuf, dict_t *xdata)
1413
cs_local_t *local = NULL;
1414
call_stub_t *stub = NULL;
1415
char *filepath = NULL;
1417
inode_t *inode = NULL;
1420
local = frame->local;
1423
local->op_ret = op_ret;
1424
local->op_errno = op_errno;
1425
gf_msg(this->name, GF_LOG_ERROR, 0, op_errno, "stat check failed");
1429
inode = local->fd->inode;
1431
inode = local->loc.inode;
1435
local->op_errno = EINVAL;
1436
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1442
ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val);
1444
if (val == GF_CS_ERROR) {
1445
cs_inode_ctx_reset(this, inode);
1447
local->op_errno = EIO;
1448
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1449
"status = GF_CS_ERROR. failed to get "
1453
ret = __cs_inode_ctx_update(this, inode, val);
1454
gf_msg_debug(this->name, 0, "status : %" PRIu64, val);
1456
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "ctx update failed");
1458
local->op_errno = ENOMEM;
1463
gf_msg_debug(this->name, 0, "status not found in dict");
1465
local->op_errno = ENOMEM;
1469
ret = dict_get_str_sizen(xdata, GF_CS_OBJECT_REMOTE, &filepath);
1471
gf_msg_debug(this->name, 0, "filepath returned %s", filepath);
1472
local->remotepath = gf_strdup(filepath);
1473
if (!local->remotepath) {
1475
local->op_errno = ENOMEM;
1479
gf_msg_debug(this->name, 0, "NULL filepath");
1482
ret = cs_update_xattrs(frame, xdata);
1487
local->xattr_rsp = dict_ref(xdata);
1488
memcpy(&local->stbuf, stbuf, sizeof(struct iatt));
1497
cs_inodelk_unlock(frame);
1499
cs_common_cbk(frame);
1505
cs_do_stat_check(call_frame_t *main_frame)
1507
cs_local_t *local = NULL;
1508
xlator_t *this = NULL;
1511
local = main_frame->local;
1512
this = main_frame->this;
1514
ret = dict_set_uint32(local->xattr_req, GF_CS_OBJECT_REPAIR, 256);
1516
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "dict_set failed");
1520
cs_set_xattr_req(main_frame);
1523
STACK_WIND(main_frame, cs_stat_check_cbk, FIRST_CHILD(this),
1524
FIRST_CHILD(this)->fops->fstat, local->fd, local->xattr_req);
1526
STACK_WIND(main_frame, cs_stat_check_cbk, FIRST_CHILD(this),
1527
FIRST_CHILD(this)->fops->stat, &local->loc,
1534
cs_inodelk_unlock(main_frame);
1536
cs_common_cbk(main_frame);
1542
cs_common_cbk(call_frame_t *frame)
1544
glusterfs_fop_t fop = -1;
1545
cs_local_t *local = NULL;
1547
local = frame->local;
1551
/*Note: Only the failure case needs to be handled here. Since for
1552
* successful stat check the fop will resume anyway. The unwind can
1553
* happen from the fop_cbk and each cbk can unlock the inodelk in case
1554
* a lock was taken before. The lock status can be stored in frame */
1556
/* for failure case */
1558
/*TODO: add other fops*/
1561
CS_STACK_UNWIND(writev, frame, local->op_ret, local->op_errno, NULL,
1565
case GF_FOP_SETXATTR:
1566
CS_STACK_UNWIND(setxattr, frame, local->op_ret, local->op_errno,
1570
CS_STACK_UNWIND(readv, frame, local->op_ret, local->op_errno, NULL,
1571
0, NULL, NULL, NULL);
1573
case GF_FOP_FTRUNCATE:
1574
CS_STACK_UNWIND(ftruncate, frame, local->op_ret, local->op_errno,
1578
case GF_FOP_TRUNCATE:
1579
CS_STACK_UNWIND(truncate, frame, local->op_ret, local->op_errno,
1590
cs_blocking_inodelk_cbk(call_frame_t *lock_frame, void *cookie, xlator_t *this,
1591
int32_t op_ret, int32_t op_errno, dict_t *xdata)
1593
cs_local_t *main_local = NULL;
1594
call_frame_t *main_frame = NULL;
1595
cs_local_t *lock_local = NULL;
1597
lock_local = lock_frame->local;
1599
main_frame = lock_local->main_frame;
1600
main_local = main_frame->local;
1603
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "inodelk failed");
1604
main_local->op_errno = op_errno;
1605
main_local->op_ret = op_ret;
1609
main_local->locked = _gf_true;
1611
cs_lock_wipe(lock_frame);
1613
cs_do_stat_check(main_frame);
1617
cs_common_cbk(main_frame);
1619
cs_lock_wipe(lock_frame);
1625
cs_build_loc(loc_t *loc, call_frame_t *frame)
1627
cs_local_t *local = NULL;
1630
local = frame->local;
1633
loc->inode = inode_ref(local->fd->inode);
1635
gf_uuid_copy(loc->gfid, loc->inode->gfid);
1643
loc->inode = inode_ref(local->loc.inode);
1645
gf_uuid_copy(loc->gfid, loc->inode->gfid);
1658
cs_blocking_inodelk(call_frame_t *parent_frame)
1660
call_frame_t *lock_frame = NULL;
1661
cs_local_t *lock_local = NULL;
1662
xlator_t *this = NULL;
1663
struct gf_flock flock = {
1668
this = parent_frame->this;
1670
lock_frame = cs_lock_frame(parent_frame);
1672
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insuffcient memory");
1676
lock_local = cs_local_init(this, lock_frame, NULL, NULL, 0);
1678
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "local init failed");
1682
lock_local->main_frame = parent_frame;
1684
flock.l_type = F_WRLCK;
1686
ret = cs_build_loc(&lock_local->loc, parent_frame);
1688
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "build_loc failed");
1692
STACK_WIND(lock_frame, cs_blocking_inodelk_cbk, FIRST_CHILD(this),
1693
FIRST_CHILD(this)->fops->inodelk, CS_LOCK_DOMAIN,
1694
&lock_local->loc, F_SETLKW, &flock, NULL);
1699
cs_lock_wipe(lock_frame);
1705
locate_and_execute(call_frame_t *frame)
1709
ret = cs_blocking_inodelk(frame);
1718
cs_resume_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc,
1719
off_t offset, dict_t *xattr_req)
1721
cs_local_t *local = NULL;
1724
local = frame->local;
1726
ret = cs_resume_postprocess(this, frame, loc->inode);
1731
cs_inodelk_unlock(frame);
1733
STACK_WIND(frame, cs_truncate_cbk, FIRST_CHILD(this),
1734
FIRST_CHILD(this)->fops->truncate, loc, offset,
1740
cs_inodelk_unlock(frame);
1742
cs_common_cbk(frame);
1748
cs_resume_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc,
1749
dict_t *dict, int32_t flags, dict_t *xdata)
1751
cs_local_t *local = NULL;
1752
cs_inode_ctx_t *ctx = NULL;
1753
gf_cs_obj_state state = GF_CS_ERROR;
1755
local = frame->local;
1757
__cs_inode_ctx_get(this, loc->inode, &ctx);
1759
state = __cs_get_file_state(loc->inode, ctx);
1761
if (state == GF_CS_ERROR) {
1762
/* file is already remote */
1764
local->op_errno = EINVAL;
1765
gf_msg(this->name, GF_LOG_WARNING, 0, 0,
1766
"file %s , could not figure file state", loc->path);
1770
if (state == GF_CS_REMOTE) {
1771
/* file is already remote */
1773
local->op_errno = EINVAL;
1774
gf_msg(this->name, GF_LOG_WARNING, 0, EINVAL,
1775
"file %s is already remote", loc->path);
1779
if (state == GF_CS_DOWNLOADING) {
1780
gf_msg(this->name, GF_LOG_WARNING, 0, 0,
1781
" file is in downloading state.");
1783
local->op_errno = EINVAL;
1787
STACK_WIND(frame, cs_setxattr_cbk, FIRST_CHILD(this),
1788
FIRST_CHILD(this)->fops->setxattr, loc, dict, flags,
1793
cs_inodelk_unlock(frame);
1795
cs_common_cbk(frame);
1801
__cs_get_file_state(inode_t *inode, cs_inode_ctx_t *ctx)
1803
gf_cs_obj_state state = -1;
1812
UNLOCK(&inode->lock);
1818
__cs_inode_ctx_get(xlator_t *this, inode_t *inode, cs_inode_ctx_t **ctx)
1820
uint64_t ctxint = 0;
1825
ret = __inode_ctx_get(inode, this, &ctxint);
1827
UNLOCK(&inode->lock);
1832
*ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint;
1838
__cs_inode_ctx_update(xlator_t *this, inode_t *inode, uint64_t val)
1840
cs_inode_ctx_t *ctx = NULL;
1841
uint64_t ctxint = 0;
1846
ret = __inode_ctx_get(inode, this, &ctxint);
1848
ctx = GF_CALLOC(1, sizeof(*ctx), gf_cs_mt_cs_inode_ctx_t);
1850
gf_msg(this->name, GF_LOG_ERROR, 0, 0, "ctx allocation failed");
1857
ctxint = (uint64_t)(uintptr_t)ctx;
1859
ret = __inode_ctx_set(inode, this, &ctxint);
1865
ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint;
1872
UNLOCK(&inode->lock);
1878
cs_inode_ctx_reset(xlator_t *this, inode_t *inode)
1880
cs_inode_ctx_t *ctx = NULL;
1881
uint64_t ctxint = 0;
1883
inode_ctx_del(inode, this, &ctxint);
1888
ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint;
1895
cs_resume_postprocess(xlator_t *this, call_frame_t *frame, inode_t *inode)
1897
cs_local_t *local = NULL;
1898
gf_cs_obj_state state = -1;
1899
cs_inode_ctx_t *ctx = NULL;
1902
local = frame->local;
1908
__cs_inode_ctx_get(this, inode, &ctx);
1910
state = __cs_get_file_state(inode, ctx);
1911
if (state == GF_CS_ERROR) {
1912
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1913
"status is GF_CS_ERROR."
1916
local->op_errno = EREMOTE;
1921
if (state == GF_CS_REMOTE || state == GF_CS_DOWNLOADING) {
1922
gf_msg_debug(this->name, 0, "status is %d", state);
1923
ret = cs_download(frame);
1925
gf_msg_debug(this->name, 0, "Winding for Final Write");
1927
gf_msg(this->name, GF_LOG_ERROR, 0, 0,
1928
" download failed, unwinding writev");
1930
local->op_errno = EREMOTE;
1939
cs_fdctx_to_dict(xlator_t *this, fd_t *fd, dict_t *dict)
1945
cs_inode(xlator_t *this)
1951
cs_inode_to_dict(xlator_t *this, dict_t *dict)
1957
cs_history(xlator_t *this)
1963
cs_fd(xlator_t *this)
1969
cs_fd_to_dict(xlator_t *this, dict_t *dict)
1975
cs_fdctx(xlator_t *this, fd_t *fd)
1981
cs_inodectx(xlator_t *this, inode_t *ino)
1987
cs_inodectx_to_dict(xlator_t *this, inode_t *ino, dict_t *dict)
1993
cs_priv_to_dict(xlator_t *this, dict_t *dict, char *brickname)
1999
cs_priv(xlator_t *this)
2005
cs_notify(xlator_t *this, int event, void *data, ...)
2007
return default_notify(this, event, data);
2010
struct xlator_fops cs_fops = {
2012
.readdirp = cs_readdirp,
2013
.truncate = cs_truncate,
2015
.statfs = cs_statfs,
2016
.fallocate = cs_fallocate,
2017
.discard = cs_discard,
2018
.getxattr = cs_getxattr,
2019
.writev = cs_writev,
2020
.setxattr = cs_setxattr,
2021
.fgetxattr = cs_fgetxattr,
2022
.lookup = cs_lookup,
2023
.fsetxattr = cs_fsetxattr,
2025
.ftruncate = cs_ftruncate,
2026
.rchecksum = cs_rchecksum,
2027
.unlink = cs_unlink,
2030
.zerofill = cs_zerofill,
2033
struct xlator_cbks cs_cbks = {
2034
.forget = cs_forget,
2037
struct xlator_dumpops cs_dumpops = {
2038
.fdctx_to_dict = cs_fdctx_to_dict,
2040
.inode_to_dict = cs_inode_to_dict,
2041
.history = cs_history,
2043
.fd_to_dict = cs_fd_to_dict,
2045
.inodectx = cs_inodectx,
2046
.inodectx_to_dict = cs_inodectx_to_dict,
2047
.priv_to_dict = cs_priv_to_dict,
2051
struct volume_options cs_options[] = {
2052
{.key = {"cloudsync-storetype"},
2053
.type = GF_OPTION_TYPE_STR,
2054
.description = "Defines which remote store is enabled"},
2055
{.key = {"cloudsync-remote-read"},
2056
.type = GF_OPTION_TYPE_BOOL,
2057
.description = "Defines a remote read fop when on"},
2058
{.key = {"cloudsync-store-id"},
2059
.type = GF_OPTION_TYPE_STR,
2060
.description = "Defines a volume wide store id"},
2061
{.key = {"cloudsync-product-id"},
2062
.type = GF_OPTION_TYPE_STR,
2063
.description = "Defines a volume wide product id"},
2067
xlator_api_t xlator_api = {
2070
.notify = cs_notify,
2071
.reconfigure = cs_reconfigure,
2072
.mem_acct_init = cs_mem_acct_init,
2073
.dumpops = &cs_dumpops,
2076
.options = cs_options,
2077
.identifier = "cloudsync",
2078
.category = GF_TECH_PREVIEW,