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
28 #include "nfs41_ops.h"
29 #include "nfs41_compound.h"
30 #include "nfs41_xdr.h"
31 #include "name_cache.h"
32 #include "delegation.h"
33 #include "daemon_debug.h"
36 int nfs41_exchange_id(
37 IN nfs41_rpc_clnt
*rpc
,
38 IN client_owner4
*owner
,
40 OUT nfs41_exchange_id_res
*res_out
)
43 nfs41_compound compound
;
46 nfs41_exchange_id_args ex_id
;
48 compound_init(&compound
, &argop
, &resop
, "exchange_id");
50 compound_add_op(&compound
, OP_EXCHANGE_ID
, &ex_id
, res_out
);
51 ex_id
.eia_clientowner
= owner
;
52 ex_id
.eia_flags
= flags_in
;
53 ex_id
.eia_state_protect
.spa_how
= SP4_NONE
;
54 ex_id
.eia_client_impl_id
= NULL
;
56 res_out
->server_owner
.so_major_id_len
= NFS4_OPAQUE_LIMIT
;
57 res_out
->server_scope_len
= NFS4_OPAQUE_LIMIT
;
59 status
= nfs41_send_compound(rpc
, (char *)&compound
.args
,
60 (char *)&compound
.res
);
64 compound_error(status
= compound
.res
.status
);
69 // AGLO: 10/07/2009 we might want lookup these values from the registry
70 static int set_fore_channel_attrs(
71 IN nfs41_rpc_clnt
*rpc
,
73 OUT nfs41_channel_attrs
*attrs
)
75 attrs
->ca_headerpadsize
= 0;
76 attrs
->ca_maxrequestsize
= rpc
->wsize
;
77 attrs
->ca_maxresponsesize
= rpc
->rsize
;
78 attrs
->ca_maxresponsesize_cached
= NFS41_MAX_SERVER_CACHE
;
79 attrs
->ca_maxoperations
= 0xffffffff;
80 attrs
->ca_maxrequests
= max_req
;
81 attrs
->ca_rdma_ird
= NULL
;
85 // AGLO: 10/07/2009 we might want lookup these values from the registry
86 static int set_back_channel_attrs(
87 IN nfs41_rpc_clnt
*rpc
,
89 OUT nfs41_channel_attrs
*attrs
)
91 attrs
->ca_headerpadsize
= 0;
92 attrs
->ca_maxrequestsize
= rpc
->wsize
;
93 attrs
->ca_maxresponsesize
= rpc
->rsize
;
94 attrs
->ca_maxresponsesize_cached
= NFS41_MAX_SERVER_CACHE
;
95 attrs
->ca_maxoperations
= 0xffffffff;
96 attrs
->ca_maxrequests
= max_req
;
97 attrs
->ca_rdma_ird
= NULL
;
101 int nfs41_create_session(nfs41_client
*clnt
, nfs41_session
*session
, bool_t try_recovery
)
104 nfs41_compound compound
;
107 nfs41_create_session_args req
= { 0 };
108 nfs41_create_session_res reply
= { 0 };
110 compound_init(&compound
, &argop
, &resop
, "create_session");
112 compound_add_op(&compound
, OP_CREATE_SESSION
, &req
, &reply
);
114 AcquireSRWLockShared(&clnt
->exid_lock
);
115 req
.csa_clientid
= clnt
->clnt_id
;
116 req
.csa_sequence
= clnt
->seq_id
;
117 ReleaseSRWLockShared(&clnt
->exid_lock
);
118 req
.csa_flags
= session
->flags
;
119 req
.csa_cb_program
= NFS41_RPC_CBPROGRAM
;
120 req
.csa_cb_secparams
[0].type
= 0; /* AUTH_NONE */
121 req
.csa_cb_secparams
[1].type
= 1; /* AUTH_SYS */
122 req
.csa_cb_secparams
[1].u
.auth_sys
.machinename
= clnt
->rpc
->server_name
;
123 req
.csa_cb_secparams
[1].u
.auth_sys
.stamp
= (uint32_t)time(NULL
);
125 // ca_maxrequests should be gotten from the rpc layer
126 set_fore_channel_attrs(clnt
->rpc
,
127 NFS41_MAX_RPC_REQS
, &req
.csa_fore_chan_attrs
);
128 set_back_channel_attrs(clnt
->rpc
,
129 1, &req
.csa_back_chan_attrs
);
131 reply
.csr_sessionid
= session
->session_id
;
132 reply
.csr_fore_chan_attrs
= &session
->fore_chan_attrs
;
133 reply
.csr_back_chan_attrs
= &session
->back_chan_attrs
;
135 status
= compound_encode_send_decode(session
, &compound
, try_recovery
);
139 if (compound_error(status
= compound
.res
.status
))
142 print_hexbuf(1, (unsigned char *)"session id: ", session
->session_id
, NFS4_SESSIONID_SIZE
);
143 // check that csa_sequence is same as csr_sequence
144 if (reply
.csr_sequence
!= clnt
->seq_id
) {
145 eprintf("ERROR: CREATE_SESSION: csa_sequence %d != "
146 "csr_sequence %d\n", clnt
->seq_id
, reply
.csr_sequence
);
147 status
= NFS4ERR_SEQ_MISORDERED
;
149 } else clnt
->seq_id
++;
151 if (reply
.csr_flags
!= req
.csa_flags
) {
152 eprintf("WARNING: requested session flags %x received %x\n",
153 req
.csa_flags
, reply
.csr_flags
);
154 if ((session
->flags
& CREATE_SESSION4_FLAG_CONN_BACK_CHAN
) &&
155 !(reply
.csr_flags
& CREATE_SESSION4_FLAG_CONN_BACK_CHAN
))
156 eprintf("WARNING: we asked to use this session for callbacks but "
158 if ((session
->flags
& CREATE_SESSION4_FLAG_PERSIST
) &&
159 !(reply
.csr_flags
& CREATE_SESSION4_FLAG_PERSIST
))
160 eprintf("WARNING: we asked for persistent session but "
162 session
->flags
= reply
.csr_flags
;
165 dprintf(1, "session flags %x\n", reply
.csr_flags
);
167 dprintf(1, "session fore_chan_attrs:\n"
168 " %-32s%d\n %-32s%d\n %-32s%d\n %-32s%d\n %-32s%d\n %-32s%d\n",
169 "headerpadsize", session
->fore_chan_attrs
.ca_headerpadsize
,
170 "maxrequestsize", session
->fore_chan_attrs
.ca_maxrequestsize
,
171 "maxresponsesize", session
->fore_chan_attrs
.ca_maxresponsesize
,
172 "maxresponsesize_cached", session
->fore_chan_attrs
.ca_maxresponsesize_cached
,
173 "maxoperations", session
->fore_chan_attrs
.ca_maxoperations
,
174 "maxrequests", session
->fore_chan_attrs
.ca_maxrequests
);
175 dprintf(1, "client supports %d max rpc slots, but server has %d\n",
176 session
->table
.max_slots
, session
->fore_chan_attrs
.ca_maxrequests
);
177 /* use the server's ca_maxrequests unless it's bigger than our array */
178 session
->table
.max_slots
= min(session
->table
.max_slots
,
179 session
->fore_chan_attrs
.ca_maxrequests
);
185 enum nfsstat4
nfs41_bind_conn_to_session(
186 IN nfs41_rpc_clnt
*rpc
,
187 IN
const unsigned char *sessionid
,
188 IN
enum channel_dir_from_client4 dir
)
191 nfs41_compound compound
;
194 nfs41_bind_conn_to_session_args bind_args
= { 0 };
195 nfs41_bind_conn_to_session_res bind_res
= { 0 };
197 compound_init(&compound
, &argop
, &resop
, "bind_conn_to_session");
199 compound_add_op(&compound
, OP_BIND_CONN_TO_SESSION
, &bind_args
, &bind_res
);
200 bind_args
.sessionid
= (unsigned char *)sessionid
;
203 status
= nfs41_send_compound(rpc
,
204 (char*)&compound
.args
, (char*)&compound
.res
);
208 compound_error(status
= compound
.res
.status
);
214 int nfs41_destroy_session(
215 IN nfs41_session
*session
)
218 nfs41_compound compound
;
221 nfs41_destroy_session_args ds_args
;
222 nfs41_destroy_session_res ds_res
;
224 compound_init(&compound
, &argop
, &resop
, "destroy_session");
226 compound_add_op(&compound
, OP_DESTROY_SESSION
, &ds_args
, &ds_res
);
227 ds_args
.dsa_sessionid
= session
->session_id
;
229 /* don't attempt to recover from BADSESSION/STALE_CLIENTID */
230 status
= compound_encode_send_decode(session
, &compound
, FALSE
);
234 status
= compound
.res
.status
;
236 eprintf("%s failed with status %d.\n",
237 nfs_opnum_to_string(OP_DESTROY_SESSION
), status
);
242 int nfs41_destroy_clientid(
243 IN nfs41_rpc_clnt
*rpc
,
244 IN
uint64_t clientid
)
247 nfs41_compound compound
;
250 nfs41_destroy_clientid_args dc_args
;
251 nfs41_destroy_clientid_res dc_res
;
253 compound_init(&compound
, &argops
, &resops
, "destroy_clientid");
255 compound_add_op(&compound
, OP_DESTROY_CLIENTID
, &dc_args
, &dc_res
);
256 dc_args
.dca_clientid
= clientid
;
258 status
= nfs41_send_compound(rpc
, (char *)&compound
.args
,
259 (char *)&compound
.res
);
263 compound_error(status
= compound
.res
.status
);
268 enum nfsstat4
nfs41_reclaim_complete(
269 IN nfs41_session
*session
)
271 enum nfsstat4 status
= NFS4_OK
;
272 nfs41_compound compound
;
273 nfs_argop4 argops
[2];
274 nfs_resop4 resops
[2];
275 nfs41_sequence_args sequence_args
;
276 nfs41_sequence_res sequence_res
;
277 nfs41_reclaim_complete_res reclaim_res
;
279 compound_init(&compound
, argops
, resops
, "reclaim_complete");
281 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
282 nfs41_session_sequence(&sequence_args
, session
, 0);
284 compound_add_op(&compound
, OP_RECLAIM_COMPLETE
, NULL
, &reclaim_res
);
286 /* don't attempt to recover from BADSESSION */
287 status
= compound_encode_send_decode(session
, &compound
, FALSE
);
291 compound_error(status
= compound
.res
.status
);
296 static void open_delegation_return(
297 IN nfs41_session
*session
,
298 IN nfs41_path_fh
*file
,
299 IN open_delegation4
*delegation
,
300 IN bool_t try_recovery
)
305 if (delegation
->type
== OPEN_DELEGATE_NONE
||
306 delegation
->type
== OPEN_DELEGATE_NONE_EXT
)
309 /* return the delegation */
311 stateid
.delegation
= NULL
;
312 stateid
.type
= STATEID_DELEG_FILE
;
313 memcpy(&stateid
.stateid
, &delegation
->stateid
, sizeof(stateid4
));
315 status
= nfs41_delegreturn(session
, file
, &stateid
, try_recovery
);
317 /* clear the delegation type returned by nfs41_open() */
318 delegation
->type
= OPEN_DELEGATE_NONE
;
321 static void open_update_cache(
322 IN nfs41_session
*session
,
323 IN nfs41_path_fh
*parent
,
324 IN nfs41_path_fh
*file
,
325 IN bool_t try_recovery
,
326 IN open_delegation4
*delegation
,
327 IN bool_t already_delegated
,
328 IN change_info4
*changeinfo
,
329 IN nfs41_getattr_res
*dir_attrs
,
330 IN nfs41_getattr_res
*file_attrs
)
332 struct nfs41_name_cache
*cache
= session_name_cache(session
);
335 /* update the attributes of the parent directory */
336 memcpy(&dir_attrs
->info
->attrmask
, &dir_attrs
->obj_attributes
.attrmask
,
338 nfs41_attr_cache_update(cache
, parent
->fh
.fileid
, dir_attrs
->info
);
340 /* add the file handle and attributes to the name cache */
341 memcpy(&file_attrs
->info
->attrmask
, &file_attrs
->obj_attributes
.attrmask
,
344 AcquireSRWLockShared(&file
->path
->lock
);
345 status
= nfs41_name_cache_insert(cache
, file
->path
->path
, &file
->name
,
346 &file
->fh
, file_attrs
->info
, changeinfo
,
347 already_delegated
? OPEN_DELEGATE_NONE
: delegation
->type
);
348 ReleaseSRWLockShared(&file
->path
->lock
);
350 if (status
== ERROR_TOO_MANY_OPEN_FILES
) {
351 /* the cache won't accept any more delegations; ask the client to
352 * return a delegation to free up a slot in the attribute cache */
353 status
= nfs41_client_delegation_return_lru(session
->client
);
354 if (status
== NFS4_OK
)
355 goto retry_cache_insert
;
358 if (status
&& delegation
->type
!= OPEN_DELEGATE_NONE
) {
359 /* if we can't make room in the cache, return this
360 * delegation immediately to free resources on the server */
361 open_delegation_return(session
, file
, delegation
, try_recovery
);
362 goto retry_cache_insert
;
367 IN nfs41_session
*session
,
368 IN nfs41_path_fh
*parent
,
369 IN nfs41_path_fh
*file
,
370 IN state_owner4
*owner
,
371 IN open_claim4
*claim
,
375 IN
uint32_t how_mode
,
376 IN OPTIONAL nfs41_file_info
*createattrs
,
377 IN bool_t try_recovery
,
378 OUT stateid4
*stateid
,
379 OUT open_delegation4
*delegation
,
380 OUT OPTIONAL nfs41_file_info
*info
)
383 nfs41_compound compound
;
384 nfs_argop4 argops
[8];
385 nfs_resop4 resops
[8];
386 nfs41_sequence_args sequence_args
;
387 nfs41_sequence_res sequence_res
;
388 nfs41_putfh_args putfh_args
[2];
389 nfs41_putfh_res putfh_res
[2];
390 nfs41_op_open_args open_args
;
391 nfs41_op_open_res open_res
;
392 nfs41_getfh_res getfh_res
;
393 bitmap4 attr_request
;
394 nfs41_getattr_args getattr_args
;
395 nfs41_getattr_res getattr_res
, pgetattr_res
;
396 nfs41_savefh_res savefh_res
;
397 nfs41_restorefh_res restorefh_res
;
398 nfs41_file_info tmp_info
, dir_info
;
399 bool_t current_fh_is_dir
;
400 bool_t already_delegated
= delegation
->type
== OPEN_DELEGATE_READ
401 || delegation
->type
== OPEN_DELEGATE_WRITE
;
403 /* depending on the claim type, OPEN expects CURRENT_FH set
404 * to either the parent directory, or to the file itself */
405 switch (claim
->claim
) {
407 case CLAIM_DELEGATE_CUR
:
408 case CLAIM_DELEGATE_PREV
:
409 /* CURRENT_FH: directory */
410 current_fh_is_dir
= TRUE
;
411 /* SEQUENCE; PUTFH(dir); SAVEFH; OPEN;
412 * GETFH(file); GETATTR(file); RESTOREFH(dir); GETATTR */
413 nfs41_superblock_getattr_mask(parent
->fh
.superblock
, &attr_request
);
417 case CLAIM_DELEG_CUR_FH
:
418 case CLAIM_DELEG_PREV_FH
:
420 /* CURRENT_FH: file being opened */
421 current_fh_is_dir
= FALSE
;
422 /* SEQUENCE; PUTFH(file); OPEN; GETATTR(file); PUTFH(dir); GETATTR */
423 nfs41_superblock_getattr_mask(file
->fh
.superblock
, &attr_request
);
430 attr_request
.arr
[0] |= FATTR4_WORD0_FSID
;
432 compound_init(&compound
, argops
, resops
, "open");
434 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
435 nfs41_session_sequence(&sequence_args
, session
, 1);
437 if (current_fh_is_dir
) {
438 /* CURRENT_FH: directory */
439 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
[0], &putfh_res
[0]);
440 putfh_args
[0].file
= parent
;
441 putfh_args
[0].in_recovery
= 0;
443 compound_add_op(&compound
, OP_SAVEFH
, NULL
, &savefh_res
);
445 /* CURRENT_FH: file being opened */
446 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
[0], &putfh_res
[0]);
447 putfh_args
[0].file
= file
;
448 putfh_args
[0].in_recovery
= 0;
451 compound_add_op(&compound
, OP_OPEN
, &open_args
, &open_res
);
453 #ifdef DISABLE_FILE_DELEGATIONS
454 open_args
.share_access
= allow
| OPEN4_SHARE_ACCESS_WANT_NO_DELEG
;
456 open_args
.share_access
= allow
;
458 open_args
.share_deny
= deny
;
459 open_args
.owner
= owner
;
460 open_args
.openhow
.opentype
= create
;
461 open_args
.openhow
.how
.mode
= how_mode
;
462 open_args
.openhow
.how
.createattrs
= createattrs
;
463 if (how_mode
== EXCLUSIVE4_1
) {
464 DWORD tid
= GetCurrentThreadId();
465 time((time_t*)open_args
.openhow
.how
.createverf
);
466 memcpy(open_args
.openhow
.how
.createverf
+4, &tid
, sizeof(tid
));
467 /* mask unsupported attributes */
468 nfs41_superblock_supported_attrs_exclcreat(
469 parent
->fh
.superblock
, &createattrs
->attrmask
);
470 } else if (createattrs
) {
471 /* mask unsupported attributes */
472 nfs41_superblock_supported_attrs(
473 parent
->fh
.superblock
, &createattrs
->attrmask
);
475 open_args
.claim
= claim
;
476 open_res
.resok4
.stateid
= stateid
;
477 open_res
.resok4
.delegation
= delegation
;
479 if (current_fh_is_dir
) {
480 compound_add_op(&compound
, OP_GETFH
, NULL
, &getfh_res
);
481 getfh_res
.fh
= &file
->fh
;
484 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
485 getattr_args
.attr_request
= &attr_request
;
486 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
487 getattr_res
.info
= info
;
489 if (current_fh_is_dir
) {
490 compound_add_op(&compound
, OP_RESTOREFH
, NULL
, &restorefh_res
);
492 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
[1], &putfh_res
[1]);
493 putfh_args
[1].file
= parent
;
494 putfh_args
[1].in_recovery
= 0;
497 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &pgetattr_res
);
498 getattr_args
.attr_request
= &attr_request
;
499 pgetattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
500 pgetattr_res
.info
= &dir_info
;
502 status
= compound_encode_send_decode(session
, &compound
, try_recovery
);
506 if (compound_error(status
= compound
.res
.status
))
509 if (dir_info
.type
== NF4ATTRDIR
) {
510 file
->fh
.superblock
= parent
->fh
.superblock
;
514 /* fill in the file handle's fileid and superblock */
515 file
->fh
.fileid
= info
->fileid
;
516 status
= nfs41_superblock_for_fh(session
, &info
->fsid
, &parent
->fh
, file
);
520 if (create
== OPEN4_CREATE
)
521 nfs41_superblock_space_changed(file
->fh
.superblock
);
523 /* update the name/attr cache with the results */
524 open_update_cache(session
, parent
, file
, try_recovery
, delegation
,
525 already_delegated
, &open_res
.resok4
.cinfo
, &pgetattr_res
, &getattr_res
);
531 IN nfs41_session
*session
,
533 IN nfs41_file_info
*createattrs
,
534 IN OPTIONAL
const char *symlink
,
535 IN nfs41_path_fh
*parent
,
536 OUT nfs41_path_fh
*file
,
537 OUT nfs41_file_info
*info
)
540 nfs41_compound compound
;
541 nfs_argop4 argops
[8];
542 nfs_resop4 resops
[8];
543 nfs41_sequence_args sequence_args
;
544 nfs41_sequence_res sequence_res
;
545 nfs41_putfh_args putfh_args
;
546 nfs41_putfh_res putfh_res
;
547 nfs41_create_args create_args
;
548 nfs41_create_res create_res
;
549 nfs41_getfh_res getfh_res
;
550 nfs41_getattr_args getattr_args
;
551 nfs41_getattr_res getattr_res
, pgetattr_res
;
552 bitmap4 attr_request
;
553 nfs41_file_info dir_info
;
554 nfs41_savefh_res savefh_res
;
555 nfs41_restorefh_res restorefh_res
;
557 nfs41_superblock_getattr_mask(parent
->fh
.superblock
, &attr_request
);
559 compound_init(&compound
, argops
, resops
, "create");
561 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
562 nfs41_session_sequence(&sequence_args
, session
, 1);
564 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
565 putfh_args
.file
= parent
;
566 putfh_args
.in_recovery
= 0;
568 compound_add_op(&compound
, OP_SAVEFH
, NULL
, &savefh_res
);
570 compound_add_op(&compound
, OP_CREATE
, &create_args
, &create_res
);
571 create_args
.objtype
.type
= type
;
572 if (type
== NF4LNK
) {
573 create_args
.objtype
.u
.lnk
.linkdata
= symlink
;
574 create_args
.objtype
.u
.lnk
.linkdata_len
= (uint32_t)strlen(symlink
);
576 create_args
.name
= &file
->name
;
577 create_args
.createattrs
= createattrs
;
578 nfs41_superblock_supported_attrs(
579 parent
->fh
.superblock
, &createattrs
->attrmask
);
581 compound_add_op(&compound
, OP_GETFH
, NULL
, &getfh_res
);
582 getfh_res
.fh
= &file
->fh
;
584 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
585 getattr_args
.attr_request
= &attr_request
;
586 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
587 getattr_res
.info
= info
;
589 compound_add_op(&compound
, OP_RESTOREFH
, NULL
, &restorefh_res
);
591 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &pgetattr_res
);
592 getattr_args
.attr_request
= &attr_request
;
593 pgetattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
594 pgetattr_res
.info
= &dir_info
;
596 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
600 if (compound_error(status
= compound
.res
.status
))
603 /* fill in the file handle's fileid and superblock */
604 file
->fh
.fileid
= info
->fileid
;
605 file
->fh
.superblock
= parent
->fh
.superblock
;
607 /* update the attributes of the parent directory */
608 memcpy(&dir_info
.attrmask
, &pgetattr_res
.obj_attributes
.attrmask
,
610 nfs41_attr_cache_update(session_name_cache(session
),
611 parent
->fh
.fileid
, &dir_info
);
613 /* add the new file handle and attributes to the name cache */
614 memcpy(&info
->attrmask
, &getattr_res
.obj_attributes
.attrmask
,
616 AcquireSRWLockShared(&file
->path
->lock
);
617 nfs41_name_cache_insert(session_name_cache(session
),
618 file
->path
->path
, &file
->name
, &file
->fh
,
619 info
, &create_res
.cinfo
, OPEN_DELEGATE_NONE
);
620 ReleaseSRWLockShared(&file
->path
->lock
);
622 nfs41_superblock_space_changed(file
->fh
.superblock
);
628 IN nfs41_session
*session
,
629 IN nfs41_path_fh
*file
,
630 IN stateid_arg
*stateid
)
633 nfs41_compound compound
;
634 nfs_argop4 argops
[4];
635 nfs_resop4 resops
[4];
636 nfs41_sequence_args sequence_args
;
637 nfs41_sequence_res sequence_res
;
638 nfs41_putfh_args putfh_args
;
639 nfs41_putfh_res putfh_res
;
640 nfs41_op_close_args close_args
;
641 nfs41_op_close_res close_res
;
642 nfs41_getattr_args getattr_args
;
643 nfs41_getattr_res getattr_res
;
644 bitmap4 attr_request
;
645 nfs41_file_info info
;
647 nfs41_superblock_getattr_mask(file
->fh
.superblock
, &attr_request
);
649 compound_init(&compound
, argops
, resops
, "close");
651 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
652 nfs41_session_sequence(&sequence_args
, session
, 1);
654 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
655 putfh_args
.file
= file
;
656 putfh_args
.in_recovery
= 0;
658 compound_add_op(&compound
, OP_CLOSE
, &close_args
, &close_res
);
659 close_args
.stateid
= stateid
;
661 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
662 getattr_args
.attr_request
= &attr_request
;
663 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
664 getattr_res
.info
= &info
;
666 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
670 if (compound_error(status
= compound
.res
.status
))
673 if (info
.type
== NF4NAMEDATTR
)
676 /* update the attributes of the parent directory */
677 memcpy(&info
.attrmask
, &getattr_res
.obj_attributes
.attrmask
,
679 nfs41_attr_cache_update(session_name_cache(session
),
680 file
->fh
.fileid
, &info
);
686 IN nfs41_session
*session
,
687 IN nfs41_path_fh
*file
,
688 IN stateid_arg
*stateid
,
689 IN
unsigned char *data
,
690 IN
uint32_t data_len
,
692 IN
enum stable_how4 stable
,
693 OUT
uint32_t *bytes_written
,
694 OUT nfs41_write_verf
*verf
,
695 OUT nfs41_file_info
*cinfo
)
698 nfs41_compound compound
;
699 nfs_argop4 argops
[4];
700 nfs_resop4 resops
[4];
701 nfs41_sequence_args sequence_args
;
702 nfs41_sequence_res sequence_res
;
703 nfs41_putfh_args putfh_args
;
704 nfs41_putfh_res putfh_res
;
705 nfs41_write_args write_args
;
706 nfs41_write_res write_res
;
707 nfs41_getattr_args getattr_args
;
708 nfs41_getattr_res getattr_res
= {0};
709 bitmap4 attr_request
;
710 nfs41_file_info info
= { 0 }, *pinfo
;
712 nfs41_superblock_getattr_mask(file
->fh
.superblock
, &attr_request
);
714 compound_init(&compound
, argops
, resops
,
715 stateid
->stateid
.seqid
== 0 ? "ds write" : "write");
717 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
718 nfs41_session_sequence(&sequence_args
, session
, 0);
720 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
721 putfh_args
.file
= file
;
722 putfh_args
.in_recovery
= 0;
724 compound_add_op(&compound
, OP_WRITE
, &write_args
, &write_res
);
725 write_args
.stateid
= stateid
;
726 write_args
.offset
= offset
;
727 write_args
.stable
= stable
;
728 write_args
.data_len
= data_len
;
729 write_args
.data
= data
;
730 write_res
.resok4
.verf
= verf
;
732 if (cinfo
) pinfo
= cinfo
;
735 if (stable
!= UNSTABLE4
) {
736 /* if the write is stable, we can't rely on COMMIT to update
737 * the attribute cache, so we do the GETATTR here */
738 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
739 getattr_args
.attr_request
= &attr_request
;
740 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
741 getattr_res
.info
= pinfo
;
744 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
748 if (compound_error(status
= compound
.res
.status
))
751 if (stable
!= UNSTABLE4
&& pinfo
->type
!= NF4NAMEDATTR
) {
752 /* update the attribute cache */
753 memcpy(&pinfo
->attrmask
, &getattr_res
.obj_attributes
.attrmask
,
755 nfs41_attr_cache_update(session_name_cache(session
),
756 file
->fh
.fileid
, pinfo
);
759 *bytes_written
= write_res
.resok4
.count
;
761 /* we shouldn't ever see this, but a buggy server could
762 * send us into an infinite loop. return NFS4ERR_IO */
763 if (!write_res
.resok4
.count
) {
765 eprintf("WRITE succeeded with count=0; returning %s\n",
766 nfs_error_string(status
));
769 nfs41_superblock_space_changed(file
->fh
.superblock
);
775 IN nfs41_session
*session
,
776 IN nfs41_path_fh
*file
,
777 IN stateid_arg
*stateid
,
780 OUT
unsigned char *data_out
,
781 OUT
uint32_t *data_len_out
,
785 nfs41_compound compound
;
786 nfs_argop4 argops
[4];
787 nfs_resop4 resops
[4];
788 nfs41_sequence_args sequence_args
;
789 nfs41_sequence_res sequence_res
;
790 nfs41_putfh_args putfh_args
;
791 nfs41_putfh_res putfh_res
;
792 nfs41_read_args read_args
;
793 nfs41_read_res read_res
;
795 compound_init(&compound
, argops
, resops
,
796 stateid
->stateid
.seqid
== 0 ? "ds read" : "read");
798 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
799 nfs41_session_sequence(&sequence_args
, session
, 0);
801 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
802 putfh_args
.file
= file
;
803 putfh_args
.in_recovery
= 0;
805 compound_add_op(&compound
, OP_READ
, &read_args
, &read_res
);
806 read_args
.stateid
= stateid
;
807 read_args
.offset
= offset
;
808 read_args
.count
= count
;
809 read_res
.resok4
.data_len
= count
;
810 read_res
.resok4
.data
= data_out
;
812 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
816 if (compound_error(status
= compound
.res
.status
))
819 *data_len_out
= read_res
.resok4
.data_len
;
820 *eof_out
= read_res
.resok4
.eof
;
822 /* we shouldn't ever see this, but a buggy server could
823 * send us into an infinite loop. return NFS4ERR_IO */
824 if (!read_res
.resok4
.data_len
&& !read_res
.resok4
.eof
) {
826 eprintf("READ succeeded with len=0 and eof=0; returning %s\n",
827 nfs_error_string(status
));
834 IN nfs41_session
*session
,
835 IN nfs41_path_fh
*file
,
838 IN bool_t do_getattr
,
839 OUT nfs41_write_verf
*verf
,
840 OUT nfs41_file_info
*cinfo
)
843 nfs41_compound compound
;
844 nfs_argop4 argops
[4];
845 nfs_resop4 resops
[4];
846 nfs41_sequence_args sequence_args
;
847 nfs41_sequence_res sequence_res
;
848 nfs41_putfh_args putfh_args
;
849 nfs41_putfh_res putfh_res
;
850 nfs41_commit_args commit_args
;
851 nfs41_commit_res commit_res
;
852 nfs41_getattr_args getattr_args
;
853 nfs41_getattr_res getattr_res
= {0};
854 bitmap4 attr_request
;
855 nfs41_file_info info
, *pinfo
;
857 compound_init(&compound
, argops
, resops
,
858 do_getattr
? "commit" : "ds commit");
860 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
861 nfs41_session_sequence(&sequence_args
, session
, 1);
863 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
864 putfh_args
.file
= file
;
865 putfh_args
.in_recovery
= 0;
867 compound_add_op(&compound
, OP_COMMIT
, &commit_args
, &commit_res
);
868 commit_args
.offset
= offset
;
869 commit_args
.count
= count
;
870 commit_res
.verf
= verf
;
872 /* send a GETATTR request to update the attribute cache,
873 * but not if we're talking to a data server! */
874 if (cinfo
) pinfo
= cinfo
;
877 nfs41_superblock_getattr_mask(file
->fh
.superblock
, &attr_request
);
879 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
880 getattr_args
.attr_request
= &attr_request
;
881 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
882 getattr_res
.info
= pinfo
;
885 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
889 if (compound_error(status
= compound
.res
.status
))
893 /* update the attribute cache */
894 memcpy(&pinfo
->attrmask
, &getattr_res
.obj_attributes
.attrmask
,
896 nfs41_attr_cache_update(session_name_cache(session
),
897 file
->fh
.fileid
, pinfo
);
899 nfs41_superblock_space_changed(file
->fh
.superblock
);
905 IN nfs41_session
*session
,
906 IN nfs41_path_fh
*file
,
907 IN state_owner4
*owner
,
912 IN bool_t try_recovery
,
913 IN OUT stateid_arg
*stateid
)
916 nfs41_compound compound
;
917 nfs_argop4 argops
[3];
918 nfs_resop4 resops
[3];
919 nfs41_sequence_args sequence_args
;
920 nfs41_sequence_res sequence_res
;
921 nfs41_putfh_args putfh_args
;
922 nfs41_putfh_res putfh_res
;
923 nfs41_lock_args lock_args
;
924 nfs41_lock_res lock_res
;
926 compound_init(&compound
, argops
, resops
, "lock");
928 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
929 nfs41_session_sequence(&sequence_args
, session
, 0);
931 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
932 putfh_args
.file
= file
;
933 putfh_args
.in_recovery
= 0;
935 compound_add_op(&compound
, OP_LOCK
, &lock_args
, &lock_res
);
936 lock_args
.locktype
= type
;
937 lock_args
.reclaim
= reclaim
;
938 lock_args
.offset
= offset
;
939 lock_args
.length
= length
;
940 if (stateid
->type
== STATEID_LOCK
) {
941 lock_args
.locker
.new_lock_owner
= 0;
942 lock_args
.locker
.u
.lock_owner
.lock_stateid
= stateid
;
943 lock_args
.locker
.u
.lock_owner
.lock_seqid
= 0; /* ignored */
945 lock_args
.locker
.new_lock_owner
= 1;
946 lock_args
.locker
.u
.open_owner
.open_seqid
= 0; /* ignored */
947 lock_args
.locker
.u
.open_owner
.open_stateid
= stateid
;
948 lock_args
.locker
.u
.open_owner
.lock_seqid
= 0; /* ignored */
949 lock_args
.locker
.u
.open_owner
.lock_owner
= owner
;
951 lock_res
.u
.resok4
.lock_stateid
= &stateid
->stateid
;
952 lock_res
.u
.denied
.owner
.owner_len
= NFS4_OPAQUE_LIMIT
;
954 status
= compound_encode_send_decode(session
, &compound
, try_recovery
);
958 if (compound_error(status
= compound
.res
.status
))
961 stateid
->type
= STATEID_LOCK
; /* returning a lock stateid */
967 IN nfs41_session
*session
,
968 IN nfs41_path_fh
*file
,
971 IN OUT stateid_arg
*stateid
)
974 nfs41_compound compound
;
975 nfs_argop4 argops
[3];
976 nfs_resop4 resops
[3];
977 nfs41_sequence_args sequence_args
;
978 nfs41_sequence_res sequence_res
;
979 nfs41_putfh_args putfh_args
;
980 nfs41_putfh_res putfh_res
;
981 nfs41_locku_args locku_args
;
982 nfs41_locku_res locku_res
;
984 compound_init(&compound
, argops
, resops
, "unlock");
986 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
987 nfs41_session_sequence(&sequence_args
, session
, 0);
989 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
990 putfh_args
.file
= file
;
991 putfh_args
.in_recovery
= 0;
993 compound_add_op(&compound
, OP_LOCKU
, &locku_args
, &locku_res
);
994 /* 18.12.3: the server MUST accept any legal value for locktype */
995 locku_args
.locktype
= READ_LT
;
996 locku_args
.offset
= offset
;
997 locku_args
.length
= length
;
998 locku_args
.lock_stateid
= stateid
;
999 locku_res
.lock_stateid
= &stateid
->stateid
;
1001 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1005 compound_error(status
= compound
.res
.status
);
1011 IN nfs41_session
*session
,
1012 IN nfs41_path_fh
*file
,
1013 IN bitmap4
*attr_request
,
1014 IN nfs41_readdir_cookie
*cookie
,
1015 OUT
unsigned char *entries
,
1016 IN OUT
uint32_t *entries_len
,
1017 OUT bool_t
*eof_out
)
1020 nfs41_compound compound
;
1021 nfs_argop4 argops
[3];
1022 nfs_resop4 resops
[3];
1023 nfs41_sequence_args sequence_args
;
1024 nfs41_sequence_res sequence_res
;
1025 nfs41_putfh_args putfh_args
;
1026 nfs41_putfh_res putfh_res
;
1027 nfs41_readdir_args readdir_args
;
1028 nfs41_readdir_res readdir_res
;
1030 compound_init(&compound
, argops
, resops
, "readdir");
1032 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1033 nfs41_session_sequence(&sequence_args
, session
, 0);
1035 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1036 putfh_args
.file
= file
;
1037 putfh_args
.in_recovery
= 0;
1039 compound_add_op(&compound
, OP_READDIR
, &readdir_args
, &readdir_res
);
1040 readdir_args
.cookie
.cookie
= cookie
->cookie
;
1041 memcpy(readdir_args
.cookie
.verf
, cookie
->verf
, NFS4_VERIFIER_SIZE
);
1042 readdir_args
.dircount
= *entries_len
;
1043 readdir_args
.maxcount
= *entries_len
+ sizeof(nfs41_readdir_res
);
1044 readdir_args
.attr_request
= attr_request
;
1045 readdir_res
.reply
.entries_len
= *entries_len
;
1046 readdir_res
.reply
.entries
= entries
;
1047 ZeroMemory(entries
, readdir_args
.dircount
);
1049 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1053 if (compound_error(status
= compound
.res
.status
))
1056 *entries_len
= readdir_res
.reply
.entries_len
;
1057 *eof_out
= readdir_res
.reply
.eof
;
1058 memcpy(cookie
->verf
, readdir_res
.cookieverf
, NFS4_VERIFIER_SIZE
);
1064 IN nfs41_session
*session
,
1065 IN OPTIONAL nfs41_path_fh
*file
,
1066 IN bitmap4
*attr_request
,
1067 OUT nfs41_file_info
*info
)
1070 nfs41_compound compound
;
1071 nfs_argop4 argops
[3];
1072 nfs_resop4 resops
[3];
1073 nfs41_sequence_args sequence_args
;
1074 nfs41_sequence_res sequence_res
;
1075 nfs41_putfh_args putfh_args
;
1076 nfs41_putfh_res putfh_res
;
1077 nfs41_getattr_args getattr_args
;
1078 nfs41_getattr_res getattr_res
;
1080 compound_init(&compound
, argops
, resops
, "getattr");
1082 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1083 nfs41_session_sequence(&sequence_args
, session
, 0);
1086 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1087 putfh_args
.file
= file
;
1088 putfh_args
.in_recovery
= 0;
1090 compound_add_op(&compound
, OP_PUTROOTFH
, NULL
, &putfh_res
);
1093 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
1094 getattr_args
.attr_request
= attr_request
;
1095 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1096 getattr_res
.info
= info
;
1098 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1102 if (compound_error(status
= compound
.res
.status
))
1106 /* update the name cache with whatever attributes we got */
1107 memcpy(&info
->attrmask
, &getattr_res
.obj_attributes
.attrmask
,
1109 nfs41_attr_cache_update(session_name_cache(session
),
1110 file
->fh
.fileid
, info
);
1116 int nfs41_superblock_getattr(
1117 IN nfs41_session
*session
,
1118 IN nfs41_path_fh
*file
,
1119 IN bitmap4
*attr_request
,
1120 OUT nfs41_file_info
*info
,
1121 OUT bool_t
*supports_named_attrs
)
1124 nfs41_compound compound
;
1125 nfs_argop4 argops
[4];
1126 nfs_resop4 resops
[4];
1127 nfs41_sequence_args sequence_args
;
1128 nfs41_sequence_res sequence_res
;
1129 nfs41_putfh_args putfh_args
;
1130 nfs41_putfh_res putfh_res
;
1131 nfs41_getattr_args getattr_args
;
1132 nfs41_getattr_res getattr_res
;
1133 nfs41_openattr_args openattr_args
;
1134 nfs41_openattr_res openattr_res
;
1136 compound_init(&compound
, argops
, resops
, "getfsattr");
1138 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1139 nfs41_session_sequence(&sequence_args
, session
, 0);
1141 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1142 putfh_args
.file
= file
;
1143 putfh_args
.in_recovery
= 0;
1145 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
1146 getattr_args
.attr_request
= attr_request
;
1147 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1148 getattr_res
.info
= info
;
1150 compound_add_op(&compound
, OP_OPENATTR
, &openattr_args
, &openattr_res
);
1151 openattr_args
.createdir
= 0;
1153 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1157 status
= sequence_res
.sr_status
;
1158 if (status
) goto out
;
1159 status
= putfh_res
.status
;
1160 if (status
) goto out
;
1161 status
= getattr_res
.status
;
1162 if (status
) goto out
;
1164 switch (status
= openattr_res
.status
) {
1165 case NFS4ERR_NOTSUPP
:
1166 *supports_named_attrs
= 0;
1172 *supports_named_attrs
= 1;
1181 IN nfs41_session
*session
,
1182 IN nfs41_path_fh
*parent
,
1183 IN
const nfs41_component
*target
,
1187 nfs41_compound compound
;
1188 nfs_argop4 argops
[4];
1189 nfs_resop4 resops
[4];
1190 nfs41_sequence_args sequence_args
;
1191 nfs41_sequence_res sequence_res
;
1192 nfs41_putfh_args putfh_args
;
1193 nfs41_putfh_res putfh_res
;
1194 nfs41_remove_args remove_args
;
1195 nfs41_remove_res remove_res
;
1196 nfs41_getattr_args getattr_args
;
1197 nfs41_getattr_res getattr_res
;
1198 bitmap4 attr_request
;
1199 nfs41_file_info info
;
1201 nfs41_superblock_getattr_mask(parent
->fh
.superblock
, &attr_request
);
1203 compound_init(&compound
, argops
, resops
, "remove");
1205 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1206 nfs41_session_sequence(&sequence_args
, session
, 1);
1208 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1209 putfh_args
.file
= parent
;
1210 putfh_args
.in_recovery
= 0;
1212 compound_add_op(&compound
, OP_REMOVE
, &remove_args
, &remove_res
);
1213 remove_args
.target
= target
;
1215 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
1216 getattr_args
.attr_request
= &attr_request
;
1217 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1218 getattr_res
.info
= &info
;
1220 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1224 if (compound_error(status
= compound
.res
.status
))
1227 if (info
.type
== NF4ATTRDIR
)
1230 /* update the attributes of the parent directory */
1231 memcpy(&info
.attrmask
, &getattr_res
.obj_attributes
.attrmask
,
1233 nfs41_attr_cache_update(session_name_cache(session
),
1234 parent
->fh
.fileid
, &info
);
1236 /* remove the target file from the cache */
1237 AcquireSRWLockShared(&parent
->path
->lock
);
1238 nfs41_name_cache_remove(session_name_cache(session
),
1239 parent
->path
->path
, target
, fileid
, &remove_res
.cinfo
);
1240 ReleaseSRWLockShared(&parent
->path
->lock
);
1242 nfs41_superblock_space_changed(parent
->fh
.superblock
);
1248 IN nfs41_session
*session
,
1249 IN nfs41_path_fh
*src_dir
,
1250 IN
const nfs41_component
*src_name
,
1251 IN nfs41_path_fh
*dst_dir
,
1252 IN
const nfs41_component
*dst_name
)
1255 nfs41_compound compound
;
1256 nfs_argop4 argops
[8];
1257 nfs_resop4 resops
[8];
1258 nfs41_sequence_args sequence_args
;
1259 nfs41_sequence_res sequence_res
;
1260 nfs41_putfh_args src_putfh_args
;
1261 nfs41_putfh_res src_putfh_res
;
1262 nfs41_savefh_res savefh_res
;
1263 nfs41_putfh_args dst_putfh_args
;
1264 nfs41_putfh_res dst_putfh_res
;
1265 nfs41_rename_args rename_args
;
1266 nfs41_rename_res rename_res
;
1267 nfs41_getattr_args getattr_args
;
1268 nfs41_getattr_res src_getattr_res
, dst_getattr_res
;
1269 nfs41_file_info src_info
, dst_info
;
1270 bitmap4 attr_request
;
1271 nfs41_restorefh_res restorefh_res
;
1273 nfs41_superblock_getattr_mask(src_dir
->fh
.superblock
, &attr_request
);
1275 compound_init(&compound
, argops
, resops
, "rename");
1277 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1278 nfs41_session_sequence(&sequence_args
, session
, 1);
1280 compound_add_op(&compound
, OP_PUTFH
, &src_putfh_args
, &src_putfh_res
);
1281 src_putfh_args
.file
= src_dir
;
1282 src_putfh_args
.in_recovery
= 0;
1284 compound_add_op(&compound
, OP_SAVEFH
, NULL
, &savefh_res
);
1286 compound_add_op(&compound
, OP_PUTFH
, &dst_putfh_args
, &dst_putfh_res
);
1287 dst_putfh_args
.file
= dst_dir
;
1288 dst_putfh_args
.in_recovery
= 0;
1290 compound_add_op(&compound
, OP_RENAME
, &rename_args
, &rename_res
);
1291 rename_args
.oldname
= src_name
;
1292 rename_args
.newname
= dst_name
;
1294 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &dst_getattr_res
);
1295 getattr_args
.attr_request
= &attr_request
;
1296 dst_getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1297 dst_getattr_res
.info
= &dst_info
;
1299 compound_add_op(&compound
, OP_RESTOREFH
, NULL
, &restorefh_res
);
1301 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &src_getattr_res
);
1302 src_getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1303 src_getattr_res
.info
= &src_info
;
1305 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1309 if (compound_error(status
= compound
.res
.status
))
1312 /* update the attributes of the source directory */
1313 memcpy(&src_info
.attrmask
, &src_getattr_res
.obj_attributes
.attrmask
,
1315 nfs41_attr_cache_update(session_name_cache(session
),
1316 src_dir
->fh
.fileid
, &src_info
);
1318 /* update the attributes of the destination directory */
1319 memcpy(&dst_info
.attrmask
, &dst_getattr_res
.obj_attributes
.attrmask
,
1321 nfs41_attr_cache_update(session_name_cache(session
),
1322 dst_dir
->fh
.fileid
, &dst_info
);
1324 if (src_dir
->path
== dst_dir
->path
) {
1325 /* source and destination are the same, only lock it once */
1326 AcquireSRWLockShared(&src_dir
->path
->lock
);
1327 } else if (src_dir
->path
< dst_dir
->path
) {
1328 /* lock the lowest memory address first */
1329 AcquireSRWLockShared(&src_dir
->path
->lock
);
1330 AcquireSRWLockShared(&dst_dir
->path
->lock
);
1332 AcquireSRWLockShared(&dst_dir
->path
->lock
);
1333 AcquireSRWLockShared(&src_dir
->path
->lock
);
1336 /* move/rename the target file's name cache entry */
1337 nfs41_name_cache_rename(session_name_cache(session
),
1338 src_dir
->path
->path
, src_name
, &rename_res
.source_cinfo
,
1339 dst_dir
->path
->path
, dst_name
, &rename_res
.target_cinfo
);
1341 if (src_dir
->path
== dst_dir
->path
) {
1342 ReleaseSRWLockShared(&src_dir
->path
->lock
);
1344 ReleaseSRWLockShared(&src_dir
->path
->lock
);
1345 ReleaseSRWLockShared(&dst_dir
->path
->lock
);
1352 IN nfs41_session
*session
,
1353 IN nfs41_path_fh
*file
,
1354 IN stateid_arg
*stateid
,
1355 IN nfs41_file_info
*info
)
1358 nfs41_compound compound
;
1359 nfs_argop4 argops
[4];
1360 nfs_resop4 resops
[4];
1361 nfs41_sequence_args sequence_args
;
1362 nfs41_sequence_res sequence_res
;
1363 nfs41_putfh_args putfh_args
;
1364 nfs41_putfh_res putfh_res
;
1365 nfs41_setattr_args setattr_args
;
1366 nfs41_setattr_res setattr_res
;
1367 nfs41_getattr_args getattr_args
;
1368 nfs41_getattr_res getattr_res
;
1369 bitmap4 attr_request
;
1371 compound_init(&compound
, argops
, resops
, "setattr");
1373 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1374 nfs41_session_sequence(&sequence_args
, session
, 0);
1376 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1377 putfh_args
.file
= file
;
1378 putfh_args
.in_recovery
= 0;
1380 compound_add_op(&compound
, OP_SETATTR
, &setattr_args
, &setattr_res
);
1381 setattr_args
.stateid
= stateid
;
1382 setattr_args
.info
= info
;
1384 nfs41_superblock_getattr_mask(file
->fh
.superblock
, &attr_request
);
1385 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
1386 getattr_args
.attr_request
= &attr_request
;
1387 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1388 getattr_res
.info
= info
;
1390 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1394 if (compound_error(status
= compound
.res
.status
))
1397 memcpy(&info
->attrmask
, &attr_request
, sizeof(bitmap4
));
1398 nfs41_attr_cache_update(session_name_cache(session
),
1399 file
->fh
.fileid
, info
);
1401 if (setattr_res
.attrsset
.arr
[0] & FATTR4_WORD0_SIZE
)
1402 nfs41_superblock_space_changed(file
->fh
.superblock
);
1408 IN nfs41_session
*session
,
1409 IN nfs41_path_fh
*src
,
1410 IN nfs41_path_fh
*dst_dir
,
1411 IN
const nfs41_component
*target
,
1412 OUT nfs41_file_info
*cinfo
)
1415 nfs41_compound compound
;
1416 nfs_argop4 argops
[9];
1417 nfs_resop4 resops
[9];
1418 nfs41_sequence_args sequence_args
;
1419 nfs41_sequence_res sequence_res
;
1420 nfs41_putfh_args putfh_args
[2];
1421 nfs41_putfh_res putfh_res
[2];
1422 nfs41_savefh_res savefh_res
;
1423 nfs41_link_args link_args
;
1424 nfs41_link_res link_res
;
1425 nfs41_lookup_args lookup_args
;
1426 nfs41_lookup_res lookup_res
;
1427 nfs41_getfh_res getfh_res
;
1428 nfs41_getattr_args getattr_args
[2];
1429 nfs41_getattr_res getattr_res
[2];
1430 nfs41_file_info info
= { 0 };
1433 nfs41_superblock_getattr_mask(src
->fh
.superblock
, &info
.attrmask
);
1434 nfs41_superblock_getattr_mask(dst_dir
->fh
.superblock
, &cinfo
->attrmask
);
1435 cinfo
->attrmask
.arr
[0] |= FATTR4_WORD0_FSID
;
1437 compound_init(&compound
, argops
, resops
, "link");
1439 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1440 nfs41_session_sequence(&sequence_args
, session
, 1);
1443 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
[0], &putfh_res
[0]);
1444 putfh_args
[0].file
= src
;
1445 putfh_args
[0].in_recovery
= 0;
1447 compound_add_op(&compound
, OP_SAVEFH
, NULL
, &savefh_res
);
1449 /* PUTFH(dst_dir) */
1450 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
[1], &putfh_res
[1]);
1451 putfh_args
[1].file
= dst_dir
;
1452 putfh_args
[1].in_recovery
= 0;
1454 compound_add_op(&compound
, OP_LINK
, &link_args
, &link_res
);
1455 link_args
.newname
= target
;
1457 /* GETATTR(dst_dir) */
1458 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
[0], &getattr_res
[0]);
1459 getattr_args
[0].attr_request
= &info
.attrmask
;
1460 getattr_res
[0].obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1461 getattr_res
[0].info
= &info
;
1463 /* LOOKUP(target) */
1464 compound_add_op(&compound
, OP_LOOKUP
, &lookup_args
, &lookup_res
);
1465 lookup_args
.name
= target
;
1467 /* GETATTR(target) */
1468 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
[1], &getattr_res
[1]);
1469 getattr_args
[1].attr_request
= &cinfo
->attrmask
;
1470 getattr_res
[1].obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1471 getattr_res
[1].info
= cinfo
;
1474 compound_add_op(&compound
, OP_GETFH
, NULL
, &getfh_res
);
1475 getfh_res
.fh
= &file
.fh
;
1477 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1481 if (compound_error(status
= compound
.res
.status
))
1484 /* fill in the file handle's fileid and superblock */
1485 file
.fh
.fileid
= cinfo
->fileid
;
1486 status
= nfs41_superblock_for_fh(session
,
1487 &cinfo
->fsid
, &dst_dir
->fh
, &file
);
1491 /* update the attributes of the destination directory */
1492 memcpy(&info
.attrmask
, &getattr_res
[0].obj_attributes
.attrmask
,
1494 nfs41_attr_cache_update(session_name_cache(session
),
1495 info
.fileid
, &info
);
1497 /* add the new file handle and attributes to the name cache */
1498 memcpy(&cinfo
->attrmask
, &getattr_res
[1].obj_attributes
.attrmask
,
1500 AcquireSRWLockShared(&dst_dir
->path
->lock
);
1501 nfs41_name_cache_insert(session_name_cache(session
),
1502 dst_dir
->path
->path
, target
, &file
.fh
,
1503 cinfo
, &link_res
.cinfo
, OPEN_DELEGATE_NONE
);
1504 ReleaseSRWLockShared(&dst_dir
->path
->lock
);
1506 nfs41_superblock_space_changed(dst_dir
->fh
.superblock
);
1512 IN nfs41_session
*session
,
1513 IN nfs41_path_fh
*file
,
1514 IN
uint32_t max_len
,
1516 OUT
uint32_t *len_out
)
1519 nfs41_compound compound
;
1520 nfs_argop4 argops
[3];
1521 nfs_resop4 resops
[3];
1522 nfs41_sequence_args sequence_args
;
1523 nfs41_sequence_res sequence_res
;
1524 nfs41_putfh_args putfh_args
;
1525 nfs41_putfh_res putfh_res
;
1526 nfs41_readlink_res readlink_res
;
1528 compound_init(&compound
, argops
, resops
, "readlink");
1530 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1531 nfs41_session_sequence(&sequence_args
, session
, 0);
1533 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1534 putfh_args
.file
= file
;
1535 putfh_args
.in_recovery
= 0;
1537 compound_add_op(&compound
, OP_READLINK
, NULL
, &readlink_res
);
1538 readlink_res
.link_len
= max_len
- 1;
1539 readlink_res
.link
= link_out
;
1541 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1545 if (compound_error(status
= compound
.res
.status
))
1548 link_out
[readlink_res
.link_len
] = '\0';
1549 *len_out
= readlink_res
.link_len
;
1555 IN nfs41_session
*session
,
1556 IN nfs41_path_fh
*file
,
1557 IN
uint32_t requested
,
1558 OUT
uint32_t *supported OPTIONAL
,
1559 OUT
uint32_t *access OPTIONAL
)
1562 nfs41_compound compound
;
1563 nfs_argop4 argops
[3];
1564 nfs_resop4 resops
[3];
1565 nfs41_sequence_args sequence_args
;
1566 nfs41_sequence_res sequence_res
;
1567 nfs41_putfh_args putfh_args
;
1568 nfs41_putfh_res putfh_res
;
1569 nfs41_access_args access_args
;
1570 nfs41_access_res access_res
;
1572 compound_init(&compound
, argops
, resops
, "access");
1574 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1575 nfs41_session_sequence(&sequence_args
, session
, 0);
1577 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1578 putfh_args
.file
= file
;
1579 putfh_args
.in_recovery
= 0;
1581 compound_add_op(&compound
, OP_ACCESS
, &access_args
, &access_res
);
1582 access_args
.access
= requested
;
1584 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1588 if (compound_error(status
= compound
.res
.status
))
1592 *supported
= access_res
.supported
;
1594 *access
= access_res
.access
;
1599 int nfs41_send_sequence(
1600 IN nfs41_session
*session
)
1603 nfs41_compound compound
;
1604 nfs_argop4 argops
[1];
1605 nfs_resop4 resops
[1];
1606 nfs41_sequence_args sequence_args
;
1607 nfs41_sequence_res sequence_res
;
1609 compound_init(&compound
, argops
, resops
, "sequence");
1611 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1612 nfs41_session_sequence(&sequence_args
, session
, 0);
1614 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1618 if (compound_error(status
= compound
.res
.status
))
1624 enum nfsstat4
nfs41_want_delegation(
1625 IN nfs41_session
*session
,
1626 IN nfs41_path_fh
*file
,
1627 IN deleg_claim4
*claim
,
1629 IN bool_t try_recovery
,
1630 OUT open_delegation4
*delegation
)
1632 enum nfsstat4 status
;
1633 nfs41_compound compound
;
1634 nfs_argop4 argops
[3];
1635 nfs_resop4 resops
[3];
1636 nfs41_sequence_args sequence_args
;
1637 nfs41_sequence_res sequence_res
;
1638 nfs41_putfh_args putfh_args
;
1639 nfs41_putfh_res putfh_res
;
1640 nfs41_want_delegation_args wd_args
;
1641 nfs41_want_delegation_res wd_res
;
1643 compound_init(&compound
, argops
, resops
, "want_delegation");
1645 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1646 nfs41_session_sequence(&sequence_args
, session
, 0);
1648 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1649 putfh_args
.file
= file
;
1650 putfh_args
.in_recovery
= 0;
1652 compound_add_op(&compound
, OP_WANT_DELEGATION
, &wd_args
, &wd_res
);
1653 wd_args
.claim
= claim
;
1654 wd_args
.want
= want
;
1655 wd_res
.delegation
= delegation
;
1657 status
= compound_encode_send_decode(session
, &compound
, try_recovery
);
1661 compound_error(status
= compound
.res
.status
);
1666 int nfs41_delegpurge(
1667 IN nfs41_session
*session
)
1670 nfs41_compound compound
;
1671 nfs_argop4 argops
[2];
1672 nfs_resop4 resops
[2];
1673 nfs41_sequence_args sequence_args
;
1674 nfs41_sequence_res sequence_res
;
1675 nfs41_delegpurge_res dp_res
;
1677 compound_init(&compound
, argops
, resops
, "delegpurge");
1679 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1680 nfs41_session_sequence(&sequence_args
, session
, 0);
1682 compound_add_op(&compound
, OP_DELEGPURGE
, NULL
, &dp_res
);
1684 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1688 compound_error(status
= compound
.res
.status
);
1693 int nfs41_delegreturn(
1694 IN nfs41_session
*session
,
1695 IN nfs41_path_fh
*file
,
1696 IN stateid_arg
*stateid
,
1697 IN bool_t try_recovery
)
1700 nfs41_compound compound
;
1701 nfs_argop4 argops
[3];
1702 nfs_resop4 resops
[3];
1703 nfs41_sequence_args sequence_args
;
1704 nfs41_sequence_res sequence_res
;
1705 nfs41_putfh_args putfh_args
;
1706 nfs41_putfh_res putfh_res
;
1707 nfs41_delegreturn_args dr_args
;
1708 nfs41_delegreturn_res dr_res
;
1710 compound_init(&compound
, argops
, resops
, "delegreturn");
1712 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1713 nfs41_session_sequence(&sequence_args
, session
, 0);
1715 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1716 putfh_args
.file
= file
;
1717 putfh_args
.in_recovery
= 0;
1719 compound_add_op(&compound
, OP_DELEGRETURN
, &dr_args
, &dr_res
);
1720 dr_args
.stateid
= stateid
;
1722 status
= compound_encode_send_decode(session
, &compound
, try_recovery
);
1726 if (compound_error(status
= compound
.res
.status
))
1729 AcquireSRWLockShared(&file
->path
->lock
);
1730 nfs41_name_cache_delegreturn(session_name_cache(session
),
1731 file
->fh
.fileid
, file
->path
->path
, &file
->name
);
1732 ReleaseSRWLockShared(&file
->path
->lock
);
1737 enum nfsstat4
nfs41_fs_locations(
1738 IN nfs41_session
*session
,
1739 IN nfs41_path_fh
*parent
,
1740 IN
const nfs41_component
*name
,
1741 OUT fs_locations4
*locations
)
1743 enum nfsstat4 status
;
1744 nfs41_compound compound
;
1745 nfs_argop4 argops
[4];
1746 nfs_resop4 resops
[4];
1747 nfs41_sequence_args sequence_args
;
1748 nfs41_sequence_res sequence_res
;
1749 nfs41_putfh_args putfh_args
;
1750 nfs41_putfh_res putfh_res
;
1751 nfs41_lookup_args lookup_args
;
1752 nfs41_lookup_res lookup_res
;
1753 nfs41_getattr_args getattr_args
;
1754 nfs41_getattr_res getattr_res
;
1755 bitmap4 attr_request
= { 1, { FATTR4_WORD0_FS_LOCATIONS
} };
1756 nfs41_file_info info
;
1758 compound_init(&compound
, argops
, resops
, "fs_locations");
1760 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1761 nfs41_session_sequence(&sequence_args
, session
, 0);
1763 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1764 putfh_args
.file
= parent
;
1765 putfh_args
.in_recovery
= 0;
1767 compound_add_op(&compound
, OP_LOOKUP
, &lookup_args
, &lookup_res
);
1768 lookup_args
.name
= name
;
1770 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
1771 getattr_args
.attr_request
= &attr_request
;
1772 info
.fs_locations
= locations
;
1773 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
1774 getattr_res
.info
= &info
;
1776 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1780 compound_error(status
= compound
.res
.status
);
1786 IN nfs41_session
*session
,
1787 IN nfs41_path_fh
*file
,
1788 IN
const nfs41_component
*name
,
1789 OUT nfs41_secinfo_info
*secinfo
)
1792 nfs41_compound compound
;
1793 nfs_argop4 argops
[3];
1794 nfs_resop4 resops
[3];
1795 nfs41_sequence_args sequence_args
;
1796 nfs41_sequence_res sequence_res
;
1797 nfs41_putfh_args putfh_args
;
1798 nfs41_putfh_res putfh_res
;
1799 nfs41_secinfo_args secinfo_args
;
1800 nfs41_secinfo_noname_res secinfo_res
;
1802 compound_init(&compound
, argops
, resops
, "secinfo");
1804 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1805 nfs41_session_sequence(&sequence_args
, session
, 0);
1808 compound_add_op(&compound
, OP_PUTROOTFH
, NULL
, &putfh_res
);
1810 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1811 putfh_args
.file
= file
;
1812 putfh_args
.in_recovery
= 0;
1815 compound_add_op(&compound
, OP_SECINFO
, &secinfo_args
, &secinfo_res
);
1816 secinfo_args
.name
= name
;
1817 secinfo_res
.secinfo
= secinfo
;
1819 status
= compound_encode_send_decode(session
, &compound
, FALSE
);
1823 compound_error(status
= compound
.res
.status
);
1828 int nfs41_secinfo_noname(
1829 IN nfs41_session
*session
,
1830 IN nfs41_path_fh
*file
,
1831 OUT nfs41_secinfo_info
*secinfo
)
1834 nfs41_compound compound
;
1835 nfs_argop4 argops
[3];
1836 nfs_resop4 resops
[3];
1837 nfs41_sequence_args sequence_args
;
1838 nfs41_sequence_res sequence_res
;
1839 nfs41_putfh_args putfh_args
;
1840 nfs41_putfh_res putfh_res
;
1841 nfs41_secinfo_noname_args noname_args
;
1842 nfs41_secinfo_noname_res noname_res
;
1844 compound_init(&compound
, argops
, resops
, "secinfo_no_name");
1846 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1847 nfs41_session_sequence(&sequence_args
, session
, 0);
1850 compound_add_op(&compound
, OP_PUTROOTFH
, NULL
, &putfh_res
);
1852 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1853 putfh_args
.file
= file
;
1854 putfh_args
.in_recovery
= 0;
1857 compound_add_op(&compound
, OP_SECINFO_NO_NAME
, &noname_args
, &noname_res
);
1858 noname_args
.type
= SECINFO_STYLE4_CURRENT_FH
;
1859 noname_res
.secinfo
= secinfo
;
1861 status
= compound_encode_send_decode(session
, &compound
, FALSE
);
1865 compound_error(status
= compound
.res
.status
);
1870 enum nfsstat4
nfs41_free_stateid(
1871 IN nfs41_session
*session
,
1872 IN stateid4
*stateid
)
1874 enum nfsstat4 status
;
1875 nfs41_compound compound
;
1876 nfs_argop4 argops
[2];
1877 nfs_resop4 resops
[2];
1878 nfs41_sequence_args sequence_args
;
1879 nfs41_sequence_res sequence_res
;
1880 nfs41_free_stateid_args freestateid_args
;
1881 nfs41_free_stateid_res freestateid_res
;
1883 compound_init(&compound
, argops
, resops
, "free_stateid");
1885 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1886 nfs41_session_sequence(&sequence_args
, session
, 0);
1888 compound_add_op(&compound
, OP_FREE_STATEID
, &freestateid_args
, &freestateid_res
);
1889 freestateid_args
.stateid
= stateid
;
1891 status
= compound_encode_send_decode(session
, &compound
, FALSE
);
1895 compound_error(status
= compound
.res
.status
);
1900 enum nfsstat4
nfs41_test_stateid(
1901 IN nfs41_session
*session
,
1902 IN stateid_arg
*stateid_array
,
1904 OUT
uint32_t *status_array
)
1906 enum nfsstat4 status
;
1907 nfs41_compound compound
;
1908 nfs_argop4 argops
[2];
1909 nfs_resop4 resops
[2];
1910 nfs41_sequence_args sequence_args
;
1911 nfs41_sequence_res sequence_res
;
1912 nfs41_test_stateid_args teststateid_args
;
1913 nfs41_test_stateid_res teststateid_res
;
1915 compound_init(&compound
, argops
, resops
, "test_stateid");
1917 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1918 nfs41_session_sequence(&sequence_args
, session
, 0);
1920 compound_add_op(&compound
, OP_TEST_STATEID
, &teststateid_args
, &teststateid_res
);
1921 teststateid_args
.stateids
= stateid_array
;
1922 teststateid_args
.count
= count
;
1923 teststateid_res
.resok
.status
= status_array
;
1924 teststateid_res
.resok
.count
= count
;
1926 status
= compound_encode_send_decode(session
, &compound
, FALSE
);
1930 compound_error(status
= compound
.res
.status
);
1935 enum nfsstat4
pnfs_rpc_layoutget(
1936 IN nfs41_session
*session
,
1937 IN nfs41_path_fh
*file
,
1938 IN stateid_arg
*stateid
,
1939 IN
enum pnfs_iomode iomode
,
1941 IN
uint64_t minlength
,
1943 OUT pnfs_layoutget_res_ok
*layoutget_res_ok
)
1945 enum nfsstat4 status
;
1946 nfs41_compound compound
;
1947 nfs_argop4 argops
[3];
1948 nfs_resop4 resops
[3];
1949 nfs41_sequence_args sequence_args
;
1950 nfs41_sequence_res sequence_res
;
1951 nfs41_putfh_args putfh_args
;
1952 nfs41_putfh_res putfh_res
;
1953 pnfs_layoutget_args layoutget_args
;
1954 pnfs_layoutget_res layoutget_res
= { 0 };
1956 struct list_entry
*entry
;
1958 compound_init(&compound
, argops
, resops
, "layoutget");
1960 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
1961 nfs41_session_sequence(&sequence_args
, session
, 0);
1963 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
1964 putfh_args
.file
= file
;
1965 putfh_args
.in_recovery
= 0;
1967 compound_add_op(&compound
, OP_LAYOUTGET
, &layoutget_args
, &layoutget_res
);
1968 layoutget_args
.signal_layout_avail
= 0;
1969 layoutget_args
.layout_type
= PNFS_LAYOUTTYPE_FILE
;
1970 layoutget_args
.iomode
= iomode
;
1971 layoutget_args
.offset
= offset
;
1972 layoutget_args
.minlength
= minlength
;
1973 layoutget_args
.length
= length
;
1974 layoutget_args
.stateid
= stateid
;
1975 layoutget_args
.maxcount
= session
->fore_chan_attrs
.ca_maxresponsesize
- READ_OVERHEAD
;
1977 layoutget_res
.u
.res_ok
= layoutget_res_ok
;
1979 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
1983 if (compound_error(status
= compound
.res
.status
))
1986 /* point each file handle to the meta server's superblock */
1987 list_for_each(entry
, &layoutget_res_ok
->layouts
) {
1988 pnfs_layout
*base
= list_container(entry
, pnfs_layout
, entry
);
1989 if (base
->type
== PNFS_LAYOUTTYPE_FILE
) {
1990 pnfs_file_layout
*layout
= (pnfs_file_layout
*)base
;
1991 for (i
= 0; i
< layout
->filehandles
.count
; i
++)
1992 layout
->filehandles
.arr
[i
].fh
.superblock
= file
->fh
.superblock
;
1999 enum nfsstat4
pnfs_rpc_layoutcommit(
2000 IN nfs41_session
*session
,
2001 IN nfs41_path_fh
*file
,
2002 IN stateid4
*stateid
,
2005 IN OPTIONAL
uint64_t *new_last_offset
,
2006 IN OPTIONAL nfstime4
*new_time_modify
,
2007 OUT nfs41_file_info
*info
)
2009 enum nfsstat4 status
;
2010 nfs41_compound compound
;
2011 nfs_argop4 argops
[4];
2012 nfs_resop4 resops
[4];
2013 nfs41_sequence_args sequence_args
;
2014 nfs41_sequence_res sequence_res
;
2015 nfs41_putfh_args putfh_args
;
2016 nfs41_putfh_res putfh_res
;
2017 pnfs_layoutcommit_args lc_args
;
2018 pnfs_layoutcommit_res lc_res
;
2019 nfs41_getattr_args getattr_args
;
2020 nfs41_getattr_res getattr_res
;
2021 bitmap4 attr_request
;
2023 nfs41_superblock_getattr_mask(file
->fh
.superblock
, &attr_request
);
2025 compound_init(&compound
, argops
, resops
, "layoutcommit");
2027 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
2028 nfs41_session_sequence(&sequence_args
, session
, 0);
2030 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
2031 putfh_args
.file
= file
;
2032 putfh_args
.in_recovery
= 0;
2034 compound_add_op(&compound
, OP_LAYOUTCOMMIT
, &lc_args
, &lc_res
);
2035 lc_args
.offset
= offset
;
2036 lc_args
.length
= length
;
2037 lc_args
.stateid
= stateid
;
2038 lc_args
.new_time
= new_time_modify
;
2039 lc_args
.new_offset
= new_last_offset
;
2041 compound_add_op(&compound
, OP_GETATTR
, &getattr_args
, &getattr_res
);
2042 getattr_args
.attr_request
= &attr_request
;
2043 getattr_res
.obj_attributes
.attr_vals_len
= NFS4_OPAQUE_LIMIT
;
2044 getattr_res
.info
= info
;
2046 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
2050 if (compound_error(status
= compound
.res
.status
))
2053 /* update the attribute cache */
2054 memcpy(&info
->attrmask
, &getattr_res
.obj_attributes
.attrmask
,
2056 nfs41_attr_cache_update(session_name_cache(session
),
2057 file
->fh
.fileid
, info
);
2062 enum nfsstat4
pnfs_rpc_layoutreturn(
2063 IN nfs41_session
*session
,
2064 IN nfs41_path_fh
*file
,
2065 IN
enum pnfs_layout_type type
,
2066 IN
enum pnfs_iomode iomode
,
2069 IN stateid4
*stateid
,
2070 OUT pnfs_layoutreturn_res
*layoutreturn_res
)
2072 enum nfsstat4 status
;
2073 nfs41_compound compound
;
2074 nfs_argop4 argops
[3];
2075 nfs_resop4 resops
[3];
2076 nfs41_sequence_args sequence_args
;
2077 nfs41_sequence_res sequence_res
;
2078 nfs41_putfh_args putfh_args
;
2079 nfs41_putfh_res putfh_res
;
2080 pnfs_layoutreturn_args layoutreturn_args
;
2082 compound_init(&compound
, argops
, resops
, "layoutreturn");
2084 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
2085 nfs41_session_sequence(&sequence_args
, session
, 0);
2087 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
2088 putfh_args
.file
= file
;
2089 putfh_args
.in_recovery
= 0;
2091 compound_add_op(&compound
, OP_LAYOUTRETURN
, &layoutreturn_args
, layoutreturn_res
);
2092 layoutreturn_args
.reclaim
= 0;
2093 layoutreturn_args
.type
= type
;
2094 layoutreturn_args
.iomode
= iomode
;
2095 layoutreturn_args
.return_type
= PNFS_RETURN_FILE
;
2096 layoutreturn_args
.offset
= offset
;
2097 layoutreturn_args
.length
= length
;
2098 layoutreturn_args
.stateid
= stateid
;
2100 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
2104 compound_error(status
= compound
.res
.status
);
2109 enum nfsstat4
pnfs_rpc_getdeviceinfo(
2110 IN nfs41_session
*session
,
2111 IN
unsigned char *deviceid
,
2112 OUT pnfs_file_device
*device
)
2114 enum nfsstat4 status
;
2115 nfs41_compound compound
;
2116 nfs_argop4 argops
[2];
2117 nfs_resop4 resops
[2];
2118 nfs41_sequence_args sequence_args
;
2119 nfs41_sequence_res sequence_res
;
2120 pnfs_getdeviceinfo_args getdeviceinfo_args
;
2121 pnfs_getdeviceinfo_res getdeviceinfo_res
;
2123 compound_init(&compound
, argops
, resops
, "get_deviceinfo");
2125 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
2126 nfs41_session_sequence(&sequence_args
, session
, 0);
2128 compound_add_op(&compound
, OP_GETDEVICEINFO
,
2129 &getdeviceinfo_args
, &getdeviceinfo_res
);
2130 getdeviceinfo_args
.deviceid
= deviceid
;
2131 getdeviceinfo_args
.layout_type
= PNFS_LAYOUTTYPE_FILE
;
2132 getdeviceinfo_args
.maxcount
= NFS41_MAX_SERVER_CACHE
; /* XXX */
2133 getdeviceinfo_args
.notify_types
.count
= 0;
2134 getdeviceinfo_res
.u
.res_ok
.device
= device
;
2136 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
2140 compound_error(status
= compound
.res
.status
);
2145 enum nfsstat4
nfs41_rpc_openattr(
2146 IN nfs41_session
*session
,
2147 IN nfs41_path_fh
*file
,
2148 IN bool_t createdir
,
2149 OUT nfs41_fh
*fh_out
)
2151 enum nfsstat4 status
;
2152 nfs41_compound compound
;
2153 nfs_argop4 argops
[4];
2154 nfs_resop4 resops
[4];
2155 nfs41_sequence_args sequence_args
;
2156 nfs41_sequence_res sequence_res
;
2157 nfs41_putfh_args putfh_args
;
2158 nfs41_putfh_res putfh_res
;
2159 nfs41_openattr_args openattr_args
;
2160 nfs41_openattr_res openattr_res
;
2161 nfs41_getfh_res getfh_res
;
2163 compound_init(&compound
, argops
, resops
, "openattr");
2165 compound_add_op(&compound
, OP_SEQUENCE
, &sequence_args
, &sequence_res
);
2166 nfs41_session_sequence(&sequence_args
, session
, 0);
2168 compound_add_op(&compound
, OP_PUTFH
, &putfh_args
, &putfh_res
);
2169 putfh_args
.file
= file
;
2170 putfh_args
.in_recovery
= FALSE
;
2172 compound_add_op(&compound
, OP_OPENATTR
, &openattr_args
, &openattr_res
);
2173 openattr_args
.createdir
= createdir
;
2175 compound_add_op(&compound
, OP_GETFH
, NULL
, &getfh_res
);
2176 getfh_res
.fh
= fh_out
;
2178 status
= compound_encode_send_decode(session
, &compound
, TRUE
);
2182 compound_error(status
= compound
.res
.status
);
2184 fh_out
->superblock
= file
->fh
.superblock
;