ReactOS  0.4.12-dev-75-g00dd17e
callback_server.c File Reference
#include <windows.h>
#include <strsafe.h>
#include "nfs41_ops.h"
#include "delegation.h"
#include "nfs41_callback.h"
#include "daemon_debug.h"
Include dependency graph for callback_server.c:

Go to the source code of this file.

Macros

#define CBSLVL   2 /* dprintf level for callback server logging */
 

Functions

static void replay_cache_write (IN nfs41_cb_session *session, IN struct cb_compound_args *args, IN struct cb_compound_res *res, IN bool_t cachethis)
 
void nfs41_callback_session_init (IN nfs41_session *session)
 
static enum_t handle_cb_layoutrecall (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_layoutrecall_args *args, OUT struct cb_layoutrecall_res *res)
 
static enum_t handle_cb_recall_slot (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_slot_args *args, OUT struct cb_recall_slot_res *res)
 
static enum_t handle_cb_sequence (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_sequence_args *args, OUT struct cb_sequence_res *res, OUT nfs41_cb_session **session_out, OUT bool_t *cachethis)
 
static enum_t handle_cb_getattr (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_getattr_args *args, OUT struct cb_getattr_res *res)
 
static enum_t handle_cb_recall (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_args *args, OUT struct cb_recall_res *res)
 
static enum_t handle_cb_notify_deviceid (IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_notify_deviceid_args *args, OUT struct cb_notify_deviceid_res *res)
 
static void replay_cache_write (IN nfs41_cb_session *session, IN OPTIONAL struct cb_compound_args *args, IN struct cb_compound_res *res, IN bool_t cachethis)
 
static bool_t replay_validate_args (IN struct cb_compound_args *args, IN const struct replay_cache *cache)
 
static bool_t replay_validate_ops (IN const struct cb_compound_args *args, IN const struct cb_compound_res *res)
 
static int replay_cache_read (IN nfs41_cb_session *session, IN struct cb_compound_args *args, OUT struct cb_compound_res **res_out)
 
static void handle_cb_compound (nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_compound_res **reply)
 
int nfs41_handle_callback (void *rpc_clnt, void *cb, struct cb_compound_res **reply)
 

Variables

static const char g_server_tag [] = "ms-nfs41-callback"
 

Macro Definition Documentation

◆ CBSLVL

Function Documentation

◆ handle_cb_compound()

static void handle_cb_compound ( nfs41_rpc_clnt rpc_clnt,
cb_req req,
struct cb_compound_res **  reply 
)
static

Definition at line 354 of file callback_server.c.

Referenced by nfs41_handle_callback().

