/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. This file is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ #include "quiesce.h" #include "defaults.h" #include "call-stub.h" /* TODO: */ /* Think about 'writev/_*_lk/setattr/xattrop/' fops to do re-transmittion */ void gf_quiesce_timeout (void *data); /* Quiesce Specific Functions */ void gf_quiesce_local_wipe (xlator_t *this, quiesce_local_t *local) { if (!local || !this || !this->private) return; if (local->loc.inode) loc_wipe (&local->loc); if (local->fd) fd_unref (local->fd); GF_FREE (local->name); GF_FREE (local->volname); if (local->dict) dict_unref (local->dict); if (local->iobref) iobref_unref (local->iobref); GF_FREE (local->vector); mem_put (local); } void __gf_quiesce_start_timer (xlator_t *this, quiesce_priv_t *priv) { struct timespec timeout = {0,}; if (!priv->timer) { timeout.tv_sec = priv->timeout; timeout.tv_nsec = 0; priv->timer = gf_timer_call_after (this->ctx, timeout, gf_quiesce_timeout, (void *) this); if (priv->timer == NULL) { gf_log (this->name, GF_LOG_ERROR, "Cannot create timer"); } } } static void __gf_quiesce_cleanup_failover_hosts (xlator_t *this, quiesce_priv_t *priv) { quiesce_failover_hosts_t *tmp = NULL; quiesce_failover_hosts_t *failover_host = NULL; list_for_each_entry_safe (failover_host, tmp, &priv->failover_list, list) { GF_FREE (failover_host->addr); list_del (&failover_host->list); GF_FREE (failover_host); } return; } void gf_quiesce_populate_failover_hosts (xlator_t *this, quiesce_priv_t *priv, const char *value) { char *dup_val = NULL; char *addr_tok = NULL; char *save_ptr = NULL; quiesce_failover_hosts_t *failover_host = NULL; if (!value) goto out; dup_val = gf_strdup (value); if (!dup_val) goto out; LOCK (&priv->lock); { if (!list_empty (&priv->failover_list)) __gf_quiesce_cleanup_failover_hosts (this, priv); addr_tok = strtok_r (dup_val, ",", &save_ptr); while (addr_tok) { if (!valid_internet_address (addr_tok, _gf_true)) { gf_msg (this->name, GF_LOG_INFO, 0, QUIESCE_MSG_INVAL_HOST, "Specified " "invalid internet address:%s", addr_tok); continue; } failover_host = GF_CALLOC (1, sizeof(*failover_host), gf_quiesce_mt_failover_hosts); failover_host->addr = gf_strdup (addr_tok); INIT_LIST_HEAD (&failover_host->list); list_add (&failover_host->list, &priv->failover_list); addr_tok = strtok_r (NULL, ",", &save_ptr); } } UNLOCK (&priv->lock); GF_FREE (dup_val); out: return; } int32_t gf_quiesce_failover_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { quiesce_priv_t *priv = NULL; if (op_ret < 0) { /* Failure here doesn't mean the failover to another host didn't * succeed, we will know if failover succeeds or not by the * CHILD_UP/CHILD_DOWN event. A failure here indicates something * went wrong with the submission of failover command, hence * just abort the failover attempts without retrying with other * hosts. */ gf_msg (this->name, GF_LOG_INFO, op_errno, QUIESCE_MSG_FAILOVER_FAILED, "Initiating failover to host:%s failed:", (char *)cookie); } GF_FREE (cookie); STACK_DESTROY (frame->root); priv = this->private; __gf_quiesce_start_timer (this, priv); return 0; } int __gf_quiesce_perform_failover (xlator_t *this) { int ret = 0; call_frame_t *frame = NULL; dict_t *dict = NULL; quiesce_priv_t *priv = NULL; quiesce_failover_hosts_t *failover_host = NULL; quiesce_failover_hosts_t *host = NULL; priv = this->private; if (priv->pass_through) { gf_msg_trace (this->name, 0, "child is up, hence not " "performing any failover"); goto out; } list_for_each_entry (failover_host, &priv->failover_list, list) { if (failover_host->tried == 0) { host = failover_host; failover_host->tried = 1; break; } } if (!host) { /*TODO: Keep trying until any of the gfproxy comes back up. Currently it tries failing over once for each host, if it doesn't succeed then returns error to mount point list_for_each_entry (failover_host, &priv->failover_list, list) { failover_host->tried = 0; }*/ gf_msg_debug (this->name, 0, "all the failover hosts have " "been tried and looks like didn't succeed"); ret = -1; goto out; } frame = create_frame (this, this->ctx->pool); dict = dict_new (); ret = dict_set_dynstr (dict, CLIENT_CMD_CONNECT, gf_strdup (host->addr)); gf_msg_trace (this->name, 0, "Initiating failover to:%s", host->addr); STACK_WIND_COOKIE (frame, gf_quiesce_failover_cbk, NULL, FIRST_CHILD (this), FIRST_CHILD (this)->fops->setxattr, NULL, dict, 0, NULL); out: if (dict) dict_unref (dict); return ret; } call_stub_t * gf_quiesce_dequeue (xlator_t *this) { call_stub_t *stub = NULL; quiesce_priv_t *priv = NULL; priv = this->private; if (!priv || list_empty (&priv->req)) return NULL; LOCK (&priv->lock); { stub = list_entry (priv->req.next, call_stub_t, list); list_del_init (&stub->list); priv->queue_size--; } UNLOCK (&priv->lock); return stub; } void * gf_quiesce_dequeue_start (void *data) { xlator_t *this = NULL; quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; this = data; priv = this->private; THIS = this; while (!list_empty (&priv->req)) { stub = gf_quiesce_dequeue (this); if (stub) { call_resume (stub); } } return 0; } void gf_quiesce_timeout (void *data) { xlator_t *this = NULL; quiesce_priv_t *priv = NULL; int ret = -1; this = data; priv = this->private; THIS = this; LOCK (&priv->lock); { priv->timer = NULL; if (priv->pass_through) { UNLOCK (&priv->lock); goto out; } ret = __gf_quiesce_perform_failover (THIS); } UNLOCK (&priv->lock); if (ret < 0) { priv->pass_through = _gf_true; gf_quiesce_dequeue_start (this); } out: return; } void gf_quiesce_enqueue (xlator_t *this, call_stub_t *stub) { quiesce_priv_t *priv = NULL; priv = this->private; if (!priv) { gf_log_callingfn (this->name, GF_LOG_ERROR, "this->private == NULL"); return; } LOCK (&priv->lock); { list_add_tail (&stub->list, &priv->req); priv->queue_size++; __gf_quiesce_start_timer (this, priv); } UNLOCK (&priv->lock); return; } /* _CBK function section */ int32_t quiesce_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *dict, struct iatt *postparent) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_lookup_stub (frame, default_lookup_resume, &local->loc, local->dict); if (!stub) { STACK_UNWIND_STRICT (lookup, frame, -1, ENOMEM, NULL, NULL, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, inode, buf, dict, postparent); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_stat_stub (frame, default_stat_resume, &local->loc, xdata); if (!stub) { STACK_UNWIND_STRICT (stat, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (stat, frame, op_ret, op_errno, buf, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_access_stub (frame, default_access_resume, &local->loc, local->flag, xdata); if (!stub) { STACK_UNWIND_STRICT (access, frame, -1, ENOMEM, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (access, frame, op_ret, op_errno, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, const char *path, struct iatt *buf, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_readlink_stub (frame, default_readlink_resume, &local->loc, local->size, xdata); if (!stub) { STACK_UNWIND_STRICT (readlink, frame, -1, ENOMEM, NULL, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (readlink, frame, op_ret, op_errno, path, buf, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_open_stub (frame, default_open_resume, &local->loc, local->flag, local->fd, xdata); if (!stub) { STACK_UNWIND_STRICT (open, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iovec *vector, int32_t count, struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_readv_stub (frame, default_readv_resume, local->fd, local->size, local->offset, local->io_flag, xdata); if (!stub) { STACK_UNWIND_STRICT (readv, frame, -1, ENOMEM, NULL, 0, NULL, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, vector, count, stbuf, iobref, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_flush_stub (frame, default_flush_resume, local->fd, xdata); if (!stub) { STACK_UNWIND_STRICT (flush, frame, -1, ENOMEM, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_fsync_stub (frame, default_fsync_resume, local->fd, local->flag, xdata); if (!stub) { STACK_UNWIND_STRICT (fsync, frame, -1, ENOMEM, NULL, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (fsync, frame, op_ret, op_errno, prebuf, postbuf, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_fstat_stub (frame, default_fstat_resume, local->fd, xdata); if (!stub) { STACK_UNWIND_STRICT (fstat, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (fstat, frame, op_ret, op_errno, buf, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_opendir_stub (frame, default_opendir_resume, &local->loc, local->fd, xdata); if (!stub) { STACK_UNWIND_STRICT (opendir, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (opendir, frame, op_ret, op_errno, fd, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_fsyncdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_fsyncdir_stub (frame, default_fsyncdir_resume, local->fd, local->flag, xdata); if (!stub) { STACK_UNWIND_STRICT (fsyncdir, frame, -1, ENOMEM, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (fsyncdir, frame, op_ret, op_errno, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct statvfs *buf, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_statfs_stub (frame, default_statfs_resume, &local->loc, xdata); if (!stub) { STACK_UNWIND_STRICT (statfs, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, buf, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_fgetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_fgetxattr_stub (frame, default_fgetxattr_resume, local->fd, local->name, xdata); if (!stub) { STACK_UNWIND_STRICT (fgetxattr, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_getxattr_stub (frame, default_getxattr_resume, &local->loc, local->name, xdata); if (!stub) { STACK_UNWIND_STRICT (getxattr, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_rchecksum_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, uint32_t weak_checksum, uint8_t *strong_checksum, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_rchecksum_stub (frame, default_rchecksum_resume, local->fd, local->offset, local->flag, xdata); if (!stub) { STACK_UNWIND_STRICT (rchecksum, frame, -1, ENOMEM, 0, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (rchecksum, frame, op_ret, op_errno, weak_checksum, strong_checksum, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_readdir_stub (frame, default_readdir_resume, local->fd, local->size, local->offset, xdata); if (!stub) { STACK_UNWIND_STRICT (readdir, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, entries, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_readdirp_stub (frame, default_readdirp_resume, local->fd, local->size, local->offset, local->dict); if (!stub) { STACK_UNWIND_STRICT (readdirp, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, entries, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } #if 0 int32_t quiesce_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_writev_stub (frame, default_writev_resume, local->fd, local->vector, local->flag, local->offset, local->io_flags, local->iobref, xdata); if (!stub) { STACK_UNWIND_STRICT (writev, frame, -1, ENOMEM, NULL, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_xattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_xattrop_stub (frame, default_xattrop_resume, &local->loc, local->xattrop_flags, local->dict, xdata); if (!stub) { STACK_UNWIND_STRICT (xattrop, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, dict, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_fxattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_fxattrop_stub (frame, default_fxattrop_resume, local->fd, local->xattrop_flags, local->dict, xdata); if (!stub) { STACK_UNWIND_STRICT (fxattrop, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (fxattrop, frame, op_ret, op_errno, dict, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct gf_flock *lock, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_lk_stub (frame, default_lk_resume, local->fd, local->flag, &local->flock, xdata); if (!stub) { STACK_UNWIND_STRICT (lk, frame, -1, ENOMEM, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (lk, frame, op_ret, op_errno, lock, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_inodelk_stub (frame, default_inodelk_resume, local->volname, &local->loc, local->flag, &local->flock, xdata); if (!stub) { STACK_UNWIND_STRICT (inodelk, frame, -1, ENOMEM, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (inodelk, frame, op_ret, op_errno, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_finodelk_stub (frame, default_finodelk_resume, local->volname, local->fd, local->flag, &local->flock, xdata); if (!stub) { STACK_UNWIND_STRICT (finodelk, frame, -1, ENOMEM, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (finodelk, frame, op_ret, op_errno, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_entrylk_stub (frame, default_entrylk_resume, local->volname, &local->loc, local->name, local->cmd, local->type, xdata); if (!stub) { STACK_UNWIND_STRICT (entrylk, frame, -1, ENOMEM, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (entrylk, frame, op_ret, op_errno, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_fentrylk_stub (frame, default_fentrylk_resume, local->volname, local->fd, local->name, local->cmd, local->type, xdata); if (!stub) { STACK_UNWIND_STRICT (fentrylk, frame, -1, ENOMEM, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (fentrylk, frame, op_ret, op_errno, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *statpre, struct iatt *statpost, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_setattr_stub (frame, default_setattr_resume, &local->loc, &local->stbuf, local->flag, xdata); if (!stub) { STACK_UNWIND_STRICT (setattr, frame, -1, ENOMEM, NULL, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, statpre, statpost, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int32_t quiesce_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *statpre, struct iatt *statpost, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_fsetattr_stub (frame, default_fsetattr_resume, local->fd, &local->stbuf, local->flag, xdata); if (!stub) { STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOMEM, NULL, NULL, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno, statpre, statpost, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } #endif /* if 0 */ /* FOP */ /* No retransmittion */ int32_t quiesce_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_removexattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); return 0; } stub = fop_removexattr_stub (frame, default_removexattr_resume, loc, name, xdata); if (!stub) { STACK_UNWIND_STRICT (removexattr, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_truncate_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); return 0; } stub = fop_truncate_stub (frame, default_truncate_resume, loc, offset, xdata); if (!stub) { STACK_UNWIND_STRICT (truncate, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, int32_t flags, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_fsetxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); return 0; } stub = fop_fsetxattr_stub (frame, default_fsetxattr_resume, fd, dict, flags, xdata); if (!stub) { STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_setxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata); return 0; } stub = fop_setxattr_stub (frame, default_setxattr_resume, loc, dict, flags, xdata); if (!stub) { STACK_UNWIND_STRICT (setxattr, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { /* Don't send O_APPEND below, as write() re-transmittions can fail with O_APPEND */ STACK_WIND (frame, default_create_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->create, loc, (flags & ~O_APPEND), mode, umask, fd, xdata); return 0; } stub = fop_create_stub (frame, default_create_resume, loc, (flags & ~O_APPEND), mode, umask, fd, xdata); if (!stub) { STACK_UNWIND_STRICT (create, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_link_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); return 0; } stub = fop_link_stub (frame, default_link_resume, oldloc, newloc, xdata); if (!stub) { STACK_UNWIND_STRICT (link, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_rename_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata); return 0; } stub = fop_rename_stub (frame, default_rename_resume, oldloc, newloc, xdata); if (!stub) { STACK_UNWIND_STRICT (rename, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int quiesce_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, loc_t *loc, mode_t umask, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_symlink_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->symlink, linkpath, loc, umask, xdata); return 0; } stub = fop_symlink_stub (frame, default_symlink_resume, linkpath, loc, umask, xdata); if (!stub) { STACK_UNWIND_STRICT (symlink, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int quiesce_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_rmdir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->rmdir, loc, flags, xdata); return 0; } stub = fop_rmdir_stub (frame, default_rmdir_resume, loc, flags, xdata); if (!stub) { STACK_UNWIND_STRICT (rmdir, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_unlink_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); return 0; } stub = fop_unlink_stub (frame, default_unlink_resume, loc, xflag, xdata); if (!stub) { STACK_UNWIND_STRICT (unlink, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int quiesce_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_mkdir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata); return 0; } stub = fop_mkdir_stub (frame, default_mkdir_resume, loc, mode, umask, xdata); if (!stub) { STACK_UNWIND_STRICT (mkdir, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int quiesce_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_mknod_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, xdata); return 0; } stub = fop_mknod_stub (frame, default_mknod_resume, loc, mode, rdev, umask, xdata); if (!stub) { STACK_UNWIND_STRICT (mknod, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv->pass_through) { STACK_WIND (frame, default_ftruncate_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); return 0; } stub = fop_ftruncate_stub (frame, default_ftruncate_resume, fd, offset, xdata); if (!stub) { STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } /* Re-transmittion */ int32_t quiesce_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); loc_dup (loc, &local->loc); local->size = size; frame->local = local; STACK_WIND (frame, quiesce_readlink_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readlink, loc, size, xdata); return 0; } stub = fop_readlink_stub (frame, default_readlink_resume, loc, size, xdata); if (!stub) { STACK_UNWIND_STRICT (readlink, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); loc_dup (loc, &local->loc); local->flag = mask; frame->local = local; STACK_WIND (frame, quiesce_access_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->access, loc, mask, xdata); return 0; } stub = fop_access_stub (frame, default_access_resume, loc, mask, xdata); if (!stub) { STACK_UNWIND_STRICT (access, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); if (name) local->name = gf_strdup (name); frame->local = local; STACK_WIND (frame, quiesce_fgetxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fgetxattr, fd, name, xdata); return 0; } stub = fop_fgetxattr_stub (frame, default_fgetxattr_resume, fd, name, xdata); if (!stub) { STACK_UNWIND_STRICT (fgetxattr, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); loc_dup (loc, &local->loc); frame->local = local; STACK_WIND (frame, quiesce_statfs_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->statfs, loc, xdata); return 0; } stub = fop_statfs_stub (frame, default_statfs_resume, loc, xdata); if (!stub) { STACK_UNWIND_STRICT (statfs, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); local->flag = flags; frame->local = local; STACK_WIND (frame, quiesce_fsyncdir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsyncdir, fd, flags, xdata); return 0; } stub = fop_fsyncdir_stub (frame, default_fsyncdir_resume, fd, flags, xdata); if (!stub) { STACK_UNWIND_STRICT (fsyncdir, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); loc_dup (loc, &local->loc); local->fd = fd_ref (fd); frame->local = local; STACK_WIND (frame, quiesce_opendir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->opendir, loc, fd, xdata); return 0; } stub = fop_opendir_stub (frame, default_opendir_resume, loc, fd, xdata); if (!stub) { STACK_UNWIND_STRICT (opendir, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); frame->local = local; STACK_WIND (frame, quiesce_fstat_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fstat, fd, xdata); return 0; } stub = fop_fstat_stub (frame, default_fstat_resume, fd, xdata); if (!stub) { STACK_UNWIND_STRICT (fstat, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); local->flag = flags; frame->local = local; STACK_WIND (frame, quiesce_fsync_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsync, fd, flags, xdata); return 0; } stub = fop_fsync_stub (frame, default_fsync_resume, fd, flags, xdata); if (!stub) { STACK_UNWIND_STRICT (fsync, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); frame->local = local; STACK_WIND (frame, quiesce_flush_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->flush, fd, xdata); return 0; } stub = fop_flush_stub (frame, default_flush_resume, fd, xdata); if (!stub) { STACK_UNWIND_STRICT (flush, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int32_t count, off_t off, uint32_t flags, struct iobref *iobref, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_writev_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, fd, vector, count, off, flags, iobref, xdata); return 0; } stub = fop_writev_stub (frame, default_writev_resume, fd, vector, count, off, flags, iobref, xdata); if (!stub) { STACK_UNWIND_STRICT (writev, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); local->size = size; local->offset = offset; local->io_flag = flags; frame->local = local; STACK_WIND (frame, quiesce_readv_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata); return 0; } stub = fop_readv_stub (frame, default_readv_resume, fd, size, offset, flags, xdata); if (!stub) { STACK_UNWIND_STRICT (readv, frame, -1, ENOMEM, NULL, 0, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, fd_t *fd, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); loc_dup (loc, &local->loc); local->fd = fd_ref (fd); /* Don't send O_APPEND below, as write() re-transmittions can fail with O_APPEND */ local->flag = (flags & ~O_APPEND); frame->local = local; STACK_WIND (frame, quiesce_open_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->open, loc, (flags & ~O_APPEND), fd, xdata); return 0; } stub = fop_open_stub (frame, default_open_resume, loc, (flags & ~O_APPEND), fd, xdata); if (!stub) { STACK_UNWIND_STRICT (open, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); loc_dup (loc, &local->loc); if (name) local->name = gf_strdup (name); frame->local = local; STACK_WIND (frame, quiesce_getxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->getxattr, loc, name, xdata); return 0; } stub = fop_getxattr_stub (frame, default_getxattr_resume, loc, name, xdata); if (!stub) { STACK_UNWIND_STRICT (getxattr, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_xattrop_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->xattrop, loc, flags, dict, xdata); return 0; } stub = fop_xattrop_stub (frame, default_xattrop_resume, loc, flags, dict, xdata); if (!stub) { STACK_UNWIND_STRICT (xattrop, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fxattrop (call_frame_t *frame, xlator_t *this, fd_t *fd, gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_fxattrop_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fxattrop, fd, flags, dict, xdata); return 0; } stub = fop_fxattrop_stub (frame, default_fxattrop_resume, fd, flags, dict, xdata); if (!stub) { STACK_UNWIND_STRICT (fxattrop, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, struct gf_flock *lock, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_lk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lk, fd, cmd, lock, xdata); return 0; } stub = fop_lk_stub (frame, default_lk_resume, fd, cmd, lock, xdata); if (!stub) { STACK_UNWIND_STRICT (lk, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_inodelk (call_frame_t *frame, xlator_t *this, const char *volume, loc_t *loc, int32_t cmd, struct gf_flock *lock, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_inodelk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, volume, loc, cmd, lock, xdata); return 0; } stub = fop_inodelk_stub (frame, default_inodelk_resume, volume, loc, cmd, lock, xdata); if (!stub) { STACK_UNWIND_STRICT (inodelk, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_finodelk (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd, int32_t cmd, struct gf_flock *lock, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_finodelk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->finodelk, volume, fd, cmd, lock, xdata); return 0; } stub = fop_finodelk_stub (frame, default_finodelk_resume, volume, fd, cmd, lock, xdata); if (!stub) { STACK_UNWIND_STRICT (finodelk, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_entrylk (call_frame_t *frame, xlator_t *this, const char *volume, loc_t *loc, const char *basename, entrylk_cmd cmd, entrylk_type type, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_entrylk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->entrylk, volume, loc, basename, cmd, type, xdata); return 0; } stub = fop_entrylk_stub (frame, default_entrylk_resume, volume, loc, basename, cmd, type, xdata); if (!stub) { STACK_UNWIND_STRICT (entrylk, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fentrylk (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd, const char *basename, entrylk_cmd cmd, entrylk_type type, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_fentrylk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fentrylk, volume, fd, basename, cmd, type, xdata); return 0; } stub = fop_fentrylk_stub (frame, default_fentrylk_resume, volume, fd, basename, cmd, type, xdata); if (!stub) { STACK_UNWIND_STRICT (fentrylk, frame, -1, ENOMEM, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_rchecksum (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, int32_t len, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); local->offset = offset; local->flag = len; frame->local = local; STACK_WIND (frame, quiesce_rchecksum_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->rchecksum, fd, offset, len, xdata); return 0; } stub = fop_rchecksum_stub (frame, default_rchecksum_resume, fd, offset, len, xdata); if (!stub) { STACK_UNWIND_STRICT (rchecksum, frame, -1, ENOMEM, 0, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); local->size = size; local->offset = off; frame->local = local; STACK_WIND (frame, quiesce_readdir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdir, fd, size, off, xdata); return 0; } stub = fop_readdir_stub (frame, default_readdir_resume, fd, size, off, xdata); if (!stub) { STACK_UNWIND_STRICT (readdir, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, dict_t *dict) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); local->size = size; local->offset = off; local->dict = dict_ref (dict); frame->local = local; STACK_WIND (frame, quiesce_readdirp_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp, fd, size, off, dict); return 0; } stub = fop_readdirp_stub (frame, default_readdirp_resume, fd, size, off, dict); if (!stub) { STACK_UNWIND_STRICT (readdirp, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf, int32_t valid, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_setattr_cbk, FIRST_CHILD (this), FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid, xdata); return 0; } stub = fop_setattr_stub (frame, default_setattr_resume, loc, stbuf, valid, xdata); if (!stub) { STACK_UNWIND_STRICT (setattr, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); loc_dup (loc, &local->loc); frame->local = local; STACK_WIND (frame, quiesce_stat_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->stat, loc, xdata); return 0; } stub = fop_stat_stub (frame, default_stat_resume, loc, xdata); if (!stub) { STACK_UNWIND_STRICT (stat, frame, -1, ENOMEM, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); loc_dup (loc, &local->loc); local->dict = dict_ref (xattr_req); frame->local = local; STACK_WIND (frame, quiesce_lookup_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, loc, xattr_req); return 0; } stub = fop_lookup_stub (frame, default_lookup_resume, loc, xattr_req); if (!stub) { STACK_UNWIND_STRICT (lookup, frame, -1, ENOMEM, NULL, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf, int32_t valid, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; priv = this->private; if (priv && priv->pass_through) { STACK_WIND (frame, default_fsetattr_cbk, FIRST_CHILD (this), FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid, xdata); return 0; } stub = fop_fsetattr_stub (frame, default_fsetattr_resume, fd, stbuf, valid, xdata); if (!stub) { STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t quiesce_fallocate (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, off_t offset, size_t len, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); local->offset = offset; local->len = len; local->flag = mode; frame->local = local; STACK_WIND (frame, default_fallocate_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fallocate, fd, mode, offset, len, xdata); return 0; } stub = fop_fallocate_stub (frame, default_fallocate_resume, fd, mode, offset, len, xdata); if (!stub) { STACK_UNWIND_STRICT (fallocate, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int quiesce_seek_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, off_t offset, dict_t *xdata) { call_stub_t *stub = NULL; quiesce_local_t *local = NULL; local = frame->local; frame->local = NULL; if ((op_ret == -1) && (op_errno == ENOTCONN)) { /* Re-transmit (by putting in the queue) */ stub = fop_seek_stub (frame, default_seek_resume, local->fd, local->offset, local->what, xdata); if (!stub) { STACK_UNWIND_STRICT (seek, frame, -1, ENOMEM, 0, NULL); goto out; } gf_quiesce_enqueue (this, stub); goto out; } STACK_UNWIND_STRICT (seek, frame, op_ret, op_errno, offset, xdata); out: gf_quiesce_local_wipe (this, local); return 0; } int quiesce_seek (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, gf_seek_what_t what, dict_t *xdata) { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { local = mem_get0 (priv->local_pool); local->fd = fd_ref (fd); local->offset = offset; local->what = what; frame->local = local; STACK_WIND (frame, quiesce_seek_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->seek, fd, offset, what, xdata); return 0; } stub = fop_seek_stub (frame, default_seek_resume, fd, offset, what, xdata); if (!stub) { STACK_UNWIND_STRICT (seek, frame, -1, ENOMEM, 0, NULL); return 0; } gf_quiesce_enqueue (this, stub); return 0; } int32_t mem_acct_init (xlator_t *this) { int ret = -1; ret = xlator_mem_acct_init (this, gf_quiesce_mt_end + 1); return ret; } int reconfigure (xlator_t *this, dict_t *options) { int32_t ret = -1; quiesce_priv_t *priv = NULL; priv = this->private; GF_OPTION_RECONF("timeout", priv->timeout, options, time, out); GF_OPTION_RECONF ("failover-hosts", priv->failover_hosts, options, str, out); gf_quiesce_populate_failover_hosts (this, priv, priv->failover_hosts); ret = 0; out: return ret; } int init (xlator_t *this) { int ret = -1; quiesce_priv_t *priv = NULL; if (!this->children || this->children->next) { gf_log (this->name, GF_LOG_ERROR, "'quiesce' not configured with exactly one child"); goto out; } if (!this->parents) { gf_log (this->name, GF_LOG_WARNING, "dangling volume. check volfile "); } priv = GF_CALLOC (1, sizeof (*priv), gf_quiesce_mt_priv_t); if (!priv) goto out; INIT_LIST_HEAD (&priv->failover_list); GF_OPTION_INIT ("timeout", priv->timeout, time, out); GF_OPTION_INIT ("failover-hosts", priv->failover_hosts, str, out); gf_quiesce_populate_failover_hosts (this, priv, priv->failover_hosts); priv->local_pool = mem_pool_new (quiesce_local_t, GF_FOPS_EXPECTED_IN_PARALLEL); LOCK_INIT (&priv->lock); priv->pass_through = _gf_false; INIT_LIST_HEAD (&priv->req); this->private = priv; ret = 0; out: return ret; } void fini (xlator_t *this) { quiesce_priv_t *priv = NULL; priv = this->private; if (!priv) goto out; this->private = NULL; mem_pool_destroy (priv->local_pool); LOCK_DESTROY (&priv->lock); GF_FREE (priv); out: return; } int notify (xlator_t *this, int event, void *data, ...) { int ret = 0; quiesce_priv_t *priv = NULL; priv = this->private; if (!priv) goto out; switch (event) { case GF_EVENT_CHILD_UP: { ret = gf_thread_create (&priv->thr, NULL, gf_quiesce_dequeue_start, this, "quiesce"); if (ret) { gf_log (this->name, GF_LOG_ERROR, "failed to create the quiesce-dequeue thread"); } LOCK (&priv->lock); { priv->pass_through = _gf_true; } UNLOCK (&priv->lock); break; } case GF_EVENT_CHILD_DOWN: LOCK (&priv->lock); { priv->pass_through = _gf_false; __gf_quiesce_start_timer (this, priv); } UNLOCK (&priv->lock); break; default: break; } ret = default_notify (this, event, data); out: return ret; } struct xlator_fops fops = { /* write/modifying fops */ .mknod = quiesce_mknod, .create = quiesce_create, .truncate = quiesce_truncate, .ftruncate = quiesce_ftruncate, .setxattr = quiesce_setxattr, .removexattr = quiesce_removexattr, .symlink = quiesce_symlink, .unlink = quiesce_unlink, .link = quiesce_link, .mkdir = quiesce_mkdir, .rmdir = quiesce_rmdir, .rename = quiesce_rename, .fallocate = quiesce_fallocate, /* The below calls are known to change state, hence re-transmittion is not advised */ .lk = quiesce_lk, .inodelk = quiesce_inodelk, .finodelk = quiesce_finodelk, .entrylk = quiesce_entrylk, .fentrylk = quiesce_fentrylk, .xattrop = quiesce_xattrop, .fxattrop = quiesce_fxattrop, .setattr = quiesce_setattr, .fsetattr = quiesce_fsetattr, /* Special case, re-transmittion is not harmful * * as offset is properly sent from above layers */ /* TODO: not re-transmitted as of now */ .writev = quiesce_writev, /* re-transmittable fops */ .lookup = quiesce_lookup, .stat = quiesce_stat, .fstat = quiesce_fstat, .access = quiesce_access, .readlink = quiesce_readlink, .getxattr = quiesce_getxattr, .open = quiesce_open, .readv = quiesce_readv, .flush = quiesce_flush, .fsync = quiesce_fsync, .statfs = quiesce_statfs, .opendir = quiesce_opendir, .readdir = quiesce_readdir, .readdirp = quiesce_readdirp, .fsyncdir = quiesce_fsyncdir, .seek = quiesce_seek, }; struct xlator_dumpops dumpops; struct xlator_cbks cbks; struct volume_options options[] = { { .key = {"timeout"}, .type = GF_OPTION_TYPE_TIME, .default_value = "45", .description = "After 'timeout' seconds since the time 'quiesce' " "option was set to \"!pass-through\", acknowledgements to file " "operations are no longer quiesced and previously " "quiesced acknowledgements are sent to the application", .op_version = { GD_OP_VERSION_4_0_0 }, .flags = OPT_FLAG_CLIENT_OPT | OPT_FLAG_SETTABLE | OPT_FLAG_DOC, }, { .key = {"failover-hosts"}, .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST, .op_version = { GD_OP_VERSION_4_0_0 }, .flags = OPT_FLAG_CLIENT_OPT | OPT_FLAG_SETTABLE | OPT_FLAG_DOC, .description = "It is a comma separated list of hostname/IP " "addresses. It Specifies the list of hosts where " "the gfproxy daemons are running, to which the " "the thin clients can failover to." }, { .key = {NULL} }, };