pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


ms-nfs42-client READ_PLUS 10min hacked prototype
Posted by Anonymous on Thu 23rd Jan 2025 14:31
raw | new post
view followups (newest first): ms-nfs42-client READ_PLUS prototype by Anonymous

  1. #
  2. # ms-nfs42-client READ_PLUS 10min hacked prototype
  3. #
  4. # Does NOT work, it goes "BOOM" here:
  5. # 2538/impersonated_user='roland_mainz'/'Kein' decode_read_plus_res_ok: start
  6. # 2538/impersonated_user='roland_mainz'/'Kein' decode_read_plus_res_ok: #mark1, res->eof=1
  7. # 2538/impersonated_user='roland_mainz'/'Kein' decode_read_plus_res_ok: #mark2, res->count=1
  8. # 2538/impersonated_user='roland_mainz'/'Kein' decode_read_plus_res_ok: #mark3
  9. # 2538: clnt_call returned rpc_status = 'RPC_CANTDECODERES'
  10. # 2538: UNHANDLED RPC_ERROR: 2
  11. # 2538: nfs41_send_compound failed 1231 for seqid=19, slotid=0
  12. # 2538/impersonated_user='roland_mainz'/'Kein' i=0, data content
  13. # 2538/impersonated_user='roland_mainz'/'Kein' decode_read_plus_res_ok: data decoded offset=0, count=210
  14. #
  15.  
  16. diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
  17. index a4e059d..bdd754d 100644
  18. --- a/daemon/nfs41_ops.c
  19. +++ b/daemon/nfs41_ops.c
  20. @@ -908,6 +908,74 @@ out:
  21.      return status;
  22.  }
  23.  
  24. +#if 1
  25. +int nfs42_read_plus(
  26. +    IN nfs41_session *session,
  27. +    IN nfs41_path_fh *file,
  28. +    IN stateid_arg *stateid,
  29. +    IN uint64_t offset,
  30. +    IN uint32_t count,
  31. +    OUT unsigned char *data_out,
  32. +    OUT uint32_t *data_len_out,
  33. +    OUT bool_t *eof_out)
  34. +{
  35. +    int status;
  36. +    nfs41_compound compound;
  37. +    nfs_argop4 argops[4];
  38. +    nfs_resop4 resops[4];
  39. +    nfs41_sequence_args sequence_args;
  40. +    nfs41_sequence_res sequence_res;
  41. +    nfs41_putfh_args putfh_args;
  42. +    nfs41_putfh_res putfh_res;
  43. +    nfs42_read_plus_args read_plus_args;
  44. +    nfs42_read_plus_res read_plus_res;
  45. +
  46. +#if 1 /* debug */
  47. +    (void)memset(&read_plus_args, 0, sizeof(read_plus_args));
  48. +    (void)memset(&read_plus_res, 0, sizeof(read_plus_res));
  49. +#endif
  50. +
  51. +    compound_init(&compound, session->client->root->nfsminorvers,
  52. +        argops, resops,
  53. +        stateid->stateid.seqid == 0 ? "ds read_plus" : "read_plus");
  54. +
  55. +    compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
  56. +    nfs41_session_sequence(&sequence_args, session, 0);
  57. +
  58. +    compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
  59. +    putfh_args.file = file;
  60. +    putfh_args.in_recovery = 0;
  61. +
  62. +    compound_add_op(&compound, OP_READ_PLUS, &read_plus_args, &read_plus_res);
  63. +    read_plus_args.stateid = stateid;
  64. +    read_plus_args.offset = offset;
  65. +    read_plus_args.count = count;
  66. +    read_plus_res.resok4.data_len = count;
  67. +    read_plus_res.resok4.data = data_out;
  68. +
  69. +    status = compound_encode_send_decode(session, &compound, TRUE);
  70. +    if (status)
  71. +        goto out;
  72. +
  73. +    if (compound_error(status = compound.res.status))
  74. +        goto out;
  75. +
  76. +    *data_len_out = read_plus_res.resok4.data_len;
  77. +    *eof_out = read_plus_res.resok4.eof;
  78. +
  79. +    /* we shouldn't ever see this, but a buggy server could
  80. +     * send us into an infinite loop. return NFS4ERR_IO */
  81. +    if (!read_plus_res.resok4.data_len && !read_plus_res.resok4.eof) {
  82. +        status = NFS4ERR_IO;
  83. +        eprintf("READ_PLUS succeeded with len=0 and eof=0; returning '%s'\n",
  84. +            nfs_error_string(status));
  85. +    }
  86. +out:
  87. +    return status;
  88. +}
  89. +#endif
  90. +
  91. +
  92.  int nfs41_commit(
  93.      IN nfs41_session *session,
  94.      IN nfs41_path_fh *file,
  95. diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h
  96. index 8dc1d7d..b581cd8 100644
  97. --- a/daemon/nfs41_ops.h
  98. +++ b/daemon/nfs41_ops.h
  99. @@ -726,6 +726,57 @@ typedef struct __nfs41_read_res {
  100.      nfs41_read_res_ok       resok4;
  101.  } nfs41_read_res;
  102.  
  103. +#if 1
  104. +typedef struct __data4 {
  105. +    uint64_t        offset;
  106. +    uint32_t        count;
  107. +    uint32_t        data_len;
  108. +    unsigned char   *data;
  109. +} data4;
  110. +
  111. +typedef struct __data_info4 {
  112. +    uint64_t offset;
  113. +    uint64_t length;
  114. +} data_info4;
  115. +
  116. +typedef enum __data_content4 {
  117. +    NFS4_CONTENT_DATA = 0,
  118. +    NFS4_CONTENT_HOLE = 1
  119. +} data_content4;
  120. +
  121. +/* OP_READ_PLUS */
  122. +typedef struct __nfs42_read_plus_args {
  123. +    stateid_arg     *stateid; /* -> nfs41_op_open_res_ok.stateid */
  124. +    uint64_t        offset;
  125. +    uint32_t        count;
  126. +} nfs42_read_plus_args;
  127. +
  128. +typedef union __nfs42_read_plus_content {
  129. +    /* switch (data_content4 rpc_content) */
  130. +    data_content4   content;
  131. +    /* case NFS4_CONTENT_DATA: */
  132. +    data4           data;
  133. +    /* case NFS4_CONTENT_HOLE: */
  134. +    data_info4      hole;
  135. +    /* default: */
  136. +} nfs42_read_plus_content;
  137. +
  138. +typedef struct __nfs42_read_plus_res_ok {
  139. +    bool_t                  eof;
  140. +    uint32_t                count;
  141. +    nfs42_read_plus_content *contents;
  142. +
  143. +    unsigned char           *data; /* caller-allocated */
  144. +    uint32_t                data_len;
  145. +} nfs42_read_plus_res_ok;
  146. +
  147. +typedef struct __nfs42_read_plus_res {
  148. +    uint32_t                status;
  149. +    /* case NFS4_OK: */
  150. +    nfs42_read_plus_res_ok  resok4;
  151. +} nfs42_read_plus_res;
  152. +
  153. +#endif
  154.  
  155.  /* OP_READDIR */
  156.  typedef struct __nfs41_readdir_args {
  157. @@ -1112,6 +1163,18 @@ int nfs41_read(
  158.      OUT uint32_t *data_len_out,
  159.      OUT bool_t *eof_out);
  160.  
  161. +#if 1
  162. +int nfs42_read_plus(
  163. +    IN nfs41_session *session,
  164. +    IN nfs41_path_fh *file,
  165. +    IN stateid_arg *stateid,
  166. +    IN uint64_t offset,
  167. +    IN uint32_t count,
  168. +    OUT unsigned char *data_out,
  169. +    OUT uint32_t *data_len_out,
  170. +    OUT bool_t *eof_out);
  171. +#endif
  172. +
  173.  int nfs41_commit(
  174.      IN nfs41_session *session,
  175.      IN nfs41_path_fh *file,
  176. diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c
  177. index f899b7b..b9e8cab 100644
  178. --- a/daemon/nfs41_xdr.c
  179. +++ b/daemon/nfs41_xdr.c
  180. @@ -2287,6 +2287,143 @@ static bool_t decode_op_read(
  181.      return TRUE;
  182.  }
  183.  
  184. +#if 1
  185. +/*
  186. + * OP_READ_PLUS
  187. + */
  188. +static bool_t encode_op_read_plus(
  189. +    XDR *xdr,
  190. +    nfs_argop4 *argop)
  191. +{
  192. +    nfs42_read_plus_args *args = (nfs42_read_plus_args *)argop->arg;
  193. +
  194. +    if (unexpected_op(argop->op, OP_READ_PLUS))
  195. +        return FALSE;
  196. +
  197. +    if (!xdr_stateid4(xdr, &args->stateid->stateid))
  198. +        return FALSE;
  199. +
  200. +    if (!xdr_u_hyper(xdr, &args->offset))
  201. +        return FALSE;
  202. +
  203. +    return xdr_u_int32_t(xdr, &args->count);
  204. +}
  205. +
  206. +static bool_t decode_read_plus_res_ok(
  207. +    XDR *xdr,
  208. +    nfs42_read_plus_res_ok *res)
  209. +{
  210. +    unsigned char *data = res->data;
  211. +
  212. +    DPRINTF(0, ("decode_read_plus_res_ok: start\n"));
  213. +
  214. +    if (!xdr_bool(xdr, &res->eof)) {
  215. +        DPRINTF(0, ("decode eof failed\n"));
  216. +        return FALSE;
  217. +    }
  218. +
  219. +    DPRINTF(0, ("decode_read_plus_res_ok: #mark1, res->eof=%d\n", (int)res->eof));
  220. +
  221. +    if (!xdr_u_int32_t(xdr, &res->count)) {
  222. +        DPRINTF(0, ("decode count failed\n"));
  223. +        return FALSE;
  224. +    }
  225. +
  226. +    DPRINTF(0, ("decode_read_plus_res_ok: #mark2, res->count=%d\n", (int)res->count));
  227. +
  228. +    /* fixme: Use |malloc()| */
  229. +    res->contents = calloc(res->count, sizeof(nfs42_read_plus_content));
  230. +    if (res->contents == NULL)
  231. +        return FALSE;
  232. +
  233. +    DPRINTF(0, ("decode_read_plus_res_ok: #mark3\n"));
  234. +
  235. +    uint32_t i, co;
  236. +
  237. +    EASSERT(res->count > 0);
  238. +
  239. +    for (i = 0 ; i < res->count ; i++) {
  240. +        if (!xdr_u_int32_t(xdr, &co)) {
  241. +            DPRINTF(0, ("i=%d, decode co failed\n", (int)i));
  242. +            return FALSE;
  243. +        }
  244. +        res->contents[i].content = co;
  245. +
  246. +        switch(co) {
  247. +            case NFS4_CONTENT_DATA:
  248. +                DPRINTF(0, ("i=%d, data content\n", (int)i));
  249. +                if (!xdr_u_hyper(xdr, &res->contents[i].data.offset)) {
  250. +                    DPRINTF(0, ("i=%d, decode data offset failed\n", (int)i));
  251. +                    return FALSE;
  252. +                }
  253. +                if (!xdr_u_int32_t(xdr, &res->contents[i].data.count)) {
  254. +                    DPRINTF(0, ("i=%d, decode data count failed\n", (int)i));
  255. +                    return FALSE;
  256. +                }
  257. +
  258. +                DPRINTF(0, ("decode_read_plus_res_ok: data decoded offset=%lld, count=%ld\n",
  259. +                    (long long)res->contents[i].data.data_len,
  260. +                    (long)res->contents[i].data.count));
  261. +
  262. +                res->contents[i].data.data = data;
  263. +                res->contents[i].data.data_len = res->contents[i].data.count;
  264. +                if (!xdr_bytes(xdr, (char **)&(res->contents[i].data.data), &(res->contents[i].data.data_len), NFS41_MAX_FILEIO_SIZE)) {
  265. +                    DPRINTF(0, ("i=%d, decode data bytes failed\n", (int)i));
  266. +                    return FALSE;
  267. +                }
  268. +                EASSERT(res->contents[i].data.data_len == res->contents[i].data.count);
  269. +                data += res->contents[i].data.count;
  270. +                break;
  271. +            case NFS4_CONTENT_HOLE:
  272. +                DPRINTF(0, ("i=%d, hole content\n", (int)i));
  273. +                if (!xdr_u_hyper(xdr, &res->contents[i].hole.offset))
  274. +                    return FALSE;
  275. +                if (!xdr_u_hyper(xdr, &res->contents[i].hole.length))
  276. +                    return FALSE;
  277. +
  278. +                /*
  279. +                 * fixme: READ_PLUS is required to return the whole hole,
  280. +                 * even if it is bigger than the requested size
  281. +                 */
  282. +                EASSERT(((data+res->contents[i].hole.length)-res->data) < res->data_len);
  283. +                (void)memset(data, 0, res->contents[i].hole.length);
  284. +                data += res->contents[i].hole.length;
  285. +            default:
  286. +                DPRINTF(0, ("decode_read_plus_res_ok: unknown co=%d\n", (int)co));
  287. +                return FALSE;
  288. +        }
  289. +
  290. +        EASSERT((data - res->data) > res->data_len);
  291. +    }
  292. +
  293. +    EASSERT((data - res->data) < UINT_MAX);
  294. +    res->data_len = (uint32_t)(data - res->data);
  295. +
  296. +    DPRINTF(0, ("decode_read_plus_res_ok: SUCCESS\n"));
  297. +    return TRUE;
  298. +}
  299. +
  300. +static bool_t decode_op_read_plus(
  301. +    XDR *xdr,
  302. +    nfs_resop4 *resop)
  303. +{
  304. +    nfs42_read_plus_res *res = (nfs42_read_plus_res *)resop->res;
  305. +
  306. +    if (unexpected_op(resop->op, OP_READ_PLUS))
  307. +        return FALSE;
  308. +
  309. +    if (!xdr_u_int32_t(xdr, &res->status))
  310. +        return FALSE;
  311. +
  312. +    if (res->status == NFS4_OK)
  313. +        return decode_read_plus_res_ok(xdr, &res->resok4);
  314. +
  315. +    return TRUE;
  316. +}
  317. +
  318. +#endif
  319. +
  320. +
  321.  
  322.  /*
  323.   * OP_READDIR
  324. @@ -3638,7 +3775,7 @@ static const op_table_entry g_op_table[] = {
  325.      { NULL, NULL }, /* OP_LAYOUTSTATS = 65, */
  326.      { NULL, NULL }, /* OP_OFFLOAD_CANCEL = 66, */
  327.      { NULL, NULL }, /* OP_OFFLOAD_STATUS = 67, */
  328. -    { NULL, NULL }, /* OP_READ_PLUS = 68, */
  329. +    { encode_op_read_plus, decode_op_read_plus }, /* OP_READ_PLUS = 68, */
  330.      { NULL, NULL }, /* OP_SEEK = 69, */
  331.      { NULL, NULL }, /* OP_WRITE_SAME = 70, */
  332.      { NULL, NULL }, /* OP_CLONE = 71, */
  333. diff --git a/daemon/readwrite.c b/daemon/readwrite.c
  334. index 355336a..402db22 100644
  335. --- a/daemon/readwrite.c
  336. +++ b/daemon/readwrite.c
  337. @@ -77,8 +77,13 @@ static int read_from_mds(
  338.      while(to_rcv > 0) {
  339.          uint32_t bytes_read = 0, chunk = min(to_rcv, maxreadsize);
  340.  
  341. +#if 1
  342. +        status = nfs42_read_plus(session, file, stateid, args->offset + reloffset, chunk,
  343. +                p, &bytes_read, &eof);
  344. +#else
  345.          status = nfs41_read(session, file, stateid, args->offset + reloffset, chunk,
  346.                  p, &bytes_read, &eof);
  347. +#endif
  348.          if (status == NFS4ERR_OPENMODE && !len) {
  349.              stateid->type = STATEID_SPECIAL;
  350.              stateid4_cpy(&stateid->stateid, &special_read_stateid);

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at