355 {
356  struct cb_compound_args args = { 0 };
357  struct cb_compound_res *res = NULL;
358  struct cb_argop *argop;
359  struct cb_resop *resop;
360  XDR *xdr = (XDR*)req->xdr;
361  nfs41_cb_session *session = NULL;
362  bool_t cachethis = FALSE;
364 
365  dprintf(CBSLVL, "--> handle_cb_compound()\n");
366 
367  /* decode the arguments */
368  if (!proc_cb_compound_args(xdr, &args)) {
370  eprintf("failed to decode compound arguments\n");
371  }
372 
373  /* allocate the compound results */
374  res = calloc(1, sizeof(struct cb_compound_res));
375  if (res == NULL) {
377  goto out;
378  }
379  res->status = status;
381  res->tag.str[CB_COMPOUND_MAX_TAG-1] = 0;
382  res->tag.len = (uint32_t)strlen(res->tag.str);
383  res->resarray = calloc(args.argarray_count, sizeof(struct cb_resop));
384  if (res->resarray == NULL) {
386  goto out;
387  }
388 
389  dprintf(CBSLVL, "CB_COMPOUND('%s', %u)\n", args.tag.str, args.argarray_count);
390  if (args.minorversion != 1) {
391  res->status = NFS4ERR_MINOR_VERS_MISMATCH; //XXXXX
392  eprintf("args.minorversion %u != 1\n", args.minorversion);
393  goto out;
394  }
395 
396  /* handle each operation in the compound */
397  for (i = 0; i < args.argarray_count && res->status == NFS4_OK; i++) {
398  argop = &args.argarray[i];
399  resop = &res->resarray[i];
400  resop->opnum = argop->opnum;
401  res->resarray_count++;
402 
403  /* 20.9.3: The error NFS4ERR_SEQUENCE_POS MUST be returned
404  * when CB_SEQUENCE is found in any position in a CB_COMPOUND
405  * beyond the first. If any other operation is in the first
406  * position of CB_COMPOUND, NFS4ERR_OP_NOT_IN_SESSION MUST
407  * be returned.
408  */
409  if (i == 0 && argop->opnum != OP_CB_SEQUENCE) {
410  res->status = resop->res.status = NFS4ERR_OP_NOT_IN_SESSION;
411  break;
412  }
413  if (i != 0 && argop->opnum == OP_CB_SEQUENCE) {
414  res->status = resop->res.status = NFS4ERR_SEQUENCE_POS;
415  break;
416  }
418  res->status = resop->res.status = status;
419  break;
420  }
421 
422  switch (argop->opnum) {
423  case OP_CB_LAYOUTRECALL:
424  dprintf(1, "OP_CB_LAYOUTRECALL\n");
425  res->status = handle_cb_layoutrecall(rpc_clnt,
426  &argop->args.layoutrecall, &resop->res.layoutrecall);
427  break;
428  case OP_CB_RECALL_SLOT:
429  dprintf(1, "OP_CB_RECALL_SLOT\n");
430  res->status = handle_cb_recall_slot(rpc_clnt,
431  &argop->args.recall_slot, &resop->res.recall_slot);
432  break;
433  case OP_CB_SEQUENCE:
434  dprintf(1, "OP_CB_SEQUENCE\n");
435  status = handle_cb_sequence(rpc_clnt, &argop->args.sequence,
436  &resop->res.sequence, &session, &cachethis);
437 
439  /* replace the current results with the cached response */
440  status = replay_cache_read(session, &args, &res);
441  if (status) res->status = status;
442  goto out;
443  }
444 
445  if (status == NFS4_OK)
446  res->status = resop->res.sequence.status;
447  break;
448  case OP_CB_GETATTR:
449  dprintf(1, "OP_CB_GETATTR\n");
450  res->status = handle_cb_getattr(rpc_clnt,
451  &argop->args.getattr, &resop->res.getattr);
452  break;
453  case OP_CB_RECALL:
454  dprintf(1, "OP_CB_RECALL\n");
455  res->status = handle_cb_recall(rpc_clnt,
456  &argop->args.recall, &resop->res.recall);
457  break;
458  case OP_CB_NOTIFY:
459  dprintf(1, "OP_CB_NOTIFY\n");
460  res->status = NFS4ERR_NOTSUPP;
461  break;
462  case OP_CB_PUSH_DELEG:
463  dprintf(1, "OP_CB_PUSH_DELEG\n");
464  res->status = NFS4ERR_NOTSUPP;
465  break;
466  case OP_CB_RECALL_ANY:
467  dprintf(1, "OP_CB_RECALL_ANY\n");
468  res->status = NFS4ERR_NOTSUPP;
469  break;
471  dprintf(1, "OP_CB_RECALLABLE_OBJ_AVAIL\n");
472  res->status = NFS4ERR_NOTSUPP;
473  break;
475  dprintf(1, "OP_CB_WANTS_CANCELLED\n");
476  res->status = NFS4ERR_NOTSUPP;
477  break;
478  case OP_CB_NOTIFY_LOCK:
479  dprintf(1, "OP_CB_NOTIFY_LOCK\n");
480  res->status = NFS4ERR_NOTSUPP;
481  break;
483  dprintf(1, "OP_CB_NOTIFY_DEVICEID\n");
484  res->status = NFS4_OK;
485  break;
486  case OP_CB_ILLEGAL:
487  dprintf(1, "OP_CB_ILLEGAL\n");
488  res->status = NFS4ERR_NOTSUPP;
489  break;
490  default:
491  eprintf("operation %u not supported\n", argop->opnum);
492  res->status = NFS4ERR_NOTSUPP;
493  break;
494  }
495  }
496 
497  /* always attempt to cache the reply */
498  if (session)
499  replay_cache_write(session, &args, res, cachethis);
500 out:
501  /* free the arguments */
502  xdr->x_op = XDR_FREE;
503  proc_cb_compound_args(xdr, &args);
504 
505  *reply = res;
506  dprintf(CBSLVL, "<-- handle_cb_compound() returning %s (%u results)\n",
507  nfs_error_string(res ? res->status : status),
508  res ? res->resarray_count : 0);
509 }
struct cb_getattr_res getattr
void * xdr
Definition: clnt.h:156
struct cb_recall_slot_res recall_slot
static enum_t handle_cb_getattr(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_getattr_args *args, OUT struct cb_getattr_res *res)
struct cb_recall_args recall
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
struct cb_resop * resarray
int32_t bool_t
Definition: types.h:101
struct cb_recall_res recall
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
struct cb_compound_tag tag
enum_t status
static const char g_server_tag[]
Definition: match.c:390
Definition: xdr.h:103
enum_t opnum
GLenum GLclampf GLint i
Definition: glfuncs.h:14
static enum_t handle_cb_layoutrecall(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_layoutrecall_args *args, OUT struct cb_layoutrecall_res *res)
#define dprintf
Definition: regdump.c:33
struct cb_layoutrecall_res layoutrecall
smooth NULL
Definition: ftsmooth.c:416
#define CB_COMPOUND_MAX_TAG
#define CBSLVL
enum xdr_op x_op
Definition: xdr.h:104
static FILE * out
Definition: regtests2xml.c:44
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
union cb_op_args args
static enum_t handle_cb_sequence(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_sequence_args *args, OUT struct cb_sequence_res *res, OUT nfs41_cb_session **session_out, OUT bool_t *cachethis)
struct cb_getattr_args getattr
uint32_t resarray_count
union cb_op_res res
enum_t opnum
struct cb_layoutrecall_args layoutrecall
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
struct cb_argop * argarray
struct cb_sequence_args sequence
static enum_t handle_cb_recall_slot(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_slot_args *args, OUT struct cb_recall_slot_res *res)
UINT32 uint32_t
Definition: types.h:75
static int replay_cache_read(IN nfs41_cb_session *session, IN struct cb_compound_args *args, OUT struct cb_compound_res **res_out)
uint32_t argarray_count
struct cb_sequence_res sequence
static enum_t handle_cb_recall(IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_args *args, OUT struct cb_recall_res *res)
Definition: xdr.h:87
#define calloc
Definition: rosglue.h:14
GLuint res
Definition: glext.h:9613
static void replay_cache_write(IN nfs41_cb_session *session, IN struct cb_compound_args *args, IN struct cb_compound_res *res, IN bool_t cachethis)
bool_t proc_cb_compound_args(XDR *xdr, struct cb_compound_args *args)
Definition: callback_xdr.c:590
#define uint32_t
Definition: nsiface.idl:61
static SERVICE_STATUS status
Definition: service.c:31
struct cb_compound_tag tag
struct cb_recall_slot_args recall_slot
Definition: ps.c:97

