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/10.0/sys/fs/nfsclient/nfs_clcomsubs.c 244042 2012-12-08 22:52:39Z 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, 3, "Open", 4, },
70 { NFSV4OP_CREATE, 3, "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(nd, NFSMNT_MDSSESSION(nmp),
207 nfs_bigreply[procnum]);
208 else
209 nfsv4_setsequence(nd, sep,
210 nfs_bigreply[procnum]);
211 }
212 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
213 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
214 *tl = txdr_unsigned(NFSV4OP_PUTFH);
215 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
216 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
217 == 2 && procnum != NFSPROC_WRITEDS &&
218 procnum != NFSPROC_COMMITDS) {
219 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
220 *tl = txdr_unsigned(NFSV4OP_GETATTR);
221 NFSWCCATTR_ATTRBIT(&attrbits);
222 (void) nfsrv_putattrbit(nd, &attrbits);
223 nd->nd_flag |= ND_V4WCCATTR;
224 }
225 }
226 if (procnum != NFSPROC_RENEW ||
227 (nd->nd_flag & ND_NFSV41) == 0) {
228 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
229 *tl = txdr_unsigned(nfsv4_opmap[procnum].op);
230 }
231 } else {
232 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
233 }
234 if (procnum < NFSV4_NPROCS)
235 NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]);
236 }
237
238 #ifndef APPLE
239 /*
240 * copies a uio scatter/gather list to an mbuf chain.
241 * NOTE: can ony handle iovcnt == 1
242 */
243 APPLESTATIC void
244 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
245 {
246 char *uiocp;
247 struct mbuf *mp, *mp2;
248 int xfer, left, mlen;
249 int uiosiz, clflg, rem;
250 char *cp, *tcp;
251
252 KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
253
254 if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
255 clflg = 1;
256 else
257 clflg = 0;
258 rem = NFSM_RNDUP(siz) - siz;
259 mp = mp2 = nd->nd_mb;
260 while (siz > 0) {
261 left = uiop->uio_iov->iov_len;
262 uiocp = uiop->uio_iov->iov_base;
263 if (left > siz)
264 left = siz;
265 uiosiz = left;
266 while (left > 0) {
267 mlen = M_TRAILINGSPACE(mp);
268 if (mlen == 0) {
269 if (clflg)
270 NFSMCLGET(mp, M_WAITOK);
271 else
272 NFSMGET(mp);
273 mbuf_setlen(mp, 0);
274 mbuf_setnext(mp2, mp);
275 mp2 = mp;
276 mlen = M_TRAILINGSPACE(mp);
277 }
278 xfer = (left > mlen) ? mlen : left;
279 #ifdef notdef
280 /* Not Yet.. */
281 if (uiop->uio_iov->iov_op != NULL)
282 (*(uiop->uio_iov->iov_op))
283 (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
284 xfer);
285 else
286 #endif
287 if (uiop->uio_segflg == UIO_SYSSPACE)
288 NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
289 xfer);
290 else
291 copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t)
292 + mbuf_len(mp), xfer);
293 mbuf_setlen(mp, mbuf_len(mp) + xfer);
294 left -= xfer;
295 uiocp += xfer;
296 uiop->uio_offset += xfer;
297 uiop->uio_resid -= xfer;
298 }
299 tcp = (char *)uiop->uio_iov->iov_base;
300 tcp += uiosiz;
301 uiop->uio_iov->iov_base = (void *)tcp;
302 uiop->uio_iov->iov_len -= uiosiz;
303 siz -= uiosiz;
304 }
305 if (rem > 0) {
306 if (rem > M_TRAILINGSPACE(mp)) {
307 NFSMGET(mp);
308 mbuf_setlen(mp, 0);
309 mbuf_setnext(mp2, mp);
310 }
311 cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
312 for (left = 0; left < rem; left++)
313 *cp++ = '\0';
314 mbuf_setlen(mp, mbuf_len(mp) + rem);
315 nd->nd_bpos = cp;
316 } else
317 nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
318 nd->nd_mb = mp;
319 }
320 #endif /* !APPLE */
321
322 /*
323 * Load vnode attributes from the xdr file attributes.
324 * Returns EBADRPC if they can't be parsed, 0 otherwise.
325 */
326 APPLESTATIC int
327 nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)
328 {
329 struct nfs_fattr *fp;
330 int error = 0;
331
332 if (nd->nd_flag & ND_NFSV4) {
333 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,
334 NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
335 } else if (nd->nd_flag & ND_NFSV3) {
336 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);
337 nap->na_type = nfsv34tov_type(fp->fa_type);
338 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
339 nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
340 fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
341 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
342 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
343 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
344 nap->na_size = fxdr_hyper(&fp->fa3_size);
345 nap->na_blocksize = NFS_FABLKSIZE;
346 nap->na_bytes = fxdr_hyper(&fp->fa3_used);
347 nap->na_fileid = fxdr_hyper(&fp->fa3_fileid);
348 fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime);
349 fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime);
350 fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime);
351 nap->na_flags = 0;
352 nap->na_filerev = 0;
353 } else {
354 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR);
355 nap->na_type = nfsv2tov_type(fp->fa_type);
356 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
357 if (nap->na_type == VNON || nap->na_type == VREG)
358 nap->na_type = IFTOVT(nap->na_mode);
359 nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev);
360
361 /*
362 * Really ugly NFSv2 kludge.
363 */
364 if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1))
365 nap->na_type = VFIFO;
366 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
367 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
368 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
369 nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
370 nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
371 nap->na_bytes =
372 (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
373 NFS_FABLKSIZE;
374 nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid);
375 fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime);
376 fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime);
377 nap->na_flags = 0;
378 nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t,
379 fp->fa2_ctime.nfsv2_sec);
380 nap->na_ctime.tv_nsec = 0;
381 nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
382 nap->na_filerev = 0;
383 }
384 nfsmout:
385 return (error);
386 }
387
388 /*
389 * This function finds the directory cookie that corresponds to the
390 * logical byte offset given.
391 */
392 APPLESTATIC nfsuint64 *
393 nfscl_getcookie(struct nfsnode *np, off_t off, int add)
394 {
395 struct nfsdmap *dp, *dp2;
396 int pos;
397
398 pos = off / NFS_DIRBLKSIZ;
399 if (pos == 0) {
400 KASSERT(!add, ("nfs getcookie add at 0"));
401 return (&nfs_nullcookie);
402 }
403 pos--;
404 dp = LIST_FIRST(&np->n_cookies);
405 if (!dp) {
406 if (add) {
407 MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
408 M_NFSDIROFF, M_WAITOK);
409 dp->ndm_eocookie = 0;
410 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
411 } else
412 return (NULL);
413 }
414 while (pos >= NFSNUMCOOKIES) {
415 pos -= NFSNUMCOOKIES;
416 if (LIST_NEXT(dp, ndm_list) != NULL) {
417 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
418 pos >= dp->ndm_eocookie)
419 return (NULL);
420 dp = LIST_NEXT(dp, ndm_list);
421 } else if (add) {
422 MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
423 M_NFSDIROFF, M_WAITOK);
424 dp2->ndm_eocookie = 0;
425 LIST_INSERT_AFTER(dp, dp2, ndm_list);
426 dp = dp2;
427 } else
428 return (NULL);
429 }
430 if (pos >= dp->ndm_eocookie) {
431 if (add)
432 dp->ndm_eocookie = pos + 1;
433 else
434 return (NULL);
435 }
436 return (&dp->ndm_cookies[pos]);
437 }
438
439 /*
440 * Gets a file handle out of an nfs reply sent to the client and returns
441 * the file handle and the file's attributes.
442 * For V4, it assumes that Getfh and Getattr Op's results are here.
443 */
444 APPLESTATIC int
445 nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp,
446 struct nfsvattr *nap, int *attrflagp)
447 {
448 u_int32_t *tl;
449 int error = 0, flag = 1;
450
451 *nfhpp = NULL;
452 *attrflagp = 0;
453 /*
454 * First get the file handle and vnode.
455 */
456 if (nd->nd_flag & ND_NFSV3) {
457 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
458 flag = fxdr_unsigned(int, *tl);
459 } else if (nd->nd_flag & ND_NFSV4) {
460 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
461 }
462 if (flag) {
463 error = nfsm_getfh(nd, nfhpp);
464 if (error)
465 return (error);
466 }
467
468 /*
469 * Now, get the attributes.
470 */
471 if (nd->nd_flag & ND_NFSV4) {
472 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
473 } else if (nd->nd_flag & ND_NFSV3) {
474 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
475 if (flag) {
476 flag = fxdr_unsigned(int, *tl);
477 } else if (fxdr_unsigned(int, *tl)) {
478 error = nfsm_advance(nd, NFSX_V3FATTR, -1);
479 if (error)
480 return (error);
481 }
482 }
483 if (flag) {
484 error = nfsm_loadattr(nd, nap);
485 if (!error)
486 *attrflagp = 1;
487 }
488 nfsmout:
489 return (error);
490 }
491
492 /*
493 * Put a state Id in the mbuf list.
494 */
495 APPLESTATIC void
496 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
497 {
498 nfsv4stateid_t *st;
499
500 NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
501 if (flag == NFSSTATEID_PUTALLZERO) {
502 st->seqid = 0;
503 st->other[0] = 0;
504 st->other[1] = 0;
505 st->other[2] = 0;
506 } else if (flag == NFSSTATEID_PUTALLONE) {
507 st->seqid = 0xffffffff;
508 st->other[0] = 0xffffffff;
509 st->other[1] = 0xffffffff;
510 st->other[2] = 0xffffffff;
511 } else if (flag == NFSSTATEID_PUTSEQIDZERO) {
512 st->seqid = 0;
513 st->other[0] = stateidp->other[0];
514 st->other[1] = stateidp->other[1];
515 st->other[2] = stateidp->other[2];
516 } else {
517 st->seqid = stateidp->seqid;
518 st->other[0] = stateidp->other[0];
519 st->other[1] = stateidp->other[1];
520 st->other[2] = stateidp->other[2];
521 }
522 }
523
524 /*
525 * Initialize the owner/delegation sleep lock.
526 */
527 APPLESTATIC void
528 nfscl_lockinit(struct nfsv4lock *lckp)
529 {
530
531 lckp->nfslock_usecnt = 0;
532 lckp->nfslock_lock = 0;
533 }
534
535 /*
536 * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one
537 * thread for each posix process in the kernel.)
538 */
539 APPLESTATIC void
540 nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex)
541 {
542 int igotlock;
543
544 do {
545 igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL);
546 } while (!igotlock);
547 }
548
549 /*
550 * Release an exclusive lock.
551 */
552 APPLESTATIC void
553 nfscl_lockunlock(struct nfsv4lock *lckp)
554 {
555
556 nfsv4_unlock(lckp, 0);
557 }
558
559 /*
560 * Called to derefernce a lock on a stateid (delegation or open owner).
561 */
562 APPLESTATIC void
563 nfscl_lockderef(struct nfsv4lock *lckp)
564 {
565
566 NFSLOCKCLSTATE();
567 lckp->nfslock_usecnt--;
568 if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) {
569 lckp->nfslock_lock &= ~NFSV4LOCK_WANTED;
570 wakeup((caddr_t)lckp);
571 }
572 NFSUNLOCKCLSTATE();
573 }
574
Cache object: 4a247052ae391db46c41f8bcdeb1922a
|