1 /* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
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.
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.
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
29 struct __nfs41_session
;
30 struct __nfs41_client
;
34 struct _FILE_GET_EA_INFORMATION
;
35 struct _FILE_FULL_EA_INFORMATION
;
37 typedef struct __nfs41_superblock
{
39 struct list_entry entry
; /* position in nfs41_server.superblocks */
41 bitmap4 supported_attrs
;
42 bitmap4 suppattr_exclcreat
;
43 bitmap4 default_getattr
;
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;
59 /* variable filesystem attributes */
63 time_t cache_expiration
; /* applies to space_ attributes */
68 typedef struct __nfs41_superblock_list
{
69 struct list_entry head
;
71 } nfs41_superblock_list
;
74 multi_addr4 addrs
; /* list of addrs we've used with this server */
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 */
89 enum delegation_status
{
95 typedef struct __nfs41_delegation_state
{
96 open_delegation4 state
;
100 struct list_entry client_entry
; /* entry in nfs41_client.delegations */
103 enum delegation_status status
;
105 CONDITION_VARIABLE cond
;
107 bool_t revoked
; /* for recovery, accessed under client.state.lock */
109 HANDLE srv_open
; /* for rdbss cache invalidation */
110 } nfs41_delegation_state
;
112 typedef struct __nfs41_lock_state
{
113 struct list_entry open_entry
; /* entry in nfs41_open_state.locks */
116 uint32_t exclusive
: 1;
117 uint32_t delegated
: 1; /* whether or not there is state on the server */
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
{
129 nfs41_path_fh parent
;
131 nfs41_readdir_cookie cookie
;
132 struct __nfs41_session
*session
;
137 struct __pnfs_layout_state
*layout
;
138 struct list_entry client_entry
; /* entry in nfs41_client.opens */
141 uint32_t share_access
;
143 uint64_t pnfs_last_offset
; /* for layoutcommit */
146 nfs41_delegation_state
*state
;
148 CONDITION_VARIABLE cond
;
151 struct { /* list of open lock state for recovery */
153 struct list_entry list
;
155 CRITICAL_SECTION lock
;
159 struct _FILE_GET_EA_INFORMATION
*list
;
161 CRITICAL_SECTION lock
;
164 HANDLE srv_open
; /* for data cache invalidation */
167 typedef struct __nfs41_rpc_clnt
{
168 struct __rpc_client
*rpc
;
171 struct __nfs41_client
*client
;
173 uint32_t addr_index
; /* index of addr we're using */
180 char server_name
[NI_MAXHOST
];
181 bool_t is_valid_session
;
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
;
192 typedef struct __nfs41_client
{
193 nfs41_server
*server
;
199 struct __nfs41_session
*session
;
200 SRWLOCK session_lock
;
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
;
209 CONDITION_VARIABLE cond
;
210 CRITICAL_SECTION lock
;
214 /* for state recovery on server reboot */
215 struct client_state state
;
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
];
223 uint32_t highest_used
;
225 ULONGLONG target_delay
;
226 CRITICAL_SECTION lock
;
227 CONDITION_VARIABLE cond
;
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
;
240 struct replay_cache
{
241 unsigned char buffer
[NFS41_MAX_SERVER_CACHE
];
245 typedef struct __nfs41_cb_session
{
247 struct replay_cache arg
;
248 struct replay_cache res
;
250 const unsigned char *cb_sessionid
; /* -> nfs41_session.session_id */
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
;
261 nfs41_slot_table table
;
266 nfs41_cb_session cb_session
;
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
;
287 /* nfs41_namespace.c */
288 int nfs41_root_create(
290 IN
uint32_t sec_flavor
,
293 OUT nfs41_root
**root_out
);
296 IN nfs41_root
*root
);
298 void nfs41_root_deref(
299 IN nfs41_root
*root
);
301 int nfs41_root_mount_addrs(
303 IN
const multi_addr4
*addrs
,
305 IN OPTIONAL
uint32_t lease_time
,
306 OUT nfs41_client
**client_out
);
308 int nfs41_root_mount_server(
310 IN nfs41_server
*server
,
312 IN OPTIONAL
uint32_t lease_time
,
313 OUT nfs41_client
**client_out
);
315 int nfs41_root_mount_referral(
317 IN
const fs_locations4
*locations
,
318 OUT
const fs_location4
**loc_out
,
319 OUT nfs41_client
**client_out
);
321 static __inline nfs41_session
* nfs41_root_session(
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
;
334 /* nfs41_session.c */
335 int nfs41_session_create(
336 IN nfs41_client
*client
,
337 IN nfs41_session
**session_out
);
339 int nfs41_session_renew(
340 IN nfs41_session
*session
);
342 int nfs41_session_set_lease(
343 IN nfs41_session
*session
,
344 IN
uint32_t lease_time
);
346 void nfs41_session_free(
347 IN nfs41_session
*session
);
349 void nfs41_session_bump_seq(
350 IN nfs41_session
*session
,
352 IN
uint32_t target_highest_slotid
);
354 void nfs41_session_free_slot(
355 IN nfs41_session
*session
,
358 void nfs41_session_get_slot(
359 IN nfs41_session
*session
,
362 OUT
uint32_t *highest
);
364 int nfs41_session_recall_slot(
365 IN nfs41_session
*session
,
366 IN OUT
uint32_t target_highest_slotid
);
368 struct __nfs41_sequence_args
;
369 void nfs41_session_sequence(
370 struct __nfs41_sequence_args
*args
,
371 nfs41_session
*session
,
374 int nfs41_session_bad_slot(
375 IN nfs41_session
*session
,
376 IN OUT
struct __nfs41_sequence_args
*args
);
380 void nfs41_server_list_init();
382 int nfs41_server_resolve(
383 IN
const char *hostname
,
384 IN
unsigned short port
,
385 OUT multi_addr4
*addrs
);
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
);
393 void nfs41_server_ref(
394 IN nfs41_server
*server
);
396 void nfs41_server_deref(
397 IN nfs41_server
*server
);
399 void nfs41_server_addrs(
400 IN nfs41_server
*server
,
401 OUT multi_addr4
*addrs
);
405 int nfs41_client_owner(
407 IN
uint32_t sec_flavor
,
408 OUT client_owner4
*owner
);
410 uint32_t nfs41_exchange_id_flags(
413 struct __nfs41_exchange_id_res
;
415 int nfs41_client_create(
416 IN nfs41_rpc_clnt
*rpc
,
417 IN
const client_owner4
*owner
,
419 IN
const struct __nfs41_exchange_id_res
*exchangeid
,
420 OUT nfs41_client
**client_out
);
422 int nfs41_client_renew(
423 IN nfs41_client
*client
);
425 void nfs41_client_free(
426 IN nfs41_client
*client
);
428 static __inline nfs41_server
* client_server(
429 IN nfs41_client
*client
)
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
);
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
);
448 static __inline
void nfs41_superblock_getattr_mask(
449 IN
const nfs41_superblock
*superblock
,
452 memcpy(attrs
, &superblock
->default_getattr
, sizeof(bitmap4
));
454 static __inline
void nfs41_superblock_supported_attrs(
455 IN
const nfs41_superblock
*superblock
,
456 IN OUT bitmap4
*attrs
)
458 bitmap_intersect(attrs
, &superblock
->supported_attrs
);
460 static __inline
void nfs41_superblock_supported_attrs_exclcreat(
461 IN
const nfs41_superblock
*superblock
,
462 IN OUT bitmap4
*attrs
)
464 bitmap_intersect(attrs
, &superblock
->suppattr_exclcreat
);
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
);
472 void nfs41_superblock_space_changed(
473 IN nfs41_superblock
*superblock
);
475 void nfs41_superblock_list_init(
476 IN nfs41_superblock_list
*superblocks
);
478 void nfs41_superblock_list_free(
479 IN nfs41_superblock_list
*superblocks
);
483 int nfs41_rpc_clnt_create(
484 IN
const multi_addr4
*addrs
,
489 IN
uint32_t sec_flavor
,
490 OUT nfs41_rpc_clnt
**rpc_out
);
492 void nfs41_rpc_clnt_free(
493 IN nfs41_rpc_clnt
*rpc
);
495 int nfs41_send_compound(
496 IN nfs41_rpc_clnt
*rpc
,
500 static __inline netaddr4
* nfs41_rpc_netaddr(
501 IN nfs41_rpc_clnt
*rpc
)
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
);
509 /* return the netaddr used to create the rpc client */
510 return &rpc
->addrs
.arr
[id
];
515 void nfs41_open_state_ref(
516 IN nfs41_open_state
*state
);
518 void nfs41_open_state_deref(
519 IN nfs41_open_state
*state
);
521 struct __stateid_arg
;
522 void nfs41_open_stateid_arg(
523 IN nfs41_open_state
*state
,
524 OUT
struct __stateid_arg
*arg
);
529 IN nfs41_open_state
*state
,
530 IN
struct _FILE_FULL_EA_INFORMATION
*ea
);
532 #endif /* __NFS41__ */