◆ handle_cb_getattr()

static enum_t handle_cb_getattr ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_getattr_args args,
OUT struct cb_getattr_res res 
)
static

Definition at line 174 of file callback_server.c.

Referenced by handle_cb_compound().

178 {
179  /* look up cached attributes for the given filehandle */
180  res->status = nfs41_delegation_getattr(rpc_clnt->client,
181  &args->fh, &args->attr_request, &res->info);
182  return res->status;
183 }
Definition: match.c:390
int nfs41_delegation_getattr(IN nfs41_client *client, IN const nfs41_fh *fh, IN const bitmap4 *attr_request, OUT nfs41_file_info *info)
Definition: delegation.c:783
GLuint res
Definition: glext.h:9613

◆ handle_cb_layoutrecall()

static enum_t handle_cb_layoutrecall ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_layoutrecall_args args,
OUT struct cb_layoutrecall_res res 
)
static

Definition at line 60 of file callback_server.c.

Referenced by handle_cb_compound().

64 {
65  enum pnfs_status status;
66 
67  status = pnfs_file_layout_recall(rpc_clnt->client, args);
68  switch (status) {
69  case PNFS_PENDING:
70  /* not enough information to process the recall yet */
71  res->status = NFS4ERR_DELAY;
72  break;
73  default:
74  /* forgetful model for layout recalls */
76  break;
77  }
78 
79  dprintf(CBSLVL, " OP_CB_LAYOUTRECALL { %s, %s, recall %u } %s\n",
81  pnfs_iomode_string(args->iomode), args->recall.type,
82  nfs_error_string(res->status));
83  return res->status;
84 }
pnfs_status
Definition: pnfs.h:58
const char * pnfs_iomode_string(enum pnfs_iomode iomode)
Definition: pnfs_debug.c:58
Definition: match.c:390
#define dprintf
Definition: regdump.c:33
const char * pnfs_layout_type_string(enum pnfs_layout_type type)
Definition: pnfs_debug.c:48
#define CBSLVL
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
GLuint res
Definition: glext.h:9613
static SERVICE_STATUS status
Definition: service.c:31
enum pnfs_status pnfs_file_layout_recall(IN struct __nfs41_client *client, IN const struct cb_layoutrecall_args *recall)

