diff options
Diffstat (limited to 'xlators/protocol/server/src')
-rw-r--r-- | xlators/protocol/server/src/server-common.c | 10 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-common.h | 5 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 8 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-resolve.c | 39 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-rpc-fops_v2.c | 130 | ||||
-rw-r--r-- | xlators/protocol/server/src/server.h | 14 |
6 files changed, 199 insertions, 7 deletions
diff --git a/xlators/protocol/server/src/server-common.c b/xlators/protocol/server/src/server-common.c index 25b36155065..0639ac3feb3 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 2844ee95756..6200415e304 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 c55a422679d..8ad2d8492ed 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 26260a5ee2c..ec768acba44 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 c5a8e482621..16570294f6d 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 2a77aba1f3c..bdf98c96f1c 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; |