ReactOS  0.4.12-dev-14-gd0c8636
callback_server.c
Go to the documentation of this file.
1 /* NFSv4.1 client for Windows
2  * Copyright 2012 The Regents of the University of Michigan
3  *
4  * Olga Kornievskaia <aglo@umich.edu>
5  * Casey Bodley <cbodley@umich.edu>
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or (at
10  * your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * without any warranty; without even the implied warranty of merchantability
14  * or fitness for a particular purpose. See the GNU Lesser General Public
15  * License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  */
21 
22 #include <windows.h>
23 #include <strsafe.h>
24 
25 #include "nfs41_ops.h"
26 #include "delegation.h"
27 #include "nfs41_callback.h"
28 #include "daemon_debug.h"
29 
30 
31 #define CBSLVL 2 /* dprintf level for callback server logging */
32 
33 
34 static const char g_server_tag[] = "ms-nfs41-callback";
35 
36 
37 /* callback session */
38 static void replay_cache_write(
39  IN nfs41_cb_session *session,
40  IN struct cb_compound_args *args,
41  IN struct cb_compound_res *res,
42  IN bool_t cachethis);
43 
45  IN nfs41_session *session)
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 }
57 
58 
59 /* OP_CB_LAYOUTRECALL */
61  IN nfs41_rpc_clnt *rpc_clnt,
63  OUT struct cb_layoutrecall_res *res)
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 */
75  res->status = NFS4ERR_NOMATCHING_LAYOUT;
76  break;
77  }
78 
79  dprintf(CBSLVL, " OP_CB_LAYOUTRECALL { %s, %s, recall %u } %s\n",
80  pnfs_layout_type_string(args->type),
81  pnfs_iomode_string(args->iomode), args->recall.type,
82  nfs_error_string(res->status));
83  return res->status;
84 }
85 
86 /* OP_CB_RECALL_SLOT */
88  IN nfs41_rpc_clnt *rpc_clnt,
89  IN struct cb_recall_slot_args *args,
90  OUT struct cb_recall_slot_res *res)
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 }
99 
100 /* OP_CB_SEQUENCE */
102  IN nfs41_rpc_clnt *rpc_clnt,
103  IN struct cb_sequence_args *args,
104  OUT struct cb_sequence_res *res,
105  OUT nfs41_cb_session **session_out,
106  OUT bool_t *cachethis)
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 }
172 
173 /* OP_CB_GETATTR */
175  IN nfs41_rpc_clnt *rpc_clnt,
176  IN struct cb_getattr_args *args,
177  OUT struct cb_getattr_res *res)
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 }
184 
185 /* OP_CB_RECALL */
187  IN nfs41_rpc_clnt *rpc_clnt,
188  IN struct cb_recall_args *args,
189  OUT struct cb_recall_res *res)
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 }
196 
197 /* OP_CB_NOTIFY_DEVICEID */
199  IN nfs41_rpc_clnt *rpc_clnt,
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 }
211 
212 static void replay_cache_write(
213  IN nfs41_cb_session *session,
215  IN struct cb_compound_res *res,
216  IN bool_t cachethis)
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 */
242  res->status = NFS4ERR_REP_TOO_BIG_TO_CACHE;
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 }
254 
256  IN struct cb_compound_args *args,
257  IN const struct replay_cache *cache)
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 }
275 
277  IN const struct cb_compound_args *args,
278  IN const struct cb_compound_res *res)
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 }
295 
296 static int replay_cache_read(
297  IN nfs41_cb_session *session,
298  IN struct cb_compound_args *args,
299  OUT struct cb_compound_res **res_out)
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 }
352 
353 /* CB_COMPOUND */
354 static void handle_cb_compound(nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_compound_res **reply)
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 }
510 
511 #ifdef __REACTOS__
512 int nfs41_handle_callback(void *rpc_clnt, void *cb, void * dummy)
513 {
514  struct cb_compound_res **reply = dummy;
515 #else
516 int nfs41_handle_callback(void *rpc_clnt, void *cb, struct cb_compound_res **reply)
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 }
pnfs_status
Definition: pnfs.h:58
Definition: cache.c:46
struct cb_getattr_res getattr
#define IN
Definition: typedefs.h:38
static bool_t replay_validate_args(IN struct cb_compound_args *args, IN const struct replay_cache *cache)
void * xdr
Definition: clnt.h:156
#define TRUE
Definition: types.h:120
const char * pnfs_iomode_string(enum pnfs_iomode iomode)
Definition: pnfs_debug.c:58
#define XDR_GETPOS(xdrs)
Definition: xdr.h:199
struct cb_recall_slot_res recall_slot
static bool_t replay_validate_ops(IN const struct cb_compound_args *args, IN const struct cb_compound_res *res)
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
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
#define NFS4_SESSIONID_SIZE
Definition: nfs41_const.h:32
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
static void handle_cb_compound(nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_compound_res **reply)
void nfs41_callback_session_init(IN nfs41_session *session)
int nfs41_delegation_recall(IN nfs41_client *client, IN nfs41_fh *fh, IN const stateid4 *stateid, IN bool_t truncate)
Definition: delegation.c:703
GLuint buffer
Definition: glext.h:5915
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
struct cb_compound_tag tag
enum_t status
const unsigned char * cb_sessionid
Definition: nfs41.h:250
#define NFS41_RPC_CBPROGRAM
Definition: nfs41_const.h:80
static const char g_server_tag[]
Definition: match.c:390
Definition: xdr.h:103
enum_t opnum
int nfs41_handle_callback(void *rpc_clnt, void *cb, struct cb_compound_res **reply)
u_int32_t rq_proc
Definition: clnt.h:155
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)
struct __nfs41_cb_session::@28 replay
#define dprintf
Definition: regdump.c:33
struct cb_layoutrecall_res layoutrecall
const char * pnfs_layout_type_string(enum pnfs_layout_type type)
Definition: pnfs_debug.c:48
int nfs41_session_recall_slot(IN nfs41_session *session, IN OUT uint32_t target_highest_slotid)
smooth NULL
Definition: ftsmooth.c:416
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)
#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
Definition: clnt.h:152
static DWORD cb
Definition: integrity.c:41
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)
int32_t enum_t
Definition: types.h:102
struct cb_getattr_args getattr
uint32_t resarray_count
Definition: xdr.h:85
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
union cb_op_res res
enum_t opnum
#define NFS41_MAX_SERVER_CACHE
Definition: nfs41_const.h:39
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
unsigned char dummy
Definition: maze.c:118
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)
u_int32_t rq_prog
Definition: clnt.h:153
void xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op)
Definition: xdr_mem.c:94
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
UINT32 uint32_t
Definition: types.h:75
Definition: tftpd.h:85
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
#define OUT
Definition: typedefs.h:39
GLuint res
Definition: glext.h:9613
Definition: xdr.h:86
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
bool_t proc_cb_compound_res(XDR *xdr, struct cb_compound_res *res)
Definition: callback_xdr.c:638
#define uint32_t
Definition: nsiface.idl:61
uint32_t cb_seqnum
Definition: nfs41.h:251
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)
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
struct cb_compound_tag tag
struct cb_recall_slot_args recall_slot
Definition: ps.c:97
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68