◆ handle_cb_notify_deviceid()

static enum_t handle_cb_notify_deviceid ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_notify_deviceid_args args,
OUT struct cb_notify_deviceid_res res 
)
static

Definition at line 198 of file callback_server.c.

202 {
203  uint32_t i;
204  for (i = 0; i < args->change_count; i++) {
205  pnfs_file_device_notify(rpc_clnt->client->devices,
206  &args->change_list[i]);
207  }
208  res->status = NFS4_OK;
209  return res->status;
210 }
Definition: match.c:390
GLenum GLclampf GLint i
Definition: glfuncs.h:14
UINT32 uint32_t
Definition: types.h:75
GLuint res
Definition: glext.h:9613
enum pnfs_status pnfs_file_device_notify(IN struct pnfs_file_device_list *devices, IN const struct notify_deviceid4 *change)
Definition: pnfs_device.c:328

◆ handle_cb_recall()

static enum_t handle_cb_recall ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_recall_args args,
OUT struct cb_recall_res res 
)
static

Definition at line 186 of file callback_server.c.

Referenced by handle_cb_compound().

190 {
191  /* return the delegation asynchronously */
192  res->status = nfs41_delegation_recall(rpc_clnt->client,
193  &args->fh, &args->stateid, args->truncate);
194  return res->status;
195 }
int nfs41_delegation_recall(IN nfs41_client *client, IN nfs41_fh *fh, IN const stateid4 *stateid, IN bool_t truncate)
Definition: delegation.c:703
Definition: match.c:390
GLuint res
Definition: glext.h:9613

◆ handle_cb_recall_slot()

static enum_t handle_cb_recall_slot ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_recall_slot_args args,
OUT struct cb_recall_slot_res res 
)
static

Definition at line 87 of file callback_server.c.

Referenced by handle_cb_compound().

91 {
92  res->status = nfs41_session_recall_slot(rpc_clnt->client->session,
93  args->target_highest_slotid);
94 
95  dprintf(CBSLVL, " OP_CB_RECALL_SLOT { %u } %s\n",
96  args->target_highest_slotid, nfs_error_string(res->status));
97  return res->status;
98 }
Definition: match.c:390
#define dprintf
Definition: regdump.c:33
int nfs41_session_recall_slot(IN nfs41_session *session, IN OUT uint32_t target_highest_slotid)
#define CBSLVL
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
GLuint res
Definition: glext.h:9613

◆ handle_cb_sequence()

static enum_t handle_cb_sequence ( IN nfs41_rpc_clnt rpc_clnt,
IN struct cb_sequence_args args,
OUT struct cb_sequence_res res,
OUT nfs41_cb_session **  session_out,
OUT bool_t cachethis 
)
static

Definition at line 101 of file callback_server.c.

Referenced by handle_cb_compound().

