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