- diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
- index a4e059d..bdd754d 100644
- --- a/daemon/nfs41_ops.c
- +++ b/daemon/nfs41_ops.c
- @@ -908,6 +908,74 @@ out:
- return status;
- }
- +#if 1
- +int nfs42_read_plus(
- + IN nfs41_session *session,
- + IN nfs41_path_fh *file,
- + IN stateid_arg *stateid,
- + IN uint64_t offset,
- + IN uint32_t count,
- + OUT unsigned char *data_out,
- + OUT uint32_t *data_len_out,
- + OUT bool_t *eof_out)
- +{
- + int status;
- + nfs41_compound compound;
- + nfs_argop4 argops[4];
- + nfs_resop4 resops[4];
- + nfs41_sequence_args sequence_args;
- + nfs41_sequence_res sequence_res;
- + nfs41_putfh_args putfh_args;
- + nfs41_putfh_res putfh_res;
- + nfs42_read_plus_args read_plus_args;
- + nfs42_read_plus_res read_plus_res;
- +
- +#if 1 /* debug */
- + (void)memset(&read_plus_args, 0, sizeof(read_plus_args));
- + (void)memset(&read_plus_res, 0, sizeof(read_plus_res));
- +#endif
- +
- + compound_init(&compound, session->client->root->nfsminorvers,
- + argops, resops,
- + stateid->stateid.seqid == 0 ? "ds read_plus" : "read_plus");
- +
- + compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
- + nfs41_session_sequence(&sequence_args, session, 0);
- +
- + compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
- + putfh_args.file = file;
- + putfh_args.in_recovery = 0;
- +
- + compound_add_op(&compound, OP_READ_PLUS, &read_plus_args, &read_plus_res);
- + read_plus_args.stateid = stateid;
- + read_plus_args.offset = offset;
- + read_plus_args.count = count;
- + read_plus_res.resok4.data_len = count;
- + read_plus_res.resok4.data = data_out;
- +
- + status = compound_encode_send_decode(session, &compound, TRUE);
- + if (status)
- + goto out;
- +
- + if (compound_error(status = compound.res.status))
- + goto out;
- +
- + *data_len_out = read_plus_res.resok4.data_len;
- + *eof_out = read_plus_res.resok4.eof;
- +
- + /* we shouldn't ever see this, but a buggy server could
- + * send us into an infinite loop. return NFS4ERR_IO */
- + if (!read_plus_res.resok4.data_len && !read_plus_res.resok4.eof) {
- + status = NFS4ERR_IO;
- + eprintf("READ_PLUS succeeded with len=0 and eof=0; returning '%s'\n",
- + nfs_error_string(status));
- + }
- +out:
- + return status;
- +}
- +#endif
- +
- +
- int nfs41_commit(
- IN nfs41_session *session,
- IN nfs41_path_fh *file,
- diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h
- index 8dc1d7d..b581cd8 100644
- --- a/daemon/nfs41_ops.h
- +++ b/daemon/nfs41_ops.h
- @@ -726,6 +726,57 @@ typedef struct __nfs41_read_res {
- nfs41_read_res_ok resok4;
- } nfs41_read_res;
- +#if 1
- +typedef struct __data4 {
- + uint64_t offset;
- + uint32_t count;
- + uint32_t data_len;
- + unsigned char *data;
- +} data4;
- +
- +typedef struct __data_info4 {
- + uint64_t offset;
- + uint64_t length;
- +} data_info4;
- +
- +typedef enum __data_content4 {
- + NFS4_CONTENT_DATA = 0,
- + NFS4_CONTENT_HOLE = 1
- +} data_content4;
- +
- +/* OP_READ_PLUS */
- +typedef struct __nfs42_read_plus_args {
- + stateid_arg *stateid; /* -> nfs41_op_open_res_ok.stateid */
- + uint64_t offset;
- + uint32_t count;
- +} nfs42_read_plus_args;
- +
- +typedef union __nfs42_read_plus_content {
- + /* switch (data_content4 rpc_content) */
- + data_content4 content;
- + /* case NFS4_CONTENT_DATA: */
- + data4 data;
- + /* case NFS4_CONTENT_HOLE: */
- + data_info4 hole;
- + /* default: */
- +} nfs42_read_plus_content;
- +
- +typedef struct __nfs42_read_plus_res_ok {
- + bool_t eof;
- + uint32_t count;
- + nfs42_read_plus_content *contents;
- +
- + unsigned char *data; /* caller-allocated */
- + uint32_t data_len;
- +} nfs42_read_plus_res_ok;
- +
- +typedef struct __nfs42_read_plus_res {
- + uint32_t status;
- + /* case NFS4_OK: */
- + nfs42_read_plus_res_ok resok4;
- +} nfs42_read_plus_res;
- +
- +#endif
- /* OP_READDIR */
- typedef struct __nfs41_readdir_args {
- @@ -1112,6 +1163,18 @@ int nfs41_read(
- OUT uint32_t *data_len_out,
- OUT bool_t *eof_out);
- +#if 1
- +int nfs42_read_plus(
- + IN nfs41_session *session,
- + IN nfs41_path_fh *file,
- + IN stateid_arg *stateid,
- + IN uint64_t offset,
- + IN uint32_t count,
- + OUT unsigned char *data_out,
- + OUT uint32_t *data_len_out,
- + OUT bool_t *eof_out);
- +#endif
- +
- int nfs41_commit(
- IN nfs41_session *session,
- IN nfs41_path_fh *file,
- diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c
- index f899b7b..1653a9b 100644
- --- a/daemon/nfs41_xdr.c
- +++ b/daemon/nfs41_xdr.c
- @@ -2287,6 +2287,165 @@ static bool_t decode_op_read(
- return TRUE;
- }
- +#if 1
- +/*
- + * OP_READ_PLUS
- + */
- +static bool_t encode_op_read_plus(
- + XDR *xdr,
- + nfs_argop4 *argop)
- +{
- + nfs42_read_plus_args *args = (nfs42_read_plus_args *)argop->arg;
- +
- + if (unexpected_op(argop->op, OP_READ_PLUS))
- + return FALSE;
- +
- + if (!xdr_stateid4(xdr, &args->stateid->stateid))
- + return FALSE;
- +
- + if (!xdr_u_hyper(xdr, &args->offset))
- + return FALSE;
- +
- + return xdr_u_int32_t(xdr, &args->count);
- +}
- +
- +static bool_t decode_read_plus_res_ok(
- + XDR *xdr,
- + nfs42_read_plus_res_ok *res)
- +{
- + unsigned char *data = res->data;
- +
- +// DPRINTF(0, ("decode_read_plus_res_ok: start\n"));
- +
- + if (!xdr_bool(xdr, &res->eof)) {
- + DPRINTF(0, ("decode eof failed\n"));
- + return FALSE;
- + }
- +
- +// DPRINTF(0, ("decode_read_plus_res_ok: #mark1, res->eof=%d\n", (int)res->eof));
- +
- + if (!xdr_u_int32_t(xdr, &res->count)) {
- + DPRINTF(0, ("decode count failed\n"));
- + return FALSE;
- + }
- +
- + /*
- + * Note that |res->count==0| is a valid value for "READ_PLUS"
- + * replies
- + */
- + if (res->count == 0) {
- + res->contents = NULL;
- + res->data_len = 0L;
- + return TRUE;
- + }
- +
- +// DPRINTF(0, ("decode_read_plus_res_ok: #mark2, res->count=%d\n", (int)res->count));
- +
- + /* fixme: Use |malloc()|. Be careful to handle the |res->count == 0| case */
- + res->contents = calloc(res->count, sizeof(nfs42_read_plus_content));
- + if (res->contents == NULL)
- + return FALSE;
- +
- +// DPRINTF(0, ("decode_read_plus_res_ok: #mark3\n"));
- +
- + uint32_t i, co;
- +
- + for (i = 0 ; i < res->count ; i++) {
- + if (!xdr_u_int32_t(xdr, &co)) {
- + DPRINTF(0, ("i=%d, decode co failed\n", (int)i));
- + return FALSE;
- + }
- + res->contents[i].content = co;
- +
- + switch(co) {
- + case NFS4_CONTENT_DATA:
- +// DPRINTF(0, ("i=%d, 'NFS4_CONTENT_DATA' content\n", (int)i));
- + if (!xdr_u_hyper(xdr, &res->contents[i].data.offset)) {
- + DPRINTF(0, ("i=%d, decoding 'offset' failed\n", (int)i));
- + return FALSE;
- + }
- +#if 0
- + DPRINTF(0, ("decode_read_plus_res_ok: data decoded offset=%lld\n",
- + (long long)res->contents[i].data.data_len));
- +
- + res->contents[i].data.data = data;
- + u_int readsize = 0;
- +
- + if (!xdr_bytes(xdr, (char **)&(res->contents[i].data.data), &readsize, NFS41_MAX_FILEIO_SIZE)) {
- + DPRINTF(0, ("i=%d, decoding 'bytes' failed\n", (int)i));
- + return FALSE;
- + }
- + res->contents[i].data.count = res->contents[i].data.data_len = readsize;
- + data += res->contents[i].data.count;
- +#else
- + if (!xdr_u_int32_t(xdr, &res->contents[i].data.count)) {
- + DPRINTF(0, ("i=%d, decoding 'count' failed\n", (int)i));
- + return FALSE;
- + }
- +
- +// DPRINTF(0, ("decode_read_plus_res_ok: data decoded offset=%lld, count=%ld\n",
- +// (long long)res->contents[i].data.data_len,
- +// (long)res->contents[i].data.count));
- +
- + res->contents[i].data.data = data;
- + res->contents[i].data.data_len = res->contents[i].data.count;
- + if (!xdr_opaque(xdr, (char *)res->contents[i].data.data, res->contents[i].data.data_len)) {
- + DPRINTF(0, ("i=%d, decoding 'bytes' failed\n", (int)i));
- + return FALSE;
- + }
- + data += res->contents[i].data.count;
- +#endif
- + break;
- + case NFS4_CONTENT_HOLE:
- + DPRINTF(0, ("i=%d, 'NFS4_CONTENT_HOLE' content\n", (int)i));
- + if (!xdr_u_hyper(xdr, &res->contents[i].hole.offset))
- + return FALSE;
- + if (!xdr_u_hyper(xdr, &res->contents[i].hole.length))
- + return FALSE;
- +
- + /*
- + * fixme: READ_PLUS is required to return the whole hole,
- + * even if it is bigger than the requested size
- + */
- + EASSERT(((data+res->contents[i].hole.length)-res->data) < res->data_len);
- + (void)memset(data, 0, res->contents[i].hole.length);
- + data += res->contents[i].hole.length;
- + default:
- + DPRINTF(0, ("decode_read_plus_res_ok: unknown co=%d\n", (int)co));
- + return FALSE;
- + }
- +
- + EASSERT((data - res->data) <= res->data_len);
- + }
- +
- + EASSERT((data - res->data) < UINT_MAX);
- + res->data_len = (uint32_t)(data - res->data);
- +
- +// DPRINTF(0, ("decode_read_plus_res_ok: SUCCESS\n"));
- + return TRUE;
- +}
- +
- +static bool_t decode_op_read_plus(
- + XDR *xdr,
- + nfs_resop4 *resop)
- +{
- + nfs42_read_plus_res *res = (nfs42_read_plus_res *)resop->res;
- +
- + if (unexpected_op(resop->op, OP_READ_PLUS))
- + return FALSE;
- +
- + if (!xdr_u_int32_t(xdr, &res->status))
- + return FALSE;
- +
- + if (res->status == NFS4_OK)
- + return decode_read_plus_res_ok(xdr, &res->resok4);
- +
- + return TRUE;
- +}
- +
- +#endif
- +
- +
- /*
- * OP_READDIR
- @@ -3638,7 +3797,7 @@ static const op_table_entry g_op_table[] = {
- { NULL, NULL }, /* OP_LAYOUTSTATS = 65, */
- { NULL, NULL }, /* OP_OFFLOAD_CANCEL = 66, */
- { NULL, NULL }, /* OP_OFFLOAD_STATUS = 67, */
- - { NULL, NULL }, /* OP_READ_PLUS = 68, */
- + { encode_op_read_plus, decode_op_read_plus }, /* OP_READ_PLUS = 68, */
- { NULL, NULL }, /* OP_SEEK = 69, */
- { NULL, NULL }, /* OP_WRITE_SAME = 70, */
- { NULL, NULL }, /* OP_CLONE = 71, */
- diff --git a/daemon/readwrite.c b/daemon/readwrite.c
- index 355336a..402db22 100644
- --- a/daemon/readwrite.c
- +++ b/daemon/readwrite.c
- @@ -77,8 +77,13 @@ static int read_from_mds(
- while(to_rcv > 0) {
- uint32_t bytes_read = 0, chunk = min(to_rcv, maxreadsize);
- +#if 1
- + status = nfs42_read_plus(session, file, stateid, args->offset + reloffset, chunk,
- + p, &bytes_read, &eof);
- +#else
- status = nfs41_read(session, file, stateid, args->offset + reloffset, chunk,
- p, &bytes_read, &eof);
- +#endif
- if (status == NFS4ERR_OPENMODE && !len) {
- stateid->type = STATEID_SPECIAL;
- stateid4_cpy(&stateid->stateid, &special_read_stateid);
- diff --git a/daemon/recovery.c b/daemon/recovery.c
- index eee4031..1cb23ea 100644
- --- a/daemon/recovery.c
- +++ b/daemon/recovery.c
- @@ -805,6 +805,11 @@ bool_t nfs41_recover_stateid(
- } else if (argop->op == OP_READ) {
- nfs41_read_args *read = (nfs41_read_args*)argop->arg;
- stateid = read->stateid;
- +#if 1
- + } else if (argop->op == OP_READ_PLUS) {
- + nfs42_read_plus_args *read_plus = (nfs42_read_plus_args *)argop->arg;
- + stateid = read_plus->stateid;
- +#endif
- } else if (argop->op == OP_WRITE) {
- nfs41_write_args *write = (nfs41_write_args*)argop->arg;
- stateid = write->stateid;
ms-nfs42-client READ_PLUS prototype
Posted by Anonymous on Thu 23rd Jan 2025 16:52
raw | new post
modification of post by Anonymous (view diff)
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.