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