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