107 {
108  nfs41_cb_session *cb_session = &rpc_clnt->client->session->cb_session;
110  res->status = NFS4_OK;
111 
112  *session_out = cb_session;
113 
114  /* validate the sessionid */
115  if (memcmp(cb_session->cb_sessionid, args->sessionid,
117  eprintf("[cb] received sessionid doesn't match session\n");
118  res->status = NFS4ERR_BADSESSION;
119  goto out;
120  }
121 
122  /* we only support 1 slot for the back channel so slotid MUST be 0 */
123  if (args->slotid != 0) {
124  eprintf("[cb] received unexpected slotid=%d\n", args->slotid);
125  res->status = NFS4ERR_BADSLOT;
126  goto out;
127  }
128  if (args->highest_slotid != 0) {
129  eprintf("[cb] received unexpected highest_slotid=%d\n",
130  args->highest_slotid);
131  res->status = NFS4ERR_BAD_HIGH_SLOT;
132  goto out;
133  }
134 
135  /* check for a retry with the same seqid */
136  if (args->sequenceid == cb_session->cb_seqnum) {
137  if (!cb_session->replay.res.length) {
138  /* return success for sequence, but fail the next operation */
139  res->status = NFS4_OK;
141  } else {
142  /* return NFS4ERR_SEQ_FALSE_RETRY for all replays; if the retry
143  * turns out to be valid, this response will be replaced anyway */
144  status = res->status = NFS4ERR_SEQ_FALSE_RETRY;
145  }
146  goto out;
147  }
148 
149  /* error on any unexpected seqids */
150  if (args->sequenceid != cb_session->cb_seqnum+1) {
151  eprintf("[cb] bad received seq#=%d, expected=%d\n",
152  args->sequenceid, cb_session->cb_seqnum+1);
153  res->status = NFS4ERR_SEQ_MISORDERED;
154  goto out;
155  }
156 
157  cb_session->cb_seqnum = args->sequenceid;
158  *cachethis = args->cachethis;
159 
160  memcpy(res->ok.sessionid, args->sessionid, NFS4_SESSIONID_SIZE);
161  res->ok.sequenceid = args->sequenceid;
162  res->ok.slotid = args->slotid;
163  res->ok.highest_slotid = args->highest_slotid;
164  res->ok.target_highest_slotid = args->highest_slotid;
165 
166 out:
167  dprintf(CBSLVL, " OP_CB_SEQUENCE { seqid %u, slot %u, cachethis %d } "
168  "%s\n", args->sequenceid, args->slotid, args->cachethis,
169  nfs_error_string(res->status));
170  return status;
171 }
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define NFS4_SESSIONID_SIZE
Definition: nfs41_const.h:32
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const unsigned char * cb_sessionid
Definition: nfs41.h:250
Definition: match.c:390
struct __nfs41_cb_session::@28 replay
#define dprintf
Definition: regdump.c:33
#define CBSLVL
static FILE * out
Definition: regtests2xml.c:44
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
UINT32 uint32_t
Definition: types.h:75
GLuint res
Definition: glext.h:9613
uint32_t cb_seqnum
Definition: nfs41.h:251
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ nfs41_callback_session_init()

void nfs41_callback_session_init ( IN nfs41_session session)

Definition at line 44 of file callback_server.c.

Referenced by session_alloc().

46 {
47  /* initialize the replay cache with status NFS4ERR_SEQ_MISORDERED */
48  struct cb_compound_res res = { 0 };
50  res.tag.len = sizeof(g_server_tag);
52 
53  session->cb_session.cb_sessionid = session->session_id;
54 
55  replay_cache_write(&session->cb_session, NULL, &res, FALSE);
56 }
struct cb_compound_tag tag
static const char g_server_tag[]
smooth NULL
Definition: ftsmooth.c:416
#define CB_COMPOUND_MAX_TAG
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
GLuint res
Definition: glext.h:9613
static void replay_cache_write(IN nfs41_cb_session *session, IN struct cb_compound_args *args, IN struct cb_compound_res *res, IN bool_t cachethis)

◆ nfs41_handle_callback()

int nfs41_handle_callback ( void rpc_clnt,
void cb,
struct cb_compound_res **  reply 
)

Definition at line 516 of file callback_server.c.

Referenced by get_client_for_netaddr(), and handle_cb_compound().

517 {
518 #endif
519  nfs41_rpc_clnt *rpc = (nfs41_rpc_clnt *)rpc_clnt;
520  cb_req *request = (cb_req *)cb;
521  uint32_t status = 0;
522 
523  dprintf(1, "nfs41_handle_callback: received call\n");
524  if (request->rq_prog != NFS41_RPC_CBPROGRAM) {
525  eprintf("invalid rpc program %u\n", request->rq_prog);
526  status = 2;
527  goto out;
528  }
529 
530  switch (request->rq_proc) {
531  case CB_NULL:
532  dprintf(1, "CB_NULL\n");
533  break;
534 
535  case CB_COMPOUND:
536  dprintf(1, "CB_COMPOUND\n");
537  handle_cb_compound(rpc, request, reply);
538  break;
539 
540  default:
541  dprintf(1, "invalid rpc procedure %u\n", request->rq_proc);
542  status = 3;
543  goto out;
544  }
545 out:
546  return status;
547 }
static void handle_cb_compound(nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_compound_res **reply)
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
#define NFS41_RPC_CBPROGRAM
Definition: nfs41_const.h:80
u_int32_t rq_proc
Definition: clnt.h:155
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
Definition: clnt.h:152
u_int32_t rq_prog
Definition: clnt.h:153
UINT32 uint32_t
Definition: types.h:75
Definition: tftpd.h:85
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ replay_cache_read()

static int replay_cache_read ( IN nfs41_cb_session session,
IN struct cb_compound_args args,
OUT struct cb_compound_res **  res_out 
)
static

Definition at line 296 of file callback_server.c.

Referenced by handle_cb_compound().

300 {
301  XDR xdr;
302  struct cb_compound_res *replay;
303  struct cb_compound_res *res = *res_out;
305 
306  replay = calloc(1, sizeof(struct cb_compound_res));
307  if (replay == NULL) {
308  eprintf("[cb] failed to allocate replay buffer\n");
309  status = NFS4ERR_SERVERFAULT;
310  goto out;
311  }
312 
313  /* decode the response from the replay cache */
314  xdrmem_create(&xdr, (char*)session->replay.res.buffer,
316  if (!proc_cb_compound_res(&xdr, replay)) {
317  eprintf("[cb] failed to decode replay buffer\n");
318  status = NFS4ERR_SEQ_FALSE_RETRY;
319  goto out_free_replay;
320  }
321 
322  /* if we cached the arguments, use them to validate the retry */
323  if (session->replay.arg.length) {
324  if (!replay_validate_args(args, &session->replay.arg)) {
325  eprintf("[cb] retry attempt with different arguments\n");
326  status = NFS4ERR_SEQ_FALSE_RETRY;
327  goto out_free_replay;
328  }
329  } else { /* otherwise, comparing opnums is the best we can do */
330  if (!replay_validate_ops(args, replay)) {
331  eprintf("[cb] retry attempt with different operations\n");
332  status = NFS4ERR_SEQ_FALSE_RETRY;
333  goto out_free_replay;
334  }
335  }
336 
337  /* free previous response and replace it with the replay */
338  xdr.x_op = XDR_FREE;
339  proc_cb_compound_res(&xdr, res);
340 
341  dprintf(2, "[cb] retry: returning cached response\n");
342 
343  *res_out = replay;
344 out:
345  return status;
346 
347 out_free_replay:
348  xdr.x_op = XDR_FREE;
349  proc_cb_compound_res(&xdr, replay);
350  goto out;
351 }
static bool_t replay_validate_args(IN struct cb_compound_args *args, IN const struct replay_cache *cache)
static bool_t replay_validate_ops(IN const struct cb_compound_args *args, IN const struct cb_compound_res *res)
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
Definition: match.c:390
Definition: xdr.h:103
#define dprintf
Definition: regdump.c:33
smooth NULL
Definition: ftsmooth.c:416
enum xdr_op x_op
Definition: xdr.h:104
static FILE * out
Definition: regtests2xml.c:44
#define NFS41_MAX_SERVER_CACHE
Definition: nfs41_const.h:39
void xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op)
Definition: xdr_mem.c:94
UINT32 uint32_t
Definition: types.h:75
Definition: xdr.h:87
#define calloc
Definition: rosglue.h:14
GLuint res
Definition: glext.h:9613
Definition: xdr.h:86
bool_t proc_cb_compound_res(XDR *xdr, struct cb_compound_res *res)
Definition: callback_xdr.c:638
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ replay_cache_write() [1/2]

static void replay_cache_write ( IN nfs41_cb_session session,
IN struct cb_compound_args args,
IN struct cb_compound_res res,
IN bool_t  cachethis 
)
static

◆ replay_cache_write() [2/2]

static void replay_cache_write ( IN nfs41_cb_session session,
IN OPTIONAL struct cb_compound_args args,
IN struct cb_compound_res res,
IN bool_t  cachethis 
)
static

Definition at line 212 of file callback_server.c.

217 {
218  XDR xdr;
219  uint32_t i;
220 
221  session->replay.arg.length = 0;
222  session->replay.res.length = 0;
223 
224  /* encode the reply directly into the replay cache */
225  xdrmem_create(&xdr, (char*)session->replay.res.buffer,
227 
228  /* always try to cache the result */
229  if (proc_cb_compound_res(&xdr, res)) {
230  session->replay.res.length = XDR_GETPOS(&xdr);
231 
232  if (args) {
233  /* encode the arguments into the request cache */
234  xdrmem_create(&xdr, (char*)session->replay.arg.buffer,
236 
237  if (proc_cb_compound_args(&xdr, args))
238  session->replay.arg.length = XDR_GETPOS(&xdr);
239  }
240  } else if (cachethis) {
241  /* on failure, only return errors if caching was requested */
243 
244  /* find the first operation that failed to encode */
245  for (i = 0; i < res->resarray_count; i++) {
246  if (!res->resarray[i].xdr_ok) {
247  res->resarray[i].res.status = NFS4ERR_REP_TOO_BIG_TO_CACHE;
248  res->resarray_count = i + 1;
249  break;
250  }
251  }
252  }
253 }
#define XDR_GETPOS(xdrs)
Definition: xdr.h:199
Definition: match.c:390
Definition: xdr.h:103
GLenum GLclampf GLint i
Definition: glfuncs.h:14
Definition: xdr.h:85
#define NFS41_MAX_SERVER_CACHE
Definition: nfs41_const.h:39
void xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op)
Definition: xdr_mem.c:94
UINT32 uint32_t
Definition: types.h:75
GLuint res
Definition: glext.h:9613
bool_t proc_cb_compound_args(XDR *xdr, struct cb_compound_args *args)
Definition: callback_xdr.c:590
bool_t proc_cb_compound_res(XDR *xdr, struct cb_compound_res *res)
Definition: callback_xdr.c:638

◆ replay_validate_args()

static bool_t replay_validate_args ( IN struct cb_compound_args args,
IN const struct replay_cache cache 
)
static

Definition at line 255 of file callback_server.c.

Referenced by replay_cache_read().

258 {
260  XDR xdr;
261 
262  /* encode the current arguments into a temporary buffer */
264 
265  if (!proc_cb_compound_args(&xdr, args))
266  return FALSE;
267 
268  /* must match the cached length */
269  if (XDR_GETPOS(&xdr) != cache->length)
270  return FALSE;
271 
272  /* must match the cached buffer contents */
273  return memcmp(cache->buffer, buffer, cache->length) == 0;
274 }
Definition: cache.c:46
#define XDR_GETPOS(xdrs)
Definition: xdr.h:199
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
GLuint buffer
Definition: glext.h:5915
Definition: match.c:390
Definition: xdr.h:103
Definition: xdr.h:85
#define NFS41_MAX_SERVER_CACHE
Definition: nfs41_const.h:39
void xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op)
Definition: xdr_mem.c:94
bool_t proc_cb_compound_args(XDR *xdr, struct cb_compound_args *args)
Definition: callback_xdr.c:590

◆ replay_validate_ops()

static bool_t replay_validate_ops ( IN const struct cb_compound_args args,
IN const struct cb_compound_res res 
)
static

Definition at line 276 of file callback_server.c.

Referenced by replay_cache_read().

279 {
280  uint32_t i;
281  for (i = 0; i < res->resarray_count; i++) {
282  /* can't have more operations than the request */
283  if (i >= args->argarray_count)
284  return FALSE;
285 
286  /* each opnum must match the request */
287  if (args->argarray[i].opnum != res->resarray[i].opnum)
288  return FALSE;
289 
290  if (res->resarray[i].res.status)
291  break;
292  }
293  return TRUE;
294 }
#define TRUE
Definition: types.h:120
Definition: match.c:390
GLenum GLclampf GLint i
Definition: glfuncs.h:14
UINT32 uint32_t
Definition: types.h:75
GLuint res
Definition: glext.h:9613

Variable Documentation

◆ g_server_tag

const char g_server_tag[] = "ms-nfs41-callback"
static

Definition at line 34 of file callback_server.c.

Referenced by handle_cb_compound(), and nfs41_callback_session_init().