nfs_clcomsubs.c revision 1.4 1 1.4 andvar /* $NetBSD: nfs_clcomsubs.c,v 1.4 2022/02/09 21:50:24 andvar Exp $ */
2 1.1 dholland /*-
3 1.1 dholland * Copyright (c) 1989, 1993
4 1.1 dholland * The Regents of the University of California. All rights reserved.
5 1.1 dholland *
6 1.1 dholland * This code is derived from software contributed to Berkeley by
7 1.1 dholland * Rick Macklem at The University of Guelph.
8 1.1 dholland *
9 1.1 dholland * Redistribution and use in source and binary forms, with or without
10 1.1 dholland * modification, are permitted provided that the following conditions
11 1.1 dholland * are met:
12 1.1 dholland * 1. Redistributions of source code must retain the above copyright
13 1.1 dholland * notice, this list of conditions and the following disclaimer.
14 1.1 dholland * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 dholland * notice, this list of conditions and the following disclaimer in the
16 1.1 dholland * documentation and/or other materials provided with the distribution.
17 1.1 dholland * 4. Neither the name of the University nor the names of its contributors
18 1.1 dholland * may be used to endorse or promote products derived from this software
19 1.1 dholland * without specific prior written permission.
20 1.1 dholland *
21 1.1 dholland * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1 dholland * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1 dholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1 dholland * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1 dholland * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1 dholland * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1 dholland * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1 dholland * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1 dholland * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1 dholland * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1 dholland * SUCH DAMAGE.
32 1.1 dholland *
33 1.1 dholland */
34 1.1 dholland
35 1.1 dholland #include <sys/cdefs.h>
36 1.2 pgoyette /* __FBSDID("FreeBSD: head/sys/fs/nfsclient/nfs_clcomsubs.c 304026 2016-08-12 22:44:59Z rmacklem "); */
37 1.4 andvar __RCSID("$NetBSD: nfs_clcomsubs.c,v 1.4 2022/02/09 21:50:24 andvar Exp $");
38 1.1 dholland
39 1.1 dholland /*
40 1.1 dholland * These functions support the macros and help fiddle mbuf chains for
41 1.1 dholland * the nfs op functions. They do things like create the rpc header and
42 1.1 dholland * copy data between mbuf chains and uio lists.
43 1.1 dholland */
44 1.1 dholland #ifndef APPLEKEXT
45 1.2 pgoyette #include <fs/nfs/common/nfsport.h>
46 1.1 dholland
47 1.2 pgoyette extern struct nfsstatsv1 nfsstatsv1;
48 1.1 dholland extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
49 1.1 dholland extern int ncl_mbuf_mlen;
50 1.1 dholland extern enum vtype newnv2tov_type[8];
51 1.1 dholland extern enum vtype nv34tov_type[8];
52 1.1 dholland extern int nfs_bigreply[NFSV41_NPROCS];
53 1.1 dholland NFSCLSTATEMUTEX;
54 1.1 dholland #endif /* !APPLEKEXT */
55 1.1 dholland
56 1.1 dholland static nfsuint64 nfs_nullcookie = {{ 0, 0 }};
57 1.1 dholland static struct {
58 1.1 dholland int op;
59 1.1 dholland int opcnt;
60 1.1 dholland const u_char *tag;
61 1.1 dholland int taglen;
62 1.1 dholland } nfsv4_opmap[NFSV41_NPROCS] = {
63 1.1 dholland { 0, 1, "Null", 4 },
64 1.1 dholland { NFSV4OP_GETATTR, 1, "Getattr", 7, },
65 1.1 dholland { NFSV4OP_SETATTR, 2, "Setattr", 7, },
66 1.1 dholland { NFSV4OP_LOOKUP, 3, "Lookup", 6, },
67 1.1 dholland { NFSV4OP_ACCESS, 2, "Access", 6, },
68 1.1 dholland { NFSV4OP_READLINK, 2, "Readlink", 8, },
69 1.1 dholland { NFSV4OP_READ, 1, "Read", 4, },
70 1.1 dholland { NFSV4OP_WRITE, 2, "Write", 5, },
71 1.2 pgoyette { NFSV4OP_OPEN, 5, "Open", 4, },
72 1.2 pgoyette { NFSV4OP_CREATE, 5, "Create", 6, },
73 1.1 dholland { NFSV4OP_CREATE, 1, "Create", 6, },
74 1.1 dholland { NFSV4OP_CREATE, 3, "Create", 6, },
75 1.1 dholland { NFSV4OP_REMOVE, 1, "Remove", 6, },
76 1.1 dholland { NFSV4OP_REMOVE, 1, "Remove", 6, },
77 1.1 dholland { NFSV4OP_SAVEFH, 5, "Rename", 6, },
78 1.1 dholland { NFSV4OP_SAVEFH, 4, "Link", 4, },
79 1.1 dholland { NFSV4OP_READDIR, 2, "Readdir", 7, },
80 1.1 dholland { NFSV4OP_READDIR, 2, "Readdir", 7, },
81 1.1 dholland { NFSV4OP_GETATTR, 1, "Getattr", 7, },
82 1.1 dholland { NFSV4OP_GETATTR, 1, "Getattr", 7, },
83 1.1 dholland { NFSV4OP_GETATTR, 1, "Getattr", 7, },
84 1.1 dholland { NFSV4OP_COMMIT, 2, "Commit", 6, },
85 1.1 dholland { NFSV4OP_LOOKUPP, 3, "Lookupp", 7, },
86 1.1 dholland { NFSV4OP_SETCLIENTID, 1, "SetClientID", 11, },
87 1.1 dholland { NFSV4OP_SETCLIENTIDCFRM, 1, "SetClientIDConfirm", 18, },
88 1.1 dholland { NFSV4OP_LOCK, 1, "Lock", 4, },
89 1.1 dholland { NFSV4OP_LOCKU, 1, "LockU", 5, },
90 1.1 dholland { NFSV4OP_OPEN, 2, "Open", 4, },
91 1.1 dholland { NFSV4OP_CLOSE, 1, "Close", 5, },
92 1.1 dholland { NFSV4OP_OPENCONFIRM, 1, "Openconfirm", 11, },
93 1.1 dholland { NFSV4OP_LOCKT, 1, "LockT", 5, },
94 1.1 dholland { NFSV4OP_OPENDOWNGRADE, 1, "Opendowngrade", 13, },
95 1.1 dholland { NFSV4OP_RENEW, 1, "Renew", 5, },
96 1.1 dholland { NFSV4OP_PUTROOTFH, 1, "Dirpath", 7, },
97 1.1 dholland { NFSV4OP_RELEASELCKOWN, 1, "Rellckown", 9, },
98 1.1 dholland { NFSV4OP_DELEGRETURN, 1, "Delegret", 8, },
99 1.1 dholland { NFSV4OP_DELEGRETURN, 3, "DelegRemove", 11, },
100 1.1 dholland { NFSV4OP_DELEGRETURN, 7, "DelegRename1", 12, },
101 1.1 dholland { NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, },
102 1.1 dholland { NFSV4OP_GETATTR, 1, "Getacl", 6, },
103 1.1 dholland { NFSV4OP_SETATTR, 1, "Setacl", 6, },
104 1.1 dholland { NFSV4OP_EXCHANGEID, 1, "ExchangeID", 10, },
105 1.1 dholland { NFSV4OP_CREATESESSION, 1, "CreateSession", 13, },
106 1.1 dholland { NFSV4OP_DESTROYSESSION, 1, "DestroySession", 14, },
107 1.1 dholland { NFSV4OP_DESTROYCLIENTID, 1, "DestroyClient", 13, },
108 1.1 dholland { NFSV4OP_FREESTATEID, 1, "FreeStateID", 11, },
109 1.1 dholland { NFSV4OP_LAYOUTGET, 1, "LayoutGet", 9, },
110 1.1 dholland { NFSV4OP_GETDEVINFO, 1, "GetDeviceInfo", 13, },
111 1.1 dholland { NFSV4OP_LAYOUTCOMMIT, 1, "LayoutCommit", 12, },
112 1.1 dholland { NFSV4OP_LAYOUTRETURN, 1, "LayoutReturn", 12, },
113 1.1 dholland { NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, },
114 1.1 dholland { NFSV4OP_WRITE, 1, "WriteDS", 7, },
115 1.1 dholland { NFSV4OP_READ, 1, "ReadDS", 6, },
116 1.1 dholland { NFSV4OP_COMMIT, 1, "CommitDS", 8, },
117 1.1 dholland };
118 1.1 dholland
119 1.1 dholland /*
120 1.1 dholland * NFS RPCS that have large request message size.
121 1.1 dholland */
122 1.1 dholland static int nfs_bigrequest[NFSV41_NPROCS] = {
123 1.1 dholland 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
124 1.1 dholland 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
125 1.1 dholland 0, 0, 0, 0, 0, 0, 1, 0, 0
126 1.1 dholland };
127 1.1 dholland
128 1.1 dholland /*
129 1.1 dholland * Start building a request. Mostly just put the first file handle in
130 1.1 dholland * place.
131 1.1 dholland */
132 1.1 dholland APPLESTATIC void
133 1.1 dholland nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
134 1.1 dholland u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep)
135 1.1 dholland {
136 1.1 dholland struct mbuf *mb;
137 1.1 dholland u_int32_t *tl;
138 1.1 dholland int opcnt;
139 1.1 dholland nfsattrbit_t attrbits;
140 1.1 dholland
141 1.1 dholland /*
142 1.1 dholland * First, fill in some of the fields of nd.
143 1.1 dholland */
144 1.1 dholland nd->nd_slotseq = NULL;
145 1.1 dholland if (NFSHASNFSV4(nmp)) {
146 1.1 dholland nd->nd_flag = ND_NFSV4 | ND_NFSCL;
147 1.1 dholland if (NFSHASNFSV4N(nmp))
148 1.1 dholland nd->nd_flag |= ND_NFSV41;
149 1.1 dholland } else if (NFSHASNFSV3(nmp))
150 1.1 dholland nd->nd_flag = ND_NFSV3 | ND_NFSCL;
151 1.1 dholland else
152 1.1 dholland nd->nd_flag = ND_NFSV2 | ND_NFSCL;
153 1.1 dholland nd->nd_procnum = procnum;
154 1.1 dholland nd->nd_repstat = 0;
155 1.1 dholland
156 1.1 dholland /*
157 1.1 dholland * Get the first mbuf for the request.
158 1.1 dholland */
159 1.1 dholland if (nfs_bigrequest[procnum])
160 1.1 dholland NFSMCLGET(mb, M_WAITOK);
161 1.1 dholland else
162 1.1 dholland NFSMGET(mb);
163 1.1 dholland mbuf_setlen(mb, 0);
164 1.1 dholland nd->nd_mreq = nd->nd_mb = mb;
165 1.1 dholland nd->nd_bpos = NFSMTOD(mb, caddr_t);
166 1.1 dholland
167 1.1 dholland /*
168 1.1 dholland * And fill the first file handle into the request.
169 1.1 dholland */
170 1.1 dholland if (nd->nd_flag & ND_NFSV4) {
171 1.1 dholland opcnt = nfsv4_opmap[procnum].opcnt +
172 1.1 dholland nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh;
173 1.1 dholland if ((nd->nd_flag & ND_NFSV41) != 0) {
174 1.1 dholland opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq;
175 1.1 dholland if (procnum == NFSPROC_RENEW)
176 1.1 dholland /*
177 1.1 dholland * For the special case of Renew, just do a
178 1.1 dholland * Sequence Op.
179 1.1 dholland */
180 1.1 dholland opcnt = 1;
181 1.1 dholland else if (procnum == NFSPROC_WRITEDS ||
182 1.1 dholland procnum == NFSPROC_COMMITDS)
183 1.1 dholland /*
184 1.1 dholland * For the special case of a Writeor Commit to
185 1.1 dholland * a DS, the opcnt == 3, for Sequence, PutFH,
186 1.1 dholland * Write/Commit.
187 1.1 dholland */
188 1.1 dholland opcnt = 3;
189 1.1 dholland }
190 1.1 dholland /*
191 1.1 dholland * What should the tag really be?
192 1.1 dholland */
193 1.1 dholland (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag,
194 1.1 dholland nfsv4_opmap[procnum].taglen);
195 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
196 1.1 dholland if ((nd->nd_flag & ND_NFSV41) != 0)
197 1.1 dholland *tl++ = txdr_unsigned(NFSV41_MINORVERSION);
198 1.1 dholland else
199 1.1 dholland *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
200 1.1 dholland if (opcntpp != NULL)
201 1.1 dholland *opcntpp = tl;
202 1.1 dholland *tl = txdr_unsigned(opcnt);
203 1.1 dholland if ((nd->nd_flag & ND_NFSV41) != 0 &&
204 1.1 dholland nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
205 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
206 1.1 dholland *tl = txdr_unsigned(NFSV4OP_SEQUENCE);
207 1.1 dholland if (sep == NULL)
208 1.2 pgoyette nfsv4_setsequence(nmp, nd,
209 1.2 pgoyette NFSMNT_MDSSESSION(nmp),
210 1.1 dholland nfs_bigreply[procnum]);
211 1.1 dholland else
212 1.2 pgoyette nfsv4_setsequence(nmp, nd, sep,
213 1.1 dholland nfs_bigreply[procnum]);
214 1.1 dholland }
215 1.1 dholland if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
216 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
217 1.1 dholland *tl = txdr_unsigned(NFSV4OP_PUTFH);
218 1.1 dholland (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
219 1.1 dholland if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
220 1.1 dholland == 2 && procnum != NFSPROC_WRITEDS &&
221 1.1 dholland procnum != NFSPROC_COMMITDS) {
222 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
223 1.1 dholland *tl = txdr_unsigned(NFSV4OP_GETATTR);
224 1.2 pgoyette /*
225 1.2 pgoyette * For Lookup Ops, we want all the directory
226 1.2 pgoyette * attributes, so we can load the name cache.
227 1.2 pgoyette */
228 1.2 pgoyette if (procnum == NFSPROC_LOOKUP ||
229 1.2 pgoyette procnum == NFSPROC_LOOKUPP)
230 1.2 pgoyette NFSGETATTR_ATTRBIT(&attrbits);
231 1.2 pgoyette else {
232 1.2 pgoyette NFSWCCATTR_ATTRBIT(&attrbits);
233 1.2 pgoyette nd->nd_flag |= ND_V4WCCATTR;
234 1.2 pgoyette }
235 1.1 dholland (void) nfsrv_putattrbit(nd, &attrbits);
236 1.1 dholland }
237 1.1 dholland }
238 1.1 dholland if (procnum != NFSPROC_RENEW ||
239 1.1 dholland (nd->nd_flag & ND_NFSV41) == 0) {
240 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
241 1.1 dholland *tl = txdr_unsigned(nfsv4_opmap[procnum].op);
242 1.1 dholland }
243 1.1 dholland } else {
244 1.1 dholland (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
245 1.1 dholland }
246 1.2 pgoyette if (procnum < NFSV41_NPROCS)
247 1.2 pgoyette NFSINCRGLOBAL(nfsstatsv1.rpccnt[procnum]);
248 1.1 dholland }
249 1.1 dholland
250 1.1 dholland #ifndef APPLE
251 1.1 dholland /*
252 1.1 dholland * copies a uio scatter/gather list to an mbuf chain.
253 1.4 andvar * NOTE: can only handle iovcnt == 1
254 1.1 dholland */
255 1.1 dholland APPLESTATIC void
256 1.1 dholland nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
257 1.1 dholland {
258 1.1 dholland char *uiocp;
259 1.1 dholland struct mbuf *mp, *mp2;
260 1.1 dholland int xfer, left, mlen;
261 1.1 dholland int uiosiz, clflg, rem;
262 1.1 dholland char *cp, *tcp;
263 1.1 dholland
264 1.1 dholland KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
265 1.1 dholland
266 1.1 dholland if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
267 1.1 dholland clflg = 1;
268 1.1 dholland else
269 1.1 dholland clflg = 0;
270 1.1 dholland rem = NFSM_RNDUP(siz) - siz;
271 1.1 dholland mp = mp2 = nd->nd_mb;
272 1.1 dholland while (siz > 0) {
273 1.1 dholland left = uiop->uio_iov->iov_len;
274 1.1 dholland uiocp = uiop->uio_iov->iov_base;
275 1.1 dholland if (left > siz)
276 1.1 dholland left = siz;
277 1.1 dholland uiosiz = left;
278 1.1 dholland while (left > 0) {
279 1.1 dholland mlen = M_TRAILINGSPACE(mp);
280 1.1 dholland if (mlen == 0) {
281 1.1 dholland if (clflg)
282 1.1 dholland NFSMCLGET(mp, M_WAITOK);
283 1.1 dholland else
284 1.1 dholland NFSMGET(mp);
285 1.1 dholland mbuf_setlen(mp, 0);
286 1.1 dholland mbuf_setnext(mp2, mp);
287 1.1 dholland mp2 = mp;
288 1.1 dholland mlen = M_TRAILINGSPACE(mp);
289 1.1 dholland }
290 1.1 dholland xfer = (left > mlen) ? mlen : left;
291 1.1 dholland #ifdef notdef
292 1.1 dholland /* Not Yet.. */
293 1.1 dholland if (uiop->uio_iov->iov_op != NULL)
294 1.1 dholland (*(uiop->uio_iov->iov_op))
295 1.1 dholland (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
296 1.1 dholland xfer);
297 1.1 dholland else
298 1.1 dholland #endif
299 1.1 dholland if (uiop->uio_segflg == UIO_SYSSPACE)
300 1.1 dholland NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
301 1.1 dholland xfer);
302 1.1 dholland else
303 1.1 dholland copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t)
304 1.1 dholland + mbuf_len(mp), xfer);
305 1.1 dholland mbuf_setlen(mp, mbuf_len(mp) + xfer);
306 1.1 dholland left -= xfer;
307 1.1 dholland uiocp += xfer;
308 1.1 dholland uiop->uio_offset += xfer;
309 1.1 dholland uiop->uio_resid -= xfer;
310 1.1 dholland }
311 1.1 dholland tcp = (char *)uiop->uio_iov->iov_base;
312 1.1 dholland tcp += uiosiz;
313 1.1 dholland uiop->uio_iov->iov_base = (void *)tcp;
314 1.1 dholland uiop->uio_iov->iov_len -= uiosiz;
315 1.1 dholland siz -= uiosiz;
316 1.1 dholland }
317 1.1 dholland if (rem > 0) {
318 1.1 dholland if (rem > M_TRAILINGSPACE(mp)) {
319 1.1 dholland NFSMGET(mp);
320 1.1 dholland mbuf_setlen(mp, 0);
321 1.1 dholland mbuf_setnext(mp2, mp);
322 1.1 dholland }
323 1.1 dholland cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
324 1.1 dholland for (left = 0; left < rem; left++)
325 1.1 dholland *cp++ = '\0';
326 1.1 dholland mbuf_setlen(mp, mbuf_len(mp) + rem);
327 1.1 dholland nd->nd_bpos = cp;
328 1.1 dholland } else
329 1.1 dholland nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
330 1.1 dholland nd->nd_mb = mp;
331 1.1 dholland }
332 1.1 dholland #endif /* !APPLE */
333 1.1 dholland
334 1.1 dholland /*
335 1.1 dholland * Load vnode attributes from the xdr file attributes.
336 1.1 dholland * Returns EBADRPC if they can't be parsed, 0 otherwise.
337 1.1 dholland */
338 1.1 dholland APPLESTATIC int
339 1.1 dholland nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)
340 1.1 dholland {
341 1.1 dholland struct nfs_fattr *fp;
342 1.1 dholland int error = 0;
343 1.1 dholland
344 1.1 dholland if (nd->nd_flag & ND_NFSV4) {
345 1.1 dholland error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,
346 1.1 dholland NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
347 1.1 dholland } else if (nd->nd_flag & ND_NFSV3) {
348 1.1 dholland NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);
349 1.1 dholland nap->na_type = nfsv34tov_type(fp->fa_type);
350 1.1 dholland nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
351 1.1 dholland nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
352 1.1 dholland fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
353 1.1 dholland nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
354 1.1 dholland nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
355 1.1 dholland nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
356 1.1 dholland nap->na_size = fxdr_hyper(&fp->fa3_size);
357 1.1 dholland nap->na_blocksize = NFS_FABLKSIZE;
358 1.1 dholland nap->na_bytes = fxdr_hyper(&fp->fa3_used);
359 1.1 dholland nap->na_fileid = fxdr_hyper(&fp->fa3_fileid);
360 1.1 dholland fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime);
361 1.1 dholland fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime);
362 1.1 dholland fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime);
363 1.1 dholland nap->na_flags = 0;
364 1.1 dholland nap->na_filerev = 0;
365 1.1 dholland } else {
366 1.1 dholland NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR);
367 1.1 dholland nap->na_type = nfsv2tov_type(fp->fa_type);
368 1.1 dholland nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
369 1.1 dholland if (nap->na_type == VNON || nap->na_type == VREG)
370 1.1 dholland nap->na_type = IFTOVT(nap->na_mode);
371 1.1 dholland nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev);
372 1.1 dholland
373 1.1 dholland /*
374 1.1 dholland * Really ugly NFSv2 kludge.
375 1.1 dholland */
376 1.1 dholland if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1))
377 1.1 dholland nap->na_type = VFIFO;
378 1.1 dholland nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
379 1.1 dholland nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
380 1.1 dholland nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
381 1.1 dholland nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
382 1.1 dholland nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
383 1.1 dholland nap->na_bytes =
384 1.1 dholland (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
385 1.1 dholland NFS_FABLKSIZE;
386 1.1 dholland nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid);
387 1.1 dholland fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime);
388 1.1 dholland fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime);
389 1.1 dholland nap->na_flags = 0;
390 1.1 dholland nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t,
391 1.1 dholland fp->fa2_ctime.nfsv2_sec);
392 1.1 dholland nap->na_ctime.tv_nsec = 0;
393 1.1 dholland nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
394 1.1 dholland nap->na_filerev = 0;
395 1.1 dholland }
396 1.1 dholland nfsmout:
397 1.1 dholland return (error);
398 1.1 dholland }
399 1.1 dholland
400 1.1 dholland /*
401 1.1 dholland * This function finds the directory cookie that corresponds to the
402 1.1 dholland * logical byte offset given.
403 1.1 dholland */
404 1.1 dholland APPLESTATIC nfsuint64 *
405 1.1 dholland nfscl_getcookie(struct nfsnode *np, off_t off, int add)
406 1.1 dholland {
407 1.1 dholland struct nfsdmap *dp, *dp2;
408 1.1 dholland int pos;
409 1.1 dholland
410 1.1 dholland pos = off / NFS_DIRBLKSIZ;
411 1.1 dholland if (pos == 0) {
412 1.1 dholland KASSERT(!add, ("nfs getcookie add at 0"));
413 1.1 dholland return (&nfs_nullcookie);
414 1.1 dholland }
415 1.1 dholland pos--;
416 1.1 dholland dp = LIST_FIRST(&np->n_cookies);
417 1.1 dholland if (!dp) {
418 1.1 dholland if (add) {
419 1.1 dholland MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
420 1.1 dholland M_NFSDIROFF, M_WAITOK);
421 1.1 dholland dp->ndm_eocookie = 0;
422 1.1 dholland LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
423 1.1 dholland } else
424 1.1 dholland return (NULL);
425 1.1 dholland }
426 1.1 dholland while (pos >= NFSNUMCOOKIES) {
427 1.1 dholland pos -= NFSNUMCOOKIES;
428 1.1 dholland if (LIST_NEXT(dp, ndm_list) != NULL) {
429 1.1 dholland if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
430 1.1 dholland pos >= dp->ndm_eocookie)
431 1.1 dholland return (NULL);
432 1.1 dholland dp = LIST_NEXT(dp, ndm_list);
433 1.1 dholland } else if (add) {
434 1.1 dholland MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
435 1.1 dholland M_NFSDIROFF, M_WAITOK);
436 1.1 dholland dp2->ndm_eocookie = 0;
437 1.1 dholland LIST_INSERT_AFTER(dp, dp2, ndm_list);
438 1.1 dholland dp = dp2;
439 1.1 dholland } else
440 1.1 dholland return (NULL);
441 1.1 dholland }
442 1.1 dholland if (pos >= dp->ndm_eocookie) {
443 1.1 dholland if (add)
444 1.1 dholland dp->ndm_eocookie = pos + 1;
445 1.1 dholland else
446 1.1 dholland return (NULL);
447 1.1 dholland }
448 1.1 dholland return (&dp->ndm_cookies[pos]);
449 1.1 dholland }
450 1.1 dholland
451 1.1 dholland /*
452 1.1 dholland * Gets a file handle out of an nfs reply sent to the client and returns
453 1.1 dholland * the file handle and the file's attributes.
454 1.1 dholland * For V4, it assumes that Getfh and Getattr Op's results are here.
455 1.1 dholland */
456 1.1 dholland APPLESTATIC int
457 1.1 dholland nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp,
458 1.1 dholland struct nfsvattr *nap, int *attrflagp)
459 1.1 dholland {
460 1.1 dholland u_int32_t *tl;
461 1.1 dholland int error = 0, flag = 1;
462 1.1 dholland
463 1.1 dholland *nfhpp = NULL;
464 1.1 dholland *attrflagp = 0;
465 1.1 dholland /*
466 1.1 dholland * First get the file handle and vnode.
467 1.1 dholland */
468 1.1 dholland if (nd->nd_flag & ND_NFSV3) {
469 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
470 1.1 dholland flag = fxdr_unsigned(int, *tl);
471 1.1 dholland } else if (nd->nd_flag & ND_NFSV4) {
472 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
473 1.1 dholland }
474 1.1 dholland if (flag) {
475 1.1 dholland error = nfsm_getfh(nd, nfhpp);
476 1.1 dholland if (error)
477 1.1 dholland return (error);
478 1.1 dholland }
479 1.1 dholland
480 1.1 dholland /*
481 1.1 dholland * Now, get the attributes.
482 1.1 dholland */
483 1.1 dholland if (nd->nd_flag & ND_NFSV4) {
484 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
485 1.1 dholland } else if (nd->nd_flag & ND_NFSV3) {
486 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
487 1.1 dholland if (flag) {
488 1.1 dholland flag = fxdr_unsigned(int, *tl);
489 1.1 dholland } else if (fxdr_unsigned(int, *tl)) {
490 1.1 dholland error = nfsm_advance(nd, NFSX_V3FATTR, -1);
491 1.1 dholland if (error)
492 1.1 dholland return (error);
493 1.1 dholland }
494 1.1 dholland }
495 1.1 dholland if (flag) {
496 1.1 dholland error = nfsm_loadattr(nd, nap);
497 1.1 dholland if (!error)
498 1.1 dholland *attrflagp = 1;
499 1.1 dholland }
500 1.1 dholland nfsmout:
501 1.1 dholland return (error);
502 1.1 dholland }
503 1.1 dholland
504 1.1 dholland /*
505 1.1 dholland * Put a state Id in the mbuf list.
506 1.1 dholland */
507 1.1 dholland APPLESTATIC void
508 1.1 dholland nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
509 1.1 dholland {
510 1.1 dholland nfsv4stateid_t *st;
511 1.1 dholland
512 1.1 dholland NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
513 1.1 dholland if (flag == NFSSTATEID_PUTALLZERO) {
514 1.1 dholland st->seqid = 0;
515 1.1 dholland st->other[0] = 0;
516 1.1 dholland st->other[1] = 0;
517 1.1 dholland st->other[2] = 0;
518 1.1 dholland } else if (flag == NFSSTATEID_PUTALLONE) {
519 1.1 dholland st->seqid = 0xffffffff;
520 1.1 dholland st->other[0] = 0xffffffff;
521 1.1 dholland st->other[1] = 0xffffffff;
522 1.1 dholland st->other[2] = 0xffffffff;
523 1.1 dholland } else if (flag == NFSSTATEID_PUTSEQIDZERO) {
524 1.1 dholland st->seqid = 0;
525 1.1 dholland st->other[0] = stateidp->other[0];
526 1.1 dholland st->other[1] = stateidp->other[1];
527 1.1 dholland st->other[2] = stateidp->other[2];
528 1.1 dholland } else {
529 1.1 dholland st->seqid = stateidp->seqid;
530 1.1 dholland st->other[0] = stateidp->other[0];
531 1.1 dholland st->other[1] = stateidp->other[1];
532 1.1 dholland st->other[2] = stateidp->other[2];
533 1.1 dholland }
534 1.1 dholland }
535 1.1 dholland
536 1.1 dholland /*
537 1.1 dholland * Initialize the owner/delegation sleep lock.
538 1.1 dholland */
539 1.1 dholland APPLESTATIC void
540 1.1 dholland nfscl_lockinit(struct nfsv4lock *lckp)
541 1.1 dholland {
542 1.1 dholland
543 1.1 dholland lckp->nfslock_usecnt = 0;
544 1.1 dholland lckp->nfslock_lock = 0;
545 1.1 dholland }
546 1.1 dholland
547 1.1 dholland /*
548 1.1 dholland * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one
549 1.1 dholland * thread for each posix process in the kernel.)
550 1.1 dholland */
551 1.1 dholland APPLESTATIC void
552 1.1 dholland nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex)
553 1.1 dholland {
554 1.1 dholland int igotlock;
555 1.1 dholland
556 1.1 dholland do {
557 1.1 dholland igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL);
558 1.1 dholland } while (!igotlock);
559 1.1 dholland }
560 1.1 dholland
561 1.1 dholland /*
562 1.1 dholland * Release an exclusive lock.
563 1.1 dholland */
564 1.1 dholland APPLESTATIC void
565 1.1 dholland nfscl_lockunlock(struct nfsv4lock *lckp)
566 1.1 dholland {
567 1.1 dholland
568 1.1 dholland nfsv4_unlock(lckp, 0);
569 1.1 dholland }
570 1.1 dholland
571 1.1 dholland /*
572 1.3 msaitoh * Called to dereference a lock on a stateid (delegation or open owner).
573 1.1 dholland */
574 1.1 dholland APPLESTATIC void
575 1.1 dholland nfscl_lockderef(struct nfsv4lock *lckp)
576 1.1 dholland {
577 1.1 dholland
578 1.1 dholland NFSLOCKCLSTATE();
579 1.1 dholland lckp->nfslock_usecnt--;
580 1.1 dholland if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) {
581 1.1 dholland lckp->nfslock_lock &= ~NFSV4LOCK_WANTED;
582 1.1 dholland wakeup((caddr_t)lckp);
583 1.1 dholland }
584 1.1 dholland NFSUNLOCKCLSTATE();
585 1.1 dholland }
586 1.1 dholland
587