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.0/sys/fs/nfsclient/nfs_clcomsubs.c 264705 2014-04-20 22:19:00Z rmacklem $");
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 nfsstats newnfsstats;
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 };
116
117 /*
118 * NFS RPCS that have large request message size.
119 */
120 static int nfs_bigrequest[NFSV41_NPROCS] = {
121 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 0, 0, 0, 0, 1, 0, 0
124 };
125
126 /*
127 * Start building a request. Mostly just put the first file handle in
128 * place.
129 */
130 APPLESTATIC void
131 nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
132 u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep)
133 {
134 struct mbuf *mb;
135 u_int32_t *tl;
136 int opcnt;
137 nfsattrbit_t attrbits;
138
139 /*
140 * First, fill in some of the fields of nd.
141 */
142 nd->nd_slotseq = NULL;
143 if (NFSHASNFSV4(nmp)) {
144 nd->nd_flag = ND_NFSV4 | ND_NFSCL;
145 if (NFSHASNFSV4N(nmp))
146 nd->nd_flag |= ND_NFSV41;
147 } else if (NFSHASNFSV3(nmp))
148 nd->nd_flag = ND_NFSV3 | ND_NFSCL;
149 else
150 nd->nd_flag = ND_NFSV2 | ND_NFSCL;
151 nd->nd_procnum = procnum;
152 nd->nd_repstat = 0;
153
154 /*
155 * Get the first mbuf for the request.
156 */
157 if (nfs_bigrequest[procnum])
158 NFSMCLGET(mb, M_WAITOK);
159 else
160 NFSMGET(mb);
161 mbuf_setlen(mb, 0);
162 nd->nd_mreq = nd->nd_mb = mb;
163 nd->nd_bpos = NFSMTOD(mb, caddr_t);
164
165 /*
166 * And fill the first file handle into the request.
167 */
168 if (nd->nd_flag & ND_NFSV4) {
169 opcnt = nfsv4_opmap[procnum].opcnt +
170 nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh;
171 if ((nd->nd_flag & ND_NFSV41) != 0) {
172 opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq;
173 if (procnum == NFSPROC_RENEW)
174 /*
175 * For the special case of Renew, just do a
176 * Sequence Op.
177 */
178 opcnt = 1;
179 else if (procnum == NFSPROC_WRITEDS ||
180 procnum == NFSPROC_COMMITDS)
181 /*
182 * For the special case of a Writeor Commit to
183 * a DS, the opcnt == 3, for Sequence, PutFH,
184 * Write/Commit.
185 */
186 opcnt = 3;
187 }
188 /*
189 * What should the tag really be?
190 */
191 (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag,
192 nfsv4_opmap[procnum].taglen);
193 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
194 if ((nd->nd_flag & ND_NFSV41) != 0)
195 *tl++ = txdr_unsigned(NFSV41_MINORVERSION);
196 else
197 *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
198 if (opcntpp != NULL)
199 *opcntpp = tl;
200 *tl = txdr_unsigned(opcnt);
201 if ((nd->nd_flag & ND_NFSV41) != 0 &&
202 nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
203 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
204 *tl = txdr_unsigned(NFSV4OP_SEQUENCE);
205 if (sep == NULL)
206 nfsv4_setsequence(nmp, nd,
207 NFSMNT_MDSSESSION(nmp),
208 nfs_bigreply[procnum]);
209 else
210 nfsv4_setsequence(nmp, nd, sep,
211 nfs_bigreply[procnum]);
212 }
213 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
214 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
215 *tl = txdr_unsigned(NFSV4OP_PUTFH);
216 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
217 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
218 == 2 && procnum != NFSPROC_WRITEDS &&
219 procnum != NFSPROC_COMMITDS) {
220 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
221 *tl = txdr_unsigned(NFSV4OP_GETATTR);
222 /*
223 * For Lookup Ops, we want all the directory
224 * attributes, so we can load the name cache.
225 */
226 if (procnum == NFSPROC_LOOKUP ||
227 procnum == NFSPROC_LOOKUPP)
228 NFSGETATTR_ATTRBIT(&attrbits);
229 else {
230 NFSWCCATTR_ATTRBIT(&attrbits);
231 nd->nd_flag |= ND_V4WCCATTR;
232 }
233 (void) nfsrv_putattrbit(nd, &attrbits);
234 }
235 }
236 if (procnum != NFSPROC_RENEW ||
237 (nd->nd_flag & ND_NFSV41) == 0) {
238 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
239 *tl = txdr_unsigned(nfsv4_opmap[procnum].op);
240 }
241 } else {
242 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
243 }
244 if (procnum < NFSV4_NPROCS)
245 NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]);
246 }
247
248 #ifndef APPLE
249 /*
250 * copies a uio scatter/gather list to an mbuf chain.
251 * NOTE: can ony handle iovcnt == 1
252 */
253 APPLESTATIC void
254 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
255 {
256 char *uiocp;
257 struct mbuf *mp, *mp2;
258 int xfer, left, mlen;
259 int uiosiz, clflg, rem;
260 char *cp, *tcp;
261
262 KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
263
264 if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
265 clflg = 1;
266 else
267 clflg = 0;
268 rem = NFSM_RNDUP(siz) - siz;
269 mp = mp2 = nd->nd_mb;
270 while (siz > 0) {
271 left = uiop->uio_iov->iov_len;
272 uiocp = uiop->uio_iov->iov_base;
273 if (left > siz)
274 left = siz;
275 uiosiz = left;
276 while (left > 0) {
277 mlen = M_TRAILINGSPACE(mp);
278 if (mlen == 0) {
279 if (clflg)
280 NFSMCLGET(mp, M_WAITOK);
281 else
282 NFSMGET(mp);
283 mbuf_setlen(mp, 0);
284 mbuf_setnext(mp2, mp);
285 mp2 = mp;
286 mlen = M_TRAILINGSPACE(mp);
287 }
288 xfer = (left > mlen) ? mlen : left;
289 #ifdef notdef
290 /* Not Yet.. */
291 if (uiop->uio_iov->iov_op != NULL)
292 (*(uiop->uio_iov->iov_op))
293 (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
294 xfer);
295 else
296 #endif
297 if (uiop->uio_segflg == UIO_SYSSPACE)
298 NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
299 xfer);
300 else
301 copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t)
302 + mbuf_len(mp), xfer);
303 mbuf_setlen(mp, mbuf_len(mp) + xfer);
304 left -= xfer;
305 uiocp += xfer;
306 uiop->uio_offset += xfer;
307 uiop->uio_resid -= xfer;
308 }
309 tcp = (char *)uiop->uio_iov->iov_base;
310 tcp += uiosiz;
311 uiop->uio_iov->iov_base = (void *)tcp;
312 uiop->uio_iov->iov_len -= uiosiz;
313 siz -= uiosiz;
314 }
315 if (rem > 0) {
316 if (rem > M_TRAILINGSPACE(mp)) {
317 NFSMGET(mp);
318 mbuf_setlen(mp, 0);
319 mbuf_setnext(mp2, mp);
320 }
321 cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
322 for (left = 0; left < rem; left++)
323 *cp++ = '\0';
324 mbuf_setlen(mp, mbuf_len(mp) + rem);
325 nd->nd_bpos = cp;
326 } else
327 nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
328 nd->nd_mb = mp;
329 }
330 #endif /* !APPLE */
331
332 /*
333 * Load vnode attributes from the xdr file attributes.
334 * Returns EBADRPC if they can't be parsed, 0 otherwise.
335 */
336 APPLESTATIC int
337 nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)
338 {
339 struct nfs_fattr *fp;
340 int error = 0;
341
342 if (nd->nd_flag & ND_NFSV4) {
343 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,
344 NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
345 } else if (nd->nd_flag & ND_NFSV3) {
346 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);
347 nap->na_type = nfsv34tov_type(fp->fa_type);
348 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
349 nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
350 fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
351 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
352 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
353 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
354 nap->na_size = fxdr_hyper(&fp->fa3_size);
355 nap->na_blocksize = NFS_FABLKSIZE;
356 nap->na_bytes = fxdr_hyper(&fp->fa3_used);
357 nap->na_fileid = fxdr_hyper(&fp->fa3_fileid);
358 fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime);
359 fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime);
360 fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime);
361 nap->na_flags = 0;
362 nap->na_filerev = 0;
363 } else {
364 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR);
365 nap->na_type = nfsv2tov_type(fp->fa_type);
366 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
367 if (nap->na_type == VNON || nap->na_type == VREG)
368 nap->na_type = IFTOVT(nap->na_mode);
369 nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev);
370
371 /*
372 * Really ugly NFSv2 kludge.
373 */
374 if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1))
375 nap->na_type = VFIFO;
376 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
377 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
378 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
379 nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
380 nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
381 nap->na_bytes =
382 (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
383 NFS_FABLKSIZE;
384 nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid);
385 fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime);
386 fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime);
387 nap->na_flags = 0;
388 nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t,
389 fp->fa2_ctime.nfsv2_sec);
390 nap->na_ctime.tv_nsec = 0;
391 nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
392 nap->na_filerev = 0;
393 }
394 nfsmout:
395 return (error);
396 }
397
398 /*
399 * This function finds the directory cookie that corresponds to the
400 * logical byte offset given.
401 */
402 APPLESTATIC nfsuint64 *
403 nfscl_getcookie(struct nfsnode *np, off_t off, int add)
404 {
405 struct nfsdmap *dp, *dp2;
406 int pos;
407
408 pos = off / NFS_DIRBLKSIZ;
409 if (pos == 0) {
410 KASSERT(!add, ("nfs getcookie add at 0"));
411 return (&nfs_nullcookie);
412 }
413 pos--;
414 dp = LIST_FIRST(&np->n_cookies);
415 if (!dp) {
416 if (add) {
417 MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
418 M_NFSDIROFF, M_WAITOK);
419 dp->ndm_eocookie = 0;
420 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
421 } else
422 return (NULL);
423 }
424 while (pos >= NFSNUMCOOKIES) {
425 pos -= NFSNUMCOOKIES;
426 if (LIST_NEXT(dp, ndm_list) != NULL) {
427 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
428 pos >= dp->ndm_eocookie)
429 return (NULL);
430 dp = LIST_NEXT(dp, ndm_list);
431 } else if (add) {
432 MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
433 M_NFSDIROFF, M_WAITOK);
434 dp2->ndm_eocookie = 0;
435 LIST_INSERT_AFTER(dp, dp2, ndm_list);
436 dp = dp2;
437 } else
438 return (NULL);
439 }
440 if (pos >= dp->ndm_eocookie) {
441 if (add)
442 dp->ndm_eocookie = pos + 1;
443 else
444 return (NULL);
445 }
446 return (&dp->ndm_cookies[pos]);
447 }
448
449 /*
450 * Gets a file handle out of an nfs reply sent to the client and returns
451 * the file handle and the file's attributes.
452 * For V4, it assumes that Getfh and Getattr Op's results are here.
453 */
454 APPLESTATIC int
455 nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp,
456 struct nfsvattr *nap, int *attrflagp)
457 {
458 u_int32_t *tl;
459 int error = 0, flag = 1;
460
461 *nfhpp = NULL;
462 *attrflagp = 0;
463 /*
464 * First get the file handle and vnode.
465 */
466 if (nd->nd_flag & ND_NFSV3) {
467 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
468 flag = fxdr_unsigned(int, *tl);
469 } else if (nd->nd_flag & ND_NFSV4) {
470 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
471 }
472 if (flag) {
473 error = nfsm_getfh(nd, nfhpp);
474 if (error)
475 return (error);
476 }
477
478 /*
479 * Now, get the attributes.
480 */
481 if (nd->nd_flag & ND_NFSV4) {
482 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
483 } else if (nd->nd_flag & ND_NFSV3) {
484 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
485 if (flag) {
486 flag = fxdr_unsigned(int, *tl);
487 } else if (fxdr_unsigned(int, *tl)) {
488 error = nfsm_advance(nd, NFSX_V3FATTR, -1);
489 if (error)
490 return (error);
491 }
492 }
493 if (flag) {
494 error = nfsm_loadattr(nd, nap);
495 if (!error)
496 *attrflagp = 1;
497 }
498 nfsmout:
499 return (error);
500 }
501
502 /*
503 * Put a state Id in the mbuf list.
504 */
505 APPLESTATIC void
506 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
507 {
508 nfsv4stateid_t *st;
509
510 NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
511 if (flag == NFSSTATEID_PUTALLZERO) {
512 st->seqid = 0;
513 st->other[0] = 0;
514 st->other[1] = 0;
515 st->other[2] = 0;
516 } else if (flag == NFSSTATEID_PUTALLONE) {
517 st->seqid = 0xffffffff;
518 st->other[0] = 0xffffffff;
519 st->other[1] = 0xffffffff;
520 st->other[2] = 0xffffffff;
521 } else if (flag == NFSSTATEID_PUTSEQIDZERO) {
522 st->seqid = 0;
523 st->other[0] = stateidp->other[0];
524 st->other[1] = stateidp->other[1];
525 st->other[2] = stateidp->other[2];
526 } else {
527 st->seqid = stateidp->seqid;
528 st->other[0] = stateidp->other[0];
529 st->other[1] = stateidp->other[1];
530 st->other[2] = stateidp->other[2];
531 }
532 }
533
534 /*
535 * Initialize the owner/delegation sleep lock.
536 */
537 APPLESTATIC void
538 nfscl_lockinit(struct nfsv4lock *lckp)
539 {
540
541 lckp->nfslock_usecnt = 0;
542 lckp->nfslock_lock = 0;
543 }
544
545 /*
546 * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one
547 * thread for each posix process in the kernel.)
548 */
549 APPLESTATIC void
550 nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex)
551 {
552 int igotlock;
553
554 do {
555 igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL);
556 } while (!igotlock);
557 }
558
559 /*
560 * Release an exclusive lock.
561 */
562 APPLESTATIC void
563 nfscl_lockunlock(struct nfsv4lock *lckp)
564 {
565
566 nfsv4_unlock(lckp, 0);
567 }
568
569 /*
570 * Called to derefernce a lock on a stateid (delegation or open owner).
571 */
572 APPLESTATIC void
573 nfscl_lockderef(struct nfsv4lock *lckp)
574 {
575
576 NFSLOCKCLSTATE();
577 lckp->nfslock_usecnt--;
578 if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) {
579 lckp->nfslock_lock &= ~NFSV4LOCK_WANTED;
580 wakeup((caddr_t)lckp);
581 }
582 NFSUNLOCKCLSTATE();
583 }
584
Cache object: 8fe9fcbb46716089bc2aab3be040c2e8
|