summaryrefslogtreecommitdiffstats
path: root/xlators/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/protocol')
-rw-r--r--xlators/protocol/client/src/client-common.c32
-rw-r--r--xlators/protocol/client/src/client-common.h6
-rw-r--r--xlators/protocol/client/src/client-helpers.c28
-rw-r--r--xlators/protocol/client/src/client-rpc-fops_v2.c141
-rw-r--r--xlators/protocol/client/src/client.c36
-rw-r--r--xlators/protocol/client/src/client.h22
-rw-r--r--xlators/protocol/server/src/server-common.c10
-rw-r--r--xlators/protocol/server/src/server-common.h5
-rw-r--r--xlators/protocol/server/src/server-helpers.c8
-rw-r--r--xlators/protocol/server/src/server-resolve.c39
-rw-r--r--xlators/protocol/server/src/server-rpc-fops_v2.c130
-rw-r--r--xlators/protocol/server/src/server.h14
12 files changed, 464 insertions, 7 deletions
diff --git a/xlators/protocol/client/src/client-common.c b/xlators/protocol/client/src/client-common.c
index 7708c82091..64db98d661 100644
--- a/xlators/protocol/client/src/client-common.c
+++ b/xlators/protocol/client/src/client-common.c
@@ -2556,6 +2556,38 @@ out:
}
int
+client_pre_copy_file_range_v2(xlator_t *this, gfx_copy_file_range_req *req,
+ fd_t *fd_in, off64_t off_in, fd_t *fd_out,
+ off64_t off_out, size_t size, int32_t flags,
+ dict_t **xdata)
+{
+ int64_t remote_fd_in = -1;
+ int64_t remote_fd_out = -1;
+ int op_errno = ESTALE;
+
+ CLIENT_GET_REMOTE_FD(this, fd_in, FALLBACK_TO_ANON_FD, remote_fd_in,
+ op_errno, out);
+
+ CLIENT_GET_REMOTE_FD(this, fd_out, FALLBACK_TO_ANON_FD, remote_fd_out,
+ op_errno, out);
+ req->size = size;
+ req->off_in = off_in;
+ req->off_out = off_out;
+ req->fd_in = remote_fd_in;
+ req->fd_out = remote_fd_out;
+ req->flag = flags;
+
+ memcpy(req->gfid1, fd_in->inode->gfid, 16);
+ memcpy(req->gfid2, fd_out->inode->gfid, 16);
+
+ dict_to_xdr(*xdata, &req->xdata);
+
+ return 0;
+out:
+ return -op_errno;
+}
+
+int
client_pre_statfs_v2(xlator_t *this, gfx_statfs_req *req, loc_t *loc,
dict_t *xdata)
{
diff --git a/xlators/protocol/client/src/client-common.h b/xlators/protocol/client/src/client-common.h
index 5214eae128..a2043d8742 100644
--- a/xlators/protocol/client/src/client-common.h
+++ b/xlators/protocol/client/src/client-common.h
@@ -621,4 +621,10 @@ client_post_rename_v2(xlator_t *this, gfx_rename_rsp *rsp, struct iatt *stbuf,
struct iatt *prenewparent, struct iatt *postnewparent,
dict_t **xdata);
+int
+client_pre_copy_file_range_v2(xlator_t *this, gfx_copy_file_range_req *req,
+ fd_t *fd_in, off64_t off_in, fd_t *fd_out,
+ off64_t off_out, size_t size, int32_t flags,
+ dict_t **xdata);
+
#endif /* __CLIENT_COMMON_H__ */
diff --git a/xlators/protocol/client/src/client-helpers.c b/xlators/protocol/client/src/client-helpers.c
index 849fdfca0b..55e87b3c37 100644
--- a/xlators/protocol/client/src/client-helpers.c
+++ b/xlators/protocol/client/src/client-helpers.c
@@ -2459,6 +2459,20 @@ client_handle_fop_requirements_v2(
lease, this, &this_req->compound_req_v2_u.compound_lease_req,
op_errno, out, &args->loc, &args->lease, args->xdata);
break;
+ case GF_FOP_COPY_FILE_RANGE:
+ /*
+ * Not going to handle the copy_file_range fop in compound
+ * operation. This is because, compound operation is going
+ * to be removed. In fact, AFR one of the heavy consumer of
+ * compound operations has stopped using that.
+ * https://github.com/gluster/glusterfs/issues/414
+ * Therefore, sending ENOTSUP error for this fop coming as
+ * comound request. Though, there was no need of handling
+ * "case GF_FOP_COPY_FILE_RANGE" technically, this comment
+ * under the label of GF_FOP_COPY_FILE_RANGE will help in
+ * understanding that this fop does not handle the compund
+ * request and why.
+ */
default:
return ENOTSUP;
}
@@ -2631,6 +2645,14 @@ compound_request_cleanup_v2(gfx_compound_req *req)
case GF_FOP_SEEK:
CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, seek);
break;
+ case GF_FOP_COPY_FILE_RANGE:
+ /*
+ * This fop is not handled in compund operations.
+ * Check the comment added under this fop's section
+ * in the compound_request_cleanup_v2. Therefore
+ * keeping this label only as a placeholder with
+ * a message that, this fop is not handled.
+ */
default:
break;
}
@@ -3004,6 +3026,12 @@ client_process_response_v2(call_frame_t *frame, xlator_t *this,
&this_args_cbk->lease, xdata);
break;
}
+ case GF_FOP_COPY_FILE_RANGE:
+ /*
+ * Not handling this fop. Returning ENOTSUP. Check
+ * the comment added for this fop in the function
+ * client_handle_fop_requirements_v2.
+ */
default:
return -ENOTSUP;
}
diff --git a/xlators/protocol/client/src/client-rpc-fops_v2.c b/xlators/protocol/client/src/client-rpc-fops_v2.c
index ca180c1db4..8f3ee41e5c 100644
--- a/xlators/protocol/client/src/client-rpc-fops_v2.c
+++ b/xlators/protocol/client/src/client-rpc-fops_v2.c
@@ -2833,6 +2833,72 @@ out:
return 0;
}
+int
+client4_0_copy_file_range_cbk(struct rpc_req *req, struct iovec *iov, int count,
+ void *myframe)
+{
+ gfx_common_3iatt_rsp rsp = {
+ 0,
+ };
+ call_frame_t *frame = NULL;
+ struct iatt stbuf = {
+ 0,
+ };
+ struct iatt prestat = {
+ 0,
+ };
+ struct iatt poststat = {
+ 0,
+ };
+ int ret = 0;
+ xlator_t *this = NULL;
+ dict_t *xdata = NULL;
+ clnt_local_t *local = NULL;
+
+ this = THIS;
+
+ frame = myframe;
+ local = frame->local;
+
+ if (-1 == req->rpc_status) {
+ rsp.op_ret = -1;
+ rsp.op_errno = ENOTCONN;
+ goto out;
+ }
+
+ ret = xdr_to_generic(*iov, &rsp, (xdrproc_t)xdr_gfx_common_3iatt_rsp);
+ if (ret < 0) {
+ gf_msg(this->name, GF_LOG_ERROR, EINVAL, PC_MSG_XDR_DECODING_FAILED,
+ "XDR decoding failed");
+ rsp.op_ret = -1;
+ rsp.op_errno = EINVAL;
+ goto out;
+ }
+
+ ret = client_post_common_3iatt(this, &rsp, &stbuf, &prestat, &poststat,
+ &xdata);
+ if (ret < 0)
+ goto out;
+out:
+ if (rsp.op_ret == -1) {
+ gf_msg(this->name, GF_LOG_WARNING, gf_error_to_errno(rsp.op_errno),
+ PC_MSG_REMOTE_OP_FAILED, "remote operation failed");
+ } else if (rsp.op_ret >= 0) {
+ if (local->attempt_reopen)
+ client_attempt_reopen(local->fd, this);
+ if (local->attempt_reopen_out)
+ client_attempt_reopen(local->fd_out, this);
+ }
+ CLIENT_STACK_UNWIND(copy_file_range, frame, rsp.op_ret,
+ gf_error_to_errno(rsp.op_errno), &stbuf, &prestat,
+ &poststat, xdata);
+
+ if (xdata)
+ dict_unref(xdata);
+
+ return 0;
+}
+
int32_t
client4_0_releasedir(call_frame_t *frame, xlator_t *this, void *data)
{
@@ -5846,6 +5912,80 @@ unwind:
}
int32_t
+client4_0_copy_file_range(call_frame_t *frame, xlator_t *this, void *data)
+{
+ clnt_args_t *args = NULL;
+ clnt_conf_t *conf = NULL;
+ clnt_local_t *local = NULL;
+ gfx_copy_file_range_req req = {
+ {
+ 0,
+ },
+ };
+ int op_errno = ESTALE;
+ int ret = 0;
+
+ if (!frame || !this || !data)
+ goto unwind;
+
+ args = data;
+ conf = this->private;
+
+ ret = client_pre_copy_file_range_v2(this, &req, args->fd, args->off_in,
+ args->fd_out, args->off_out, args->size,
+ args->flags, &args->xdata);
+
+ if (ret) {
+ op_errno = -ret;
+ goto unwind;
+ }
+
+ ret = client_fd_fop_prepare_local(frame, args->fd, req.fd_in);
+ if (ret) {
+ op_errno = -ret;
+ goto unwind;
+ }
+
+ /*
+ * Since frame->local is allocated in above function call
+ * itself, better to use it (with the assumption that it
+ * has been allocated) directly instead of again calling
+ * client_fd_fop_prepare_local or modifying it, as doing
+ * so requires changes in other places as well.
+ */
+
+ local = frame->local;
+ local->fd_out = fd_ref(args->fd_out);
+ local->attempt_reopen_out = client_is_reopen_needed(args->fd_out, this,
+ req.fd_out);
+
+ ret = client_submit_request(
+ this, &req, frame, conf->fops, GFS3_OP_COPY_FILE_RANGE,
+ client4_0_copy_file_range_cbk, NULL, NULL, 0, NULL, 0, NULL,
+ (xdrproc_t)xdr_gfx_copy_file_range_req);
+ if (ret) {
+ /*
+ * If the lower layers fail to submit a request, they'll also
+ * do the unwind for us (see rpc_clnt_submit), so don't unwind
+ * here in such cases.
+ */
+ gf_msg(this->name, GF_LOG_WARNING, 0, PC_MSG_FOP_SEND_FAILED,
+ "failed to send the fop");
+ }
+
+ GF_FREE(req.xdata.pairs.pairs_val);
+
+ return 0;
+
+unwind:
+ CLIENT_STACK_UNWIND(copy_file_range, frame, -1, op_errno, NULL, NULL, NULL,
+ NULL);
+ GF_FREE(req.xdata.pairs.pairs_val);
+
+ return 0;
+}
+
+int32_t
client4_0_fsetattr(call_frame_t *frame, xlator_t *this, void *data)
{
clnt_args_t *args = NULL;
@@ -6257,6 +6397,7 @@ rpc_clnt_procedure_t clnt4_0_fop_actors[GF_FOP_MAXVALUE] = {
[GF_FOP_COMPOUND] = {"COMPOUND", client4_0_compound},
[GF_FOP_ICREATE] = {"ICREATE", client4_0_icreate},
[GF_FOP_NAMELINK] = {"NAMELINK", client4_0_namelink},
+ [GF_FOP_COPY_FILE_RANGE] = {"COPY-FILE-RANGE", client4_0_copy_file_range},
};
rpc_clnt_prog_t clnt4_0_fop_prog = {
diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c
index 38723b43b4..c8e84f6e1b 100644
--- a/xlators/protocol/client/src/client.c
+++ b/xlators/protocol/client/src/client.c
@@ -1129,6 +1129,41 @@ out:
return 0;
}
+int32_t
+client_copy_file_range(call_frame_t *frame, xlator_t *this, fd_t *fd_in,
+ off_t off_in, fd_t *fd_out, off_t off_out, size_t len,
+ uint32_t flags, dict_t *xdata)
+{
+ int ret = -1;
+ clnt_conf_t *conf = NULL;
+ rpc_clnt_procedure_t *proc = NULL;
+ clnt_args_t args = {
+ 0,
+ };
+
+ conf = this->private;
+ if (!conf || !conf->fops)
+ goto out;
+
+ args.fd = fd_in;
+ args.fd_out = fd_out;
+ args.offset = off_in;
+ args.off_out = off_out;
+ args.size = len;
+ args.flags = flags;
+ args.xdata = xdata;
+
+ proc = &conf->fops->proctable[GF_FOP_COPY_FILE_RANGE];
+ if (proc->fn)
+ ret = proc->fn(frame, this, &args);
+out:
+ if (ret)
+ STACK_UNWIND_STRICT(copy_file_range, frame, -1, ENOTCONN, NULL, NULL,
+ NULL, NULL);
+
+ return 0;
+}
+
static gf_boolean_t
is_client_rpc_init_command(dict_t *dict, xlator_t *this, char **value)
{
@@ -2898,6 +2933,7 @@ struct xlator_fops fops = {
.icreate = client_icreate,
.namelink = client_namelink,
.put = client_put,
+ .copy_file_range = client_copy_file_range,
};
struct xlator_dumpops dumpops = {
diff --git a/xlators/protocol/client/src/client.h b/xlators/protocol/client/src/client.h
index 5fc75a8462..71f84f3ca8 100644
--- a/xlators/protocol/client/src/client.h
+++ b/xlators/protocol/client/src/client.h
@@ -269,6 +269,7 @@ typedef struct client_local {
loc_t loc;
loc_t loc2;
fd_t *fd;
+ fd_t *fd_out; /* used in copy_file_range */
clnt_fd_ctx_t *fdctx;
uint32_t flags;
struct iobref *iobref;
@@ -280,6 +281,11 @@ typedef struct client_local {
pthread_mutex_t mutex;
char *name;
gf_boolean_t attempt_reopen;
+ /*
+ * The below boolean variable is used
+ * only for copy_file_range fop
+ */
+ gf_boolean_t attempt_reopen_out;
/* required for compound fops */
compound_args_t *compound_args;
unsigned int length; /* length of a compound fop */
@@ -289,7 +295,13 @@ typedef struct client_local {
typedef struct client_args {
loc_t *loc;
+ /*
+ * This is the source fd for copy_file_range and
+ * the default fd for any other fd based fop which
+ * requires only one fd (i.e. opetates on one fd)
+ */
fd_t *fd;
+ fd_t *fd_out; /* this is the destination fd for copy_file_range */
const char *linkname;
struct iobref *iobref;
struct iovec *vector;
@@ -301,7 +313,17 @@ typedef struct client_args {
struct gf_flock *flock;
const char *volume;
const char *basename;
+
off_t offset;
+ /*
+ * According to the man page of copy_file_range,
+ * the offsets for source and destination file
+ * are of type loff_t. But the type loff_t is
+ * linux specific and is actual a typedef of
+ * off64_t.
+ */
+ off64_t off_in; /* used in copy_file_range for source fd */
+ off64_t off_out; /* used in copy_file_range for dst fd */
int32_t mask;
int32_t cmd;
size_t size;
diff --git a/xlators/protocol/server/src/server-common.c b/xlators/protocol/server/src/server-common.c
index 25b3615506..0639ac3feb 100644
--- a/xlators/protocol/server/src/server-common.c
+++ b/xlators/protocol/server/src/server-common.c
@@ -541,6 +541,16 @@ server4_post_common_3iatt(server_state_t *state, gfx_common_3iatt_rsp *rsp,
}
void
+server4_post_common_3iatt_noinode(gfx_common_3iatt_rsp *rsp, struct iatt *stbuf,
+ struct iatt *prebuf_dst,
+ struct iatt *postbuf_dst)
+{
+ gfx_stat_from_iattx(&rsp->stat, stbuf);
+ gfx_stat_from_iattx(&rsp->preparent, prebuf_dst);
+ gfx_stat_from_iattx(&rsp->postparent, postbuf_dst);
+}
+
+void
server4_post_common_2iatt(gfx_common_2iatt_rsp *rsp, struct iatt *prebuf,
struct iatt *postbuf)
{
diff --git a/xlators/protocol/server/src/server-common.h b/xlators/protocol/server/src/server-common.h
index 2844ee9575..6200415e30 100644
--- a/xlators/protocol/server/src/server-common.h
+++ b/xlators/protocol/server/src/server-common.h
@@ -192,3 +192,8 @@ void
server4_post_link(server_state_t *state, gfx_common_3iatt_rsp *rsp,
inode_t *inode, struct iatt *stbuf, struct iatt *pre,
struct iatt *post);
+
+void
+server4_post_common_3iatt_noinode(gfx_common_3iatt_rsp *rsp, struct iatt *stbuf,
+ struct iatt *prebuf_dst,
+ struct iatt *postbuf_dst);
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
index c55a422679..8ad2d8492e 100644
--- a/xlators/protocol/server/src/server-helpers.c
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -4948,6 +4948,8 @@ server_populate_compound_response_v2(xlator_t *this, gfx_compound_rsp *rsp,
rsp_args->op_errno = gf_errno_to_error(this_args_cbk->op_errno);
break;
}
+ case GF_FOP_COPY_FILE_RANGE:
+ /* Not handling this fop. */
default:
return ENOTSUP;
}
@@ -5380,6 +5382,12 @@ server_get_compound_resolve_v2(server_state_t *state, gfx_compound_req *req)
memcpy(state->resolve.gfid, this_req.gfid, 16);
break;
}
+ case GF_FOP_COPY_FILE_RANGE:
+ /*
+ * Compound operations is not being used anymore and
+ * planned for subsequent removal. Hence not handling
+ * this fop here.
+ */
default:
return ENOTSUP;
}
diff --git a/xlators/protocol/server/src/server-resolve.c b/xlators/protocol/server/src/server-resolve.c
index 26260a5ee2..ec768acba4 100644
--- a/xlators/protocol/server/src/server-resolve.c
+++ b/xlators/protocol/server/src/server-resolve.c
@@ -545,14 +545,39 @@ server_resolve_fd(call_frame_t *frame)
return 0;
}
- state->fd = gf_fd_fdptr_get(serv_ctx->fdtable, fd_no);
-
+ /*
+ * With copy_file_range, there will be 2 fds to resolve.
+ * This same function is called to resolve both the source
+ * fd and the destination fd. As of now, this function does
+ * not have any mechanism to distinguish between the 2 fds
+ * being resolved except for checking the value of state->fd.
+ * The assumption is that, if source fd the one which is
+ * being resolved here, then state->fd would be NULL. If it
+ * is not NULL, then it is the destination fd which is being
+ * resolved.
+ * This method (provided the above assumption is true) is
+ * to achieve the ability to distinguish between 2 fds with
+ * minimum changes being done to this function. If this way
+ * is not correct, then more changes might be needed.
+ */
if (!state->fd) {
- gf_msg("", GF_LOG_INFO, EBADF, PS_MSG_FD_NOT_FOUND,
- "fd not "
- "found in context");
- resolve->op_ret = -1;
- resolve->op_errno = EBADF;
+ state->fd = gf_fd_fdptr_get(serv_ctx->fdtable, fd_no);
+ if (!state->fd) {
+ gf_msg("", GF_LOG_INFO, EBADF, PS_MSG_FD_NOT_FOUND,
+ "fd not "
+ "found in context");
+ resolve->op_ret = -1;
+ resolve->op_errno = EBADF;
+ }
+ } else {
+ state->fd_out = gf_fd_fdptr_get(serv_ctx->fdtable, fd_no);
+ if (!state->fd_out) {
+ gf_msg("", GF_LOG_INFO, EBADF, PS_MSG_FD_NOT_FOUND,
+ "fd not "
+ "found in context");
+ resolve->op_ret = -1;
+ resolve->op_errno = EBADF;
+ }
}
server_resolve_all(frame);
diff --git a/xlators/protocol/server/src/server-rpc-fops_v2.c b/xlators/protocol/server/src/server-rpc-fops_v2.c
index c5a8e48262..16570294f6 100644
--- a/xlators/protocol/server/src/server-rpc-fops_v2.c
+++ b/xlators/protocol/server/src/server-rpc-fops_v2.c
@@ -2259,6 +2259,64 @@ out:
return 0;
}
+int
+server4_copy_file_range_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno,
+ struct iatt *stbuf, struct iatt *prebuf_dst,
+ struct iatt *postbuf_dst, dict_t *xdata)
+{
+ gfx_common_3iatt_rsp rsp = {
+ 0,
+ };
+ server_state_t *state = NULL;
+ rpcsvc_request_t *req = NULL;
+ char in_gfid[GF_UUID_BUF_SIZE] = {0};
+ char out_gfid[GF_UUID_BUF_SIZE] = {0};
+
+ dict_to_xdr(xdata, &rsp.xdata);
+
+ if (op_ret < 0) {
+ state = CALL_STATE(frame);
+
+ uuid_utoa_r(state->resolve.gfid, in_gfid);
+ uuid_utoa_r(state->resolve2.gfid, out_gfid);
+
+ gf_msg(this->name, fop_log_level(GF_FOP_COPY_FILE_RANGE, op_errno),
+ op_errno, PS_MSG_WRITE_INFO,
+ "%" PRId64 ": COPY_FILE_RANGE %" PRId64 " (%s), %" PRId64
+ " (%s) client: %s, "
+ "error-xlator: %s",
+ frame->root->unique, state->resolve.fd_no, in_gfid,
+ state->resolve2.fd_no, out_gfid, STACK_CLIENT_NAME(frame->root),
+ STACK_ERR_XL_NAME(frame->root));
+ goto out;
+ }
+
+ /*
+ * server4_post_common_3iatt (ex: used by server4_put_cbk and some
+ * other cbks) also performs inode linking along with copying of 3
+ * iatt structures to the response. But, for copy_file_range, linking
+ * of inode is not needed. Therefore a new function is used to
+ * construct the response using 3 iatt structures.
+ * @stbuf: iatt or stat of the source file (or fd)
+ * @prebuf_dst: iatt or stat of destination file (or fd) before the fop
+ * @postbuf_dst: iatt or stat of destination file (or fd) after the fop
+ */
+ server4_post_common_3iatt_noinode(&rsp, stbuf, prebuf_dst, postbuf_dst);
+
+out:
+ rsp.op_ret = op_ret;
+ rsp.op_errno = gf_errno_to_error(op_errno);
+
+ req = frame->local;
+ server_submit_reply(frame, req, &rsp, NULL, 0, NULL,
+ (xdrproc_t)xdr_gfx_common_3iatt_rsp);
+
+ GF_FREE(rsp.xdata.pairs.pairs_val);
+
+ return 0;
+}
+
/* Resume function section */
int
@@ -3448,6 +3506,29 @@ err:
}
int
+server4_copy_file_range_resume(call_frame_t *frame, xlator_t *bound_xl)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state->resolve.op_ret != 0)
+ goto err;
+
+ STACK_WIND(frame, server4_copy_file_range_cbk, bound_xl,
+ bound_xl->fops->copy_file_range, state->fd, state->off_in,
+ state->fd_out, state->off_out, state->size, state->flags,
+ state->xdata);
+
+ return 0;
+err:
+ server4_copy_file_range_cbk(frame, NULL, frame->this, state->resolve.op_ret,
+ state->resolve.op_errno, NULL, NULL, NULL,
+ NULL);
+ return 0;
+}
+
+int
server4_0_stat(rpcsvc_request_t *req)
{
server_state_t *state = NULL;
@@ -6104,6 +6185,53 @@ out:
return ret;
}
+int
+server4_0_copy_file_range(rpcsvc_request_t *req)
+{
+ server_state_t *state = NULL;
+ call_frame_t *frame = NULL;
+ gfx_copy_file_range_req args = {
+ {
+ 0,
+ },
+ };
+ ssize_t len = 0;
+ int ret = -1;
+ int op_errno = 0;
+
+ if (!req)
+ return ret;
+
+ ret = rpc_receive_common(req, &frame, &state, &len, &args,
+ xdr_gfx_copy_file_range_req,
+ GF_FOP_COPY_FILE_RANGE);
+ if (ret != 0) {
+ goto out;
+ }
+
+ state->resolve.type = RESOLVE_MUST;
+ state->resolve.fd_no = args.fd_in;
+ state->resolve2.type = RESOLVE_MUST; /*making this resolve must */
+ state->resolve2.fd_no = args.fd_out;
+ state->off_in = args.off_in;
+ state->off_out = args.off_out;
+ state->size = args.size;
+ state->flags = args.flag;
+ memcpy(state->resolve.gfid, args.gfid1, 16);
+ memcpy(state->resolve2.gfid, args.gfid2, 16);
+
+ xdr_to_dict(&args.xdata, &state->xdata);
+
+ ret = 0;
+ resolve_and_resume(frame, server4_copy_file_range_resume);
+out:
+
+ if (op_errno)
+ SERVER_REQ_SET_ERROR(req, ret);
+
+ return ret;
+}
+
rpcsvc_actor_t glusterfs4_0_fop_actors[] = {
[GFS3_OP_NULL] = {"NULL", GFS3_OP_NULL, server_null, NULL, 0},
[GFS3_OP_STAT] = {"STAT", GFS3_OP_STAT, server4_0_stat, NULL, 0},
@@ -6195,6 +6323,8 @@ rpcsvc_actor_t glusterfs4_0_fop_actors[] = {
DRC_NA},
[GFS3_OP_NAMELINK] = {"NAMELINK", GFS3_OP_NAMELINK, server4_0_namelink,
NULL, 0, DRC_NA},
+ [GFS3_OP_COPY_FILE_RANGE] = {"COPY-FILE-RANGE", GFS3_OP_COPY_FILE_RANGE,
+ server4_0_copy_file_range, NULL, 0, DRC_NA},
};
struct rpcsvc_program glusterfs4_0_fop_prog = {
diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h
index 2a77aba1f3..bdf98c96f1 100644
--- a/xlators/protocol/server/src/server.h
+++ b/xlators/protocol/server/src/server.h
@@ -180,7 +180,12 @@ struct _server_state {
struct iatt stbuf;
int valid;
+ /*
+ * this fd is used in all the fd based operations PLUS
+ * as a source fd in copy_file_range
+ */
fd_t *fd;
+ fd_t *fd_out; /* destination fd in copy_file_range */
dict_t *params;
int32_t flags;
int wbflags;
@@ -191,6 +196,15 @@ struct _server_state {
size_t size;
off_t offset;
+ /*
+ * According to the man page of copy_file_range,
+ * the offsets for source and destination file
+ * are of type loff_t. But the type loff_t is
+ * linux specific and is actual a typedef of
+ * off64_t.
+ */
+ off64_t off_in; /* source offset in copy_file_range */
+ off64_t off_out; /* destination offset in copy_file_range */
mode_t mode;
dev_t dev;
size_t nr_count;