xref: /reactos/base/services/nfsd/nfs41.h (revision 1734f297)
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 #ifndef __NFS41__
23 #define __NFS41__
24 
25 #include "util.h"
26 #include "list.h"
27 
28 
29 struct __nfs41_session;
30 struct __nfs41_client;
31 struct __rpc_client;
32 struct __nfs41_root;
33 
34 struct _FILE_GET_EA_INFORMATION;
35 struct _FILE_FULL_EA_INFORMATION;
36 
37 typedef struct __nfs41_superblock {
38     nfs41_fsid fsid;
39     struct list_entry entry; /* position in nfs41_server.superblocks */
40 
41     bitmap4 supported_attrs;
42     bitmap4 suppattr_exclcreat;
43     bitmap4 default_getattr;
44 
45     nfstime4 time_delta;
46     uint64_t maxread;
47     uint64_t maxwrite;
48 
49     /* constant filesystem attributes */
50     unsigned int layout_types : 3;
51     unsigned int aclsupport : 3;
52     unsigned int cansettime : 1;
53     unsigned int link_support : 1;
54     unsigned int symlink_support : 1;
55     unsigned int ea_support : 1;
56     unsigned int case_preserving : 1;
57     unsigned int case_insensitive : 1;
58 
59     /* variable filesystem attributes */
60     uint64_t space_avail;
61     uint64_t space_free;
62     uint64_t space_total;
63     time_t cache_expiration; /* applies to space_ attributes */
64 
65     SRWLOCK lock;
66 } nfs41_superblock;
67 
68 typedef struct __nfs41_superblock_list {
69     struct list_entry head;
70     SRWLOCK lock;
71 } nfs41_superblock_list;
72 
73 struct server_addrs {
74     multi_addr4 addrs; /* list of addrs we've used with this server */
75     uint32_t next_index;
76     SRWLOCK lock;
77 };
78 
79 typedef struct __nfs41_server {
80     char scope[NFS4_OPAQUE_LIMIT]; /* server_scope from exchangeid */
81     char owner[NFS4_OPAQUE_LIMIT]; /* server_owner.major_id from exchangeid */
82     struct server_addrs addrs;
83     nfs41_superblock_list superblocks;
84     struct nfs41_name_cache *name_cache;
85     struct list_entry entry; /* position in global server list */
86     LONG ref_count;
87 } nfs41_server;
88 
89 enum delegation_status {
90     DELEGATION_GRANTED,
91     DELEGATION_RETURNING,
92     DELEGATION_RETURNED,
93 };
94 
95 typedef struct __nfs41_delegation_state {
96     open_delegation4 state;
97     nfs41_abs_path path;
98     nfs41_path_fh parent;
99     nfs41_path_fh file;
100     struct list_entry client_entry; /* entry in nfs41_client.delegations */
101     LONG ref_count;
102 
103     enum delegation_status status;
104     SRWLOCK lock;
105     CONDITION_VARIABLE cond;
106 
107     bool_t revoked; /* for recovery, accessed under client.state.lock */
108 
109     HANDLE srv_open; /* for rdbss cache invalidation */
110 } nfs41_delegation_state;
111 
112 typedef struct __nfs41_lock_state {
113     struct list_entry open_entry; /* entry in nfs41_open_state.locks */
114     uint64_t offset;
115     uint64_t length;
116     uint32_t exclusive : 1;
117     uint32_t delegated : 1; /* whether or not there is state on the server */
118     uint32_t id : 30;
119 } nfs41_lock_state;
120 
121 /* nfs41_open_state reference counting:
122  * one reference is held implicitly by the driver (initialized to 1 on
123  * OPEN and released on CLOSE). other references must be held during
124  * upcalls to prevent a parallel CLOSE from freeing it prematurely. by
125  * calling upcall_open_state_ref() when parsing the upcall, you are
126  * guaranteed a matching dereference on upcall_cleanup() */
127 typedef struct __nfs41_open_state {
128     nfs41_abs_path path;
129     nfs41_path_fh parent;
130     nfs41_path_fh file;
131     nfs41_readdir_cookie cookie;
132     struct __nfs41_session *session;
133     uint32_t type;
134     bool_t do_close;
135     stateid4 stateid;
136     state_owner4 owner;
137     struct __pnfs_layout_state *layout;
138     struct list_entry client_entry; /* entry in nfs41_client.opens */
139     SRWLOCK lock;
140     LONG ref_count;
141     uint32_t share_access;
142     uint32_t share_deny;
143     uint64_t pnfs_last_offset; /* for layoutcommit */
144 
145     struct {
146         nfs41_delegation_state *state;
147         bool_t reclaim;
148         CONDITION_VARIABLE cond;
149     } delegation;
150 
151     struct { /* list of open lock state for recovery */
152         stateid4 stateid;
153         struct list_entry list;
154         uint32_t counter;
155         CRITICAL_SECTION lock;
156     } locks;
157 
158     struct {
159         struct _FILE_GET_EA_INFORMATION *list;
160         uint32_t index;
161         CRITICAL_SECTION lock;
162     } ea;
163 
164     HANDLE srv_open; /* for data cache invalidation */
165 } nfs41_open_state;
166 
167 typedef struct __nfs41_rpc_clnt {
168     struct __rpc_client *rpc;
169     SRWLOCK lock;
170     HANDLE cond;
171     struct __nfs41_client *client;
172     multi_addr4 addrs;
173     uint32_t addr_index; /* index of addr we're using */
174     uint32_t wsize;
175     uint32_t rsize;
176     uint32_t version;
177     uint32_t sec_flavor;
178     uint32_t uid;
179     uint32_t gid;
180     char server_name[NI_MAXHOST];
181     bool_t is_valid_session;
182     bool_t in_recovery;
183     bool_t needcb;
184 } nfs41_rpc_clnt;
185 
186 struct client_state {
187     struct list_entry opens; /* list of associated nfs41_open_state */
188     struct list_entry delegations; /* list of associated delegations */
189     CRITICAL_SECTION lock;
190 };
191 
192 typedef struct __nfs41_client {
193     nfs41_server *server;
194     client_owner4 owner;
195     uint64_t clnt_id;
196     uint32_t seq_id;
197     uint32_t roles;
198     SRWLOCK exid_lock;
199     struct __nfs41_session *session;
200     SRWLOCK session_lock;
201     nfs41_rpc_clnt *rpc;
202     bool_t is_data;
203     struct pnfs_layout_list *layouts;
204     struct pnfs_file_device_list *devices;
205     struct list_entry root_entry; /* position in nfs41_root.clients */
206     struct __nfs41_root *root;
207 
208     struct {
209         CONDITION_VARIABLE cond;
210         CRITICAL_SECTION lock;
211         bool_t in_recovery;
212     } recovery;
213 
214     /* for state recovery on server reboot */
215     struct client_state state;
216 } nfs41_client;
217 
218 #define NFS41_MAX_NUM_SLOTS NFS41_MAX_RPC_REQS
219 typedef struct __nfs41_slot_table {
220     uint32_t seq_nums[NFS41_MAX_NUM_SLOTS];
221     uint32_t used_slots[NFS41_MAX_NUM_SLOTS];
222     uint32_t max_slots;
223     uint32_t highest_used;
224     uint32_t num_used;
225     ULONGLONG target_delay;
226     CRITICAL_SECTION lock;
227     CONDITION_VARIABLE cond;
228 } nfs41_slot_table;
229 
230 typedef struct __nfs41_channel_attrs {
231     uint32_t                ca_headerpadsize;
232     uint32_t                ca_maxrequestsize;
233     uint32_t                ca_maxresponsesize;
234     uint32_t                ca_maxresponsesize_cached;
235     uint32_t                ca_maxoperations;
236     uint32_t                ca_maxrequests;
237     uint32_t                *ca_rdma_ird;
238 } nfs41_channel_attrs;
239 
240 struct replay_cache {
241     unsigned char buffer[NFS41_MAX_SERVER_CACHE];
242     uint32_t length;
243 };
244 
245 typedef struct __nfs41_cb_session {
246     struct {
247         struct replay_cache arg;
248         struct replay_cache res;
249     } replay;
250     const unsigned char *cb_sessionid; /* -> nfs41_session.session_id */
251     uint32_t cb_seqnum;
252     uint32_t cb_slotid;
253 } nfs41_cb_session;
254 
255 typedef struct __nfs41_session {
256     nfs41_client *client;
257     unsigned char session_id[NFS4_SESSIONID_SIZE];
258     nfs41_channel_attrs fore_chan_attrs;
259     nfs41_channel_attrs back_chan_attrs;
260     uint32_t lease_time;
261     nfs41_slot_table table;
262     // array of slots
263     HANDLE renew_thread;
264     bool_t isValidState;
265     uint32_t flags;
266     nfs41_cb_session cb_session;
267 } nfs41_session;
268 
269 /* nfs41_root reference counting:
270  * similar to nfs41_open_state, the driver holds an implicit reference
271  * between MOUNT and UNMOUNT. all other upcalls use upcall_root_ref() on
272  * upcall_parse(), which prevents the root/clients from being freed and
273  * guarantees a matching deref on upcall_cleanup() */
274 typedef struct __nfs41_root {
275     client_owner4 client_owner;
276     CRITICAL_SECTION lock;
277     struct list_entry clients;
278     uint32_t wsize;
279     uint32_t rsize;
280     LONG ref_count;
281     uint32_t uid;
282     uint32_t gid;
283     DWORD sec_flavor;
284 } nfs41_root;
285 
286 
287 /* nfs41_namespace.c */
288 int nfs41_root_create(
289     IN const char *name,
290     IN uint32_t sec_flavor,
291     IN uint32_t wsize,
292     IN uint32_t rsize,
293     OUT nfs41_root **root_out);
294 
295 void nfs41_root_ref(
296     IN nfs41_root *root);
297 
298 void nfs41_root_deref(
299     IN nfs41_root *root);
300 
301 int nfs41_root_mount_addrs(
302     IN nfs41_root *root,
303     IN const multi_addr4 *addrs,
304     IN bool_t is_data,
305     IN OPTIONAL uint32_t lease_time,
306     OUT nfs41_client **client_out);
307 
308 int nfs41_root_mount_server(
309     IN nfs41_root *root,
310     IN nfs41_server *server,
311     IN bool_t is_data,
312     IN OPTIONAL uint32_t lease_time,
313     OUT nfs41_client **client_out);
314 
315 int nfs41_root_mount_referral(
316     IN nfs41_root *root,
317     IN const fs_locations4 *locations,
318     OUT const fs_location4 **loc_out,
319     OUT nfs41_client **client_out);
320 
321 static __inline nfs41_session* nfs41_root_session(
322     IN nfs41_root *root)
323 {
324     nfs41_client *client;
325     /* return a session for the server at the root of the namespace.
326      * because we created it on mount, it's the first one in the list */
327     EnterCriticalSection(&root->lock);
328     client = list_container(root->clients.next, nfs41_client, root_entry);
329     LeaveCriticalSection(&root->lock);
330     return client->session;
331 }
332 
333 
334 /* nfs41_session.c */
335 int nfs41_session_create(
336     IN nfs41_client *client,
337     IN nfs41_session **session_out);
338 
339 int nfs41_session_renew(
340     IN nfs41_session *session);
341 
342 int nfs41_session_set_lease(
343     IN nfs41_session *session,
344     IN uint32_t lease_time);
345 
346 void nfs41_session_free(
347     IN nfs41_session *session);
348 
349 void nfs41_session_bump_seq(
350     IN nfs41_session *session,
351     IN uint32_t slotid,
352     IN uint32_t target_highest_slotid);
353 
354 void nfs41_session_free_slot(
355     IN nfs41_session *session,
356     IN uint32_t slotid);
357 
358 void nfs41_session_get_slot(
359     IN nfs41_session *session,
360     OUT uint32_t *slot,
361     OUT uint32_t *seq,
362     OUT uint32_t *highest);
363 
364 int nfs41_session_recall_slot(
365     IN nfs41_session *session,
366     IN OUT uint32_t target_highest_slotid);
367 
368 struct __nfs41_sequence_args;
369 void nfs41_session_sequence(
370     struct __nfs41_sequence_args *args,
371     nfs41_session *session,
372     bool_t cachethis);
373 
374 int nfs41_session_bad_slot(
375     IN nfs41_session *session,
376     IN OUT struct __nfs41_sequence_args *args);
377 
378 
379 /* nfs41_server.c */
380 void nfs41_server_list_init();
381 
382 int nfs41_server_resolve(
383     IN const char *hostname,
384     IN unsigned short port,
385     OUT multi_addr4 *addrs);
386 
387 int nfs41_server_find_or_create(
388     IN const char *server_owner_major_id,
389     IN const char *server_scope,
390     IN const netaddr4 *addr,
391     OUT nfs41_server **server_out);
392 
393 void nfs41_server_ref(
394     IN nfs41_server *server);
395 
396 void nfs41_server_deref(
397     IN nfs41_server *server);
398 
399 void nfs41_server_addrs(
400     IN nfs41_server *server,
401     OUT multi_addr4 *addrs);
402 
403 
404 /* nfs41_client.c */
405 int nfs41_client_owner(
406     IN const char *name,
407     IN uint32_t sec_flavor,
408     OUT client_owner4 *owner);
409 
410 uint32_t nfs41_exchange_id_flags(
411     IN bool_t is_data);
412 
413 struct __nfs41_exchange_id_res;
414 
415 int nfs41_client_create(
416     IN nfs41_rpc_clnt *rpc,
417     IN const client_owner4 *owner,
418     IN bool_t is_data,
419     IN const struct __nfs41_exchange_id_res *exchangeid,
420     OUT nfs41_client **client_out);
421 
422 int nfs41_client_renew(
423     IN nfs41_client *client);
424 
425 void nfs41_client_free(
426     IN nfs41_client *client);
427 
428 static __inline nfs41_server* client_server(
429     IN nfs41_client *client)
430 {
431     /* the client's server could change during nfs41_client_renew(),
432      * so access to client->server must be protected */
433     nfs41_server *server;
434     AcquireSRWLockShared(&client->exid_lock);
435     server = client->server;
436     ReleaseSRWLockShared(&client->exid_lock);
437     return server;
438 }
439 
440 
441 /* nfs41_superblock.c */
442 int nfs41_superblock_for_fh(
443     IN nfs41_session *session,
444     IN const nfs41_fsid *fsid,
445     IN const nfs41_fh *parent OPTIONAL,
446     OUT nfs41_path_fh *file);
447 
448 static __inline void nfs41_superblock_getattr_mask(
449     IN const nfs41_superblock *superblock,
450     OUT bitmap4 *attrs)
451 {
452     memcpy(attrs, &superblock->default_getattr, sizeof(bitmap4));
453 }
454 static __inline void nfs41_superblock_supported_attrs(
455     IN const nfs41_superblock *superblock,
456     IN OUT bitmap4 *attrs)
457 {
458     bitmap_intersect(attrs, &superblock->supported_attrs);
459 }
460 static __inline void nfs41_superblock_supported_attrs_exclcreat(
461     IN const nfs41_superblock *superblock,
462     IN OUT bitmap4 *attrs)
463 {
464     bitmap_intersect(attrs, &superblock->suppattr_exclcreat);
465 }
466 
467 struct _FILE_FS_ATTRIBUTE_INFORMATION;
468 void nfs41_superblock_fs_attributes(
469     IN const nfs41_superblock *superblock,
470     OUT struct _FILE_FS_ATTRIBUTE_INFORMATION *FsAttrs);
471 
472 void nfs41_superblock_space_changed(
473     IN nfs41_superblock *superblock);
474 
475 void nfs41_superblock_list_init(
476     IN nfs41_superblock_list *superblocks);
477 
478 void nfs41_superblock_list_free(
479     IN nfs41_superblock_list *superblocks);
480 
481 
482 /* nfs41_rpc.c */
483 int nfs41_rpc_clnt_create(
484     IN const multi_addr4 *addrs,
485     IN uint32_t wsize,
486     IN uint32_t rsize,
487     IN uint32_t uid,
488     IN uint32_t gid,
489     IN uint32_t sec_flavor,
490     OUT nfs41_rpc_clnt **rpc_out);
491 
492 void nfs41_rpc_clnt_free(
493     IN nfs41_rpc_clnt *rpc);
494 
495 int nfs41_send_compound(
496     IN nfs41_rpc_clnt *rpc,
497     IN char *inbuf,
498     OUT char *outbuf);
499 
500 static __inline netaddr4* nfs41_rpc_netaddr(
501     IN nfs41_rpc_clnt *rpc)
502 {
503     uint32_t id;
504     AcquireSRWLockShared(&rpc->lock);
505     /* only addr_index needs to be protected, as rpc->addrs is write-once */
506     id = rpc->addr_index;
507     ReleaseSRWLockShared(&rpc->lock);
508 
509     /* return the netaddr used to create the rpc client */
510     return &rpc->addrs.arr[id];
511 }
512 
513 
514 /* open.c */
515 void nfs41_open_state_ref(
516     IN nfs41_open_state *state);
517 
518 void nfs41_open_state_deref(
519     IN nfs41_open_state *state);
520 
521 struct __stateid_arg;
522 void nfs41_open_stateid_arg(
523     IN nfs41_open_state *state,
524     OUT struct __stateid_arg *arg);
525 
526 
527 /* ea.c */
528 int nfs41_ea_set(
529     IN nfs41_open_state *state,
530     IN struct _FILE_FULL_EA_INFORMATION *ea);
531 
532 #endif /* __NFS41__ */
533