xref: /reactos/base/services/nfsd/nfs41_ops.c (revision c2c66aff)
1*c2c66affSColin Finck /* NFSv4.1 client for Windows
2*c2c66affSColin Finck  * Copyright � 2012 The Regents of the University of Michigan
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  * Olga Kornievskaia <aglo@umich.edu>
5*c2c66affSColin Finck  * Casey Bodley <cbodley@umich.edu>
6*c2c66affSColin Finck  *
7*c2c66affSColin Finck  * This library is free software; you can redistribute it and/or modify it
8*c2c66affSColin Finck  * under the terms of the GNU Lesser General Public License as published by
9*c2c66affSColin Finck  * the Free Software Foundation; either version 2.1 of the License, or (at
10*c2c66affSColin Finck  * your option) any later version.
11*c2c66affSColin Finck  *
12*c2c66affSColin Finck  * This library is distributed in the hope that it will be useful, but
13*c2c66affSColin Finck  * without any warranty; without even the implied warranty of merchantability
14*c2c66affSColin Finck  * or fitness for a particular purpose.  See the GNU Lesser General Public
15*c2c66affSColin Finck  * License for more details.
16*c2c66affSColin Finck  *
17*c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public License
18*c2c66affSColin Finck  * along with this library; if not, write to the Free Software Foundation,
19*c2c66affSColin Finck  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20*c2c66affSColin Finck  */
21*c2c66affSColin Finck 
22*c2c66affSColin Finck #include <windows.h>
23*c2c66affSColin Finck #include <strsafe.h>
24*c2c66affSColin Finck #include <stdio.h>
25*c2c66affSColin Finck #include <stdlib.h>
26*c2c66affSColin Finck #include <time.h>
27*c2c66affSColin Finck 
28*c2c66affSColin Finck #include "nfs41_ops.h"
29*c2c66affSColin Finck #include "nfs41_compound.h"
30*c2c66affSColin Finck #include "nfs41_xdr.h"
31*c2c66affSColin Finck #include "name_cache.h"
32*c2c66affSColin Finck #include "delegation.h"
33*c2c66affSColin Finck #include "daemon_debug.h"
34*c2c66affSColin Finck #include "util.h"
35*c2c66affSColin Finck 
nfs41_exchange_id(IN nfs41_rpc_clnt * rpc,IN client_owner4 * owner,IN uint32_t flags_in,OUT nfs41_exchange_id_res * res_out)36*c2c66affSColin Finck int nfs41_exchange_id(
37*c2c66affSColin Finck     IN nfs41_rpc_clnt *rpc,
38*c2c66affSColin Finck     IN client_owner4 *owner,
39*c2c66affSColin Finck     IN uint32_t flags_in,
40*c2c66affSColin Finck     OUT nfs41_exchange_id_res *res_out)
41*c2c66affSColin Finck {
42*c2c66affSColin Finck     int status = 0;
43*c2c66affSColin Finck     nfs41_compound compound;
44*c2c66affSColin Finck     nfs_argop4 argop;
45*c2c66affSColin Finck     nfs_resop4 resop;
46*c2c66affSColin Finck     nfs41_exchange_id_args ex_id;
47*c2c66affSColin Finck 
48*c2c66affSColin Finck     compound_init(&compound, &argop, &resop, "exchange_id");
49*c2c66affSColin Finck 
50*c2c66affSColin Finck     compound_add_op(&compound, OP_EXCHANGE_ID, &ex_id, res_out);
51*c2c66affSColin Finck     ex_id.eia_clientowner = owner;
52*c2c66affSColin Finck     ex_id.eia_flags = flags_in;
53*c2c66affSColin Finck     ex_id.eia_state_protect.spa_how = SP4_NONE;
54*c2c66affSColin Finck     ex_id.eia_client_impl_id = NULL;
55*c2c66affSColin Finck 
56*c2c66affSColin Finck     res_out->server_owner.so_major_id_len = NFS4_OPAQUE_LIMIT;
57*c2c66affSColin Finck     res_out->server_scope_len = NFS4_OPAQUE_LIMIT;
58*c2c66affSColin Finck 
59*c2c66affSColin Finck     status = nfs41_send_compound(rpc, (char *)&compound.args,
60*c2c66affSColin Finck         (char *)&compound.res);
61*c2c66affSColin Finck     if (status)
62*c2c66affSColin Finck         goto out;
63*c2c66affSColin Finck 
64*c2c66affSColin Finck     compound_error(status = compound.res.status);
65*c2c66affSColin Finck out:
66*c2c66affSColin Finck     return status;
67*c2c66affSColin Finck }
68*c2c66affSColin Finck 
69*c2c66affSColin Finck // AGLO: 10/07/2009 we might want lookup these values from the registry
set_fore_channel_attrs(IN nfs41_rpc_clnt * rpc,IN uint32_t max_req,OUT nfs41_channel_attrs * attrs)70*c2c66affSColin Finck static int set_fore_channel_attrs(
71*c2c66affSColin Finck     IN nfs41_rpc_clnt *rpc,
72*c2c66affSColin Finck     IN uint32_t max_req,
73*c2c66affSColin Finck     OUT nfs41_channel_attrs *attrs)
74*c2c66affSColin Finck {
75*c2c66affSColin Finck     attrs->ca_headerpadsize = 0;
76*c2c66affSColin Finck     attrs->ca_maxrequestsize = rpc->wsize;
77*c2c66affSColin Finck     attrs->ca_maxresponsesize = rpc->rsize;
78*c2c66affSColin Finck     attrs->ca_maxresponsesize_cached = NFS41_MAX_SERVER_CACHE;
79*c2c66affSColin Finck     attrs->ca_maxoperations = 0xffffffff;
80*c2c66affSColin Finck     attrs->ca_maxrequests = max_req;
81*c2c66affSColin Finck     attrs->ca_rdma_ird = NULL;
82*c2c66affSColin Finck     return 0;
83*c2c66affSColin Finck }
84*c2c66affSColin Finck 
85*c2c66affSColin Finck // AGLO: 10/07/2009 we might want lookup these values from the registry
set_back_channel_attrs(IN nfs41_rpc_clnt * rpc,IN uint32_t max_req,OUT nfs41_channel_attrs * attrs)86*c2c66affSColin Finck static int set_back_channel_attrs(
87*c2c66affSColin Finck     IN nfs41_rpc_clnt *rpc,
88*c2c66affSColin Finck     IN uint32_t max_req,
89*c2c66affSColin Finck     OUT nfs41_channel_attrs *attrs)
90*c2c66affSColin Finck {
91*c2c66affSColin Finck     attrs->ca_headerpadsize = 0;
92*c2c66affSColin Finck     attrs->ca_maxrequestsize = rpc->wsize;
93*c2c66affSColin Finck     attrs->ca_maxresponsesize = rpc->rsize;
94*c2c66affSColin Finck     attrs->ca_maxresponsesize_cached = NFS41_MAX_SERVER_CACHE;
95*c2c66affSColin Finck     attrs->ca_maxoperations = 0xffffffff;
96*c2c66affSColin Finck     attrs->ca_maxrequests = max_req;
97*c2c66affSColin Finck     attrs->ca_rdma_ird = NULL;
98*c2c66affSColin Finck     return 0;
99*c2c66affSColin Finck }
100*c2c66affSColin Finck 
nfs41_create_session(nfs41_client * clnt,nfs41_session * session,bool_t try_recovery)101*c2c66affSColin Finck int nfs41_create_session(nfs41_client *clnt, nfs41_session *session, bool_t try_recovery)
102*c2c66affSColin Finck {
103*c2c66affSColin Finck     int status = 0;
104*c2c66affSColin Finck     nfs41_compound compound;
105*c2c66affSColin Finck     nfs_argop4 argop;
106*c2c66affSColin Finck     nfs_resop4 resop;
107*c2c66affSColin Finck     nfs41_create_session_args req = { 0 };
108*c2c66affSColin Finck     nfs41_create_session_res reply = { 0 };
109*c2c66affSColin Finck 
110*c2c66affSColin Finck     compound_init(&compound, &argop, &resop, "create_session");
111*c2c66affSColin Finck 
112*c2c66affSColin Finck     compound_add_op(&compound, OP_CREATE_SESSION, &req, &reply);
113*c2c66affSColin Finck 
114*c2c66affSColin Finck     AcquireSRWLockShared(&clnt->exid_lock);
115*c2c66affSColin Finck     req.csa_clientid = clnt->clnt_id;
116*c2c66affSColin Finck     req.csa_sequence = clnt->seq_id;
117*c2c66affSColin Finck     ReleaseSRWLockShared(&clnt->exid_lock);
118*c2c66affSColin Finck     req.csa_flags = session->flags;
119*c2c66affSColin Finck     req.csa_cb_program = NFS41_RPC_CBPROGRAM;
120*c2c66affSColin Finck     req.csa_cb_secparams[0].type = 0; /* AUTH_NONE */
121*c2c66affSColin Finck     req.csa_cb_secparams[1].type = 1; /* AUTH_SYS */
122*c2c66affSColin Finck     req.csa_cb_secparams[1].u.auth_sys.machinename = clnt->rpc->server_name;
123*c2c66affSColin Finck     req.csa_cb_secparams[1].u.auth_sys.stamp = (uint32_t)time(NULL);
124*c2c66affSColin Finck 
125*c2c66affSColin Finck     // ca_maxrequests should be gotten from the rpc layer
126*c2c66affSColin Finck     set_fore_channel_attrs(clnt->rpc,
127*c2c66affSColin Finck         NFS41_MAX_RPC_REQS, &req.csa_fore_chan_attrs);
128*c2c66affSColin Finck     set_back_channel_attrs(clnt->rpc,
129*c2c66affSColin Finck         1, &req.csa_back_chan_attrs);
130*c2c66affSColin Finck 
131*c2c66affSColin Finck     reply.csr_sessionid = session->session_id;
132*c2c66affSColin Finck     reply.csr_fore_chan_attrs = &session->fore_chan_attrs;
133*c2c66affSColin Finck     reply.csr_back_chan_attrs = &session->back_chan_attrs;
134*c2c66affSColin Finck 
135*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, try_recovery);
136*c2c66affSColin Finck     if (status)
137*c2c66affSColin Finck         goto out;
138*c2c66affSColin Finck 
139*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
140*c2c66affSColin Finck         goto out;
141*c2c66affSColin Finck 
142*c2c66affSColin Finck     print_hexbuf(1, (unsigned char *)"session id: ", session->session_id, NFS4_SESSIONID_SIZE);
143*c2c66affSColin Finck     // check that csa_sequence is same as csr_sequence
144*c2c66affSColin Finck     if (reply.csr_sequence != clnt->seq_id) {
145*c2c66affSColin Finck         eprintf("ERROR: CREATE_SESSION: csa_sequence %d != "
146*c2c66affSColin Finck             "csr_sequence %d\n", clnt->seq_id, reply.csr_sequence);
147*c2c66affSColin Finck         status = NFS4ERR_SEQ_MISORDERED;
148*c2c66affSColin Finck         goto out;
149*c2c66affSColin Finck     } else clnt->seq_id++;
150*c2c66affSColin Finck 
151*c2c66affSColin Finck     if (reply.csr_flags != req.csa_flags) {
152*c2c66affSColin Finck         eprintf("WARNING: requested session flags %x received %x\n",
153*c2c66affSColin Finck             req.csa_flags, reply.csr_flags);
154*c2c66affSColin Finck         if ((session->flags & CREATE_SESSION4_FLAG_CONN_BACK_CHAN) &&
155*c2c66affSColin Finck                 !(reply.csr_flags & CREATE_SESSION4_FLAG_CONN_BACK_CHAN))
156*c2c66affSColin Finck             eprintf("WARNING: we asked to use this session for callbacks but "
157*c2c66affSColin Finck                     "server refused\n");
158*c2c66affSColin Finck         if ((session->flags & CREATE_SESSION4_FLAG_PERSIST) &&
159*c2c66affSColin Finck             !(reply.csr_flags & CREATE_SESSION4_FLAG_PERSIST))
160*c2c66affSColin Finck             eprintf("WARNING: we asked for persistent session but "
161*c2c66affSColin Finck                     "server refused\n");
162*c2c66affSColin Finck         session->flags = reply.csr_flags;
163*c2c66affSColin Finck     }
164*c2c66affSColin Finck     else
165*c2c66affSColin Finck         dprintf(1, "session flags %x\n", reply.csr_flags);
166*c2c66affSColin Finck 
167*c2c66affSColin Finck     dprintf(1, "session fore_chan_attrs:\n"
168*c2c66affSColin Finck         "  %-32s%d\n  %-32s%d\n  %-32s%d\n  %-32s%d\n  %-32s%d\n  %-32s%d\n",
169*c2c66affSColin Finck         "headerpadsize", session->fore_chan_attrs.ca_headerpadsize,
170*c2c66affSColin Finck         "maxrequestsize", session->fore_chan_attrs.ca_maxrequestsize,
171*c2c66affSColin Finck         "maxresponsesize", session->fore_chan_attrs.ca_maxresponsesize,
172*c2c66affSColin Finck         "maxresponsesize_cached", session->fore_chan_attrs.ca_maxresponsesize_cached,
173*c2c66affSColin Finck         "maxoperations", session->fore_chan_attrs.ca_maxoperations,
174*c2c66affSColin Finck         "maxrequests", session->fore_chan_attrs.ca_maxrequests);
175*c2c66affSColin Finck     dprintf(1, "client supports %d max rpc slots, but server has %d\n",
176*c2c66affSColin Finck         session->table.max_slots, session->fore_chan_attrs.ca_maxrequests);
177*c2c66affSColin Finck     /* use the server's ca_maxrequests unless it's bigger than our array */
178*c2c66affSColin Finck     session->table.max_slots = min(session->table.max_slots,
179*c2c66affSColin Finck         session->fore_chan_attrs.ca_maxrequests);
180*c2c66affSColin Finck     status = 0;
181*c2c66affSColin Finck out:
182*c2c66affSColin Finck     return status;
183*c2c66affSColin Finck }
184*c2c66affSColin Finck 
nfs41_bind_conn_to_session(IN nfs41_rpc_clnt * rpc,IN const unsigned char * sessionid,IN enum channel_dir_from_client4 dir)185*c2c66affSColin Finck enum nfsstat4 nfs41_bind_conn_to_session(
186*c2c66affSColin Finck     IN nfs41_rpc_clnt *rpc,
187*c2c66affSColin Finck     IN const unsigned char *sessionid,
188*c2c66affSColin Finck     IN enum channel_dir_from_client4 dir)
189*c2c66affSColin Finck {
190*c2c66affSColin Finck     int status;
191*c2c66affSColin Finck     nfs41_compound compound;
192*c2c66affSColin Finck     nfs_argop4 argop;
193*c2c66affSColin Finck     nfs_resop4 resop;
194*c2c66affSColin Finck     nfs41_bind_conn_to_session_args bind_args = { 0 };
195*c2c66affSColin Finck     nfs41_bind_conn_to_session_res bind_res = { 0 };
196*c2c66affSColin Finck 
197*c2c66affSColin Finck     compound_init(&compound, &argop, &resop, "bind_conn_to_session");
198*c2c66affSColin Finck 
199*c2c66affSColin Finck     compound_add_op(&compound, OP_BIND_CONN_TO_SESSION, &bind_args, &bind_res);
200*c2c66affSColin Finck     bind_args.sessionid = (unsigned char *)sessionid;
201*c2c66affSColin Finck     bind_args.dir = dir;
202*c2c66affSColin Finck 
203*c2c66affSColin Finck     status = nfs41_send_compound(rpc,
204*c2c66affSColin Finck         (char*)&compound.args, (char*)&compound.res);
205*c2c66affSColin Finck     if (status)
206*c2c66affSColin Finck         goto out;
207*c2c66affSColin Finck 
208*c2c66affSColin Finck     compound_error(status = compound.res.status);
209*c2c66affSColin Finck 
210*c2c66affSColin Finck out:
211*c2c66affSColin Finck     return status;
212*c2c66affSColin Finck }
213*c2c66affSColin Finck 
nfs41_destroy_session(IN nfs41_session * session)214*c2c66affSColin Finck int nfs41_destroy_session(
215*c2c66affSColin Finck     IN nfs41_session *session)
216*c2c66affSColin Finck {
217*c2c66affSColin Finck     int status;
218*c2c66affSColin Finck     nfs41_compound compound;
219*c2c66affSColin Finck     nfs_argop4 argop;
220*c2c66affSColin Finck     nfs_resop4 resop;
221*c2c66affSColin Finck     nfs41_destroy_session_args ds_args;
222*c2c66affSColin Finck     nfs41_destroy_session_res ds_res;
223*c2c66affSColin Finck 
224*c2c66affSColin Finck     compound_init(&compound, &argop, &resop, "destroy_session");
225*c2c66affSColin Finck 
226*c2c66affSColin Finck     compound_add_op(&compound, OP_DESTROY_SESSION, &ds_args, &ds_res);
227*c2c66affSColin Finck     ds_args.dsa_sessionid = session->session_id;
228*c2c66affSColin Finck 
229*c2c66affSColin Finck     /* don't attempt to recover from BADSESSION/STALE_CLIENTID */
230*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, FALSE);
231*c2c66affSColin Finck     if (status)
232*c2c66affSColin Finck         goto out;
233*c2c66affSColin Finck 
234*c2c66affSColin Finck     status = compound.res.status;
235*c2c66affSColin Finck     if (status)
236*c2c66affSColin Finck         eprintf("%s failed with status %d.\n",
237*c2c66affSColin Finck             nfs_opnum_to_string(OP_DESTROY_SESSION), status);
238*c2c66affSColin Finck out:
239*c2c66affSColin Finck     return status;
240*c2c66affSColin Finck }
241*c2c66affSColin Finck 
nfs41_destroy_clientid(IN nfs41_rpc_clnt * rpc,IN uint64_t clientid)242*c2c66affSColin Finck int nfs41_destroy_clientid(
243*c2c66affSColin Finck     IN nfs41_rpc_clnt *rpc,
244*c2c66affSColin Finck     IN uint64_t clientid)
245*c2c66affSColin Finck {
246*c2c66affSColin Finck     int status;
247*c2c66affSColin Finck     nfs41_compound compound;
248*c2c66affSColin Finck     nfs_argop4 argops;
249*c2c66affSColin Finck     nfs_resop4 resops;
250*c2c66affSColin Finck     nfs41_destroy_clientid_args dc_args;
251*c2c66affSColin Finck     nfs41_destroy_clientid_res dc_res;
252*c2c66affSColin Finck 
253*c2c66affSColin Finck     compound_init(&compound, &argops, &resops, "destroy_clientid");
254*c2c66affSColin Finck 
255*c2c66affSColin Finck     compound_add_op(&compound, OP_DESTROY_CLIENTID, &dc_args, &dc_res);
256*c2c66affSColin Finck     dc_args.dca_clientid = clientid;
257*c2c66affSColin Finck 
258*c2c66affSColin Finck     status = nfs41_send_compound(rpc, (char *)&compound.args,
259*c2c66affSColin Finck         (char *)&compound.res);
260*c2c66affSColin Finck     if (status)
261*c2c66affSColin Finck         goto out;
262*c2c66affSColin Finck 
263*c2c66affSColin Finck     compound_error(status = compound.res.status);
264*c2c66affSColin Finck out:
265*c2c66affSColin Finck     return status;
266*c2c66affSColin Finck }
267*c2c66affSColin Finck 
nfs41_reclaim_complete(IN nfs41_session * session)268*c2c66affSColin Finck enum nfsstat4 nfs41_reclaim_complete(
269*c2c66affSColin Finck     IN nfs41_session *session)
270*c2c66affSColin Finck {
271*c2c66affSColin Finck     enum nfsstat4 status = NFS4_OK;
272*c2c66affSColin Finck     nfs41_compound compound;
273*c2c66affSColin Finck     nfs_argop4 argops[2];
274*c2c66affSColin Finck     nfs_resop4 resops[2];
275*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
276*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
277*c2c66affSColin Finck     nfs41_reclaim_complete_res reclaim_res;
278*c2c66affSColin Finck 
279*c2c66affSColin Finck     compound_init(&compound, argops, resops, "reclaim_complete");
280*c2c66affSColin Finck 
281*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
282*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
283*c2c66affSColin Finck 
284*c2c66affSColin Finck     compound_add_op(&compound, OP_RECLAIM_COMPLETE, NULL, &reclaim_res);
285*c2c66affSColin Finck 
286*c2c66affSColin Finck     /* don't attempt to recover from BADSESSION */
287*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, FALSE);
288*c2c66affSColin Finck     if (status)
289*c2c66affSColin Finck         goto out;
290*c2c66affSColin Finck 
291*c2c66affSColin Finck     compound_error(status = compound.res.status);
292*c2c66affSColin Finck out:
293*c2c66affSColin Finck     return status;
294*c2c66affSColin Finck }
295*c2c66affSColin Finck 
open_delegation_return(IN nfs41_session * session,IN nfs41_path_fh * file,IN open_delegation4 * delegation,IN bool_t try_recovery)296*c2c66affSColin Finck static void open_delegation_return(
297*c2c66affSColin Finck     IN nfs41_session *session,
298*c2c66affSColin Finck     IN nfs41_path_fh *file,
299*c2c66affSColin Finck     IN open_delegation4 *delegation,
300*c2c66affSColin Finck     IN bool_t try_recovery)
301*c2c66affSColin Finck {
302*c2c66affSColin Finck     stateid_arg stateid;
303*c2c66affSColin Finck     int status;
304*c2c66affSColin Finck 
305*c2c66affSColin Finck     if (delegation->type == OPEN_DELEGATE_NONE ||
306*c2c66affSColin Finck         delegation->type == OPEN_DELEGATE_NONE_EXT)
307*c2c66affSColin Finck         return;
308*c2c66affSColin Finck 
309*c2c66affSColin Finck     /* return the delegation */
310*c2c66affSColin Finck     stateid.open = NULL;
311*c2c66affSColin Finck     stateid.delegation = NULL;
312*c2c66affSColin Finck     stateid.type = STATEID_DELEG_FILE;
313*c2c66affSColin Finck     memcpy(&stateid.stateid, &delegation->stateid, sizeof(stateid4));
314*c2c66affSColin Finck 
315*c2c66affSColin Finck     status = nfs41_delegreturn(session, file, &stateid, try_recovery);
316*c2c66affSColin Finck 
317*c2c66affSColin Finck     /* clear the delegation type returned by nfs41_open() */
318*c2c66affSColin Finck     delegation->type = OPEN_DELEGATE_NONE;
319*c2c66affSColin Finck }
320*c2c66affSColin Finck 
open_update_cache(IN nfs41_session * session,IN nfs41_path_fh * parent,IN nfs41_path_fh * file,IN bool_t try_recovery,IN open_delegation4 * delegation,IN bool_t already_delegated,IN change_info4 * changeinfo,IN nfs41_getattr_res * dir_attrs,IN nfs41_getattr_res * file_attrs)321*c2c66affSColin Finck static void open_update_cache(
322*c2c66affSColin Finck     IN nfs41_session *session,
323*c2c66affSColin Finck     IN nfs41_path_fh *parent,
324*c2c66affSColin Finck     IN nfs41_path_fh *file,
325*c2c66affSColin Finck     IN bool_t try_recovery,
326*c2c66affSColin Finck     IN open_delegation4 *delegation,
327*c2c66affSColin Finck     IN bool_t already_delegated,
328*c2c66affSColin Finck     IN change_info4 *changeinfo,
329*c2c66affSColin Finck     IN nfs41_getattr_res *dir_attrs,
330*c2c66affSColin Finck     IN nfs41_getattr_res *file_attrs)
331*c2c66affSColin Finck {
332*c2c66affSColin Finck     struct nfs41_name_cache *cache = session_name_cache(session);
333*c2c66affSColin Finck     uint32_t status;
334*c2c66affSColin Finck 
335*c2c66affSColin Finck     /* update the attributes of the parent directory */
336*c2c66affSColin Finck     memcpy(&dir_attrs->info->attrmask, &dir_attrs->obj_attributes.attrmask,
337*c2c66affSColin Finck         sizeof(bitmap4));
338*c2c66affSColin Finck     nfs41_attr_cache_update(cache, parent->fh.fileid, dir_attrs->info);
339*c2c66affSColin Finck 
340*c2c66affSColin Finck     /* add the file handle and attributes to the name cache */
341*c2c66affSColin Finck     memcpy(&file_attrs->info->attrmask, &file_attrs->obj_attributes.attrmask,
342*c2c66affSColin Finck         sizeof(bitmap4));
343*c2c66affSColin Finck retry_cache_insert:
344*c2c66affSColin Finck     AcquireSRWLockShared(&file->path->lock);
345*c2c66affSColin Finck     status = nfs41_name_cache_insert(cache, file->path->path, &file->name,
346*c2c66affSColin Finck         &file->fh, file_attrs->info, changeinfo,
347*c2c66affSColin Finck         already_delegated ? OPEN_DELEGATE_NONE : delegation->type);
348*c2c66affSColin Finck     ReleaseSRWLockShared(&file->path->lock);
349*c2c66affSColin Finck 
350*c2c66affSColin Finck     if (status == ERROR_TOO_MANY_OPEN_FILES) {
351*c2c66affSColin Finck         /* the cache won't accept any more delegations; ask the client to
352*c2c66affSColin Finck          * return a delegation to free up a slot in the attribute cache */
353*c2c66affSColin Finck         status = nfs41_client_delegation_return_lru(session->client);
354*c2c66affSColin Finck         if (status == NFS4_OK)
355*c2c66affSColin Finck             goto retry_cache_insert;
356*c2c66affSColin Finck     }
357*c2c66affSColin Finck 
358*c2c66affSColin Finck     if (status && delegation->type != OPEN_DELEGATE_NONE) {
359*c2c66affSColin Finck         /* if we can't make room in the cache, return this
360*c2c66affSColin Finck          * delegation immediately to free resources on the server */
361*c2c66affSColin Finck         open_delegation_return(session, file, delegation, try_recovery);
362*c2c66affSColin Finck         goto retry_cache_insert;
363*c2c66affSColin Finck     }
364*c2c66affSColin Finck }
365*c2c66affSColin Finck 
nfs41_open(IN nfs41_session * session,IN nfs41_path_fh * parent,IN nfs41_path_fh * file,IN state_owner4 * owner,IN open_claim4 * claim,IN uint32_t allow,IN uint32_t deny,IN uint32_t create,IN uint32_t how_mode,IN OPTIONAL nfs41_file_info * createattrs,IN bool_t try_recovery,OUT stateid4 * stateid,OUT open_delegation4 * delegation,OUT OPTIONAL nfs41_file_info * info)366*c2c66affSColin Finck int nfs41_open(
367*c2c66affSColin Finck     IN nfs41_session *session,
368*c2c66affSColin Finck     IN nfs41_path_fh *parent,
369*c2c66affSColin Finck     IN nfs41_path_fh *file,
370*c2c66affSColin Finck     IN state_owner4 *owner,
371*c2c66affSColin Finck     IN open_claim4 *claim,
372*c2c66affSColin Finck     IN uint32_t allow,
373*c2c66affSColin Finck     IN uint32_t deny,
374*c2c66affSColin Finck     IN uint32_t create,
375*c2c66affSColin Finck     IN uint32_t how_mode,
376*c2c66affSColin Finck     IN OPTIONAL nfs41_file_info *createattrs,
377*c2c66affSColin Finck     IN bool_t try_recovery,
378*c2c66affSColin Finck     OUT stateid4 *stateid,
379*c2c66affSColin Finck     OUT open_delegation4 *delegation,
380*c2c66affSColin Finck     OUT OPTIONAL nfs41_file_info *info)
381*c2c66affSColin Finck {
382*c2c66affSColin Finck     int status;
383*c2c66affSColin Finck     nfs41_compound compound;
384*c2c66affSColin Finck     nfs_argop4 argops[8];
385*c2c66affSColin Finck     nfs_resop4 resops[8];
386*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
387*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
388*c2c66affSColin Finck     nfs41_putfh_args putfh_args[2];
389*c2c66affSColin Finck     nfs41_putfh_res putfh_res[2];
390*c2c66affSColin Finck     nfs41_op_open_args open_args;
391*c2c66affSColin Finck     nfs41_op_open_res open_res;
392*c2c66affSColin Finck     nfs41_getfh_res getfh_res;
393*c2c66affSColin Finck     bitmap4 attr_request;
394*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
395*c2c66affSColin Finck     nfs41_getattr_res getattr_res, pgetattr_res;
396*c2c66affSColin Finck     nfs41_savefh_res savefh_res;
397*c2c66affSColin Finck     nfs41_restorefh_res restorefh_res;
398*c2c66affSColin Finck     nfs41_file_info tmp_info, dir_info;
399*c2c66affSColin Finck     bool_t current_fh_is_dir;
400*c2c66affSColin Finck     bool_t already_delegated = delegation->type == OPEN_DELEGATE_READ
401*c2c66affSColin Finck         || delegation->type == OPEN_DELEGATE_WRITE;
402*c2c66affSColin Finck 
403*c2c66affSColin Finck     /* depending on the claim type, OPEN expects CURRENT_FH set
404*c2c66affSColin Finck      * to either the parent directory, or to the file itself */
405*c2c66affSColin Finck     switch (claim->claim) {
406*c2c66affSColin Finck     case CLAIM_NULL:
407*c2c66affSColin Finck     case CLAIM_DELEGATE_CUR:
408*c2c66affSColin Finck     case CLAIM_DELEGATE_PREV:
409*c2c66affSColin Finck         /* CURRENT_FH: directory */
410*c2c66affSColin Finck         current_fh_is_dir = TRUE;
411*c2c66affSColin Finck         /* SEQUENCE; PUTFH(dir); SAVEFH; OPEN;
412*c2c66affSColin Finck          * GETFH(file); GETATTR(file); RESTOREFH(dir); GETATTR */
413*c2c66affSColin Finck         nfs41_superblock_getattr_mask(parent->fh.superblock, &attr_request);
414*c2c66affSColin Finck         break;
415*c2c66affSColin Finck     case CLAIM_PREVIOUS:
416*c2c66affSColin Finck     case CLAIM_FH:
417*c2c66affSColin Finck     case CLAIM_DELEG_CUR_FH:
418*c2c66affSColin Finck     case CLAIM_DELEG_PREV_FH:
419*c2c66affSColin Finck     default:
420*c2c66affSColin Finck         /* CURRENT_FH: file being opened */
421*c2c66affSColin Finck         current_fh_is_dir = FALSE;
422*c2c66affSColin Finck         /* SEQUENCE; PUTFH(file); OPEN; GETATTR(file); PUTFH(dir); GETATTR */
423*c2c66affSColin Finck         nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
424*c2c66affSColin Finck         break;
425*c2c66affSColin Finck     }
426*c2c66affSColin Finck 
427*c2c66affSColin Finck     if (info == NULL)
428*c2c66affSColin Finck         info = &tmp_info;
429*c2c66affSColin Finck 
430*c2c66affSColin Finck     attr_request.arr[0] |= FATTR4_WORD0_FSID;
431*c2c66affSColin Finck 
432*c2c66affSColin Finck     compound_init(&compound, argops, resops, "open");
433*c2c66affSColin Finck 
434*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
435*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 1);
436*c2c66affSColin Finck 
437*c2c66affSColin Finck     if (current_fh_is_dir) {
438*c2c66affSColin Finck         /* CURRENT_FH: directory */
439*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTFH, &putfh_args[0], &putfh_res[0]);
440*c2c66affSColin Finck         putfh_args[0].file = parent;
441*c2c66affSColin Finck         putfh_args[0].in_recovery = 0;
442*c2c66affSColin Finck 
443*c2c66affSColin Finck         compound_add_op(&compound, OP_SAVEFH, NULL, &savefh_res);
444*c2c66affSColin Finck     } else {
445*c2c66affSColin Finck         /* CURRENT_FH: file being opened */
446*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTFH, &putfh_args[0], &putfh_res[0]);
447*c2c66affSColin Finck         putfh_args[0].file = file;
448*c2c66affSColin Finck         putfh_args[0].in_recovery = 0;
449*c2c66affSColin Finck     }
450*c2c66affSColin Finck 
451*c2c66affSColin Finck     compound_add_op(&compound, OP_OPEN, &open_args, &open_res);
452*c2c66affSColin Finck     open_args.seqid = 0;
453*c2c66affSColin Finck #ifdef DISABLE_FILE_DELEGATIONS
454*c2c66affSColin Finck     open_args.share_access = allow | OPEN4_SHARE_ACCESS_WANT_NO_DELEG;
455*c2c66affSColin Finck #else
456*c2c66affSColin Finck     open_args.share_access = allow;
457*c2c66affSColin Finck #endif
458*c2c66affSColin Finck     open_args.share_deny = deny;
459*c2c66affSColin Finck     open_args.owner = owner;
460*c2c66affSColin Finck     open_args.openhow.opentype = create;
461*c2c66affSColin Finck     open_args.openhow.how.mode = how_mode;
462*c2c66affSColin Finck     open_args.openhow.how.createattrs = createattrs;
463*c2c66affSColin Finck     if (how_mode == EXCLUSIVE4_1) {
464*c2c66affSColin Finck         DWORD tid = GetCurrentThreadId();
465*c2c66affSColin Finck         time((time_t*)open_args.openhow.how.createverf);
466*c2c66affSColin Finck         memcpy(open_args.openhow.how.createverf+4, &tid, sizeof(tid));
467*c2c66affSColin Finck         /* mask unsupported attributes */
468*c2c66affSColin Finck         nfs41_superblock_supported_attrs_exclcreat(
469*c2c66affSColin Finck             parent->fh.superblock, &createattrs->attrmask);
470*c2c66affSColin Finck     } else if (createattrs) {
471*c2c66affSColin Finck         /* mask unsupported attributes */
472*c2c66affSColin Finck         nfs41_superblock_supported_attrs(
473*c2c66affSColin Finck             parent->fh.superblock, &createattrs->attrmask);
474*c2c66affSColin Finck     }
475*c2c66affSColin Finck     open_args.claim = claim;
476*c2c66affSColin Finck     open_res.resok4.stateid = stateid;
477*c2c66affSColin Finck     open_res.resok4.delegation = delegation;
478*c2c66affSColin Finck 
479*c2c66affSColin Finck     if (current_fh_is_dir) {
480*c2c66affSColin Finck         compound_add_op(&compound, OP_GETFH, NULL, &getfh_res);
481*c2c66affSColin Finck         getfh_res.fh = &file->fh;
482*c2c66affSColin Finck     }
483*c2c66affSColin Finck 
484*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
485*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
486*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
487*c2c66affSColin Finck     getattr_res.info = info;
488*c2c66affSColin Finck 
489*c2c66affSColin Finck     if (current_fh_is_dir) {
490*c2c66affSColin Finck         compound_add_op(&compound, OP_RESTOREFH, NULL, &restorefh_res);
491*c2c66affSColin Finck     } else {
492*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTFH, &putfh_args[1], &putfh_res[1]);
493*c2c66affSColin Finck         putfh_args[1].file = parent;
494*c2c66affSColin Finck         putfh_args[1].in_recovery = 0;
495*c2c66affSColin Finck     }
496*c2c66affSColin Finck 
497*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &pgetattr_res);
498*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
499*c2c66affSColin Finck     pgetattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
500*c2c66affSColin Finck     pgetattr_res.info = &dir_info;
501*c2c66affSColin Finck 
502*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, try_recovery);
503*c2c66affSColin Finck     if (status)
504*c2c66affSColin Finck         goto out;
505*c2c66affSColin Finck 
506*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
507*c2c66affSColin Finck         goto out;
508*c2c66affSColin Finck 
509*c2c66affSColin Finck     if (dir_info.type == NF4ATTRDIR) {
510*c2c66affSColin Finck         file->fh.superblock = parent->fh.superblock;
511*c2c66affSColin Finck         goto out;
512*c2c66affSColin Finck     }
513*c2c66affSColin Finck 
514*c2c66affSColin Finck     /* fill in the file handle's fileid and superblock */
515*c2c66affSColin Finck     file->fh.fileid = info->fileid;
516*c2c66affSColin Finck     status = nfs41_superblock_for_fh(session, &info->fsid, &parent->fh, file);
517*c2c66affSColin Finck     if (status)
518*c2c66affSColin Finck         goto out;
519*c2c66affSColin Finck 
520*c2c66affSColin Finck     if (create == OPEN4_CREATE)
521*c2c66affSColin Finck         nfs41_superblock_space_changed(file->fh.superblock);
522*c2c66affSColin Finck 
523*c2c66affSColin Finck     /* update the name/attr cache with the results */
524*c2c66affSColin Finck     open_update_cache(session, parent, file, try_recovery, delegation,
525*c2c66affSColin Finck         already_delegated, &open_res.resok4.cinfo, &pgetattr_res, &getattr_res);
526*c2c66affSColin Finck out:
527*c2c66affSColin Finck     return status;
528*c2c66affSColin Finck }
529*c2c66affSColin Finck 
nfs41_create(IN nfs41_session * session,IN uint32_t type,IN nfs41_file_info * createattrs,IN OPTIONAL const char * symlink,IN nfs41_path_fh * parent,OUT nfs41_path_fh * file,OUT nfs41_file_info * info)530*c2c66affSColin Finck int nfs41_create(
531*c2c66affSColin Finck     IN nfs41_session *session,
532*c2c66affSColin Finck     IN uint32_t type,
533*c2c66affSColin Finck     IN nfs41_file_info *createattrs,
534*c2c66affSColin Finck     IN OPTIONAL const char *symlink,
535*c2c66affSColin Finck     IN nfs41_path_fh *parent,
536*c2c66affSColin Finck     OUT nfs41_path_fh *file,
537*c2c66affSColin Finck     OUT nfs41_file_info *info)
538*c2c66affSColin Finck {
539*c2c66affSColin Finck     int status;
540*c2c66affSColin Finck     nfs41_compound compound;
541*c2c66affSColin Finck     nfs_argop4 argops[8];
542*c2c66affSColin Finck     nfs_resop4 resops[8];
543*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
544*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
545*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
546*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
547*c2c66affSColin Finck     nfs41_create_args create_args;
548*c2c66affSColin Finck     nfs41_create_res create_res;
549*c2c66affSColin Finck     nfs41_getfh_res getfh_res;
550*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
551*c2c66affSColin Finck     nfs41_getattr_res getattr_res, pgetattr_res;
552*c2c66affSColin Finck     bitmap4 attr_request;
553*c2c66affSColin Finck     nfs41_file_info dir_info;
554*c2c66affSColin Finck     nfs41_savefh_res savefh_res;
555*c2c66affSColin Finck     nfs41_restorefh_res restorefh_res;
556*c2c66affSColin Finck 
557*c2c66affSColin Finck     nfs41_superblock_getattr_mask(parent->fh.superblock, &attr_request);
558*c2c66affSColin Finck 
559*c2c66affSColin Finck     compound_init(&compound, argops, resops, "create");
560*c2c66affSColin Finck 
561*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
562*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 1);
563*c2c66affSColin Finck 
564*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
565*c2c66affSColin Finck     putfh_args.file = parent;
566*c2c66affSColin Finck     putfh_args.in_recovery = 0;
567*c2c66affSColin Finck 
568*c2c66affSColin Finck     compound_add_op(&compound, OP_SAVEFH, NULL, &savefh_res);
569*c2c66affSColin Finck 
570*c2c66affSColin Finck     compound_add_op(&compound, OP_CREATE, &create_args, &create_res);
571*c2c66affSColin Finck     create_args.objtype.type = type;
572*c2c66affSColin Finck     if (type == NF4LNK) {
573*c2c66affSColin Finck         create_args.objtype.u.lnk.linkdata = symlink;
574*c2c66affSColin Finck         create_args.objtype.u.lnk.linkdata_len = (uint32_t)strlen(symlink);
575*c2c66affSColin Finck     }
576*c2c66affSColin Finck     create_args.name = &file->name;
577*c2c66affSColin Finck     create_args.createattrs = createattrs;
578*c2c66affSColin Finck     nfs41_superblock_supported_attrs(
579*c2c66affSColin Finck                 parent->fh.superblock, &createattrs->attrmask);
580*c2c66affSColin Finck 
581*c2c66affSColin Finck     compound_add_op(&compound, OP_GETFH, NULL, &getfh_res);
582*c2c66affSColin Finck     getfh_res.fh = &file->fh;
583*c2c66affSColin Finck 
584*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
585*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
586*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
587*c2c66affSColin Finck     getattr_res.info = info;
588*c2c66affSColin Finck 
589*c2c66affSColin Finck     compound_add_op(&compound, OP_RESTOREFH, NULL, &restorefh_res);
590*c2c66affSColin Finck 
591*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &pgetattr_res);
592*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
593*c2c66affSColin Finck     pgetattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
594*c2c66affSColin Finck     pgetattr_res.info = &dir_info;
595*c2c66affSColin Finck 
596*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
597*c2c66affSColin Finck     if (status)
598*c2c66affSColin Finck         goto out;
599*c2c66affSColin Finck 
600*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
601*c2c66affSColin Finck         goto out;
602*c2c66affSColin Finck 
603*c2c66affSColin Finck     /* fill in the file handle's fileid and superblock */
604*c2c66affSColin Finck     file->fh.fileid = info->fileid;
605*c2c66affSColin Finck     file->fh.superblock = parent->fh.superblock;
606*c2c66affSColin Finck 
607*c2c66affSColin Finck     /* update the attributes of the parent directory */
608*c2c66affSColin Finck     memcpy(&dir_info.attrmask, &pgetattr_res.obj_attributes.attrmask,
609*c2c66affSColin Finck         sizeof(bitmap4));
610*c2c66affSColin Finck     nfs41_attr_cache_update(session_name_cache(session),
611*c2c66affSColin Finck         parent->fh.fileid, &dir_info);
612*c2c66affSColin Finck 
613*c2c66affSColin Finck     /* add the new file handle and attributes to the name cache */
614*c2c66affSColin Finck     memcpy(&info->attrmask, &getattr_res.obj_attributes.attrmask,
615*c2c66affSColin Finck         sizeof(bitmap4));
616*c2c66affSColin Finck     AcquireSRWLockShared(&file->path->lock);
617*c2c66affSColin Finck     nfs41_name_cache_insert(session_name_cache(session),
618*c2c66affSColin Finck         file->path->path, &file->name, &file->fh,
619*c2c66affSColin Finck         info, &create_res.cinfo, OPEN_DELEGATE_NONE);
620*c2c66affSColin Finck     ReleaseSRWLockShared(&file->path->lock);
621*c2c66affSColin Finck 
622*c2c66affSColin Finck     nfs41_superblock_space_changed(file->fh.superblock);
623*c2c66affSColin Finck out:
624*c2c66affSColin Finck     return status;
625*c2c66affSColin Finck }
626*c2c66affSColin Finck 
nfs41_close(IN nfs41_session * session,IN nfs41_path_fh * file,IN stateid_arg * stateid)627*c2c66affSColin Finck int nfs41_close(
628*c2c66affSColin Finck     IN nfs41_session *session,
629*c2c66affSColin Finck     IN nfs41_path_fh *file,
630*c2c66affSColin Finck     IN stateid_arg *stateid)
631*c2c66affSColin Finck {
632*c2c66affSColin Finck     int status;
633*c2c66affSColin Finck     nfs41_compound compound;
634*c2c66affSColin Finck     nfs_argop4 argops[4];
635*c2c66affSColin Finck     nfs_resop4 resops[4];
636*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
637*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
638*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
639*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
640*c2c66affSColin Finck     nfs41_op_close_args close_args;
641*c2c66affSColin Finck     nfs41_op_close_res close_res;
642*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
643*c2c66affSColin Finck     nfs41_getattr_res getattr_res;
644*c2c66affSColin Finck     bitmap4 attr_request;
645*c2c66affSColin Finck     nfs41_file_info info;
646*c2c66affSColin Finck 
647*c2c66affSColin Finck     nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
648*c2c66affSColin Finck 
649*c2c66affSColin Finck     compound_init(&compound, argops, resops, "close");
650*c2c66affSColin Finck 
651*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
652*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 1);
653*c2c66affSColin Finck 
654*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
655*c2c66affSColin Finck     putfh_args.file = file;
656*c2c66affSColin Finck     putfh_args.in_recovery = 0;
657*c2c66affSColin Finck 
658*c2c66affSColin Finck     compound_add_op(&compound, OP_CLOSE, &close_args, &close_res);
659*c2c66affSColin Finck     close_args.stateid = stateid;
660*c2c66affSColin Finck 
661*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
662*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
663*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
664*c2c66affSColin Finck     getattr_res.info = &info;
665*c2c66affSColin Finck 
666*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
667*c2c66affSColin Finck     if (status)
668*c2c66affSColin Finck         goto out;
669*c2c66affSColin Finck 
670*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
671*c2c66affSColin Finck         goto out;
672*c2c66affSColin Finck 
673*c2c66affSColin Finck     if (info.type == NF4NAMEDATTR)
674*c2c66affSColin Finck         goto out;
675*c2c66affSColin Finck 
676*c2c66affSColin Finck     /* update the attributes of the parent directory */
677*c2c66affSColin Finck     memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask,
678*c2c66affSColin Finck         sizeof(bitmap4));
679*c2c66affSColin Finck     nfs41_attr_cache_update(session_name_cache(session),
680*c2c66affSColin Finck         file->fh.fileid, &info);
681*c2c66affSColin Finck out:
682*c2c66affSColin Finck     return status;
683*c2c66affSColin Finck }
684*c2c66affSColin Finck 
nfs41_write(IN nfs41_session * session,IN nfs41_path_fh * file,IN stateid_arg * stateid,IN unsigned char * data,IN uint32_t data_len,IN uint64_t offset,IN enum stable_how4 stable,OUT uint32_t * bytes_written,OUT nfs41_write_verf * verf,OUT nfs41_file_info * cinfo)685*c2c66affSColin Finck int nfs41_write(
686*c2c66affSColin Finck     IN nfs41_session *session,
687*c2c66affSColin Finck     IN nfs41_path_fh *file,
688*c2c66affSColin Finck     IN stateid_arg *stateid,
689*c2c66affSColin Finck     IN unsigned char *data,
690*c2c66affSColin Finck     IN uint32_t data_len,
691*c2c66affSColin Finck     IN uint64_t offset,
692*c2c66affSColin Finck     IN enum stable_how4 stable,
693*c2c66affSColin Finck     OUT uint32_t *bytes_written,
694*c2c66affSColin Finck     OUT nfs41_write_verf *verf,
695*c2c66affSColin Finck     OUT nfs41_file_info *cinfo)
696*c2c66affSColin Finck {
697*c2c66affSColin Finck     int status;
698*c2c66affSColin Finck     nfs41_compound compound;
699*c2c66affSColin Finck     nfs_argop4 argops[4];
700*c2c66affSColin Finck     nfs_resop4 resops[4];
701*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
702*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
703*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
704*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
705*c2c66affSColin Finck     nfs41_write_args write_args;
706*c2c66affSColin Finck     nfs41_write_res write_res;
707*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
708*c2c66affSColin Finck     nfs41_getattr_res getattr_res = {0};
709*c2c66affSColin Finck     bitmap4 attr_request;
710*c2c66affSColin Finck     nfs41_file_info info = { 0 }, *pinfo;
711*c2c66affSColin Finck 
712*c2c66affSColin Finck     nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
713*c2c66affSColin Finck 
714*c2c66affSColin Finck     compound_init(&compound, argops, resops,
715*c2c66affSColin Finck         stateid->stateid.seqid == 0 ? "ds write" : "write");
716*c2c66affSColin Finck 
717*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
718*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
719*c2c66affSColin Finck 
720*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
721*c2c66affSColin Finck     putfh_args.file = file;
722*c2c66affSColin Finck     putfh_args.in_recovery = 0;
723*c2c66affSColin Finck 
724*c2c66affSColin Finck     compound_add_op(&compound, OP_WRITE, &write_args, &write_res);
725*c2c66affSColin Finck     write_args.stateid = stateid;
726*c2c66affSColin Finck     write_args.offset = offset;
727*c2c66affSColin Finck     write_args.stable = stable;
728*c2c66affSColin Finck     write_args.data_len = data_len;
729*c2c66affSColin Finck     write_args.data = data;
730*c2c66affSColin Finck     write_res.resok4.verf = verf;
731*c2c66affSColin Finck 
732*c2c66affSColin Finck     if (cinfo) pinfo = cinfo;
733*c2c66affSColin Finck     else pinfo = &info;
734*c2c66affSColin Finck 
735*c2c66affSColin Finck     if (stable != UNSTABLE4) {
736*c2c66affSColin Finck         /* if the write is stable, we can't rely on COMMIT to update
737*c2c66affSColin Finck          * the attribute cache, so we do the GETATTR here */
738*c2c66affSColin Finck         compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
739*c2c66affSColin Finck         getattr_args.attr_request = &attr_request;
740*c2c66affSColin Finck         getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
741*c2c66affSColin Finck         getattr_res.info = pinfo;
742*c2c66affSColin Finck     }
743*c2c66affSColin Finck 
744*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
745*c2c66affSColin Finck     if (status)
746*c2c66affSColin Finck         goto out;
747*c2c66affSColin Finck 
748*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
749*c2c66affSColin Finck         goto out;
750*c2c66affSColin Finck 
751*c2c66affSColin Finck     if (stable != UNSTABLE4 && pinfo->type != NF4NAMEDATTR) {
752*c2c66affSColin Finck         /* update the attribute cache */
753*c2c66affSColin Finck         memcpy(&pinfo->attrmask, &getattr_res.obj_attributes.attrmask,
754*c2c66affSColin Finck             sizeof(bitmap4));
755*c2c66affSColin Finck         nfs41_attr_cache_update(session_name_cache(session),
756*c2c66affSColin Finck             file->fh.fileid, pinfo);
757*c2c66affSColin Finck     }
758*c2c66affSColin Finck 
759*c2c66affSColin Finck     *bytes_written = write_res.resok4.count;
760*c2c66affSColin Finck 
761*c2c66affSColin Finck     /* we shouldn't ever see this, but a buggy server could
762*c2c66affSColin Finck      * send us into an infinite loop. return NFS4ERR_IO */
763*c2c66affSColin Finck     if (!write_res.resok4.count) {
764*c2c66affSColin Finck         status = NFS4ERR_IO;
765*c2c66affSColin Finck         eprintf("WRITE succeeded with count=0; returning %s\n",
766*c2c66affSColin Finck             nfs_error_string(status));
767*c2c66affSColin Finck     }
768*c2c66affSColin Finck 
769*c2c66affSColin Finck     nfs41_superblock_space_changed(file->fh.superblock);
770*c2c66affSColin Finck out:
771*c2c66affSColin Finck     return status;
772*c2c66affSColin Finck }
773*c2c66affSColin Finck 
nfs41_read(IN nfs41_session * session,IN nfs41_path_fh * file,IN stateid_arg * stateid,IN uint64_t offset,IN uint32_t count,OUT unsigned char * data_out,OUT uint32_t * data_len_out,OUT bool_t * eof_out)774*c2c66affSColin Finck int nfs41_read(
775*c2c66affSColin Finck     IN nfs41_session *session,
776*c2c66affSColin Finck     IN nfs41_path_fh *file,
777*c2c66affSColin Finck     IN stateid_arg *stateid,
778*c2c66affSColin Finck     IN uint64_t offset,
779*c2c66affSColin Finck     IN uint32_t count,
780*c2c66affSColin Finck     OUT unsigned char *data_out,
781*c2c66affSColin Finck     OUT uint32_t *data_len_out,
782*c2c66affSColin Finck     OUT bool_t *eof_out)
783*c2c66affSColin Finck {
784*c2c66affSColin Finck     int status;
785*c2c66affSColin Finck     nfs41_compound compound;
786*c2c66affSColin Finck     nfs_argop4 argops[4];
787*c2c66affSColin Finck     nfs_resop4 resops[4];
788*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
789*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
790*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
791*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
792*c2c66affSColin Finck     nfs41_read_args read_args;
793*c2c66affSColin Finck     nfs41_read_res read_res;
794*c2c66affSColin Finck 
795*c2c66affSColin Finck     compound_init(&compound, argops, resops,
796*c2c66affSColin Finck         stateid->stateid.seqid == 0 ? "ds read" : "read");
797*c2c66affSColin Finck 
798*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
799*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
800*c2c66affSColin Finck 
801*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
802*c2c66affSColin Finck     putfh_args.file = file;
803*c2c66affSColin Finck     putfh_args.in_recovery = 0;
804*c2c66affSColin Finck 
805*c2c66affSColin Finck     compound_add_op(&compound, OP_READ, &read_args, &read_res);
806*c2c66affSColin Finck     read_args.stateid = stateid;
807*c2c66affSColin Finck     read_args.offset = offset;
808*c2c66affSColin Finck     read_args.count = count;
809*c2c66affSColin Finck     read_res.resok4.data_len = count;
810*c2c66affSColin Finck     read_res.resok4.data = data_out;
811*c2c66affSColin Finck 
812*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
813*c2c66affSColin Finck     if (status)
814*c2c66affSColin Finck         goto out;
815*c2c66affSColin Finck 
816*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
817*c2c66affSColin Finck         goto out;
818*c2c66affSColin Finck 
819*c2c66affSColin Finck     *data_len_out = read_res.resok4.data_len;
820*c2c66affSColin Finck     *eof_out = read_res.resok4.eof;
821*c2c66affSColin Finck 
822*c2c66affSColin Finck     /* we shouldn't ever see this, but a buggy server could
823*c2c66affSColin Finck      * send us into an infinite loop. return NFS4ERR_IO */
824*c2c66affSColin Finck     if (!read_res.resok4.data_len && !read_res.resok4.eof) {
825*c2c66affSColin Finck         status = NFS4ERR_IO;
826*c2c66affSColin Finck         eprintf("READ succeeded with len=0 and eof=0; returning %s\n",
827*c2c66affSColin Finck             nfs_error_string(status));
828*c2c66affSColin Finck     }
829*c2c66affSColin Finck out:
830*c2c66affSColin Finck     return status;
831*c2c66affSColin Finck }
832*c2c66affSColin Finck 
nfs41_commit(IN nfs41_session * session,IN nfs41_path_fh * file,IN uint64_t offset,IN uint32_t count,IN bool_t do_getattr,OUT nfs41_write_verf * verf,OUT nfs41_file_info * cinfo)833*c2c66affSColin Finck int nfs41_commit(
834*c2c66affSColin Finck     IN nfs41_session *session,
835*c2c66affSColin Finck     IN nfs41_path_fh *file,
836*c2c66affSColin Finck     IN uint64_t offset,
837*c2c66affSColin Finck     IN uint32_t count,
838*c2c66affSColin Finck     IN bool_t do_getattr,
839*c2c66affSColin Finck     OUT nfs41_write_verf *verf,
840*c2c66affSColin Finck     OUT nfs41_file_info *cinfo)
841*c2c66affSColin Finck {
842*c2c66affSColin Finck     int status;
843*c2c66affSColin Finck     nfs41_compound compound;
844*c2c66affSColin Finck     nfs_argop4 argops[4];
845*c2c66affSColin Finck     nfs_resop4 resops[4];
846*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
847*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
848*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
849*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
850*c2c66affSColin Finck     nfs41_commit_args commit_args;
851*c2c66affSColin Finck     nfs41_commit_res commit_res;
852*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
853*c2c66affSColin Finck     nfs41_getattr_res getattr_res = {0};
854*c2c66affSColin Finck     bitmap4 attr_request;
855*c2c66affSColin Finck     nfs41_file_info info, *pinfo;
856*c2c66affSColin Finck 
857*c2c66affSColin Finck     compound_init(&compound, argops, resops,
858*c2c66affSColin Finck         do_getattr ? "commit" : "ds commit");
859*c2c66affSColin Finck 
860*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
861*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 1);
862*c2c66affSColin Finck 
863*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
864*c2c66affSColin Finck     putfh_args.file = file;
865*c2c66affSColin Finck     putfh_args.in_recovery = 0;
866*c2c66affSColin Finck 
867*c2c66affSColin Finck     compound_add_op(&compound, OP_COMMIT, &commit_args, &commit_res);
868*c2c66affSColin Finck     commit_args.offset = offset;
869*c2c66affSColin Finck     commit_args.count = count;
870*c2c66affSColin Finck     commit_res.verf = verf;
871*c2c66affSColin Finck 
872*c2c66affSColin Finck     /* send a GETATTR request to update the attribute cache,
873*c2c66affSColin Finck      * but not if we're talking to a data server! */
874*c2c66affSColin Finck     if (cinfo) pinfo = cinfo;
875*c2c66affSColin Finck     else pinfo = &info;
876*c2c66affSColin Finck     if (do_getattr) {
877*c2c66affSColin Finck         nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
878*c2c66affSColin Finck 
879*c2c66affSColin Finck         compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
880*c2c66affSColin Finck         getattr_args.attr_request = &attr_request;
881*c2c66affSColin Finck         getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
882*c2c66affSColin Finck         getattr_res.info = pinfo;
883*c2c66affSColin Finck     }
884*c2c66affSColin Finck 
885*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
886*c2c66affSColin Finck     if (status)
887*c2c66affSColin Finck         goto out;
888*c2c66affSColin Finck 
889*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
890*c2c66affSColin Finck         goto out;
891*c2c66affSColin Finck 
892*c2c66affSColin Finck     if (do_getattr) {
893*c2c66affSColin Finck         /* update the attribute cache */
894*c2c66affSColin Finck         memcpy(&pinfo->attrmask, &getattr_res.obj_attributes.attrmask,
895*c2c66affSColin Finck             sizeof(bitmap4));
896*c2c66affSColin Finck         nfs41_attr_cache_update(session_name_cache(session),
897*c2c66affSColin Finck             file->fh.fileid, pinfo);
898*c2c66affSColin Finck     }
899*c2c66affSColin Finck     nfs41_superblock_space_changed(file->fh.superblock);
900*c2c66affSColin Finck out:
901*c2c66affSColin Finck     return status;
902*c2c66affSColin Finck }
903*c2c66affSColin Finck 
nfs41_lock(IN nfs41_session * session,IN nfs41_path_fh * file,IN state_owner4 * owner,IN uint32_t type,IN uint64_t offset,IN uint64_t length,IN bool_t reclaim,IN bool_t try_recovery,IN OUT stateid_arg * stateid)904*c2c66affSColin Finck int nfs41_lock(
905*c2c66affSColin Finck     IN nfs41_session *session,
906*c2c66affSColin Finck     IN nfs41_path_fh *file,
907*c2c66affSColin Finck     IN state_owner4 *owner,
908*c2c66affSColin Finck     IN uint32_t type,
909*c2c66affSColin Finck     IN uint64_t offset,
910*c2c66affSColin Finck     IN uint64_t length,
911*c2c66affSColin Finck     IN bool_t reclaim,
912*c2c66affSColin Finck     IN bool_t try_recovery,
913*c2c66affSColin Finck     IN OUT stateid_arg *stateid)
914*c2c66affSColin Finck {
915*c2c66affSColin Finck     int status;
916*c2c66affSColin Finck     nfs41_compound compound;
917*c2c66affSColin Finck     nfs_argop4 argops[3];
918*c2c66affSColin Finck     nfs_resop4 resops[3];
919*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
920*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
921*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
922*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
923*c2c66affSColin Finck     nfs41_lock_args lock_args;
924*c2c66affSColin Finck     nfs41_lock_res lock_res;
925*c2c66affSColin Finck 
926*c2c66affSColin Finck     compound_init(&compound, argops, resops, "lock");
927*c2c66affSColin Finck 
928*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
929*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
930*c2c66affSColin Finck 
931*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
932*c2c66affSColin Finck     putfh_args.file = file;
933*c2c66affSColin Finck     putfh_args.in_recovery = 0;
934*c2c66affSColin Finck 
935*c2c66affSColin Finck     compound_add_op(&compound, OP_LOCK, &lock_args, &lock_res);
936*c2c66affSColin Finck     lock_args.locktype = type;
937*c2c66affSColin Finck     lock_args.reclaim = reclaim;
938*c2c66affSColin Finck     lock_args.offset = offset;
939*c2c66affSColin Finck     lock_args.length = length;
940*c2c66affSColin Finck     if (stateid->type == STATEID_LOCK) {
941*c2c66affSColin Finck         lock_args.locker.new_lock_owner = 0;
942*c2c66affSColin Finck         lock_args.locker.u.lock_owner.lock_stateid = stateid;
943*c2c66affSColin Finck         lock_args.locker.u.lock_owner.lock_seqid = 0; /* ignored */
944*c2c66affSColin Finck     } else {
945*c2c66affSColin Finck         lock_args.locker.new_lock_owner = 1;
946*c2c66affSColin Finck         lock_args.locker.u.open_owner.open_seqid = 0; /* ignored */
947*c2c66affSColin Finck         lock_args.locker.u.open_owner.open_stateid = stateid;
948*c2c66affSColin Finck         lock_args.locker.u.open_owner.lock_seqid = 0; /* ignored */
949*c2c66affSColin Finck         lock_args.locker.u.open_owner.lock_owner = owner;
950*c2c66affSColin Finck     }
951*c2c66affSColin Finck     lock_res.u.resok4.lock_stateid = &stateid->stateid;
952*c2c66affSColin Finck     lock_res.u.denied.owner.owner_len = NFS4_OPAQUE_LIMIT;
953*c2c66affSColin Finck 
954*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, try_recovery);
955*c2c66affSColin Finck     if (status)
956*c2c66affSColin Finck         goto out;
957*c2c66affSColin Finck 
958*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
959*c2c66affSColin Finck         goto out;
960*c2c66affSColin Finck 
961*c2c66affSColin Finck     stateid->type = STATEID_LOCK; /* returning a lock stateid */
962*c2c66affSColin Finck out:
963*c2c66affSColin Finck     return status;
964*c2c66affSColin Finck }
965*c2c66affSColin Finck 
nfs41_unlock(IN nfs41_session * session,IN nfs41_path_fh * file,IN uint64_t offset,IN uint64_t length,IN OUT stateid_arg * stateid)966*c2c66affSColin Finck int nfs41_unlock(
967*c2c66affSColin Finck     IN nfs41_session *session,
968*c2c66affSColin Finck     IN nfs41_path_fh *file,
969*c2c66affSColin Finck     IN uint64_t offset,
970*c2c66affSColin Finck     IN uint64_t length,
971*c2c66affSColin Finck     IN OUT stateid_arg *stateid)
972*c2c66affSColin Finck {
973*c2c66affSColin Finck     int status;
974*c2c66affSColin Finck     nfs41_compound compound;
975*c2c66affSColin Finck     nfs_argop4 argops[3];
976*c2c66affSColin Finck     nfs_resop4 resops[3];
977*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
978*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
979*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
980*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
981*c2c66affSColin Finck     nfs41_locku_args locku_args;
982*c2c66affSColin Finck     nfs41_locku_res locku_res;
983*c2c66affSColin Finck 
984*c2c66affSColin Finck     compound_init(&compound, argops, resops, "unlock");
985*c2c66affSColin Finck 
986*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
987*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
988*c2c66affSColin Finck 
989*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
990*c2c66affSColin Finck     putfh_args.file = file;
991*c2c66affSColin Finck     putfh_args.in_recovery = 0;
992*c2c66affSColin Finck 
993*c2c66affSColin Finck     compound_add_op(&compound, OP_LOCKU, &locku_args, &locku_res);
994*c2c66affSColin Finck     /* 18.12.3: the server MUST accept any legal value for locktype */
995*c2c66affSColin Finck     locku_args.locktype = READ_LT;
996*c2c66affSColin Finck     locku_args.offset = offset;
997*c2c66affSColin Finck     locku_args.length = length;
998*c2c66affSColin Finck     locku_args.lock_stateid = stateid;
999*c2c66affSColin Finck     locku_res.lock_stateid = &stateid->stateid;
1000*c2c66affSColin Finck 
1001*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1002*c2c66affSColin Finck     if (status)
1003*c2c66affSColin Finck         goto out;
1004*c2c66affSColin Finck 
1005*c2c66affSColin Finck     compound_error(status = compound.res.status);
1006*c2c66affSColin Finck out:
1007*c2c66affSColin Finck     return status;
1008*c2c66affSColin Finck }
1009*c2c66affSColin Finck 
nfs41_readdir(IN nfs41_session * session,IN nfs41_path_fh * file,IN bitmap4 * attr_request,IN nfs41_readdir_cookie * cookie,OUT unsigned char * entries,IN OUT uint32_t * entries_len,OUT bool_t * eof_out)1010*c2c66affSColin Finck int nfs41_readdir(
1011*c2c66affSColin Finck     IN nfs41_session *session,
1012*c2c66affSColin Finck     IN nfs41_path_fh *file,
1013*c2c66affSColin Finck     IN bitmap4 *attr_request,
1014*c2c66affSColin Finck     IN nfs41_readdir_cookie *cookie,
1015*c2c66affSColin Finck     OUT unsigned char *entries,
1016*c2c66affSColin Finck     IN OUT uint32_t *entries_len,
1017*c2c66affSColin Finck     OUT bool_t *eof_out)
1018*c2c66affSColin Finck {
1019*c2c66affSColin Finck     int status;
1020*c2c66affSColin Finck     nfs41_compound compound;
1021*c2c66affSColin Finck     nfs_argop4 argops[3];
1022*c2c66affSColin Finck     nfs_resop4 resops[3];
1023*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1024*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1025*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1026*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1027*c2c66affSColin Finck     nfs41_readdir_args readdir_args;
1028*c2c66affSColin Finck     nfs41_readdir_res readdir_res;
1029*c2c66affSColin Finck 
1030*c2c66affSColin Finck     compound_init(&compound, argops, resops, "readdir");
1031*c2c66affSColin Finck 
1032*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1033*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1034*c2c66affSColin Finck 
1035*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1036*c2c66affSColin Finck     putfh_args.file = file;
1037*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1038*c2c66affSColin Finck 
1039*c2c66affSColin Finck     compound_add_op(&compound, OP_READDIR, &readdir_args, &readdir_res);
1040*c2c66affSColin Finck     readdir_args.cookie.cookie = cookie->cookie;
1041*c2c66affSColin Finck     memcpy(readdir_args.cookie.verf, cookie->verf, NFS4_VERIFIER_SIZE);
1042*c2c66affSColin Finck     readdir_args.dircount = *entries_len;
1043*c2c66affSColin Finck     readdir_args.maxcount = *entries_len + sizeof(nfs41_readdir_res);
1044*c2c66affSColin Finck     readdir_args.attr_request = attr_request;
1045*c2c66affSColin Finck     readdir_res.reply.entries_len = *entries_len;
1046*c2c66affSColin Finck     readdir_res.reply.entries = entries;
1047*c2c66affSColin Finck     ZeroMemory(entries, readdir_args.dircount);
1048*c2c66affSColin Finck 
1049*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1050*c2c66affSColin Finck     if (status)
1051*c2c66affSColin Finck         goto out;
1052*c2c66affSColin Finck 
1053*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1054*c2c66affSColin Finck         goto out;
1055*c2c66affSColin Finck 
1056*c2c66affSColin Finck     *entries_len = readdir_res.reply.entries_len;
1057*c2c66affSColin Finck     *eof_out = readdir_res.reply.eof;
1058*c2c66affSColin Finck     memcpy(cookie->verf, readdir_res.cookieverf, NFS4_VERIFIER_SIZE);
1059*c2c66affSColin Finck out:
1060*c2c66affSColin Finck     return status;
1061*c2c66affSColin Finck }
1062*c2c66affSColin Finck 
nfs41_getattr(IN nfs41_session * session,IN OPTIONAL nfs41_path_fh * file,IN bitmap4 * attr_request,OUT nfs41_file_info * info)1063*c2c66affSColin Finck int nfs41_getattr(
1064*c2c66affSColin Finck     IN nfs41_session *session,
1065*c2c66affSColin Finck     IN OPTIONAL nfs41_path_fh *file,
1066*c2c66affSColin Finck     IN bitmap4 *attr_request,
1067*c2c66affSColin Finck     OUT nfs41_file_info *info)
1068*c2c66affSColin Finck {
1069*c2c66affSColin Finck     int status;
1070*c2c66affSColin Finck     nfs41_compound compound;
1071*c2c66affSColin Finck     nfs_argop4 argops[3];
1072*c2c66affSColin Finck     nfs_resop4 resops[3];
1073*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1074*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1075*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1076*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1077*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
1078*c2c66affSColin Finck     nfs41_getattr_res getattr_res;
1079*c2c66affSColin Finck 
1080*c2c66affSColin Finck     compound_init(&compound, argops, resops, "getattr");
1081*c2c66affSColin Finck 
1082*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1083*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1084*c2c66affSColin Finck 
1085*c2c66affSColin Finck     if (file) {
1086*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1087*c2c66affSColin Finck         putfh_args.file = file;
1088*c2c66affSColin Finck         putfh_args.in_recovery = 0;
1089*c2c66affSColin Finck     } else {
1090*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
1091*c2c66affSColin Finck     }
1092*c2c66affSColin Finck 
1093*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
1094*c2c66affSColin Finck     getattr_args.attr_request = attr_request;
1095*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1096*c2c66affSColin Finck     getattr_res.info = info;
1097*c2c66affSColin Finck 
1098*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1099*c2c66affSColin Finck     if (status)
1100*c2c66affSColin Finck         goto out;
1101*c2c66affSColin Finck 
1102*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1103*c2c66affSColin Finck         goto out;
1104*c2c66affSColin Finck 
1105*c2c66affSColin Finck     if (file) {
1106*c2c66affSColin Finck         /* update the name cache with whatever attributes we got */
1107*c2c66affSColin Finck         memcpy(&info->attrmask, &getattr_res.obj_attributes.attrmask,
1108*c2c66affSColin Finck             sizeof(bitmap4));
1109*c2c66affSColin Finck         nfs41_attr_cache_update(session_name_cache(session),
1110*c2c66affSColin Finck             file->fh.fileid, info);
1111*c2c66affSColin Finck     }
1112*c2c66affSColin Finck out:
1113*c2c66affSColin Finck     return status;
1114*c2c66affSColin Finck }
1115*c2c66affSColin Finck 
nfs41_superblock_getattr(IN nfs41_session * session,IN nfs41_path_fh * file,IN bitmap4 * attr_request,OUT nfs41_file_info * info,OUT bool_t * supports_named_attrs)1116*c2c66affSColin Finck int nfs41_superblock_getattr(
1117*c2c66affSColin Finck     IN nfs41_session *session,
1118*c2c66affSColin Finck     IN nfs41_path_fh *file,
1119*c2c66affSColin Finck     IN bitmap4 *attr_request,
1120*c2c66affSColin Finck     OUT nfs41_file_info *info,
1121*c2c66affSColin Finck     OUT bool_t *supports_named_attrs)
1122*c2c66affSColin Finck {
1123*c2c66affSColin Finck     int status;
1124*c2c66affSColin Finck     nfs41_compound compound;
1125*c2c66affSColin Finck     nfs_argop4 argops[4];
1126*c2c66affSColin Finck     nfs_resop4 resops[4];
1127*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1128*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1129*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1130*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1131*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
1132*c2c66affSColin Finck     nfs41_getattr_res getattr_res;
1133*c2c66affSColin Finck     nfs41_openattr_args openattr_args;
1134*c2c66affSColin Finck     nfs41_openattr_res openattr_res;
1135*c2c66affSColin Finck 
1136*c2c66affSColin Finck     compound_init(&compound, argops, resops, "getfsattr");
1137*c2c66affSColin Finck 
1138*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1139*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1140*c2c66affSColin Finck 
1141*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1142*c2c66affSColin Finck     putfh_args.file = file;
1143*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1144*c2c66affSColin Finck 
1145*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
1146*c2c66affSColin Finck     getattr_args.attr_request = attr_request;
1147*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1148*c2c66affSColin Finck     getattr_res.info = info;
1149*c2c66affSColin Finck 
1150*c2c66affSColin Finck     compound_add_op(&compound, OP_OPENATTR, &openattr_args, &openattr_res);
1151*c2c66affSColin Finck     openattr_args.createdir = 0;
1152*c2c66affSColin Finck 
1153*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1154*c2c66affSColin Finck     if (status)
1155*c2c66affSColin Finck         goto out;
1156*c2c66affSColin Finck 
1157*c2c66affSColin Finck     status = sequence_res.sr_status;
1158*c2c66affSColin Finck     if (status) goto out;
1159*c2c66affSColin Finck     status = putfh_res.status;
1160*c2c66affSColin Finck     if (status) goto out;
1161*c2c66affSColin Finck     status = getattr_res.status;
1162*c2c66affSColin Finck     if (status) goto out;
1163*c2c66affSColin Finck 
1164*c2c66affSColin Finck     switch (status = openattr_res.status) {
1165*c2c66affSColin Finck     case NFS4ERR_NOTSUPP:
1166*c2c66affSColin Finck         *supports_named_attrs = 0;
1167*c2c66affSColin Finck         status = NFS4_OK;
1168*c2c66affSColin Finck         break;
1169*c2c66affSColin Finck 
1170*c2c66affSColin Finck     case NFS4ERR_NOENT:
1171*c2c66affSColin Finck     case NFS4_OK:
1172*c2c66affSColin Finck         *supports_named_attrs = 1;
1173*c2c66affSColin Finck         status = NFS4_OK;
1174*c2c66affSColin Finck         break;
1175*c2c66affSColin Finck     }
1176*c2c66affSColin Finck out:
1177*c2c66affSColin Finck     return status;
1178*c2c66affSColin Finck }
1179*c2c66affSColin Finck 
nfs41_remove(IN nfs41_session * session,IN nfs41_path_fh * parent,IN const nfs41_component * target,IN uint64_t fileid)1180*c2c66affSColin Finck int nfs41_remove(
1181*c2c66affSColin Finck     IN nfs41_session *session,
1182*c2c66affSColin Finck     IN nfs41_path_fh *parent,
1183*c2c66affSColin Finck     IN const nfs41_component *target,
1184*c2c66affSColin Finck     IN uint64_t fileid)
1185*c2c66affSColin Finck {
1186*c2c66affSColin Finck     int status;
1187*c2c66affSColin Finck     nfs41_compound compound;
1188*c2c66affSColin Finck     nfs_argop4 argops[4];
1189*c2c66affSColin Finck     nfs_resop4 resops[4];
1190*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1191*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1192*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1193*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1194*c2c66affSColin Finck     nfs41_remove_args remove_args;
1195*c2c66affSColin Finck     nfs41_remove_res remove_res;
1196*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
1197*c2c66affSColin Finck     nfs41_getattr_res getattr_res;
1198*c2c66affSColin Finck     bitmap4 attr_request;
1199*c2c66affSColin Finck     nfs41_file_info info;
1200*c2c66affSColin Finck 
1201*c2c66affSColin Finck     nfs41_superblock_getattr_mask(parent->fh.superblock, &attr_request);
1202*c2c66affSColin Finck 
1203*c2c66affSColin Finck     compound_init(&compound, argops, resops, "remove");
1204*c2c66affSColin Finck 
1205*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1206*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 1);
1207*c2c66affSColin Finck 
1208*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1209*c2c66affSColin Finck     putfh_args.file = parent;
1210*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1211*c2c66affSColin Finck 
1212*c2c66affSColin Finck     compound_add_op(&compound, OP_REMOVE, &remove_args, &remove_res);
1213*c2c66affSColin Finck     remove_args.target = target;
1214*c2c66affSColin Finck 
1215*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
1216*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
1217*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1218*c2c66affSColin Finck     getattr_res.info = &info;
1219*c2c66affSColin Finck 
1220*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1221*c2c66affSColin Finck     if (status)
1222*c2c66affSColin Finck         goto out;
1223*c2c66affSColin Finck 
1224*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1225*c2c66affSColin Finck         goto out;
1226*c2c66affSColin Finck 
1227*c2c66affSColin Finck     if (info.type == NF4ATTRDIR)
1228*c2c66affSColin Finck         goto out;
1229*c2c66affSColin Finck 
1230*c2c66affSColin Finck     /* update the attributes of the parent directory */
1231*c2c66affSColin Finck     memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask,
1232*c2c66affSColin Finck         sizeof(bitmap4));
1233*c2c66affSColin Finck     nfs41_attr_cache_update(session_name_cache(session),
1234*c2c66affSColin Finck         parent->fh.fileid, &info);
1235*c2c66affSColin Finck 
1236*c2c66affSColin Finck     /* remove the target file from the cache */
1237*c2c66affSColin Finck     AcquireSRWLockShared(&parent->path->lock);
1238*c2c66affSColin Finck     nfs41_name_cache_remove(session_name_cache(session),
1239*c2c66affSColin Finck         parent->path->path, target, fileid, &remove_res.cinfo);
1240*c2c66affSColin Finck     ReleaseSRWLockShared(&parent->path->lock);
1241*c2c66affSColin Finck 
1242*c2c66affSColin Finck     nfs41_superblock_space_changed(parent->fh.superblock);
1243*c2c66affSColin Finck out:
1244*c2c66affSColin Finck     return status;
1245*c2c66affSColin Finck }
1246*c2c66affSColin Finck 
nfs41_rename(IN nfs41_session * session,IN nfs41_path_fh * src_dir,IN const nfs41_component * src_name,IN nfs41_path_fh * dst_dir,IN const nfs41_component * dst_name)1247*c2c66affSColin Finck int nfs41_rename(
1248*c2c66affSColin Finck     IN nfs41_session *session,
1249*c2c66affSColin Finck     IN nfs41_path_fh *src_dir,
1250*c2c66affSColin Finck     IN const nfs41_component *src_name,
1251*c2c66affSColin Finck     IN nfs41_path_fh *dst_dir,
1252*c2c66affSColin Finck     IN const nfs41_component *dst_name)
1253*c2c66affSColin Finck {
1254*c2c66affSColin Finck     int status;
1255*c2c66affSColin Finck     nfs41_compound compound;
1256*c2c66affSColin Finck     nfs_argop4 argops[8];
1257*c2c66affSColin Finck     nfs_resop4 resops[8];
1258*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1259*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1260*c2c66affSColin Finck     nfs41_putfh_args src_putfh_args;
1261*c2c66affSColin Finck     nfs41_putfh_res src_putfh_res;
1262*c2c66affSColin Finck     nfs41_savefh_res savefh_res;
1263*c2c66affSColin Finck     nfs41_putfh_args dst_putfh_args;
1264*c2c66affSColin Finck     nfs41_putfh_res dst_putfh_res;
1265*c2c66affSColin Finck     nfs41_rename_args rename_args;
1266*c2c66affSColin Finck     nfs41_rename_res rename_res;
1267*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
1268*c2c66affSColin Finck     nfs41_getattr_res src_getattr_res, dst_getattr_res;
1269*c2c66affSColin Finck     nfs41_file_info src_info, dst_info;
1270*c2c66affSColin Finck     bitmap4 attr_request;
1271*c2c66affSColin Finck     nfs41_restorefh_res restorefh_res;
1272*c2c66affSColin Finck 
1273*c2c66affSColin Finck     nfs41_superblock_getattr_mask(src_dir->fh.superblock, &attr_request);
1274*c2c66affSColin Finck 
1275*c2c66affSColin Finck     compound_init(&compound, argops, resops, "rename");
1276*c2c66affSColin Finck 
1277*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1278*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 1);
1279*c2c66affSColin Finck 
1280*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &src_putfh_args, &src_putfh_res);
1281*c2c66affSColin Finck     src_putfh_args.file = src_dir;
1282*c2c66affSColin Finck     src_putfh_args.in_recovery = 0;
1283*c2c66affSColin Finck 
1284*c2c66affSColin Finck     compound_add_op(&compound, OP_SAVEFH, NULL, &savefh_res);
1285*c2c66affSColin Finck 
1286*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &dst_putfh_args, &dst_putfh_res);
1287*c2c66affSColin Finck     dst_putfh_args.file = dst_dir;
1288*c2c66affSColin Finck     dst_putfh_args.in_recovery = 0;
1289*c2c66affSColin Finck 
1290*c2c66affSColin Finck     compound_add_op(&compound, OP_RENAME, &rename_args, &rename_res);
1291*c2c66affSColin Finck     rename_args.oldname = src_name;
1292*c2c66affSColin Finck     rename_args.newname = dst_name;
1293*c2c66affSColin Finck 
1294*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &dst_getattr_res);
1295*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
1296*c2c66affSColin Finck     dst_getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1297*c2c66affSColin Finck     dst_getattr_res.info = &dst_info;
1298*c2c66affSColin Finck 
1299*c2c66affSColin Finck     compound_add_op(&compound, OP_RESTOREFH, NULL, &restorefh_res);
1300*c2c66affSColin Finck 
1301*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &src_getattr_res);
1302*c2c66affSColin Finck     src_getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1303*c2c66affSColin Finck     src_getattr_res.info = &src_info;
1304*c2c66affSColin Finck 
1305*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1306*c2c66affSColin Finck     if (status)
1307*c2c66affSColin Finck         goto out;
1308*c2c66affSColin Finck 
1309*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1310*c2c66affSColin Finck         goto out;
1311*c2c66affSColin Finck 
1312*c2c66affSColin Finck     /* update the attributes of the source directory */
1313*c2c66affSColin Finck     memcpy(&src_info.attrmask, &src_getattr_res.obj_attributes.attrmask,
1314*c2c66affSColin Finck         sizeof(bitmap4));
1315*c2c66affSColin Finck     nfs41_attr_cache_update(session_name_cache(session),
1316*c2c66affSColin Finck         src_dir->fh.fileid, &src_info);
1317*c2c66affSColin Finck 
1318*c2c66affSColin Finck     /* update the attributes of the destination directory */
1319*c2c66affSColin Finck     memcpy(&dst_info.attrmask, &dst_getattr_res.obj_attributes.attrmask,
1320*c2c66affSColin Finck         sizeof(bitmap4));
1321*c2c66affSColin Finck     nfs41_attr_cache_update(session_name_cache(session),
1322*c2c66affSColin Finck         dst_dir->fh.fileid, &dst_info);
1323*c2c66affSColin Finck 
1324*c2c66affSColin Finck     if (src_dir->path == dst_dir->path) {
1325*c2c66affSColin Finck         /* source and destination are the same, only lock it once */
1326*c2c66affSColin Finck         AcquireSRWLockShared(&src_dir->path->lock);
1327*c2c66affSColin Finck     } else if (src_dir->path < dst_dir->path) {
1328*c2c66affSColin Finck         /* lock the lowest memory address first */
1329*c2c66affSColin Finck         AcquireSRWLockShared(&src_dir->path->lock);
1330*c2c66affSColin Finck         AcquireSRWLockShared(&dst_dir->path->lock);
1331*c2c66affSColin Finck     } else {
1332*c2c66affSColin Finck         AcquireSRWLockShared(&dst_dir->path->lock);
1333*c2c66affSColin Finck         AcquireSRWLockShared(&src_dir->path->lock);
1334*c2c66affSColin Finck     }
1335*c2c66affSColin Finck 
1336*c2c66affSColin Finck     /* move/rename the target file's name cache entry */
1337*c2c66affSColin Finck     nfs41_name_cache_rename(session_name_cache(session),
1338*c2c66affSColin Finck         src_dir->path->path, src_name, &rename_res.source_cinfo,
1339*c2c66affSColin Finck         dst_dir->path->path, dst_name, &rename_res.target_cinfo);
1340*c2c66affSColin Finck 
1341*c2c66affSColin Finck     if (src_dir->path == dst_dir->path) {
1342*c2c66affSColin Finck         ReleaseSRWLockShared(&src_dir->path->lock);
1343*c2c66affSColin Finck     } else {
1344*c2c66affSColin Finck         ReleaseSRWLockShared(&src_dir->path->lock);
1345*c2c66affSColin Finck         ReleaseSRWLockShared(&dst_dir->path->lock);
1346*c2c66affSColin Finck     }
1347*c2c66affSColin Finck out:
1348*c2c66affSColin Finck     return status;
1349*c2c66affSColin Finck }
1350*c2c66affSColin Finck 
nfs41_setattr(IN nfs41_session * session,IN nfs41_path_fh * file,IN stateid_arg * stateid,IN nfs41_file_info * info)1351*c2c66affSColin Finck int nfs41_setattr(
1352*c2c66affSColin Finck     IN nfs41_session *session,
1353*c2c66affSColin Finck     IN nfs41_path_fh *file,
1354*c2c66affSColin Finck     IN stateid_arg *stateid,
1355*c2c66affSColin Finck     IN nfs41_file_info *info)
1356*c2c66affSColin Finck {
1357*c2c66affSColin Finck     int status;
1358*c2c66affSColin Finck     nfs41_compound compound;
1359*c2c66affSColin Finck     nfs_argop4 argops[4];
1360*c2c66affSColin Finck     nfs_resop4 resops[4];
1361*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1362*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1363*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1364*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1365*c2c66affSColin Finck     nfs41_setattr_args setattr_args;
1366*c2c66affSColin Finck     nfs41_setattr_res setattr_res;
1367*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
1368*c2c66affSColin Finck     nfs41_getattr_res getattr_res;
1369*c2c66affSColin Finck     bitmap4 attr_request;
1370*c2c66affSColin Finck 
1371*c2c66affSColin Finck     compound_init(&compound, argops, resops, "setattr");
1372*c2c66affSColin Finck 
1373*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1374*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1375*c2c66affSColin Finck 
1376*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1377*c2c66affSColin Finck     putfh_args.file = file;
1378*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1379*c2c66affSColin Finck 
1380*c2c66affSColin Finck     compound_add_op(&compound, OP_SETATTR, &setattr_args, &setattr_res);
1381*c2c66affSColin Finck     setattr_args.stateid = stateid;
1382*c2c66affSColin Finck     setattr_args.info = info;
1383*c2c66affSColin Finck 
1384*c2c66affSColin Finck     nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
1385*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
1386*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
1387*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1388*c2c66affSColin Finck     getattr_res.info = info;
1389*c2c66affSColin Finck 
1390*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1391*c2c66affSColin Finck     if (status)
1392*c2c66affSColin Finck         goto out;
1393*c2c66affSColin Finck 
1394*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1395*c2c66affSColin Finck         goto out;
1396*c2c66affSColin Finck 
1397*c2c66affSColin Finck     memcpy(&info->attrmask, &attr_request, sizeof(bitmap4));
1398*c2c66affSColin Finck     nfs41_attr_cache_update(session_name_cache(session),
1399*c2c66affSColin Finck         file->fh.fileid, info);
1400*c2c66affSColin Finck 
1401*c2c66affSColin Finck     if (setattr_res.attrsset.arr[0] & FATTR4_WORD0_SIZE)
1402*c2c66affSColin Finck         nfs41_superblock_space_changed(file->fh.superblock);
1403*c2c66affSColin Finck out:
1404*c2c66affSColin Finck     return status;
1405*c2c66affSColin Finck }
1406*c2c66affSColin Finck 
nfs41_link(IN nfs41_session * session,IN nfs41_path_fh * src,IN nfs41_path_fh * dst_dir,IN const nfs41_component * target,OUT nfs41_file_info * cinfo)1407*c2c66affSColin Finck int nfs41_link(
1408*c2c66affSColin Finck     IN nfs41_session *session,
1409*c2c66affSColin Finck     IN nfs41_path_fh *src,
1410*c2c66affSColin Finck     IN nfs41_path_fh *dst_dir,
1411*c2c66affSColin Finck     IN const nfs41_component *target,
1412*c2c66affSColin Finck     OUT nfs41_file_info *cinfo)
1413*c2c66affSColin Finck {
1414*c2c66affSColin Finck     int status;
1415*c2c66affSColin Finck     nfs41_compound compound;
1416*c2c66affSColin Finck     nfs_argop4 argops[9];
1417*c2c66affSColin Finck     nfs_resop4 resops[9];
1418*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1419*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1420*c2c66affSColin Finck     nfs41_putfh_args putfh_args[2];
1421*c2c66affSColin Finck     nfs41_putfh_res putfh_res[2];
1422*c2c66affSColin Finck     nfs41_savefh_res savefh_res;
1423*c2c66affSColin Finck     nfs41_link_args link_args;
1424*c2c66affSColin Finck     nfs41_link_res link_res;
1425*c2c66affSColin Finck     nfs41_lookup_args lookup_args;
1426*c2c66affSColin Finck     nfs41_lookup_res lookup_res;
1427*c2c66affSColin Finck     nfs41_getfh_res getfh_res;
1428*c2c66affSColin Finck     nfs41_getattr_args getattr_args[2];
1429*c2c66affSColin Finck     nfs41_getattr_res getattr_res[2];
1430*c2c66affSColin Finck     nfs41_file_info info = { 0 };
1431*c2c66affSColin Finck     nfs41_path_fh file;
1432*c2c66affSColin Finck 
1433*c2c66affSColin Finck     nfs41_superblock_getattr_mask(src->fh.superblock, &info.attrmask);
1434*c2c66affSColin Finck     nfs41_superblock_getattr_mask(dst_dir->fh.superblock, &cinfo->attrmask);
1435*c2c66affSColin Finck     cinfo->attrmask.arr[0] |= FATTR4_WORD0_FSID;
1436*c2c66affSColin Finck 
1437*c2c66affSColin Finck     compound_init(&compound, argops, resops, "link");
1438*c2c66affSColin Finck 
1439*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1440*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 1);
1441*c2c66affSColin Finck 
1442*c2c66affSColin Finck     /* PUTFH(src) */
1443*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args[0], &putfh_res[0]);
1444*c2c66affSColin Finck     putfh_args[0].file = src;
1445*c2c66affSColin Finck     putfh_args[0].in_recovery = 0;
1446*c2c66affSColin Finck 
1447*c2c66affSColin Finck     compound_add_op(&compound, OP_SAVEFH, NULL, &savefh_res);
1448*c2c66affSColin Finck 
1449*c2c66affSColin Finck     /* PUTFH(dst_dir) */
1450*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args[1], &putfh_res[1]);
1451*c2c66affSColin Finck     putfh_args[1].file = dst_dir;
1452*c2c66affSColin Finck     putfh_args[1].in_recovery = 0;
1453*c2c66affSColin Finck 
1454*c2c66affSColin Finck     compound_add_op(&compound, OP_LINK, &link_args, &link_res);
1455*c2c66affSColin Finck     link_args.newname = target;
1456*c2c66affSColin Finck 
1457*c2c66affSColin Finck     /* GETATTR(dst_dir) */
1458*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args[0], &getattr_res[0]);
1459*c2c66affSColin Finck     getattr_args[0].attr_request = &info.attrmask;
1460*c2c66affSColin Finck     getattr_res[0].obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1461*c2c66affSColin Finck     getattr_res[0].info = &info;
1462*c2c66affSColin Finck 
1463*c2c66affSColin Finck     /* LOOKUP(target) */
1464*c2c66affSColin Finck     compound_add_op(&compound, OP_LOOKUP, &lookup_args, &lookup_res);
1465*c2c66affSColin Finck     lookup_args.name = target;
1466*c2c66affSColin Finck 
1467*c2c66affSColin Finck     /* GETATTR(target) */
1468*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args[1], &getattr_res[1]);
1469*c2c66affSColin Finck     getattr_args[1].attr_request = &cinfo->attrmask;
1470*c2c66affSColin Finck     getattr_res[1].obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1471*c2c66affSColin Finck     getattr_res[1].info = cinfo;
1472*c2c66affSColin Finck 
1473*c2c66affSColin Finck     /* GETFH(target) */
1474*c2c66affSColin Finck     compound_add_op(&compound, OP_GETFH, NULL, &getfh_res);
1475*c2c66affSColin Finck     getfh_res.fh = &file.fh;
1476*c2c66affSColin Finck 
1477*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1478*c2c66affSColin Finck     if (status)
1479*c2c66affSColin Finck         goto out;
1480*c2c66affSColin Finck 
1481*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1482*c2c66affSColin Finck         goto out;
1483*c2c66affSColin Finck 
1484*c2c66affSColin Finck     /* fill in the file handle's fileid and superblock */
1485*c2c66affSColin Finck     file.fh.fileid = cinfo->fileid;
1486*c2c66affSColin Finck     status = nfs41_superblock_for_fh(session,
1487*c2c66affSColin Finck         &cinfo->fsid, &dst_dir->fh, &file);
1488*c2c66affSColin Finck     if (status)
1489*c2c66affSColin Finck         goto out;
1490*c2c66affSColin Finck 
1491*c2c66affSColin Finck     /* update the attributes of the destination directory */
1492*c2c66affSColin Finck     memcpy(&info.attrmask, &getattr_res[0].obj_attributes.attrmask,
1493*c2c66affSColin Finck         sizeof(bitmap4));
1494*c2c66affSColin Finck     nfs41_attr_cache_update(session_name_cache(session),
1495*c2c66affSColin Finck         info.fileid, &info);
1496*c2c66affSColin Finck 
1497*c2c66affSColin Finck     /* add the new file handle and attributes to the name cache */
1498*c2c66affSColin Finck     memcpy(&cinfo->attrmask, &getattr_res[1].obj_attributes.attrmask,
1499*c2c66affSColin Finck         sizeof(bitmap4));
1500*c2c66affSColin Finck     AcquireSRWLockShared(&dst_dir->path->lock);
1501*c2c66affSColin Finck     nfs41_name_cache_insert(session_name_cache(session),
1502*c2c66affSColin Finck         dst_dir->path->path, target, &file.fh,
1503*c2c66affSColin Finck         cinfo, &link_res.cinfo, OPEN_DELEGATE_NONE);
1504*c2c66affSColin Finck     ReleaseSRWLockShared(&dst_dir->path->lock);
1505*c2c66affSColin Finck 
1506*c2c66affSColin Finck     nfs41_superblock_space_changed(dst_dir->fh.superblock);
1507*c2c66affSColin Finck out:
1508*c2c66affSColin Finck     return status;
1509*c2c66affSColin Finck }
1510*c2c66affSColin Finck 
nfs41_readlink(IN nfs41_session * session,IN nfs41_path_fh * file,IN uint32_t max_len,OUT char * link_out,OUT uint32_t * len_out)1511*c2c66affSColin Finck int nfs41_readlink(
1512*c2c66affSColin Finck     IN nfs41_session *session,
1513*c2c66affSColin Finck     IN nfs41_path_fh *file,
1514*c2c66affSColin Finck     IN uint32_t max_len,
1515*c2c66affSColin Finck     OUT char *link_out,
1516*c2c66affSColin Finck     OUT uint32_t *len_out)
1517*c2c66affSColin Finck {
1518*c2c66affSColin Finck     int status;
1519*c2c66affSColin Finck     nfs41_compound compound;
1520*c2c66affSColin Finck     nfs_argop4 argops[3];
1521*c2c66affSColin Finck     nfs_resop4 resops[3];
1522*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1523*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1524*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1525*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1526*c2c66affSColin Finck     nfs41_readlink_res readlink_res;
1527*c2c66affSColin Finck 
1528*c2c66affSColin Finck     compound_init(&compound, argops, resops, "readlink");
1529*c2c66affSColin Finck 
1530*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1531*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1532*c2c66affSColin Finck 
1533*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1534*c2c66affSColin Finck     putfh_args.file = file;
1535*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1536*c2c66affSColin Finck 
1537*c2c66affSColin Finck     compound_add_op(&compound, OP_READLINK, NULL, &readlink_res);
1538*c2c66affSColin Finck     readlink_res.link_len = max_len - 1;
1539*c2c66affSColin Finck     readlink_res.link = link_out;
1540*c2c66affSColin Finck 
1541*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1542*c2c66affSColin Finck     if (status)
1543*c2c66affSColin Finck         goto out;
1544*c2c66affSColin Finck 
1545*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1546*c2c66affSColin Finck         goto out;
1547*c2c66affSColin Finck 
1548*c2c66affSColin Finck     link_out[readlink_res.link_len] = '\0';
1549*c2c66affSColin Finck     *len_out = readlink_res.link_len;
1550*c2c66affSColin Finck out:
1551*c2c66affSColin Finck     return status;
1552*c2c66affSColin Finck }
1553*c2c66affSColin Finck 
nfs41_access(IN nfs41_session * session,IN nfs41_path_fh * file,IN uint32_t requested,OUT uint32_t * supported OPTIONAL,OUT uint32_t * access OPTIONAL)1554*c2c66affSColin Finck int nfs41_access(
1555*c2c66affSColin Finck     IN nfs41_session *session,
1556*c2c66affSColin Finck     IN nfs41_path_fh *file,
1557*c2c66affSColin Finck     IN uint32_t requested,
1558*c2c66affSColin Finck     OUT uint32_t *supported OPTIONAL,
1559*c2c66affSColin Finck     OUT uint32_t *access OPTIONAL)
1560*c2c66affSColin Finck {
1561*c2c66affSColin Finck     int status;
1562*c2c66affSColin Finck     nfs41_compound compound;
1563*c2c66affSColin Finck     nfs_argop4 argops[3];
1564*c2c66affSColin Finck     nfs_resop4 resops[3];
1565*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1566*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1567*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1568*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1569*c2c66affSColin Finck     nfs41_access_args access_args;
1570*c2c66affSColin Finck     nfs41_access_res access_res;
1571*c2c66affSColin Finck 
1572*c2c66affSColin Finck     compound_init(&compound, argops, resops, "access");
1573*c2c66affSColin Finck 
1574*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1575*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1576*c2c66affSColin Finck 
1577*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1578*c2c66affSColin Finck     putfh_args.file = file;
1579*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1580*c2c66affSColin Finck 
1581*c2c66affSColin Finck     compound_add_op(&compound, OP_ACCESS, &access_args, &access_res);
1582*c2c66affSColin Finck     access_args.access = requested;
1583*c2c66affSColin Finck 
1584*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1585*c2c66affSColin Finck     if (status)
1586*c2c66affSColin Finck         goto out;
1587*c2c66affSColin Finck 
1588*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1589*c2c66affSColin Finck         goto out;
1590*c2c66affSColin Finck 
1591*c2c66affSColin Finck     if (supported)
1592*c2c66affSColin Finck         *supported = access_res.supported;
1593*c2c66affSColin Finck     if (access)
1594*c2c66affSColin Finck         *access = access_res.access;
1595*c2c66affSColin Finck out:
1596*c2c66affSColin Finck     return status;
1597*c2c66affSColin Finck }
1598*c2c66affSColin Finck 
nfs41_send_sequence(IN nfs41_session * session)1599*c2c66affSColin Finck int nfs41_send_sequence(
1600*c2c66affSColin Finck     IN nfs41_session *session)
1601*c2c66affSColin Finck {
1602*c2c66affSColin Finck     int status;
1603*c2c66affSColin Finck     nfs41_compound compound;
1604*c2c66affSColin Finck     nfs_argop4 argops[1];
1605*c2c66affSColin Finck     nfs_resop4 resops[1];
1606*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1607*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1608*c2c66affSColin Finck 
1609*c2c66affSColin Finck     compound_init(&compound, argops, resops, "sequence");
1610*c2c66affSColin Finck 
1611*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1612*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1613*c2c66affSColin Finck 
1614*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1615*c2c66affSColin Finck     if (status)
1616*c2c66affSColin Finck         goto out;
1617*c2c66affSColin Finck 
1618*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1619*c2c66affSColin Finck         goto out;
1620*c2c66affSColin Finck out:
1621*c2c66affSColin Finck     return status;
1622*c2c66affSColin Finck }
1623*c2c66affSColin Finck 
nfs41_want_delegation(IN nfs41_session * session,IN nfs41_path_fh * file,IN deleg_claim4 * claim,IN uint32_t want,IN bool_t try_recovery,OUT open_delegation4 * delegation)1624*c2c66affSColin Finck enum nfsstat4 nfs41_want_delegation(
1625*c2c66affSColin Finck     IN nfs41_session *session,
1626*c2c66affSColin Finck     IN nfs41_path_fh *file,
1627*c2c66affSColin Finck     IN deleg_claim4 *claim,
1628*c2c66affSColin Finck     IN uint32_t want,
1629*c2c66affSColin Finck     IN bool_t try_recovery,
1630*c2c66affSColin Finck     OUT open_delegation4 *delegation)
1631*c2c66affSColin Finck {
1632*c2c66affSColin Finck     enum nfsstat4 status;
1633*c2c66affSColin Finck     nfs41_compound compound;
1634*c2c66affSColin Finck     nfs_argop4 argops[3];
1635*c2c66affSColin Finck     nfs_resop4 resops[3];
1636*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1637*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1638*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1639*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1640*c2c66affSColin Finck     nfs41_want_delegation_args wd_args;
1641*c2c66affSColin Finck     nfs41_want_delegation_res wd_res;
1642*c2c66affSColin Finck 
1643*c2c66affSColin Finck     compound_init(&compound, argops, resops, "want_delegation");
1644*c2c66affSColin Finck 
1645*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1646*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1647*c2c66affSColin Finck 
1648*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1649*c2c66affSColin Finck     putfh_args.file = file;
1650*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1651*c2c66affSColin Finck 
1652*c2c66affSColin Finck     compound_add_op(&compound, OP_WANT_DELEGATION, &wd_args, &wd_res);
1653*c2c66affSColin Finck     wd_args.claim = claim;
1654*c2c66affSColin Finck     wd_args.want = want;
1655*c2c66affSColin Finck     wd_res.delegation = delegation;
1656*c2c66affSColin Finck 
1657*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, try_recovery);
1658*c2c66affSColin Finck     if (status)
1659*c2c66affSColin Finck         goto out;
1660*c2c66affSColin Finck 
1661*c2c66affSColin Finck     compound_error(status = compound.res.status);
1662*c2c66affSColin Finck out:
1663*c2c66affSColin Finck     return status;
1664*c2c66affSColin Finck }
1665*c2c66affSColin Finck 
nfs41_delegpurge(IN nfs41_session * session)1666*c2c66affSColin Finck int nfs41_delegpurge(
1667*c2c66affSColin Finck     IN nfs41_session *session)
1668*c2c66affSColin Finck {
1669*c2c66affSColin Finck     int status;
1670*c2c66affSColin Finck     nfs41_compound compound;
1671*c2c66affSColin Finck     nfs_argop4 argops[2];
1672*c2c66affSColin Finck     nfs_resop4 resops[2];
1673*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1674*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1675*c2c66affSColin Finck     nfs41_delegpurge_res dp_res;
1676*c2c66affSColin Finck 
1677*c2c66affSColin Finck     compound_init(&compound, argops, resops, "delegpurge");
1678*c2c66affSColin Finck 
1679*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1680*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1681*c2c66affSColin Finck 
1682*c2c66affSColin Finck     compound_add_op(&compound, OP_DELEGPURGE, NULL, &dp_res);
1683*c2c66affSColin Finck 
1684*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1685*c2c66affSColin Finck     if (status)
1686*c2c66affSColin Finck         goto out;
1687*c2c66affSColin Finck 
1688*c2c66affSColin Finck     compound_error(status = compound.res.status);
1689*c2c66affSColin Finck out:
1690*c2c66affSColin Finck     return status;
1691*c2c66affSColin Finck }
1692*c2c66affSColin Finck 
nfs41_delegreturn(IN nfs41_session * session,IN nfs41_path_fh * file,IN stateid_arg * stateid,IN bool_t try_recovery)1693*c2c66affSColin Finck int nfs41_delegreturn(
1694*c2c66affSColin Finck     IN nfs41_session *session,
1695*c2c66affSColin Finck     IN nfs41_path_fh *file,
1696*c2c66affSColin Finck     IN stateid_arg *stateid,
1697*c2c66affSColin Finck     IN bool_t try_recovery)
1698*c2c66affSColin Finck {
1699*c2c66affSColin Finck     int status;
1700*c2c66affSColin Finck     nfs41_compound compound;
1701*c2c66affSColin Finck     nfs_argop4 argops[3];
1702*c2c66affSColin Finck     nfs_resop4 resops[3];
1703*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1704*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1705*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1706*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1707*c2c66affSColin Finck     nfs41_delegreturn_args dr_args;
1708*c2c66affSColin Finck     nfs41_delegreturn_res dr_res;
1709*c2c66affSColin Finck 
1710*c2c66affSColin Finck     compound_init(&compound, argops, resops, "delegreturn");
1711*c2c66affSColin Finck 
1712*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1713*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1714*c2c66affSColin Finck 
1715*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1716*c2c66affSColin Finck     putfh_args.file = file;
1717*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1718*c2c66affSColin Finck 
1719*c2c66affSColin Finck     compound_add_op(&compound, OP_DELEGRETURN, &dr_args, &dr_res);
1720*c2c66affSColin Finck     dr_args.stateid = stateid;
1721*c2c66affSColin Finck 
1722*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, try_recovery);
1723*c2c66affSColin Finck     if (status)
1724*c2c66affSColin Finck         goto out;
1725*c2c66affSColin Finck 
1726*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1727*c2c66affSColin Finck         goto out;
1728*c2c66affSColin Finck 
1729*c2c66affSColin Finck     AcquireSRWLockShared(&file->path->lock);
1730*c2c66affSColin Finck     nfs41_name_cache_delegreturn(session_name_cache(session),
1731*c2c66affSColin Finck         file->fh.fileid, file->path->path, &file->name);
1732*c2c66affSColin Finck     ReleaseSRWLockShared(&file->path->lock);
1733*c2c66affSColin Finck out:
1734*c2c66affSColin Finck     return status;
1735*c2c66affSColin Finck }
1736*c2c66affSColin Finck 
nfs41_fs_locations(IN nfs41_session * session,IN nfs41_path_fh * parent,IN const nfs41_component * name,OUT fs_locations4 * locations)1737*c2c66affSColin Finck enum nfsstat4 nfs41_fs_locations(
1738*c2c66affSColin Finck     IN nfs41_session *session,
1739*c2c66affSColin Finck     IN nfs41_path_fh *parent,
1740*c2c66affSColin Finck     IN const nfs41_component *name,
1741*c2c66affSColin Finck     OUT fs_locations4 *locations)
1742*c2c66affSColin Finck {
1743*c2c66affSColin Finck     enum nfsstat4 status;
1744*c2c66affSColin Finck     nfs41_compound compound;
1745*c2c66affSColin Finck     nfs_argop4 argops[4];
1746*c2c66affSColin Finck     nfs_resop4 resops[4];
1747*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1748*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1749*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1750*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1751*c2c66affSColin Finck     nfs41_lookup_args lookup_args;
1752*c2c66affSColin Finck     nfs41_lookup_res lookup_res;
1753*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
1754*c2c66affSColin Finck     nfs41_getattr_res getattr_res;
1755*c2c66affSColin Finck     bitmap4 attr_request = { 1, { FATTR4_WORD0_FS_LOCATIONS } };
1756*c2c66affSColin Finck     nfs41_file_info info;
1757*c2c66affSColin Finck 
1758*c2c66affSColin Finck     compound_init(&compound, argops, resops, "fs_locations");
1759*c2c66affSColin Finck 
1760*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1761*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1762*c2c66affSColin Finck 
1763*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1764*c2c66affSColin Finck     putfh_args.file = parent;
1765*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1766*c2c66affSColin Finck 
1767*c2c66affSColin Finck     compound_add_op(&compound, OP_LOOKUP, &lookup_args, &lookup_res);
1768*c2c66affSColin Finck     lookup_args.name = name;
1769*c2c66affSColin Finck 
1770*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
1771*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
1772*c2c66affSColin Finck     info.fs_locations = locations;
1773*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
1774*c2c66affSColin Finck     getattr_res.info = &info;
1775*c2c66affSColin Finck 
1776*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1777*c2c66affSColin Finck     if (status)
1778*c2c66affSColin Finck         goto out;
1779*c2c66affSColin Finck 
1780*c2c66affSColin Finck     compound_error(status = compound.res.status);
1781*c2c66affSColin Finck out:
1782*c2c66affSColin Finck     return status;
1783*c2c66affSColin Finck }
1784*c2c66affSColin Finck 
nfs41_secinfo(IN nfs41_session * session,IN nfs41_path_fh * file,IN const nfs41_component * name,OUT nfs41_secinfo_info * secinfo)1785*c2c66affSColin Finck int nfs41_secinfo(
1786*c2c66affSColin Finck     IN nfs41_session *session,
1787*c2c66affSColin Finck     IN nfs41_path_fh *file,
1788*c2c66affSColin Finck     IN const nfs41_component *name,
1789*c2c66affSColin Finck     OUT nfs41_secinfo_info *secinfo)
1790*c2c66affSColin Finck {
1791*c2c66affSColin Finck     int status;
1792*c2c66affSColin Finck     nfs41_compound compound;
1793*c2c66affSColin Finck     nfs_argop4 argops[3];
1794*c2c66affSColin Finck     nfs_resop4 resops[3];
1795*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1796*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1797*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1798*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1799*c2c66affSColin Finck     nfs41_secinfo_args secinfo_args;
1800*c2c66affSColin Finck     nfs41_secinfo_noname_res secinfo_res;
1801*c2c66affSColin Finck 
1802*c2c66affSColin Finck     compound_init(&compound, argops, resops, "secinfo");
1803*c2c66affSColin Finck 
1804*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1805*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1806*c2c66affSColin Finck 
1807*c2c66affSColin Finck     if (file == NULL)
1808*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
1809*c2c66affSColin Finck     else {
1810*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1811*c2c66affSColin Finck         putfh_args.file = file;
1812*c2c66affSColin Finck         putfh_args.in_recovery = 0;
1813*c2c66affSColin Finck     }
1814*c2c66affSColin Finck 
1815*c2c66affSColin Finck     compound_add_op(&compound, OP_SECINFO, &secinfo_args, &secinfo_res);
1816*c2c66affSColin Finck     secinfo_args.name = name;
1817*c2c66affSColin Finck     secinfo_res.secinfo = secinfo;
1818*c2c66affSColin Finck 
1819*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, FALSE);
1820*c2c66affSColin Finck     if (status)
1821*c2c66affSColin Finck         goto out;
1822*c2c66affSColin Finck 
1823*c2c66affSColin Finck     compound_error(status = compound.res.status);
1824*c2c66affSColin Finck out:
1825*c2c66affSColin Finck     return status;
1826*c2c66affSColin Finck }
1827*c2c66affSColin Finck 
nfs41_secinfo_noname(IN nfs41_session * session,IN nfs41_path_fh * file,OUT nfs41_secinfo_info * secinfo)1828*c2c66affSColin Finck int nfs41_secinfo_noname(
1829*c2c66affSColin Finck     IN nfs41_session *session,
1830*c2c66affSColin Finck     IN nfs41_path_fh *file,
1831*c2c66affSColin Finck     OUT nfs41_secinfo_info *secinfo)
1832*c2c66affSColin Finck {
1833*c2c66affSColin Finck     int status;
1834*c2c66affSColin Finck     nfs41_compound compound;
1835*c2c66affSColin Finck     nfs_argop4 argops[3];
1836*c2c66affSColin Finck     nfs_resop4 resops[3];
1837*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1838*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1839*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1840*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1841*c2c66affSColin Finck     nfs41_secinfo_noname_args noname_args;
1842*c2c66affSColin Finck     nfs41_secinfo_noname_res noname_res;
1843*c2c66affSColin Finck 
1844*c2c66affSColin Finck     compound_init(&compound, argops, resops, "secinfo_no_name");
1845*c2c66affSColin Finck 
1846*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1847*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1848*c2c66affSColin Finck 
1849*c2c66affSColin Finck     if (file == NULL)
1850*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
1851*c2c66affSColin Finck     else {
1852*c2c66affSColin Finck         compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1853*c2c66affSColin Finck         putfh_args.file = file;
1854*c2c66affSColin Finck         putfh_args.in_recovery = 0;
1855*c2c66affSColin Finck     }
1856*c2c66affSColin Finck 
1857*c2c66affSColin Finck     compound_add_op(&compound, OP_SECINFO_NO_NAME, &noname_args, &noname_res);
1858*c2c66affSColin Finck     noname_args.type = SECINFO_STYLE4_CURRENT_FH;
1859*c2c66affSColin Finck     noname_res.secinfo = secinfo;
1860*c2c66affSColin Finck 
1861*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, FALSE);
1862*c2c66affSColin Finck     if (status)
1863*c2c66affSColin Finck         goto out;
1864*c2c66affSColin Finck 
1865*c2c66affSColin Finck     compound_error(status = compound.res.status);
1866*c2c66affSColin Finck out:
1867*c2c66affSColin Finck     return status;
1868*c2c66affSColin Finck }
1869*c2c66affSColin Finck 
nfs41_free_stateid(IN nfs41_session * session,IN stateid4 * stateid)1870*c2c66affSColin Finck enum nfsstat4 nfs41_free_stateid(
1871*c2c66affSColin Finck     IN nfs41_session *session,
1872*c2c66affSColin Finck     IN stateid4 *stateid)
1873*c2c66affSColin Finck {
1874*c2c66affSColin Finck     enum nfsstat4 status;
1875*c2c66affSColin Finck     nfs41_compound compound;
1876*c2c66affSColin Finck     nfs_argop4 argops[2];
1877*c2c66affSColin Finck     nfs_resop4 resops[2];
1878*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1879*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1880*c2c66affSColin Finck     nfs41_free_stateid_args freestateid_args;
1881*c2c66affSColin Finck     nfs41_free_stateid_res freestateid_res;
1882*c2c66affSColin Finck 
1883*c2c66affSColin Finck     compound_init(&compound, argops, resops, "free_stateid");
1884*c2c66affSColin Finck 
1885*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1886*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1887*c2c66affSColin Finck 
1888*c2c66affSColin Finck     compound_add_op(&compound, OP_FREE_STATEID, &freestateid_args, &freestateid_res);
1889*c2c66affSColin Finck     freestateid_args.stateid = stateid;
1890*c2c66affSColin Finck 
1891*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, FALSE);
1892*c2c66affSColin Finck     if (status)
1893*c2c66affSColin Finck         goto out;
1894*c2c66affSColin Finck 
1895*c2c66affSColin Finck     compound_error(status = compound.res.status);
1896*c2c66affSColin Finck out:
1897*c2c66affSColin Finck     return status;
1898*c2c66affSColin Finck }
1899*c2c66affSColin Finck 
nfs41_test_stateid(IN nfs41_session * session,IN stateid_arg * stateid_array,IN uint32_t count,OUT uint32_t * status_array)1900*c2c66affSColin Finck enum nfsstat4 nfs41_test_stateid(
1901*c2c66affSColin Finck     IN nfs41_session *session,
1902*c2c66affSColin Finck     IN stateid_arg *stateid_array,
1903*c2c66affSColin Finck     IN uint32_t count,
1904*c2c66affSColin Finck     OUT uint32_t *status_array)
1905*c2c66affSColin Finck {
1906*c2c66affSColin Finck     enum nfsstat4 status;
1907*c2c66affSColin Finck     nfs41_compound compound;
1908*c2c66affSColin Finck     nfs_argop4 argops[2];
1909*c2c66affSColin Finck     nfs_resop4 resops[2];
1910*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1911*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1912*c2c66affSColin Finck     nfs41_test_stateid_args teststateid_args;
1913*c2c66affSColin Finck     nfs41_test_stateid_res teststateid_res;
1914*c2c66affSColin Finck 
1915*c2c66affSColin Finck     compound_init(&compound, argops, resops, "test_stateid");
1916*c2c66affSColin Finck 
1917*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1918*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1919*c2c66affSColin Finck 
1920*c2c66affSColin Finck     compound_add_op(&compound, OP_TEST_STATEID, &teststateid_args, &teststateid_res);
1921*c2c66affSColin Finck     teststateid_args.stateids = stateid_array;
1922*c2c66affSColin Finck     teststateid_args.count = count;
1923*c2c66affSColin Finck     teststateid_res.resok.status = status_array;
1924*c2c66affSColin Finck     teststateid_res.resok.count = count;
1925*c2c66affSColin Finck 
1926*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, FALSE);
1927*c2c66affSColin Finck     if (status)
1928*c2c66affSColin Finck         goto out;
1929*c2c66affSColin Finck 
1930*c2c66affSColin Finck     compound_error(status = compound.res.status);
1931*c2c66affSColin Finck out:
1932*c2c66affSColin Finck     return status;
1933*c2c66affSColin Finck }
1934*c2c66affSColin Finck 
pnfs_rpc_layoutget(IN nfs41_session * session,IN nfs41_path_fh * file,IN stateid_arg * stateid,IN enum pnfs_iomode iomode,IN uint64_t offset,IN uint64_t minlength,IN uint64_t length,OUT pnfs_layoutget_res_ok * layoutget_res_ok)1935*c2c66affSColin Finck enum nfsstat4 pnfs_rpc_layoutget(
1936*c2c66affSColin Finck     IN nfs41_session *session,
1937*c2c66affSColin Finck     IN nfs41_path_fh *file,
1938*c2c66affSColin Finck     IN stateid_arg *stateid,
1939*c2c66affSColin Finck     IN enum pnfs_iomode iomode,
1940*c2c66affSColin Finck     IN uint64_t offset,
1941*c2c66affSColin Finck     IN uint64_t minlength,
1942*c2c66affSColin Finck     IN uint64_t length,
1943*c2c66affSColin Finck     OUT pnfs_layoutget_res_ok *layoutget_res_ok)
1944*c2c66affSColin Finck {
1945*c2c66affSColin Finck     enum nfsstat4 status;
1946*c2c66affSColin Finck     nfs41_compound compound;
1947*c2c66affSColin Finck     nfs_argop4 argops[3];
1948*c2c66affSColin Finck     nfs_resop4 resops[3];
1949*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
1950*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
1951*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
1952*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
1953*c2c66affSColin Finck     pnfs_layoutget_args layoutget_args;
1954*c2c66affSColin Finck     pnfs_layoutget_res layoutget_res = { 0 };
1955*c2c66affSColin Finck     uint32_t i;
1956*c2c66affSColin Finck     struct list_entry *entry;
1957*c2c66affSColin Finck 
1958*c2c66affSColin Finck     compound_init(&compound, argops, resops, "layoutget");
1959*c2c66affSColin Finck 
1960*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1961*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
1962*c2c66affSColin Finck 
1963*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
1964*c2c66affSColin Finck     putfh_args.file = file;
1965*c2c66affSColin Finck     putfh_args.in_recovery = 0;
1966*c2c66affSColin Finck 
1967*c2c66affSColin Finck     compound_add_op(&compound, OP_LAYOUTGET, &layoutget_args, &layoutget_res);
1968*c2c66affSColin Finck     layoutget_args.signal_layout_avail = 0;
1969*c2c66affSColin Finck     layoutget_args.layout_type = PNFS_LAYOUTTYPE_FILE;
1970*c2c66affSColin Finck     layoutget_args.iomode = iomode;
1971*c2c66affSColin Finck     layoutget_args.offset = offset;
1972*c2c66affSColin Finck     layoutget_args.minlength = minlength;
1973*c2c66affSColin Finck     layoutget_args.length = length;
1974*c2c66affSColin Finck     layoutget_args.stateid = stateid;
1975*c2c66affSColin Finck     layoutget_args.maxcount = session->fore_chan_attrs.ca_maxresponsesize - READ_OVERHEAD;
1976*c2c66affSColin Finck 
1977*c2c66affSColin Finck     layoutget_res.u.res_ok = layoutget_res_ok;
1978*c2c66affSColin Finck 
1979*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
1980*c2c66affSColin Finck     if (status)
1981*c2c66affSColin Finck         goto out;
1982*c2c66affSColin Finck 
1983*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
1984*c2c66affSColin Finck         goto out;
1985*c2c66affSColin Finck 
1986*c2c66affSColin Finck     /* point each file handle to the meta server's superblock */
1987*c2c66affSColin Finck     list_for_each(entry, &layoutget_res_ok->layouts) {
1988*c2c66affSColin Finck         pnfs_layout *base = list_container(entry, pnfs_layout, entry);
1989*c2c66affSColin Finck         if (base->type == PNFS_LAYOUTTYPE_FILE) {
1990*c2c66affSColin Finck             pnfs_file_layout *layout = (pnfs_file_layout*)base;
1991*c2c66affSColin Finck             for (i = 0; i < layout->filehandles.count; i++)
1992*c2c66affSColin Finck                 layout->filehandles.arr[i].fh.superblock = file->fh.superblock;
1993*c2c66affSColin Finck         }
1994*c2c66affSColin Finck     }
1995*c2c66affSColin Finck out:
1996*c2c66affSColin Finck     return status;
1997*c2c66affSColin Finck }
1998*c2c66affSColin Finck 
pnfs_rpc_layoutcommit(IN nfs41_session * session,IN nfs41_path_fh * file,IN stateid4 * stateid,IN uint64_t offset,IN uint64_t length,IN OPTIONAL uint64_t * new_last_offset,IN OPTIONAL nfstime4 * new_time_modify,OUT nfs41_file_info * info)1999*c2c66affSColin Finck enum nfsstat4 pnfs_rpc_layoutcommit(
2000*c2c66affSColin Finck     IN nfs41_session *session,
2001*c2c66affSColin Finck     IN nfs41_path_fh *file,
2002*c2c66affSColin Finck     IN stateid4 *stateid,
2003*c2c66affSColin Finck     IN uint64_t offset,
2004*c2c66affSColin Finck     IN uint64_t length,
2005*c2c66affSColin Finck     IN OPTIONAL uint64_t *new_last_offset,
2006*c2c66affSColin Finck     IN OPTIONAL nfstime4 *new_time_modify,
2007*c2c66affSColin Finck     OUT nfs41_file_info *info)
2008*c2c66affSColin Finck {
2009*c2c66affSColin Finck     enum nfsstat4 status;
2010*c2c66affSColin Finck     nfs41_compound compound;
2011*c2c66affSColin Finck     nfs_argop4 argops[4];
2012*c2c66affSColin Finck     nfs_resop4 resops[4];
2013*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
2014*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
2015*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
2016*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
2017*c2c66affSColin Finck     pnfs_layoutcommit_args lc_args;
2018*c2c66affSColin Finck     pnfs_layoutcommit_res lc_res;
2019*c2c66affSColin Finck     nfs41_getattr_args getattr_args;
2020*c2c66affSColin Finck     nfs41_getattr_res getattr_res;
2021*c2c66affSColin Finck     bitmap4 attr_request;
2022*c2c66affSColin Finck 
2023*c2c66affSColin Finck     nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
2024*c2c66affSColin Finck 
2025*c2c66affSColin Finck     compound_init(&compound, argops, resops, "layoutcommit");
2026*c2c66affSColin Finck 
2027*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
2028*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
2029*c2c66affSColin Finck 
2030*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
2031*c2c66affSColin Finck     putfh_args.file = file;
2032*c2c66affSColin Finck     putfh_args.in_recovery = 0;
2033*c2c66affSColin Finck 
2034*c2c66affSColin Finck     compound_add_op(&compound, OP_LAYOUTCOMMIT, &lc_args, &lc_res);
2035*c2c66affSColin Finck     lc_args.offset = offset;
2036*c2c66affSColin Finck     lc_args.length = length;
2037*c2c66affSColin Finck     lc_args.stateid = stateid;
2038*c2c66affSColin Finck     lc_args.new_time = new_time_modify;
2039*c2c66affSColin Finck     lc_args.new_offset = new_last_offset;
2040*c2c66affSColin Finck 
2041*c2c66affSColin Finck     compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
2042*c2c66affSColin Finck     getattr_args.attr_request = &attr_request;
2043*c2c66affSColin Finck     getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT;
2044*c2c66affSColin Finck     getattr_res.info = info;
2045*c2c66affSColin Finck 
2046*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
2047*c2c66affSColin Finck     if (status)
2048*c2c66affSColin Finck         goto out;
2049*c2c66affSColin Finck 
2050*c2c66affSColin Finck     if (compound_error(status = compound.res.status))
2051*c2c66affSColin Finck         goto out;
2052*c2c66affSColin Finck 
2053*c2c66affSColin Finck     /* update the attribute cache */
2054*c2c66affSColin Finck     memcpy(&info->attrmask, &getattr_res.obj_attributes.attrmask,
2055*c2c66affSColin Finck         sizeof(bitmap4));
2056*c2c66affSColin Finck     nfs41_attr_cache_update(session_name_cache(session),
2057*c2c66affSColin Finck         file->fh.fileid, info);
2058*c2c66affSColin Finck out:
2059*c2c66affSColin Finck     return status;
2060*c2c66affSColin Finck }
2061*c2c66affSColin Finck 
pnfs_rpc_layoutreturn(IN nfs41_session * session,IN nfs41_path_fh * file,IN enum pnfs_layout_type type,IN enum pnfs_iomode iomode,IN uint64_t offset,IN uint64_t length,IN stateid4 * stateid,OUT pnfs_layoutreturn_res * layoutreturn_res)2062*c2c66affSColin Finck enum nfsstat4 pnfs_rpc_layoutreturn(
2063*c2c66affSColin Finck     IN nfs41_session *session,
2064*c2c66affSColin Finck     IN nfs41_path_fh *file,
2065*c2c66affSColin Finck     IN enum pnfs_layout_type type,
2066*c2c66affSColin Finck     IN enum pnfs_iomode iomode,
2067*c2c66affSColin Finck     IN uint64_t offset,
2068*c2c66affSColin Finck     IN uint64_t length,
2069*c2c66affSColin Finck     IN stateid4 *stateid,
2070*c2c66affSColin Finck     OUT pnfs_layoutreturn_res *layoutreturn_res)
2071*c2c66affSColin Finck {
2072*c2c66affSColin Finck     enum nfsstat4 status;
2073*c2c66affSColin Finck     nfs41_compound compound;
2074*c2c66affSColin Finck     nfs_argop4 argops[3];
2075*c2c66affSColin Finck     nfs_resop4 resops[3];
2076*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
2077*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
2078*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
2079*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
2080*c2c66affSColin Finck     pnfs_layoutreturn_args layoutreturn_args;
2081*c2c66affSColin Finck 
2082*c2c66affSColin Finck     compound_init(&compound, argops, resops, "layoutreturn");
2083*c2c66affSColin Finck 
2084*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
2085*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
2086*c2c66affSColin Finck 
2087*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
2088*c2c66affSColin Finck     putfh_args.file = file;
2089*c2c66affSColin Finck     putfh_args.in_recovery = 0;
2090*c2c66affSColin Finck 
2091*c2c66affSColin Finck     compound_add_op(&compound, OP_LAYOUTRETURN, &layoutreturn_args, layoutreturn_res);
2092*c2c66affSColin Finck     layoutreturn_args.reclaim = 0;
2093*c2c66affSColin Finck     layoutreturn_args.type = type;
2094*c2c66affSColin Finck     layoutreturn_args.iomode = iomode;
2095*c2c66affSColin Finck     layoutreturn_args.return_type = PNFS_RETURN_FILE;
2096*c2c66affSColin Finck     layoutreturn_args.offset = offset;
2097*c2c66affSColin Finck     layoutreturn_args.length = length;
2098*c2c66affSColin Finck     layoutreturn_args.stateid = stateid;
2099*c2c66affSColin Finck 
2100*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
2101*c2c66affSColin Finck     if (status)
2102*c2c66affSColin Finck         goto out;
2103*c2c66affSColin Finck 
2104*c2c66affSColin Finck     compound_error(status = compound.res.status);
2105*c2c66affSColin Finck out:
2106*c2c66affSColin Finck     return status;
2107*c2c66affSColin Finck }
2108*c2c66affSColin Finck 
pnfs_rpc_getdeviceinfo(IN nfs41_session * session,IN unsigned char * deviceid,OUT pnfs_file_device * device)2109*c2c66affSColin Finck enum nfsstat4 pnfs_rpc_getdeviceinfo(
2110*c2c66affSColin Finck     IN nfs41_session *session,
2111*c2c66affSColin Finck     IN unsigned char *deviceid,
2112*c2c66affSColin Finck     OUT pnfs_file_device *device)
2113*c2c66affSColin Finck {
2114*c2c66affSColin Finck     enum nfsstat4 status;
2115*c2c66affSColin Finck     nfs41_compound compound;
2116*c2c66affSColin Finck     nfs_argop4 argops[2];
2117*c2c66affSColin Finck     nfs_resop4 resops[2];
2118*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
2119*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
2120*c2c66affSColin Finck     pnfs_getdeviceinfo_args getdeviceinfo_args;
2121*c2c66affSColin Finck     pnfs_getdeviceinfo_res getdeviceinfo_res;
2122*c2c66affSColin Finck 
2123*c2c66affSColin Finck     compound_init(&compound, argops, resops, "get_deviceinfo");
2124*c2c66affSColin Finck 
2125*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
2126*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
2127*c2c66affSColin Finck 
2128*c2c66affSColin Finck     compound_add_op(&compound, OP_GETDEVICEINFO,
2129*c2c66affSColin Finck         &getdeviceinfo_args, &getdeviceinfo_res);
2130*c2c66affSColin Finck     getdeviceinfo_args.deviceid = deviceid;
2131*c2c66affSColin Finck     getdeviceinfo_args.layout_type = PNFS_LAYOUTTYPE_FILE;
2132*c2c66affSColin Finck     getdeviceinfo_args.maxcount = NFS41_MAX_SERVER_CACHE; /* XXX */
2133*c2c66affSColin Finck     getdeviceinfo_args.notify_types.count = 0;
2134*c2c66affSColin Finck     getdeviceinfo_res.u.res_ok.device = device;
2135*c2c66affSColin Finck 
2136*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
2137*c2c66affSColin Finck     if (status)
2138*c2c66affSColin Finck         goto out;
2139*c2c66affSColin Finck 
2140*c2c66affSColin Finck     compound_error(status = compound.res.status);
2141*c2c66affSColin Finck out:
2142*c2c66affSColin Finck     return status;
2143*c2c66affSColin Finck }
2144*c2c66affSColin Finck 
nfs41_rpc_openattr(IN nfs41_session * session,IN nfs41_path_fh * file,IN bool_t createdir,OUT nfs41_fh * fh_out)2145*c2c66affSColin Finck enum nfsstat4 nfs41_rpc_openattr(
2146*c2c66affSColin Finck     IN nfs41_session *session,
2147*c2c66affSColin Finck     IN nfs41_path_fh *file,
2148*c2c66affSColin Finck     IN bool_t createdir,
2149*c2c66affSColin Finck     OUT nfs41_fh *fh_out)
2150*c2c66affSColin Finck {
2151*c2c66affSColin Finck     enum nfsstat4 status;
2152*c2c66affSColin Finck     nfs41_compound compound;
2153*c2c66affSColin Finck     nfs_argop4 argops[4];
2154*c2c66affSColin Finck     nfs_resop4 resops[4];
2155*c2c66affSColin Finck     nfs41_sequence_args sequence_args;
2156*c2c66affSColin Finck     nfs41_sequence_res sequence_res;
2157*c2c66affSColin Finck     nfs41_putfh_args putfh_args;
2158*c2c66affSColin Finck     nfs41_putfh_res putfh_res;
2159*c2c66affSColin Finck     nfs41_openattr_args openattr_args;
2160*c2c66affSColin Finck     nfs41_openattr_res openattr_res;
2161*c2c66affSColin Finck     nfs41_getfh_res getfh_res;
2162*c2c66affSColin Finck 
2163*c2c66affSColin Finck     compound_init(&compound, argops, resops, "openattr");
2164*c2c66affSColin Finck 
2165*c2c66affSColin Finck     compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
2166*c2c66affSColin Finck     nfs41_session_sequence(&sequence_args, session, 0);
2167*c2c66affSColin Finck 
2168*c2c66affSColin Finck     compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
2169*c2c66affSColin Finck     putfh_args.file = file;
2170*c2c66affSColin Finck     putfh_args.in_recovery = FALSE;
2171*c2c66affSColin Finck 
2172*c2c66affSColin Finck     compound_add_op(&compound, OP_OPENATTR, &openattr_args, &openattr_res);
2173*c2c66affSColin Finck     openattr_args.createdir = createdir;
2174*c2c66affSColin Finck 
2175*c2c66affSColin Finck     compound_add_op(&compound, OP_GETFH, NULL, &getfh_res);
2176*c2c66affSColin Finck     getfh_res.fh = fh_out;
2177*c2c66affSColin Finck 
2178*c2c66affSColin Finck     status = compound_encode_send_decode(session, &compound, TRUE);
2179*c2c66affSColin Finck     if (status)
2180*c2c66affSColin Finck         goto out;
2181*c2c66affSColin Finck 
2182*c2c66affSColin Finck     compound_error(status = compound.res.status);
2183*c2c66affSColin Finck 
2184*c2c66affSColin Finck     fh_out->superblock = file->fh.superblock;
2185*c2c66affSColin Finck out:
2186*c2c66affSColin Finck     return status;
2187*c2c66affSColin Finck }
2188