summaryrefslogtreecommitdiffstats
path: root/xlators/protocol/server/src/server-helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/protocol/server/src/server-helpers.c')
-rw-r--r--xlators/protocol/server/src/server-helpers.c649
1 files changed, 409 insertions, 240 deletions
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
index 98894143f..f0b040c74 100644
--- a/xlators/protocol/server/src/server-helpers.c
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -15,8 +15,6 @@
#include "server.h"
#include "server-helpers.h"
-#include "client_t.h"
-#include "lock-table.h"
#include <fnmatch.h>
@@ -76,11 +74,6 @@ server_resolve_wipe (server_resolve_t *resolve)
void
free_state (server_state_t *state)
{
- if (state->client) {
- /* should we gf_client_unref(state->client) here? */
- state->client = NULL;
- }
-
if (state->xprt) {
rpc_transport_unref (state->xprt);
state->xprt = NULL;
@@ -130,170 +123,6 @@ free_state (server_state_t *state)
static int
-server_nop_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, dict_t *xdata)
-{
- int ret = -1;
- server_state_t *state = NULL;
-
- GF_VALIDATE_OR_GOTO ("server", frame, out);
- GF_VALIDATE_OR_GOTO ("server", cookie, out);
- GF_VALIDATE_OR_GOTO ("server", this, out);
-
- state = CALL_STATE(frame);
-
- if (state) {
- gf_client_unref (state->client);
- free_state (state);
- }
-
- STACK_DESTROY (frame->root);
-
- ret = 0;
-out:
- return ret;
-}
-
-
-static int
-do_lock_table_cleanup (xlator_t *this, client_t *client, call_frame_t *frame,
- struct _lock_table *ltable)
-{
- call_frame_t *tmp_frame = NULL;
- xlator_t *bound_xl = NULL;
- struct _locker *locker = NULL, *tmp = NULL;
- char *path = NULL;
- int ret = -1;
- struct gf_flock flock = {0, };
- struct list_head inodelk_lockers, entrylk_lockers;
-
- GF_VALIDATE_OR_GOTO ("server", this, out);
- GF_VALIDATE_OR_GOTO ("server", frame, out);
- GF_VALIDATE_OR_GOTO ("server", ltable, out);
-
- bound_xl = client->bound_xl;
- INIT_LIST_HEAD (&inodelk_lockers);
- INIT_LIST_HEAD (&entrylk_lockers);
-
- list_splice_init (&ltable->inodelk_lockers,
- &inodelk_lockers);
-
- list_splice_init (&ltable->entrylk_lockers, &entrylk_lockers);
- GF_FREE (ltable);
-
- flock.l_type = F_UNLCK;
- flock.l_start = 0;
- flock.l_len = 0;
- list_for_each_entry_safe (locker, tmp, &inodelk_lockers, lockers) {
- tmp_frame = copy_frame (frame);
- if (tmp_frame == NULL) {
- goto out;
- }
- /*
- lock owner = 0 is a special case that tells posix-locks
- to release all locks from this transport
- */
- tmp_frame->root->pid = 0;
- gf_client_ref (client);
- tmp_frame->root->trans = client;
-
- memset (&tmp_frame->root->lk_owner, 0, sizeof (gf_lkowner_t));
-
- if (locker->fd) {
- GF_ASSERT (locker->fd->inode);
-
- ret = inode_path (locker->fd->inode, NULL, &path);
-
- if (ret > 0) {
- gf_log (this->name, GF_LOG_INFO,
- "finodelk released on %s", path);
- GF_FREE (path);
- } else {
-
- gf_log (this->name, GF_LOG_INFO,
- "finodelk released on inode with gfid %s",
- uuid_utoa (locker->fd->inode->gfid));
- }
-
- STACK_WIND (tmp_frame, server_nop_cbk, bound_xl,
- bound_xl->fops->finodelk,
- locker->volume,
- locker->fd, F_SETLK, &flock, NULL);
- fd_unref (locker->fd);
- } else {
- gf_log (this->name, GF_LOG_INFO,
- "inodelk released on %s", locker->loc.path);
-
- STACK_WIND (tmp_frame, server_nop_cbk, bound_xl,
- bound_xl->fops->inodelk,
- locker->volume,
- &(locker->loc), F_SETLK, &flock, NULL);
- loc_wipe (&locker->loc);
- }
-
- GF_FREE (locker->volume);
-
- list_del_init (&locker->lockers);
- GF_FREE (locker);
- }
-
- tmp = NULL;
- locker = NULL;
- list_for_each_entry_safe (locker, tmp, &entrylk_lockers, lockers) {
- tmp_frame = copy_frame (frame);
-
- tmp_frame->root->pid = 0;
- gf_client_ref (client);
- tmp_frame->root->trans = client;
- memset (&tmp_frame->root->lk_owner, 0, sizeof (gf_lkowner_t));
-
- if (locker->fd) {
- GF_ASSERT (locker->fd->inode);
-
- ret = inode_path (locker->fd->inode, NULL, &path);
-
- if (ret > 0) {
- gf_log (this->name, GF_LOG_INFO,
- "fentrylk released on %s", path);
- GF_FREE (path);
- } else {
-
- gf_log (this->name, GF_LOG_INFO,
- "fentrylk released on inode with gfid %s",
- uuid_utoa (locker->fd->inode->gfid));
- }
-
- STACK_WIND (tmp_frame, server_nop_cbk, bound_xl,
- bound_xl->fops->fentrylk,
- locker->volume,
- locker->fd, NULL,
- ENTRYLK_UNLOCK, ENTRYLK_WRLCK, NULL);
- fd_unref (locker->fd);
- } else {
- gf_log (this->name, GF_LOG_INFO,
- "entrylk released on %s", locker->loc.path);
-
- STACK_WIND (tmp_frame, server_nop_cbk, bound_xl,
- bound_xl->fops->entrylk,
- locker->volume,
- &(locker->loc), NULL,
- ENTRYLK_UNLOCK, ENTRYLK_WRLCK, NULL);
- loc_wipe (&locker->loc);
- }
-
- GF_FREE (locker->volume);
-
- list_del_init (&locker->lockers);
- GF_FREE (locker);
- }
- ret = 0;
-
-out:
- return ret;
-}
-
-
-static int
server_connection_cleanup_flush_cbk (call_frame_t *frame, void *cookie,
xlator_t *this, int32_t op_ret,
int32_t op_errno, dict_t *xdata)
@@ -307,7 +136,7 @@ server_connection_cleanup_flush_cbk (call_frame_t *frame, void *cookie,
GF_VALIDATE_OR_GOTO ("server", frame, out);
fd = frame->local;
- client = frame->root->trans;
+ client = frame->root->client;
fd_unref (fd);
frame->local = NULL;
@@ -322,8 +151,7 @@ out:
static int
-do_fd_cleanup (xlator_t *this, client_t* client, call_frame_t *frame,
- fdentry_t *fdentries, int fd_count)
+do_fd_cleanup (xlator_t *this, client_t* client, fdentry_t *fdentries, int fd_count)
{
fd_t *fd = NULL;
int i = 0, ret = -1;
@@ -332,7 +160,6 @@ do_fd_cleanup (xlator_t *this, client_t* client, call_frame_t *frame,
char *path = NULL;
GF_VALIDATE_OR_GOTO ("server", this, out);
- GF_VALIDATE_OR_GOTO ("server", frame, out);
GF_VALIDATE_OR_GOTO ("server", fdentries, out);
bound_xl = client->bound_xl;
@@ -340,7 +167,7 @@ do_fd_cleanup (xlator_t *this, client_t* client, call_frame_t *frame,
fd = fdentries[i].fd;
if (fd != NULL) {
- tmp_frame = copy_frame (frame);
+ tmp_frame = create_frame (this, this->ctx->pool);
if (tmp_frame == NULL) {
goto out;
}
@@ -364,7 +191,6 @@ do_fd_cleanup (xlator_t *this, client_t* client, call_frame_t *frame,
tmp_frame->root->pid = 0;
gf_client_ref (client);
- tmp_frame->root->trans = client;
memset (&tmp_frame->root->lk_owner, 0,
sizeof (gf_lkowner_t));
@@ -382,79 +208,49 @@ out:
}
-static int
-do_connection_cleanup (xlator_t *this, client_t *client,
- struct _lock_table *ltable,
- fdentry_t *fdentries, int fd_count)
-{
- int ret = 0;
- int saved_ret = 0;
- call_frame_t *frame = NULL;
- server_state_t *state = NULL;
-
- GF_VALIDATE_OR_GOTO ("server", this, out);
-
- if (!ltable && !fdentries)
- goto out;
-
- frame = create_frame (this, this->ctx->pool);
- if (frame == NULL) {
- goto out;
- }
-
- if (ltable)
- saved_ret = do_lock_table_cleanup (this, client, frame, ltable);
-
- if (fdentries != NULL) {
- ret = do_fd_cleanup (this, client, frame, fdentries, fd_count);
- }
-
- state = CALL_STATE (frame);
- GF_FREE (state);
-
- STACK_DESTROY (frame->root);
-
- if (saved_ret || ret) {
- ret = -1;
- }
-
-out:
- return ret;
-}
-
int
server_connection_cleanup (xlator_t *this, client_t *client,
int32_t flags)
{
- struct _lock_table *ltable = NULL;
+ server_ctx_t *serv_ctx = NULL;
fdentry_t *fdentries = NULL;
uint32_t fd_count = 0;
+ int cd_ret = 0;
int ret = 0;
GF_VALIDATE_OR_GOTO (this->name, this, out);
GF_VALIDATE_OR_GOTO (this->name, client, out);
GF_VALIDATE_OR_GOTO (this->name, flags, out);
- LOCK (&client->locks_ctx.ltable_lock);
- {
- if (client->locks_ctx.ltable && (flags & INTERNAL_LOCKS)) {
- ltable = client->locks_ctx.ltable;
- client->locks_ctx.ltable = gf_lock_table_new ();
- }
+ serv_ctx = server_ctx_get (client, client->this);
+
+ if (serv_ctx == NULL) {
+ gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed");
+ goto out;
}
- UNLOCK (&client->locks_ctx.ltable_lock);
- LOCK (&client->server_ctx.fdtable_lock);
+ LOCK (&serv_ctx->fdtable_lock);
{
- if (client->server_ctx.fdtable && (flags & POSIX_LOCKS))
- fdentries = gf_fd_fdtable_get_all_fds (client->server_ctx.fdtable,
+ if (serv_ctx->fdtable && (flags & POSIX_LOCKS))
+ fdentries = gf_fd_fdtable_get_all_fds (serv_ctx->fdtable,
&fd_count);
}
- UNLOCK (&client->server_ctx.fdtable_lock);
+ UNLOCK (&serv_ctx->fdtable_lock);
- if (client->bound_xl)
- ret = do_connection_cleanup (this, client, ltable, fdentries,
- fd_count);
+ if (client->bound_xl == NULL)
+ goto out;
+
+ if (flags & INTERNAL_LOCKS) {
+ cd_ret = gf_client_disconnect (client);
+ }
+
+ if (fdentries != NULL)
+ ret = do_fd_cleanup (this, client, fdentries, fd_count);
+ else
+ gf_log (this->name, GF_LOG_INFO, "no fdentries to clean");
+
+ if (cd_ret || ret)
+ ret = -1;
out:
return ret;
@@ -488,11 +284,10 @@ server_alloc_frame (rpcsvc_request_t *req)
state->itable = client->bound_xl->itable;
state->xprt = rpc_transport_ref (req->trans);
- state->client = client;
-
state->resolve.fd_no = -1;
state->resolve2.fd_no = -1;
+ frame->root->client = client;
frame->root->state = state; /* which socket */
frame->root->unique = 0; /* which call */
@@ -524,7 +319,7 @@ get_frame_from_request (rpcsvc_request_t *req)
frame->root->gid = req->gid;
frame->root->pid = req->pid;
gf_client_ref (client);
- frame->root->trans = client;
+ frame->root->client = client;
frame->root->lk_owner = req->lk_owner;
server_decode_groups (frame, req);
@@ -735,8 +530,10 @@ server_print_params (char *str, int size, server_state_t *state)
filled += snprintf (str + filled, size - filled,
"volume=%s,", state->volume);
+/* FIXME
snprintf (str + filled, size - filled,
"bound_xl=%s}", state->client->bound_xl->name);
+*/
out:
return;
}
@@ -1066,6 +863,7 @@ gf_server_check_setxattr_cmd (call_frame_t *frame, dict_t *dict)
gf_boolean_t
server_cancel_grace_timer (xlator_t *this, client_t *client)
{
+ server_ctx_t *serv_ctx = NULL;
gf_timer_t *timer = NULL;
gf_boolean_t cancelled = _gf_false;
@@ -1075,18 +873,389 @@ server_cancel_grace_timer (xlator_t *this, client_t *client)
return cancelled;
}
- LOCK (&client->server_ctx.fdtable_lock);
+ serv_ctx = server_ctx_get (client, client->this);
+
+ if (serv_ctx == NULL) {
+ gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed");
+ goto out;
+ }
+
+ LOCK (&serv_ctx->fdtable_lock);
{
- if (client->server_ctx.grace_timer) {
- timer = client->server_ctx.grace_timer;
- client->server_ctx.grace_timer = NULL;
+ if (serv_ctx->grace_timer) {
+ timer = serv_ctx->grace_timer;
+ serv_ctx->grace_timer = NULL;
}
}
- UNLOCK (&client->server_ctx.fdtable_lock);
+ UNLOCK (&serv_ctx->fdtable_lock);
if (timer) {
gf_timer_call_cancel (this->ctx, timer);
cancelled = _gf_true;
}
+out:
return cancelled;
}
+
+server_ctx_t*
+server_ctx_get (client_t *client, xlator_t *xlator)
+{
+ void *tmp = NULL;
+ server_ctx_t *ctx = NULL;
+
+ client_ctx_get (client, xlator, &tmp);
+
+ ctx = tmp;
+
+ if (ctx != NULL)
+ goto out;
+
+ ctx = GF_CALLOC (1, sizeof (server_ctx_t), gf_server_mt_server_conf_t);
+
+ if (ctx == NULL)
+ goto out;
+
+ /* ctx->lk_version = 0; redundant */
+ ctx->fdtable = gf_fd_fdtable_alloc ();
+
+ if (ctx->fdtable == NULL) {
+ GF_FREE (ctx);
+ ctx = NULL;
+ goto out;
+ }
+
+ LOCK_INIT (&ctx->fdtable_lock);
+
+ if (client_ctx_set (client, xlator, ctx) != 0) {
+ LOCK_DESTROY (&ctx->fdtable_lock);
+ GF_FREE (ctx);
+ ctx = NULL;
+ }
+
+out:
+ return ctx;
+}
+
+int32_t
+gf_barrier_transmit (server_conf_t *conf, gf_barrier_payload_t *payload)
+{
+ gf_barrier_t *barrier = NULL;
+ int32_t ret = -1;
+ client_t *client = NULL;
+ gf_boolean_t lk_heal = _gf_false;
+ call_frame_t *frame = NULL;
+ server_state_t *state = NULL;
+
+ GF_VALIDATE_OR_GOTO ("barrier", conf, out);
+ GF_VALIDATE_OR_GOTO ("barrier", conf->barrier, out);
+ GF_VALIDATE_OR_GOTO ("barrier", payload, out);
+
+ barrier = conf->barrier;
+
+ frame = payload->frame;
+ if (frame) {
+ state = CALL_STATE (frame);
+ frame->local = NULL;
+ client = frame->root->client;
+ }
+ /* currently lk fops are not barrier'ed. This is reflecting code in
+ * server_submit_reply */
+ if (client)
+ lk_heal = ((server_conf_t *) client->this->private)->lk_heal;
+
+ ret = rpcsvc_submit_generic (payload->req, &payload->rsp, 1,
+ payload->payload, payload->payload_count,
+ payload->iobref);
+ iobuf_unref (payload->iob);
+ if (ret == -1) {
+ gf_log_callingfn ("", GF_LOG_ERROR, "Reply submission failed");
+ if (frame && client && !lk_heal) {
+ server_connection_cleanup (frame->this, client,
+ INTERNAL_LOCKS | POSIX_LOCKS);
+ } else {
+ /* TODO: Failure of open(dir), create, inodelk, entrylk
+ or lk fops send failure must be handled specially. */
+ }
+ goto ret;
+ }
+
+ ret = 0;
+ret:
+ if (state) {
+ free_state (state);
+ }
+
+ if (frame) {
+ gf_client_unref (client);
+ STACK_DESTROY (frame->root);
+ }
+
+ if (payload->free_iobref) {
+ iobref_unref (payload->iobref);
+ }
+out:
+ return ret;
+}
+
+gf_barrier_payload_t *
+gf_barrier_dequeue (gf_barrier_t *barrier)
+{
+ gf_barrier_payload_t *payload = NULL;
+
+ if (!barrier || list_empty (&barrier->queue))
+ return NULL;
+
+ payload = list_entry (barrier->queue.next,
+ gf_barrier_payload_t, list);
+ if (payload) {
+ list_del_init (&payload->list);
+ barrier->cur_size--;
+ }
+
+ return payload;
+}
+
+
+void*
+gf_barrier_dequeue_start (void *data)
+{
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ gf_barrier_payload_t *payload = NULL;
+
+ conf = (server_conf_t *)data;
+ if (!conf || !conf->barrier)
+ return NULL;
+ barrier = conf->barrier;
+
+ LOCK (&barrier->lock);
+ {
+ while (barrier->cur_size) {
+ payload = gf_barrier_dequeue (barrier);
+ if (payload) {
+ if (gf_barrier_transmit (conf, payload)) {
+ gf_log ("server", GF_LOG_WARNING,
+ "Failed to transmit");
+ }
+ GF_FREE (payload);
+ }
+ }
+ }
+ UNLOCK (&barrier->lock);
+ return NULL;
+}
+
+void
+gf_barrier_timeout (void *data)
+{
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ gf_boolean_t need_dequeue = _gf_false;
+
+ conf = (server_conf_t *)data;
+ if (!conf || !conf->barrier)
+ goto out;
+ barrier = conf->barrier;
+
+ gf_log ("", GF_LOG_INFO, "barrier timed-out");
+ LOCK (&barrier->lock);
+ {
+ need_dequeue = barrier->on;
+ barrier->on = _gf_false;
+ }
+ UNLOCK (&barrier->lock);
+
+ if (need_dequeue == _gf_true)
+ gf_barrier_dequeue_start (data);
+out:
+ return;
+}
+
+
+int32_t
+gf_barrier_start (xlator_t *this)
+{
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ int32_t ret = -1;
+ struct timespec time = {0,};
+
+ conf = this->private;
+
+ GF_VALIDATE_OR_GOTO ("server", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf->barrier, out);
+
+ barrier = conf->barrier;
+
+ gf_log (this->name, GF_LOG_INFO, "barrier start called");
+ LOCK (&barrier->lock);
+ {
+ /* if barrier is on, reset timer */
+ if (barrier->on == _gf_true) {
+ ret = gf_timer_call_cancel (this->ctx, barrier->timer);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "unset timer, failing barrier start");
+ goto unlock;
+ }
+ }
+
+ barrier->on = _gf_true;
+ time.tv_sec = barrier->time_out;
+ time.tv_nsec = 0;
+
+ barrier->timer = gf_timer_call_after (this->ctx, time,
+ gf_barrier_timeout,
+ (void *)conf);
+ if (!barrier->timer) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set "
+ "timer, failing barrier start");
+ barrier->on = _gf_false;
+ }
+ }
+unlock:
+ UNLOCK (&barrier->lock);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int32_t
+gf_barrier_stop (xlator_t *this)
+{
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ int32_t ret = -1;
+ gf_boolean_t need_dequeue = _gf_false;
+
+ conf = this->private;
+
+ GF_VALIDATE_OR_GOTO ("server", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf->barrier, out);
+
+ barrier = conf->barrier;
+
+ gf_log (this->name, GF_LOG_INFO, "barrier stop called");
+ LOCK (&barrier->lock);
+ {
+ need_dequeue = barrier->on;
+ barrier->on = _gf_false;
+ }
+ UNLOCK (&barrier->lock);
+
+ if (need_dequeue == _gf_true) {
+ gf_timer_call_cancel (this->ctx, barrier->timer);
+ ret = gf_thread_create (&conf->barrier_th, NULL,
+ gf_barrier_dequeue_start,
+ conf);
+ if (ret) {
+ gf_log (this->name, GF_LOG_CRITICAL,
+ "Failed to start un-barriering");
+ goto out;
+ }
+ }
+ ret = 0;
+out:
+ return ret;
+}
+
+int32_t
+gf_barrier_fops_configure (xlator_t *this, gf_barrier_t *barrier, char *str)
+{
+ int32_t ret = -1;
+ char *dup_str = NULL;
+ char *str_tok = NULL;
+ char *save_ptr = NULL;
+ uint64_t fops = 0;
+
+ /* by defaul fsync & flush needs to be barriered */
+
+ fops |= 1 << GFS3_OP_FSYNC;
+ fops |= 1 << GFS3_OP_FLUSH;
+
+ if (!str)
+ goto done;
+
+ dup_str = gf_strdup (str);
+ if (!dup_str)
+ goto done;
+
+ str_tok = strtok_r (dup_str, ",", &save_ptr);
+ if (!str_tok)
+ goto done;
+
+ fops = 0;
+ while (str_tok) {
+ if (!strcmp(str_tok, "writev")) {
+ fops |= ((uint64_t)1 << GFS3_OP_WRITE);
+ } else if (!strcmp(str_tok, "fsync")) {
+ fops |= ((uint64_t)1 << GFS3_OP_FSYNC);
+ } else if (!strcmp(str_tok, "read")) {
+ fops |= ((uint64_t)1 << GFS3_OP_READ);
+ } else if (!strcmp(str_tok, "rename")) {
+ fops |= ((uint64_t)1 << GFS3_OP_RENAME);
+ } else if (!strcmp(str_tok, "flush")) {
+ fops |= ((uint64_t)1 << GFS3_OP_FLUSH);
+ } else if (!strcmp(str_tok, "ftruncate")) {
+ fops |= ((uint64_t)1 << GFS3_OP_FTRUNCATE);
+ } else if (!strcmp(str_tok, "fallocate")) {
+ fops |= ((uint64_t)1 << GFS3_OP_FALLOCATE);
+ } else if (!strcmp(str_tok, "rmdir")) {
+ fops |= ((uint64_t)1 << GFS3_OP_RMDIR);
+ } else {
+ gf_log ("barrier", GF_LOG_ERROR,
+ "Invalid barrier fop %s", str_tok);
+ }
+
+ str_tok = strtok_r (NULL, ",", &save_ptr);
+ }
+done:
+ LOCK (&barrier->lock);
+ {
+ barrier->fops = fops;
+ }
+ UNLOCK (&barrier->lock);
+ ret = 0;
+
+ GF_FREE (dup_str);
+ return ret;
+}
+
+void
+gf_barrier_enqueue (gf_barrier_t *barrier, gf_barrier_payload_t *payload)
+{
+ list_add_tail (&payload->list, &barrier->queue);
+ barrier->cur_size++;
+}
+
+gf_barrier_payload_t *
+gf_barrier_payload (rpcsvc_request_t *req, struct iovec *rsp,
+ call_frame_t *frame, struct iovec *payload_orig,
+ int payloadcount, struct iobref *iobref,
+ struct iobuf *iob, gf_boolean_t free_iobref)
+{
+ gf_barrier_payload_t *payload = NULL;
+
+ if (!rsp)
+ return NULL;
+
+ payload = GF_CALLOC (1, sizeof (*payload),1);
+ if (!payload)
+ return NULL;
+
+ INIT_LIST_HEAD (&payload->list);
+
+ payload->req = req;
+ memcpy (&payload->rsp, rsp, sizeof (struct iovec));
+ payload->frame = frame;
+ payload->payload = payload_orig;
+ payload->payload_count = payloadcount;
+ payload->iobref = iobref;
+ payload->iob = iob;
+ payload->free_iobref = free_iobref;
+
+ return payload;
+}