From 8462dd88ad3531837ebfccd17a083467faa40227 Mon Sep 17 00:00:00 2001 From: Amar Tumballi Date: Thu, 26 Feb 2009 08:09:25 -0800 Subject: volumefile modification awareness to make sure there are no inconsistencies. Complete (including feature to properly umount) in my sense. Signed-off-by: Anand V. Avati --- glusterfsd/src/glusterfsd.c | 14 ++ glusterfsd/src/glusterfsd.h | 2 + libglusterfs/src/common-utils.c | 51 +++++ libglusterfs/src/common-utils.h | 2 + libglusterfs/src/glusterfs.h | 3 + xlators/mount/fuse/src/fuse-bridge.c | 40 +++- xlators/mount/fuse/utils/mount.glusterfs.in | 9 +- xlators/mount/fuse/utils/mount_glusterfs.in | 12 +- xlators/protocol/client/src/client-protocol.c | 22 ++- xlators/protocol/server/src/server-protocol.c | 275 ++++++++++++++++++-------- xlators/protocol/server/src/server-protocol.h | 12 +- 11 files changed, 346 insertions(+), 96 deletions(-) diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index a6f00bb5b..37eefa01b 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -130,6 +130,8 @@ static struct argp_option gf_options[] = { {"attribute-timeout", ARGP_ATTRIBUTE_TIMEOUT_KEY, "SECONDS", 0, "Set attribute timeout to SECONDS for inodes in fuse kernel module " "[default: 1]"}, + {"volfile-check", ARGP_VOLFILE_CHECK_KEY, 0, 0, + "enable strict volume file check in fuse notify"}, #ifdef GF_DARWIN_HOST_OS {"non-local", ARGP_NON_LOCAL_KEY, 0, 0, "Mount the macfuse volume without '-o local' option"}, @@ -236,6 +238,10 @@ _add_fuse_mount (xlator_t *graph) ret = dict_set_double (top->options, ZR_ENTRY_TIMEOUT_OPT, cmd_args->fuse_entry_timeout); + if (cmd_args->volfile_check) + ret = dict_set_int32 (top->options, ZR_STRICT_VOLFILE_CHECK, + cmd_args->volfile_check); + #ifdef GF_DARWIN_HOST_OS /* On Darwin machines, O_APPEND is not handled, * which may corrupt the data @@ -335,6 +341,7 @@ static xlator_t * _parse_specfp (glusterfs_ctx_t *ctx, FILE *specfp) { + int spec_fd = 0; cmd_args_t *cmd_args = NULL; xlator_t *tree = NULL, *trav = NULL, *new_tree = NULL; @@ -365,6 +372,9 @@ _parse_specfp (glusterfs_ctx_t *ctx, return NULL; } + spec_fd = fileno (specfp); + get_checksum_for_file (spec_fd, &ctx->volfile_checksum); + /* if volume_name is given, then we attach to it */ if (cmd_args->volume_name) { while (trav) { @@ -756,6 +766,10 @@ parse_opts (int key, char *arg, struct argp_state *state) "unknown attribute timeout %s", arg); break; + case ARGP_VOLFILE_CHECK_KEY: + cmd_args->volfile_check = 1; + break; + case ARGP_VOLUME_NAME_KEY: cmd_args->volume_name = strdup (arg); break; diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h index 87eca94ac..0d6423ab4 100644 --- a/glusterfsd/src/glusterfsd.h +++ b/glusterfsd/src/glusterfsd.h @@ -48,6 +48,7 @@ #define ZR_ATTR_TIMEOUT_OPT "attribute-timeout" #define ZR_ENTRY_TIMEOUT_OPT "entry-timeout" #define ZR_DIRECT_IO_OPT "direct-io-mode" +#define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check" enum argp_option_keys { ARGP_VOLFILE_SERVER_KEY = 's', @@ -69,6 +70,7 @@ enum argp_option_keys { ARGP_NON_LOCAL_KEY = 139, #endif /* DARWIN */ ARGP_VOLFILE_ID_KEY = 143, + ARGP_VOLFILE_CHECK_KEY = 144, }; /* Moved here from fetch-spec.h */ diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 1b4106c41..e8a7c9ab5 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -1388,3 +1388,54 @@ gf_unlockfd (int fd) return fcntl (fd, F_SETLK, &fl); } +static void +compute_checksum (char *buf, size_t size, uint32_t *checksum) +{ + int ret = -1; + char *checksum_buf = NULL; + + checksum_buf = (char *)(checksum); + + if (!(*checksum)) { + checksum_buf [0] = 0xba; + checksum_buf [1] = 0xbe; + checksum_buf [2] = 0xb0; + checksum_buf [3] = 0x0b; + } + + for (ret = 0; ret < (size - 4); ret += 4) { + checksum_buf[0] ^= (buf[ret]); + checksum_buf[1] ^= (buf[ret + 1] << 1) ; + checksum_buf[2] ^= (buf[ret + 2] << 2); + checksum_buf[3] ^= (buf[ret + 3] << 3); + } + + for (ret = 0; ret <= (size % 4); ret++) { + checksum_buf[ret] ^= (buf[(size - 4) + ret] << ret); + } + + return; +} + +#define GF_CHECKSUM_BUF_SIZE 1024 + +int +get_checksum_for_file (int fd, uint32_t *checksum) +{ + int ret = -1; + char buf[GF_CHECKSUM_BUF_SIZE] = {0,}; + + /* goto first place */ + lseek (fd, 0L, SEEK_SET); + do { + ret = read (fd, &buf, GF_CHECKSUM_BUF_SIZE); + if (ret > 0) + compute_checksum (buf, GF_CHECKSUM_BUF_SIZE, + checksum); + } while (ret > 0); + + /* set it back */ + lseek (fd, 0L, SEEK_SET); + + return ret; +} diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index f3a39226c..b3630d478 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -310,5 +310,7 @@ int gf_string2time (const char *str, uint32_t *n); int gf_lockfd (int fd); int gf_unlockfd (int fd); +int get_checksum_for_file (int fd, uint32_t *checksum); + #endif /* _COMMON_UTILS_H */ diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index be6412f22..d00ec4866 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -227,6 +227,7 @@ struct _cmd_args { /* fuse options */ int fuse_direct_io_mode_flag; + int volfile_check; double fuse_entry_timeout; double fuse_attribute_timeout; char *volume_name; @@ -258,6 +259,7 @@ struct _glusterfs_ctx { void *event_pool; pthread_mutex_t lock; int xl_count; + uint32_t volfile_checksum; }; typedef struct _glusterfs_ctx glusterfs_ctx_t; @@ -272,6 +274,7 @@ typedef enum { GF_EVENT_CHILD_CONNECTING, GF_EVENT_TRANSPORT_CLEANUP, GF_EVENT_TRANSPORT_CONNECTED, + GF_EVENT_VOLFILE_MODIFIED, } glusterfs_event_t; #define GF_MUST_CHECK __attribute__((warn_unused_result)) diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index e876799a2..4affd40d5 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -53,8 +53,9 @@ /* TODO: when supporting posix acl, remove this definition */ #define DISABLE_POSIX_ACL -#define ZR_MOUNTPOINT_OPT "mountpoint" -#define ZR_DIRECT_IO_OPT "direct-io-mode" +#define ZR_MOUNTPOINT_OPT "mountpoint" +#define ZR_DIRECT_IO_OPT "direct-io-mode" +#define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check" #define BIG_FUSE_CHANNEL_SIZE 1048576 @@ -72,7 +73,7 @@ struct fuse_private { uint32_t direct_io_mode; double entry_timeout; double attribute_timeout; - + gf_boolean_t strict_volfile_check; }; typedef struct fuse_private fuse_private_t; @@ -2553,6 +2554,10 @@ int32_t notify (xlator_t *this, int32_t event, void *data, ...) { + int32_t ret = 0; + fuse_private_t *private = NULL; + + private = this->private; switch (event) { @@ -2577,8 +2582,6 @@ notify (xlator_t *this, int32_t event, #endif /* DARWIN */ { - fuse_private_t *private = this->private; - int32_t ret = 0; if (!private->fuse_thread_started) { @@ -2597,6 +2600,21 @@ notify (xlator_t *this, int32_t event, case GF_EVENT_PARENT_UP: { default_notify (this, GF_EVENT_PARENT_UP, data); + break; + } + case GF_EVENT_VOLFILE_MODIFIED: + { + gf_log ("fuse", GF_LOG_CRITICAL, + "remote volume file changed, try re-mounting"); + if (private->strict_volfile_check) { + //fuse_session_remove_chan (private->ch); + //fuse_session_destroy (private->se); + //fuse_unmount (private->mount_point, private->ch); + /* TODO: Above code if works, will be a cleaner way, + but for now, lets just achieve what we want */ + raise (SIGTERM); + } + break; } default: break; @@ -2736,7 +2754,14 @@ init (xlator_t *this_xl) if (value_string) { ret = gf_string2boolean (value_string, &priv->direct_io_mode); } - + + priv->strict_volfile_check = 0; + ret = dict_get_str (options, ZR_STRICT_VOLFILE_CHECK, &value_string); + if (value_string) { + ret = gf_string2boolean (value_string, + &priv->strict_volfile_check); + } + priv->ch = fuse_mount (priv->mount_point, &args); if (priv->ch == NULL) { if (errno == ENOTCONN) { @@ -2851,5 +2876,8 @@ struct volume_options options[] = { { .key = {"entry-timeout"}, .type = GF_OPTION_TYPE_DOUBLE }, + { .key = {"strict-volfile-check"}, + .type = GF_OPTION_TYPE_BOOL + }, { .key = {NULL} }, }; diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in index 481fd265f..58da509f1 100755 --- a/xlators/mount/fuse/utils/mount.glusterfs.in +++ b/xlators/mount/fuse/utils/mount.glusterfs.in @@ -66,6 +66,10 @@ start_glusterfs () cmd_line=$(echo "$cmd_line --log-file=$log_file"); fi + if [ -n "$volfile_check" ]; then + cmd_line=$(echo "$cmd_line --volfile-check"); + fi + if [ -n "$direct_io_mode" ]; then cmd_line=$(echo "$cmd_line --direct-io-mode=$direct_io_mode"); fi @@ -115,7 +119,9 @@ main () volume_name=$(echo "$options" | sed -n 's/.*volume-name=\([^,]*\).*/\1/p'); volume_id=$(echo "$options" | sed -n 's/.*volume-id=\([^,]*\).*/\1/p'); - + + volfile_check=$(echo "$options" | sed -n 's/.*volfile-check=\([^,]*\).*/\1/p'); + volfile_loc="$1"; [ -r "$volfile_loc" ] || { @@ -131,6 +137,7 @@ main () -e 's/[,]*log-level=[^,]*//' \ -e 's/[,]*volume-name=[^,]*//' \ -e 's/[,]*direct-io-mode=[^,]*//' \ + -e 's/[,]*volfile-check=[^,]*//' \ -e 's/[,]*transport=[^,]*//' \ -e 's/[,]*volume-id=[^,]*//'); # following line is product of love towards sed diff --git a/xlators/mount/fuse/utils/mount_glusterfs.in b/xlators/mount/fuse/utils/mount_glusterfs.in index 1376a8897..b064e1ead 100755 --- a/xlators/mount/fuse/utils/mount_glusterfs.in +++ b/xlators/mount/fuse/utils/mount_glusterfs.in @@ -66,8 +66,12 @@ start_glusterfs () cmd_line=$(echo "$cmd_line --log-file=$log_file"); fi + if [ -n "$volfile_check" ]; then + cmd_line=$(echo "$cmd_line --volfile-check"); + fi + if [ -n "$direct_io_mode" ]; then - cmd_line=$(echo "$cmd_line --direct-io-mode=$direct_io_mode"); + cmd_line=$(echo "$cmd_line --disable-direct-io-mode"); fi if [ -z "$volfile_loc" ]; then @@ -107,6 +111,7 @@ main () direct_io_mode="" volume_name="" new_fs_options="" + volfile_check="" while getopts o: opt; do case "$opt" in @@ -128,6 +133,10 @@ main () direct_io_mode=$(echo "$options" | sed -n 's/.*direct-io-mode=\([^,]*\).*/\1/p'); } + [ -z $volfile_check ] && { + volfile_check=$(echo "$options" | sed -n 's/.*volfile-check=\([^,]*\).*/\1/p'); + } + [ -z $volume_name ] && { volume_name=$(echo "$options" | sed -n 's/.*volume-name=\([^,]*\).*/\1/p'); } @@ -139,6 +148,7 @@ main () this_option=$(echo "$options" | sed -e 's/[,]*log-file=[^,]*//' \ -e 's/[,]*log-level=[^,]*//' \ -e 's/[,]*volume-name=[^,]*//' \ + -e 's/[,]*volfile-check=[^,]*//' \ -e 's/[,]*direct-io-mode=[^,]*//' \ -e 's/[,]*transport=[^,]*//' \ -e 's/[,]*volume-id=[^,]*//'); diff --git a/xlators/protocol/client/src/client-protocol.c b/xlators/protocol/client/src/client-protocol.c index da2242ad6..11e669833 100644 --- a/xlators/protocol/client/src/client-protocol.c +++ b/xlators/protocol/client/src/client-protocol.c @@ -5875,7 +5875,7 @@ client_setvolume_cbk (call_frame_t *frame, op_ret = ntoh32 (hdr->rsp.op_ret); op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno)); - if (op_ret < 0 && op_errno == ENOTCONN) { + if ((op_ret < 0) && (op_errno == ENOTCONN)) { gf_log (this->name, GF_LOG_ERROR, "setvolume failed (%s)", strerror (op_errno)); @@ -5911,8 +5911,16 @@ client_setvolume_cbk (call_frame_t *frame, "SETVOLUME on remote-host failed: %s", remote_error ? remote_error : strerror (op_errno)); errno = op_errno; - if (op_errno == ENOTCONN) - goto out; + if (op_errno == ESTALE) { + parent = trans->xl->parents; + while (parent) { + parent->xlator->notify (parent->xlator, + GF_EVENT_VOLFILE_MODIFIED, + trans->xl); + parent = parent->next; + } + } + } else { ctx = get_global_ctx_ptr (); if (process_uuid && !strcmp (ctx->process_uuid,process_uuid)) { @@ -6439,6 +6447,14 @@ protocol_client_handshake (xlator_t *this, transport_t *trans) PACKAGE_VERSION); } + if (this->ctx->cmd_args.volfile_server) { + if (this->ctx->cmd_args.volfile_id) + ret = dict_set_str (options, "volfile-key", + this->ctx->cmd_args.volfile_id); + ret = dict_set_uint32 (options, "volfile-checksum", + this->ctx->volfile_checksum); + } + dict_len = dict_serialized_length (options); if (dict_len < 0) { gf_log (this->name, GF_LOG_ERROR, diff --git a/xlators/protocol/server/src/server-protocol.c b/xlators/protocol/server/src/server-protocol.c index 68e1cc06c..4e06aaa5e 100644 --- a/xlators/protocol/server/src/server-protocol.c +++ b/xlators/protocol/server/src/server-protocol.c @@ -6777,6 +6777,150 @@ out: /* xxx_MOPS */ + +int +_volfile_update_checksum (xlator_t *this, char *key, uint32_t checksum) +{ + server_conf_t *conf = NULL; + struct _volfile_ctx *temp_volfile = NULL; + + conf = this->private; + temp_volfile = conf->volfile; + + while (temp_volfile) { + if ((NULL == key) && (NULL == temp_volfile->key)) + break; + if ((NULL == key) || (NULL == temp_volfile->key)) { + temp_volfile = temp_volfile->next; + continue; + } + if (strcmp (temp_volfile->key, key) == 0) + break; + temp_volfile = temp_volfile->next; + } + + if (!temp_volfile) { + temp_volfile = CALLOC (1, sizeof (struct _volfile_ctx)); + + temp_volfile->next = conf->volfile; + temp_volfile->key = (key)? strdup (key): NULL; + temp_volfile->checksum = checksum; + + conf->volfile = temp_volfile; + goto out; + } + + if (temp_volfile->checksum != checksum) { + gf_log (this->name, GF_LOG_CRITICAL, + "the volume file got modified between earlier access " + "and now, this may lead to inconsistency between " + "clients, advised to remount client"); + temp_volfile->checksum = checksum; + } + + out: + return 0; +} + + +char * +build_volfile_path (xlator_t *this, char *key) +{ + int ret = -1; + char *filename = NULL; + char data_key[256] = {0,}; + + /* Inform users that this option is changed now */ + ret = dict_get_str (this->options, "client-volume-filename", + &filename); + if (ret == 0) { + gf_log (this->name, GF_LOG_WARNING, + "option 'client-volume-filename' is changed to " + "'volume-filename.' which now takes 'key' as an " + "option to choose/fetch different files from server. " + "Refer documentation or contact developers for more " + "info. Currently defaulting to given file '%s'", + filename); + } + + if (key && !filename) { + sprintf (data_key, "volume-filename.%s", key); + ret = dict_get_str (this->options, data_key, &filename); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get corresponding volume file " + "for the key '%s'.", key); + } + } + + if (!filename) { + ret = dict_get_str (this->options, + "volume-filename.default", &filename); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "no default volume filename given, " + "defaulting to %s", DEFAULT_VOLUME_FILE_PATH); + + filename = DEFAULT_VOLUME_FILE_PATH; + } + } + + return filename; +} + +int +_validate_volfile_checksum (xlator_t *this, char *key, + uint32_t checksum) +{ + char *filename = NULL; + server_conf_t *conf = NULL; + struct _volfile_ctx *temp_volfile = NULL; + int ret = 0; + uint32_t local_checksum = 0; + + conf = this->private; + temp_volfile = conf->volfile; + + if (!checksum) + goto out; + + if (!temp_volfile) { + filename = build_volfile_path (this, key); + if (NULL == filename) + goto out; + ret = open (filename, O_RDONLY); + if (-1 == ret) { + ret = 0; + gf_log (this->name, GF_LOG_DEBUG, + "failed to open volume file (%s) : %s", + filename, strerror (errno)); + goto out; + } + get_checksum_for_file (ret, &local_checksum); + _volfile_update_checksum (this, key, local_checksum); + close (ret); + } + + temp_volfile = conf->volfile; + while (temp_volfile) { + if ((NULL == key) && (NULL == temp_volfile->key)) + break; + if (strcmp (temp_volfile->key, key) == 0) + break; + temp_volfile = temp_volfile->next; + } + + if (!temp_volfile) + goto out; + + if ((temp_volfile->checksum) && + (checksum != temp_volfile->checksum)) + ret = -1; + + out: + return ret; +} + /* Management Calls */ /* * mop_getspec - getspec function for server protocol @@ -6799,17 +6943,14 @@ mop_getspec (call_frame_t *frame, int32_t spec_fd = -1; size_t file_len = 0; size_t _hdrlen = 0; - char tmp_filename[ZR_FILENAME_MAX] = {0,}; - char data_key[256] = {0,}; char *filename = NULL; struct stat stbuf = {0,}; - peer_info_t *peerinfo = NULL; - transport_t *trans = NULL; gf_mop_getspec_req_t *req = NULL; + uint32_t checksum = 0; uint32_t flags = 0; uint32_t keylen = 0; - char *key = NULL; + char *key = NULL; req = gf_param (hdr); flags = ntoh32 (req->flags); @@ -6818,85 +6959,32 @@ mop_getspec (call_frame_t *frame, key = req->key; } - trans = TRANSPORT_FROM_FRAME(frame); - - peerinfo = &(trans->peerinfo); - /* Inform users that this option is changed now */ - ret = dict_get_str (frame->this->options, "client-volume-filename", - &filename); - if (ret == 0) { - gf_log (trans->xl->name, GF_LOG_WARNING, - "option 'client-volume-filename' is changed to " - "'volume-filename.' which now takes 'key' as an " - "option to choose/fetch different files from server. " - "Refer documentation or contact developers for more " - "info. Currently defaulting to given file '%s'", - filename); - } - - if (key && !filename) { - sprintf (data_key, "volume-filename.%s", key); - ret = dict_get_str (frame->this->options, data_key, &filename); - if (ret < 0) { - gf_log (trans->xl->name, GF_LOG_ERROR, - "failed to get corresponding volume file " - "for the key '%s'. using default file %s", - key, GLUSTERFSD_SPEC_PATH); - } - } - - if (!filename) { - ret = dict_get_str (frame->this->options, - "volume-filename.default", &filename); - if (ret < 0) { - gf_log (trans->xl->name, GF_LOG_DEBUG, - "no default volume filename given, " - "defaulting to %s", GLUSTERFSD_SPEC_PATH); - - filename = GLUSTERFSD_SPEC_PATH; - } - } - - { - sprintf (tmp_filename, "%s.%s", - filename, peerinfo->identifier); - - /* Try for ip specific client volfile. - * If not found, then go for, regular client file. - */ - ret = open (tmp_filename, O_RDONLY); - spec_fd = ret; - if (spec_fd < 0) { - gf_log (trans->xl->name, GF_LOG_DEBUG, - "Unable to open %s (%s)", - tmp_filename, strerror (errno)); - /* fall back */ - ret = open (filename, O_RDONLY); - spec_fd = ret; - if (spec_fd < 0) { - gf_log (trans->xl->name, GF_LOG_ERROR, - "Unable to open %s (%s)", - filename, strerror (errno)); - goto fail; - } - } else { - /* Successful */ - filename = tmp_filename; - } - } - - /* to allocate the proper buffer to hold the file data */ - { + filename = build_volfile_path (frame->this, key); + if (filename) { + /* to allocate the proper buffer to hold the file data */ ret = stat (filename, &stbuf); if (ret < 0){ - gf_log (trans->xl->name, GF_LOG_ERROR, + gf_log (frame->this->name, GF_LOG_ERROR, "Unable to stat %s (%s)", filename, strerror (errno)); goto fail; } - - file_len = stbuf.st_size; - } + + ret = open (filename, O_RDONLY); + spec_fd = ret; + if (spec_fd < 0) { + gf_log (frame->this->name, GF_LOG_ERROR, + "Unable to open %s (%s)", + filename, strerror (errno)); + goto fail; + } + ret = 0; + file_len = stbuf.st_size; + get_checksum_for_file (spec_fd, &checksum); + _volfile_update_checksum (frame->this, key, checksum); + } else { + errno = ENOENT; + } fail: op_errno = errno; @@ -6910,7 +6998,7 @@ fail: _hdr->rsp.op_errno = hton32 (gf_errno); if (file_len) { - read (spec_fd, rsp->spec, file_len); + ret = read (spec_fd, rsp->spec, file_len); close (spec_fd); } protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_GETSPEC, @@ -7043,7 +7131,7 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, gf_hdr_common_t *req_hdr, size_t req_hdrlen, char *req_buf, size_t req_buflen) { - server_connection_t *conn = NULL; + server_connection_t *conn = NULL; server_conf_t *conf = NULL; gf_hdr_common_t *rsp_hdr = NULL; gf_mop_setvolume_req_t *req = NULL; @@ -7064,6 +7152,9 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, size_t rsp_hdrlen = -1; size_t dict_len = -1; size_t req_dictlen = -1; + char *msg = NULL; + char *volfile_key = NULL; + uint32_t checksum = 0; params = dict_new (); reply = dict_new (); @@ -7124,7 +7215,6 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, ret = strcmp (version, PACKAGE_VERSION); if (ret != 0) { - char *msg = NULL; asprintf (&msg, "Version mismatch: client(%s) Vs server (%s)", version, PACKAGE_VERSION); @@ -7138,7 +7228,6 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, goto fail; } - ret = dict_get_str (params, "remote-subvolume", &name); if (ret < 0) { @@ -7155,7 +7244,6 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, xl = get_xlator_by_name (frame->this, name); if (xl == NULL) { - char *msg = NULL; asprintf (&msg, "remote-subvolume \"%s\" is not found", name); ret = dict_set_dynstr (reply, "ERROR", msg); if (ret < 0) @@ -7167,6 +7255,27 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, goto fail; } + ret = dict_get_uint32 (params, "volfile-checksum", &checksum); + if (ret == 0) { + ret = dict_get_str (params, "volfile-key", &volfile_key); + + ret = _validate_volfile_checksum (trans->xl, volfile_key, + checksum); + if (-1 == ret) { + ret = dict_set_str (reply, "ERROR", + "volume-file checksum varies from " + "earlier access"); + if (ret < 0) + gf_log (trans->xl->name, GF_LOG_ERROR, + "failed to set error msg"); + + op_ret = -1; + op_errno = ESTALE; + goto fail; + } + } + + peerinfo = &trans->peerinfo; ret = dict_set_static_ptr (params, "peer-info", peerinfo); if (ret < 0) diff --git a/xlators/protocol/server/src/server-protocol.h b/xlators/protocol/server/src/server-protocol.h index 3b28a3e5e..30ccb91e7 100644 --- a/xlators/protocol/server/src/server-protocol.h +++ b/xlators/protocol/server/src/server-protocol.h @@ -35,8 +35,8 @@ #include "fd.h" #include "byte-order.h" -#define DEFAULT_BLOCK_SIZE 4194304 /* 4MB */ -#define GLUSTERFSD_SPEC_PATH CONFDIR "/glusterfs-client.vol" +#define DEFAULT_BLOCK_SIZE 4194304 /* 4MB */ +#define DEFAULT_VOLUME_FILE_PATH CONFDIR "/glusterfs.vol" typedef struct _server_state server_state_t; @@ -86,7 +86,15 @@ server_nop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno); +struct _volfile_ctx { + struct _volfile_ctx *next; + char *key; + uint32_t checksum; +}; + typedef struct { + struct _volfile_ctx *volfile; + dict_t *auth_modules; transport_t *trans; int32_t max_block_size; -- cgit