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