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