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