Add additional sanity checks, remove unused arguments to vm_page_startup().
[dragonfly.git] / sys / vfs / nfs / nfsm_subs.h
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  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *      @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
37  * $FreeBSD: src/sys/nfs/nfsm_subs.h,v 1.27.2.1 2000/10/28 16:27:27 dwmalone Exp $
38  * $DragonFly: src/sys/vfs/nfs/nfsm_subs.h,v 1.8 2005/05/29 10:08:36 hsu Exp $
39  */
40
41
42 #ifndef _NFS_NFSM_SUBS_H_
43 #define _NFS_NFSM_SUBS_H_
44
45 struct ucred;
46 struct vnode;
47
48 /*
49  * These macros do strange and peculiar things to mbuf chains for
50  * the assistance of the nfs code. To attempt to use them for any
51  * other purpose will be dangerous. (they make weird assumptions)
52  */
53
54 /*
55  * First define what the actual subs. return
56  */
57 struct mbuf *nfsm_reqh (struct vnode *vp, u_long procid, int hsiz,
58                             caddr_t *bposp);
59 struct mbuf *nfsm_rpchead (struct ucred *cr, int nmflag, int procid,
60                                int auth_type, int auth_len, char *auth_str,
61                                int verf_len, char *verf_str,
62                                struct mbuf *mrest, int mrest_len,
63                                struct mbuf **mbp, u_int32_t *xidp);
64
65 #define M_HASCL(m)      ((m)->m_flags & M_EXT)
66 #define NFSMINOFF(m) \
67         do { \
68                 if (M_HASCL(m)) \
69                         (m)->m_data = (m)->m_ext.ext_buf; \
70                 else if ((m)->m_flags & M_PKTHDR) \
71                         (m)->m_data = (m)->m_pktdat; \
72                 else \
73                         (m)->m_data = (m)->m_dat; \
74         } while (0)
75 #define NFSMADV(m, s) \
76         do { \
77                 (m)->m_data += (s); \
78         } while (0)
79 #define NFSMSIZ(m)      ((M_HASCL(m))?MCLBYTES: \
80                                 (((m)->m_flags & M_PKTHDR)?MHLEN:MLEN))
81
82 /*
83  * Now for the macros that do the simple stuff and call the functions
84  * for the hard stuff.
85  * These macros use several vars. declared in nfsm_reqhead and these
86  * vars. must not be used elsewhere unless you are careful not to corrupt
87  * them. The vars. starting with pN and tN (N=1,2,3,..) are temporaries
88  * that may be used so long as the value is not expected to retained
89  * after a macro.
90  * I know, this is kind of dorkey, but it makes the actual op functions
91  * fairly clean and deals with the mess caused by the xdr discriminating
92  * unions.
93  */
94
95 #define nfsm_build(a,c,s) \
96         do { \
97                 if ((s) > M_TRAILINGSPACE(mb)) { \
98                         MGET(mb2, MB_WAIT, MT_DATA); \
99                         if ((s) > MLEN) \
100                                 panic("build > MLEN"); \
101                         mb->m_next = mb2; \
102                         mb = mb2; \
103                         mb->m_len = 0; \
104                         bpos = mtod(mb, caddr_t); \
105                 } \
106                 (a) = (c)(bpos); \
107                 mb->m_len += (s); \
108                 bpos += (s); \
109         } while (0)
110
111 #define nfsm_dissect(a, c, s) \
112         do { \
113                 t1 = mtod(md, caddr_t)+md->m_len-dpos; \
114                 if (t1 >= (s)) { \
115                         (a) = (c)(dpos); \
116                         dpos += (s); \
117                 } else if ((t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \
118                         error = t1; \
119                         m_freem(mrep); \
120                         goto nfsmout; \
121                 } else { \
122                         (a) = (c)cp2; \
123                 } \
124         } while (0)
125
126 #define nfsm_fhtom(v, v3) \
127         do { \
128                 if (v3) { \
129                         t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
130                         if (t2 <= M_TRAILINGSPACE(mb)) { \
131                                 nfsm_build(tl, u_int32_t *, t2); \
132                                 *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
133                                 *(tl + ((t2>>2) - 2)) = 0; \
134                                 bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
135                                         VTONFS(v)->n_fhsize); \
136                         } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, \
137                                 (caddr_t)VTONFS(v)->n_fhp, \
138                                 VTONFS(v)->n_fhsize)) != 0) { \
139                                 error = t2; \
140                                 m_freem(mreq); \
141                                 goto nfsmout; \
142                         } \
143                 } else { \
144                         nfsm_build(cp, caddr_t, NFSX_V2FH); \
145                         bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
146                 } \
147         } while (0)
148
149 #define nfsm_srvfhtom(f, v3) \
150         do { \
151                 if (v3) { \
152                         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FH);\
153                         *tl++ = txdr_unsigned(NFSX_V3FH); \
154                         bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
155                 } else { \
156                         nfsm_build(cp, caddr_t, NFSX_V2FH); \
157                         bcopy((caddr_t)(f), cp, NFSX_V2FH); \
158                 } \
159         } while (0)
160
161 #define nfsm_srvpostop_fh(f) \
162         do { \
163                 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
164                 *tl++ = nfs_true; \
165                 *tl++ = txdr_unsigned(NFSX_V3FH); \
166                 bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
167         } while (0)
168
169 #define nfsm_mtofh(d, v, v3, f) \
170         do { \
171                 struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
172                 if (v3) { \
173                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
174                         (f) = fxdr_unsigned(int, *tl); \
175                 } else \
176                         (f) = 1; \
177                 if (f) { \
178                         nfsm_getfh(ttfhp, ttfhsize, (v3)); \
179                         if ((t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
180                                 &ttnp)) != 0) { \
181                                 error = t1; \
182                                 m_freem(mrep); \
183                                 goto nfsmout; \
184                         } \
185                         (v) = NFSTOV(ttnp); \
186                 } \
187                 if (v3) { \
188                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
189                         if (f) \
190                                 (f) = fxdr_unsigned(int, *tl); \
191                         else if (fxdr_unsigned(int, *tl)) \
192                                 nfsm_adv(NFSX_V3FATTR); \
193                 } \
194                 if (f) \
195                         nfsm_loadattr((v), (struct vattr *)0); \
196         } while (0)
197
198 #define nfsm_getfh(f, s, v3) \
199         do { \
200                 if (v3) { \
201                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
202                         if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
203                                 (s) > NFSX_V3FHMAX) { \
204                                 m_freem(mrep); \
205                                 error = EBADRPC; \
206                                 goto nfsmout; \
207                         } \
208                 } else \
209                         (s) = NFSX_V2FH; \
210                 nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); \
211         } while (0)
212
213 #define nfsm_loadattr(v, a) \
214         do { \
215                 struct vnode *ttvp = (v); \
216                 if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a), 0)) != 0) { \
217                         error = t1; \
218                         m_freem(mrep); \
219                         goto nfsmout; \
220                 } \
221                 (v) = ttvp; \
222         } while (0)
223
224 #define nfsm_postop_attr(v, f, lflags) \
225         do { \
226                 struct vnode *ttvp = (v); \
227                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
228                 if (((f) = fxdr_unsigned(int, *tl)) != 0) { \
229                         if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
230                                 (struct vattr *)0, lflags)) != 0) { \
231                                 error = t1; \
232                                 (f) = 0; \
233                                 m_freem(mrep); \
234                                 goto nfsmout; \
235                         } \
236                         (v) = ttvp; \
237                 } \
238         } while (0)
239
240 /*
241  * This function updates the attribute cache based on data returned in the
242  * NFS reply for NFS RPCs that modify the target file.  If the RPC succeeds
243  * a 'before' and 'after' mtime is returned that allows us to determine if
244  * the new mtime attribute represents our modification or someone else's
245  * modification.  
246  *
247  * The flag argument returns non-0 if the original times matched, zero if
248  * they did not match.  NRMODIFIED is automatically set if the before time
249  * does not match the original n_mtime, and n_mtime is automatically updated
250  * to the new after time (by nfsm_postop_attr()).
251  */
252 /* Used as (f) for nfsm_wcc_data() */
253 #define NFSV3_WCCRATTR  0
254 #define NFSV3_WCCCHK    1
255
256 #define nfsm_wcc_data(v, f) \
257         do { \
258                 int ttattrf, ttretf = 0; \
259                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
260                 if (*tl == nfs_true) { \
261                         nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \
262                         if (f) { \
263                                 ttretf = (VTONFS(v)->n_mtime == \
264                                         fxdr_unsigned(u_int32_t, *(tl + 2))); \
265                                 if (!ttretf) \
266                                         VTONFS(v)->n_flag |= NRMODIFIED; \
267                         } \
268                         nfsm_postop_attr((v), ttattrf, NFS_LATTR_NOSHRINK|NFS_LATTR_NOMTIMECHECK); \
269                 } else { \
270                         nfsm_postop_attr((v), ttattrf, NFS_LATTR_NOSHRINK); \
271                 } \
272                 if (f) { \
273                         (f) = ttretf; \
274                 } else { \
275                         (f) = ttattrf; \
276                 } \
277         } while (0)
278
279 /* If full is true, set all fields, otherwise just set mode and time fields */
280 #define nfsm_v3attrbuild(a, full) \
281         do { \
282                 if ((a)->va_mode != (mode_t)VNOVAL) {                   \
283                         nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
284                         *tl++ = nfs_true;                               \
285                         *tl = txdr_unsigned((a)->va_mode);              \
286                 } else {                                                \
287                         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
288                         *tl = nfs_false;                                \
289                 }                                                       \
290                 if ((full) && (a)->va_uid != (uid_t)VNOVAL) {           \
291                         nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
292                         *tl++ = nfs_true;                               \
293                         *tl = txdr_unsigned((a)->va_uid);               \
294                 } else {                                                \
295                         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
296                         *tl = nfs_false;                                \
297                 }                                                       \
298                 if ((full) && (a)->va_gid != (gid_t)VNOVAL) {           \
299                         nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
300                         *tl++ = nfs_true;                               \
301                         *tl = txdr_unsigned((a)->va_gid);               \
302                 } else {                                                \
303                         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
304                         *tl = nfs_false;                                \
305                 }                                                       \
306                 if ((full) && (a)->va_size != VNOVAL) {                 \
307                         nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \
308                         *tl++ = nfs_true;                               \
309                         txdr_hyper((a)->va_size, tl);                   \
310                 } else {                                                \
311                         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
312                         *tl = nfs_false;                                \
313                 }                                                       \
314                 if ((a)->va_atime.tv_sec != VNOVAL) {                   \
315                         if ((a)->va_atime.tv_sec != time_second) {      \
316                                 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
317                                 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
318                                 txdr_nfsv3time(&(a)->va_atime, tl);     \
319                         } else {                                        \
320                                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
321                                 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
322                         }                                               \
323                 } else {                                                \
324                         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
325                         *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
326                 }                                                       \
327                 if ((a)->va_mtime.tv_sec != VNOVAL) {                   \
328                         if ((a)->va_mtime.tv_sec != time_second) {      \
329                                 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
330                                 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
331                                 txdr_nfsv3time(&(a)->va_mtime, tl);     \
332                         } else {                                        \
333                                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
334                                 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
335                         }                                               \
336                 } else {                                                \
337                         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
338                         *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
339                 }                                                       \
340         } while (0)
341                                 
342
343 #define nfsm_strsiz(s,m) \
344         do { \
345                 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
346                 if (((s) = fxdr_unsigned(int32_t,*tl)) > (m)) { \
347                         m_freem(mrep); \
348                         error = EBADRPC; \
349                         goto nfsmout; \
350                 } \
351         } while (0)
352
353 #define nfsm_srvstrsiz(s,m) \
354         do { \
355                 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
356                 if (((s) = fxdr_unsigned(int32_t,*tl)) > (m) || (s) <= 0) { \
357                         error = EBADRPC; \
358                         nfsm_reply(0); \
359                 } \
360         } while (0)
361
362 #define nfsm_srvnamesiz(s) \
363         do { \
364                 nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
365                 if (((s) = fxdr_unsigned(int32_t,*tl)) > NFS_MAXNAMLEN) \
366                         error = NFSERR_NAMETOL; \
367                 if ((s) <= 0) \
368                         error = EBADRPC; \
369                 if (error) \
370                         nfsm_reply(0); \
371         } while (0)
372
373 #define nfsm_mtouio(p,s) \
374         do {\
375                 if ((s) > 0 && \
376                    (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \
377                         error = t1; \
378                         m_freem(mrep); \
379                         goto nfsmout; \
380                 } \
381         } while (0)
382
383 #define nfsm_uiotom(p,s) \
384         do { \
385                 if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \
386                         error = t1; \
387                         m_freem(mreq); \
388                         goto nfsmout; \
389                 } \
390         } while (0)
391
392 #define nfsm_reqhead(v,a,s) \
393         do { \
394                 mb = mreq = nfsm_reqh((v),(a),(s),&bpos); \
395         } while (0)
396
397 #define nfsm_rndup(a)   (((a)+3)&(~0x3))
398
399 #define nfsm_request(v, t, td, c) \
400         do { \
401                 if ((error = nfs_request((v), mreq, (t), (td), \
402                    (c), &mrep, &md, &dpos)) != 0) { \
403                         if (error & NFSERR_RETERR) \
404                                 error &= ~NFSERR_RETERR; \
405                         else \
406                                 goto nfsmout; \
407                 } \
408         } while (0)
409
410 #define nfsm_strtom(a,s,m) \
411         do {\
412                 if ((s) > (m)) { \
413                         m_freem(mreq); \
414                         error = ENAMETOOLONG; \
415                         goto nfsmout; \
416                 } \
417                 t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \
418                 if (t2 <= M_TRAILINGSPACE(mb)) { \
419                         nfsm_build(tl,u_int32_t *,t2); \
420                         *tl++ = txdr_unsigned(s); \
421                         *(tl+((t2>>2)-2)) = 0; \
422                         bcopy((const char *)(a), (caddr_t)tl, (s)); \
423                 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \
424                         error = t2; \
425                         m_freem(mreq); \
426                         goto nfsmout; \
427                 } \
428         } while (0)
429
430 #define nfsm_srvdone \
431         do { \
432                 nfsmout: \
433                 return (error); \
434         } while (0)
435
436 #define nfsm_reply(s) \
437         do { \
438                 nfsd->nd_repstat = error; \
439                 if (error && !(nfsd->nd_flag & ND_NFSV3)) \
440                    (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
441                         mrq, &mb, &bpos); \
442                 else \
443                    (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
444                         mrq, &mb, &bpos); \
445                 if (mrep != NULL) { \
446                         m_freem(mrep); \
447                         mrep = NULL; \
448                 } \
449                 mreq = *mrq; \
450                 if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
451                         error == EBADRPC)) { \
452                         error = 0; \
453                         goto nfsmout; \
454                 } \
455         } while (0)
456
457 #define nfsm_writereply(s, v3) \
458         do { \
459                 nfsd->nd_repstat = error; \
460                 if (error && !(v3)) \
461                    (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
462                         &mreq, &mb, &bpos); \
463                 else \
464                    (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
465                         &mreq, &mb, &bpos); \
466         } while (0)
467
468 #define nfsm_adv(s) \
469         do { \
470                 t1 = mtod(md, caddr_t)+md->m_len-dpos; \
471                 if (t1 >= (s)) { \
472                         dpos += (s); \
473                 } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \
474                         error = t1; \
475                         m_freem(mrep); \
476                         goto nfsmout; \
477                 } \
478         } while (0)
479
480 #define nfsm_srvmtofh(f) \
481         do { \
482                 int fhlen; \
483                 if (nfsd->nd_flag & ND_NFSV3) { \
484                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
485                         fhlen = fxdr_unsigned(int, *tl); \
486                         if (fhlen != 0 && fhlen != NFSX_V3FH) { \
487                                 error = EBADRPC; \
488                                 nfsm_reply(0); \
489                         } \
490                 } else { \
491                         fhlen = NFSX_V2FH; \
492                 } \
493                 if (fhlen != 0) { \
494                         nfsm_dissect(tl, u_int32_t *, fhlen); \
495                         bcopy((caddr_t)tl, (caddr_t)(f), fhlen); \
496                 } else {\
497                         bzero((caddr_t)(f), NFSX_V3FH); \
498                 } \
499         } while (0)
500
501 #define nfsm_clget \
502         do { \
503                 if (bp >= be) { \
504                         if (mp == mb) \
505                                 mp->m_len += bp-bpos; \
506                         mp = m_getcl(MB_WAIT, MT_DATA, 0); \
507                         mp->m_len = MCLBYTES; \
508                         mp2->m_next = mp; \
509                         mp2 = mp; \
510                         bp = mtod(mp, caddr_t); \
511                         be = bp+mp->m_len; \
512                 } \
513                 tl = (u_int32_t *)bp; \
514         } while (0)
515
516 #define nfsm_srvfillattr(a, f) \
517         do { \
518                 nfsm_srvfattr(nfsd, (a), (f)); \
519         } while (0)
520
521 #define nfsm_srvwcc_data(br, b, ar, a) \
522         do { \
523                 nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \
524         } while (0)
525
526 #define nfsm_srvpostop_attr(r, a) \
527         do { \
528                 nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \
529         } while (0)
530
531 #define nfsm_srvsattr(a) \
532         do { \
533                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
534                 if (*tl == nfs_true) { \
535                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
536                         (a)->va_mode = nfstov_mode(*tl); \
537                 } \
538                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
539                 if (*tl == nfs_true) { \
540                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
541                         (a)->va_uid = fxdr_unsigned(uid_t, *tl); \
542                 } \
543                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
544                 if (*tl == nfs_true) { \
545                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
546                         (a)->va_gid = fxdr_unsigned(gid_t, *tl); \
547                 } \
548                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
549                 if (*tl == nfs_true) { \
550                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
551                         (a)->va_size = fxdr_hyper(tl); \
552                 } \
553                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
554                 switch (fxdr_unsigned(int, *tl)) { \
555                 case NFSV3SATTRTIME_TOCLIENT: \
556                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
557                         fxdr_nfsv3time(tl, &(a)->va_atime); \
558                         break; \
559                 case NFSV3SATTRTIME_TOSERVER: \
560                         getnanotime(&(a)->va_atime); \
561                         break; \
562                 }; \
563                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
564                 switch (fxdr_unsigned(int, *tl)) { \
565                 case NFSV3SATTRTIME_TOCLIENT: \
566                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
567                         fxdr_nfsv3time(tl, &(a)->va_mtime); \
568                         break; \
569                 case NFSV3SATTRTIME_TOSERVER: \
570                         getnanotime(&(a)->va_mtime); \
571                         break; \
572                 } \
573         } while (0)
574
575 #endif