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