1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 /* 40 * Socket operations for use by the nfs server. 41 */ 42 43 #include <fs/nfs/nfsport.h> 44 45 extern struct nfsstatsv1 nfsstatsv1; 46 extern struct nfsrvfh nfs_pubfh, nfs_rootfh; 47 extern int nfs_pubfhset, nfs_rootfhset; 48 extern struct nfsv4lock nfsv4rootfs_lock; 49 extern struct nfsrv_stablefirst nfsrv_stablefirst; 50 extern struct nfsclienthashhead *nfsclienthash; 51 extern int nfsrv_clienthashsize; 52 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies; 53 extern int nfsd_debuglevel; 54 extern int nfsrv_layouthighwater; 55 extern volatile int nfsrv_layoutcnt; 56 NFSV4ROOTLOCKMUTEX; 57 NFSSTATESPINLOCK; 58 59 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *, 60 int, vnode_t , struct nfsexstuff *) = { 61 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 62 nfsrvd_getattr, 63 nfsrvd_setattr, 64 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 65 nfsrvd_access, 66 nfsrvd_readlink, 67 nfsrvd_read, 68 nfsrvd_write, 69 nfsrvd_create, 70 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 71 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 72 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 73 nfsrvd_remove, 74 nfsrvd_remove, 75 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 76 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 77 nfsrvd_readdir, 78 nfsrvd_readdirplus, 79 nfsrvd_statfs, 80 nfsrvd_fsinfo, 81 nfsrvd_pathconf, 82 nfsrvd_commit, 83 }; 84 85 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *, 86 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = { 87 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 88 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 89 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 90 nfsrvd_lookup, 91 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 92 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 93 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 94 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 95 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 96 nfsrvd_mkdir, 97 nfsrvd_symlink, 98 nfsrvd_mknod, 99 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 100 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 101 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 102 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 103 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 104 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 105 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 106 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 107 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 108 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 109 }; 110 111 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *, 112 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = { 113 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 114 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 115 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 116 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 117 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 118 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 119 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 120 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 121 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 122 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 123 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 124 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 125 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 126 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 127 nfsrvd_rename, 128 nfsrvd_link, 129 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 130 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 131 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 132 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 133 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 134 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 135 }; 136 137 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *, 138 int, vnode_t , struct nfsexstuff *) = { 139 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 140 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 141 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 142 nfsrvd_access, 143 nfsrvd_close, 144 nfsrvd_commit, 145 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 146 nfsrvd_delegpurge, 147 nfsrvd_delegreturn, 148 nfsrvd_getattr, 149 nfsrvd_getfh, 150 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 151 nfsrvd_lock, 152 nfsrvd_lockt, 153 nfsrvd_locku, 154 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 155 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 156 nfsrvd_verify, 157 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 158 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 159 nfsrvd_openconfirm, 160 nfsrvd_opendowngrade, 161 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 162 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 163 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 164 nfsrvd_read, 165 nfsrvd_readdirplus, 166 nfsrvd_readlink, 167 nfsrvd_remove, 168 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 169 nfsrvd_renew, 170 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 171 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 172 nfsrvd_secinfo, 173 nfsrvd_setattr, 174 nfsrvd_setclientid, 175 nfsrvd_setclientidcfrm, 176 nfsrvd_verify, 177 nfsrvd_write, 178 nfsrvd_releaselckown, 179 nfsrvd_notsupp, 180 nfsrvd_bindconnsess, 181 nfsrvd_exchangeid, 182 nfsrvd_createsession, 183 nfsrvd_destroysession, 184 nfsrvd_freestateid, 185 nfsrvd_notsupp, 186 nfsrvd_getdevinfo, 187 nfsrvd_notsupp, 188 nfsrvd_layoutcommit, 189 nfsrvd_layoutget, 190 nfsrvd_layoutreturn, 191 nfsrvd_secinfononame, 192 nfsrvd_sequence, 193 nfsrvd_notsupp, 194 nfsrvd_teststateid, 195 nfsrvd_notsupp, 196 nfsrvd_destroyclientid, 197 nfsrvd_reclaimcomplete, 198 nfsrvd_allocate, 199 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, 200 nfsrvd_notsupp, 201 nfsrvd_notsupp, 202 nfsrvd_ioadvise, 203 nfsrvd_layouterror, 204 nfsrvd_layoutstats, 205 nfsrvd_notsupp, 206 nfsrvd_notsupp, 207 nfsrvd_notsupp, 208 nfsrvd_seek, 209 nfsrvd_notsupp, 210 nfsrvd_notsupp, 211 nfsrvd_getxattr, 212 nfsrvd_setxattr, 213 nfsrvd_listxattr, 214 nfsrvd_rmxattr, 215 }; 216 217 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *, 218 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = { 219 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 220 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 221 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 222 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 223 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 224 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 225 nfsrvd_mknod, 226 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 227 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 228 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 229 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 230 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 231 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 232 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 233 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 234 nfsrvd_lookup, 235 nfsrvd_lookup, 236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 237 nfsrvd_open, 238 nfsrvd_openattr, 239 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 240 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 241 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 242 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 243 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 244 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 245 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 246 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 247 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 248 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 249 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 250 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 251 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 252 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 253 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 254 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 255 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 256 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 257 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 258 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 259 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 260 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 261 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 262 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 263 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 264 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 265 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 266 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 267 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 268 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 269 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 270 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 271 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 272 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 273 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 274 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 275 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 276 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 277 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 278 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 279 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 280 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 281 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 282 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 283 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 284 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 285 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 286 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 287 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 288 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 289 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 290 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 291 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 292 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 293 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 294 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0, 295 }; 296 297 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *, 298 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = { 299 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 300 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 301 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 302 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 303 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 304 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 305 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 306 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 307 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 308 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 309 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 310 nfsrvd_link, 311 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 312 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 313 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 314 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 315 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 316 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 317 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 318 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 319 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 320 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 321 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 322 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 323 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 324 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 325 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 326 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 327 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 328 nfsrvd_rename, 329 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 330 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 331 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 332 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 333 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 334 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 335 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 336 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 337 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 338 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 339 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 340 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 341 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 342 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 343 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 344 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 345 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 346 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 347 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 348 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 349 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 350 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 351 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 352 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 353 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 354 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 355 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 356 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 357 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 358 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 359 nfsrvd_copy_file_range, 360 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 361 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 362 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 363 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 364 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 365 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 366 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 367 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 368 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 369 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 370 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 371 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 372 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 373 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 374 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0, 375 }; 376 377 /* 378 * Static array that defines which nfs rpc's are nonidempotent 379 */ 380 static int nfsrv_nonidempotent[NFS_V3NPROCS] = { 381 FALSE, 382 FALSE, 383 TRUE, 384 FALSE, 385 FALSE, 386 FALSE, 387 FALSE, 388 TRUE, 389 TRUE, 390 TRUE, 391 TRUE, 392 TRUE, 393 TRUE, 394 TRUE, 395 TRUE, 396 TRUE, 397 FALSE, 398 FALSE, 399 FALSE, 400 FALSE, 401 FALSE, 402 FALSE, 403 }; 404 405 /* 406 * This static array indicates whether or not the RPC modifies the 407 * file system. 408 */ 409 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0, 410 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 412 413 SYSCTL_DECL(_vfs_nfsd); 414 static int nfs_minminorv4 = NFSV4_MINORVERSION; 415 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN, 416 &nfs_minminorv4, 0, 417 "The lowest minor version of NFSv4 handled by the server"); 418 419 static int nfs_maxminorv4 = NFSV42_MINORVERSION; 420 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN, 421 &nfs_maxminorv4, 0, 422 "The highest minor version of NFSv4 handled by the server"); 423 424 /* local functions */ 425 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, 426 u_char *tag, int taglen, u_int32_t minorvers); 427 428 /* 429 * This static array indicates which server procedures require the extra 430 * arguments to return the current file handle for V2, 3. 431 */ 432 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 433 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 }; 434 435 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS]; 436 437 static int nfsv3to4op[NFS_V3NPROCS] = { 438 NFSPROC_NULL, 439 NFSV4OP_GETATTR, 440 NFSV4OP_SETATTR, 441 NFSV4OP_LOOKUP, 442 NFSV4OP_ACCESS, 443 NFSV4OP_READLINK, 444 NFSV4OP_READ, 445 NFSV4OP_WRITE, 446 NFSV4OP_V3CREATE, 447 NFSV4OP_MKDIR, 448 NFSV4OP_SYMLINK, 449 NFSV4OP_MKNOD, 450 NFSV4OP_REMOVE, 451 NFSV4OP_RMDIR, 452 NFSV4OP_RENAME, 453 NFSV4OP_LINK, 454 NFSV4OP_READDIR, 455 NFSV4OP_READDIRPLUS, 456 NFSV4OP_FSSTAT, 457 NFSV4OP_FSINFO, 458 NFSV4OP_PATHCONF, 459 NFSV4OP_COMMIT, 460 }; 461 462 static struct mtx nfsrvd_statmtx; 463 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF); 464 465 static void 466 nfsrvd_statstart(int op, struct bintime *now) 467 { 468 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) { 469 printf("%s: op %d invalid\n", __func__, op); 470 return; 471 } 472 473 mtx_lock(&nfsrvd_statmtx); 474 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) { 475 if (now != NULL) 476 nfsstatsv1.busyfrom = *now; 477 else 478 binuptime(&nfsstatsv1.busyfrom); 479 480 } 481 nfsstatsv1.srvrpccnt[op]++; 482 nfsstatsv1.srvstartcnt++; 483 mtx_unlock(&nfsrvd_statmtx); 484 485 } 486 487 static void 488 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now, 489 struct bintime *then) 490 { 491 struct bintime dt, lnow; 492 493 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) { 494 printf("%s: op %d invalid\n", __func__, op); 495 return; 496 } 497 498 if (now == NULL) { 499 now = &lnow; 500 binuptime(now); 501 } 502 503 mtx_lock(&nfsrvd_statmtx); 504 505 nfsstatsv1.srvbytes[op] += bytes; 506 nfsstatsv1.srvops[op]++; 507 508 if (then != NULL) { 509 dt = *now; 510 bintime_sub(&dt, then); 511 bintime_add(&nfsstatsv1.srvduration[op], &dt); 512 } 513 514 dt = *now; 515 bintime_sub(&dt, &nfsstatsv1.busyfrom); 516 bintime_add(&nfsstatsv1.busytime, &dt); 517 nfsstatsv1.busyfrom = *now; 518 519 nfsstatsv1.srvdonecnt++; 520 521 mtx_unlock(&nfsrvd_statmtx); 522 } 523 524 /* 525 * Do an RPC. Basically, get the file handles translated to vnode pointers 526 * and then call the appropriate server routine. The server routines are 527 * split into groups, based on whether they use a file handle or file 528 * handle plus name or ... 529 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound(). 530 */ 531 void 532 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen, 533 u_int32_t minorvers) 534 { 535 int error = 0, lktype; 536 vnode_t vp; 537 mount_t mp; 538 struct nfsrvfh fh; 539 struct nfsexstuff nes; 540 struct mbuf *md; 541 char *dpos; 542 543 /* 544 * Save the current position in the request mbuf list so 545 * that a rollback to this location can be done upon an 546 * ERELOOKUP error return from an RPC function. 547 */ 548 md = nd->nd_md; 549 dpos = nd->nd_dpos; 550 tryagain: 551 mp = NULL; 552 553 /* 554 * Get a locked vnode for the first file handle 555 */ 556 if (!(nd->nd_flag & ND_NFSV4)) { 557 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc")); 558 /* 559 * For NFSv3, if the malloc/mget allocation is near limits, 560 * return NFSERR_DELAY. 561 */ 562 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) { 563 nd->nd_repstat = NFSERR_DELAY; 564 vp = NULL; 565 } else { 566 error = nfsrv_mtofh(nd, &fh); 567 if (error) { 568 if (error != EBADRPC) 569 printf("nfs dorpc err1=%d\n", error); 570 nd->nd_repstat = NFSERR_GARBAGE; 571 goto out; 572 } 573 if (nd->nd_procnum == NFSPROC_READ || 574 nd->nd_procnum == NFSPROC_WRITE || 575 nd->nd_procnum == NFSPROC_READDIR || 576 nd->nd_procnum == NFSPROC_READDIRPLUS || 577 nd->nd_procnum == NFSPROC_READLINK || 578 nd->nd_procnum == NFSPROC_GETATTR || 579 nd->nd_procnum == NFSPROC_ACCESS || 580 nd->nd_procnum == NFSPROC_FSSTAT || 581 nd->nd_procnum == NFSPROC_FSINFO) 582 lktype = LK_SHARED; 583 else 584 lktype = LK_EXCLUSIVE; 585 if (nd->nd_flag & ND_PUBLOOKUP) 586 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes, 587 &mp, nfsrv_writerpc[nd->nd_procnum], -1); 588 else 589 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes, 590 &mp, nfsrv_writerpc[nd->nd_procnum], -1); 591 if (nd->nd_repstat == NFSERR_PROGNOTV4) 592 goto out; 593 } 594 } 595 596 /* 597 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request 598 * cache, as required. 599 * For V4, nfsrvd_compound() does this. 600 */ 601 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum]) 602 nd->nd_flag |= ND_SAVEREPLY; 603 604 nfsrvd_rephead(nd); 605 /* 606 * If nd_repstat is non-zero, just fill in the reply status 607 * to complete the RPC reply for V2. Otherwise, you must do 608 * the RPC. 609 */ 610 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) { 611 *nd->nd_errp = nfsd_errmap(nd); 612 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL); 613 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0, 614 /*now*/ NULL, /*then*/ NULL); 615 vn_finished_write(mp); 616 goto out; 617 } 618 619 /* 620 * Now the procedure can be performed. For V4, nfsrvd_compound() 621 * works through the sub-rpcs, otherwise just call the procedure. 622 * The procedures are in three groups with different arguments. 623 * The group is indicated by the value in nfs_retfh[]. 624 */ 625 if (nd->nd_flag & ND_NFSV4) { 626 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers); 627 } else { 628 struct bintime start_time; 629 630 binuptime(&start_time); 631 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time); 632 633 if (nfs_retfh[nd->nd_procnum] == 1) { 634 if (vp) 635 NFSVOPUNLOCK(vp); 636 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram, 637 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes); 638 } else if (nfs_retfh[nd->nd_procnum] == 2) { 639 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram, 640 vp, NULL, &nes, NULL); 641 } else { 642 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram, 643 vp, &nes); 644 } 645 vn_finished_write(mp); 646 647 if (error == 0 && nd->nd_repstat == ERELOOKUP) { 648 /* 649 * Roll back to the beginning of the RPC request 650 * arguments. 651 */ 652 nd->nd_md = md; 653 nd->nd_dpos = dpos; 654 655 /* Free the junk RPC reply and redo the RPC. */ 656 m_freem(nd->nd_mreq); 657 nd->nd_mreq = nd->nd_mb = NULL; 658 nd->nd_repstat = 0; 659 goto tryagain; 660 } 661 662 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0, 663 /*now*/ NULL, /*then*/ &start_time); 664 } 665 if (error) { 666 if (error != EBADRPC) 667 printf("nfs dorpc err2=%d\n", error); 668 nd->nd_repstat = NFSERR_GARBAGE; 669 } 670 *nd->nd_errp = nfsd_errmap(nd); 671 672 /* 673 * Don't cache certain reply status values. 674 */ 675 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) && 676 (nd->nd_repstat == NFSERR_GARBAGE || 677 nd->nd_repstat == NFSERR_BADXDR || 678 nd->nd_repstat == NFSERR_MOVED || 679 nd->nd_repstat == NFSERR_DELAY || 680 nd->nd_repstat == NFSERR_BADSEQID || 681 nd->nd_repstat == NFSERR_RESOURCE || 682 nd->nd_repstat == NFSERR_SERVERFAULT || 683 nd->nd_repstat == NFSERR_STALECLIENTID || 684 nd->nd_repstat == NFSERR_STALESTATEID || 685 nd->nd_repstat == NFSERR_OLDSTATEID || 686 nd->nd_repstat == NFSERR_BADSTATEID || 687 nd->nd_repstat == NFSERR_GRACE || 688 nd->nd_repstat == NFSERR_NOGRACE)) 689 nd->nd_flag &= ~ND_SAVEREPLY; 690 691 out: 692 NFSEXITCODE2(0, nd); 693 } 694 695 /* 696 * Breaks down a compound RPC request and calls the server routines for 697 * the subprocedures. 698 * Some suboperations are performed directly here to simplify file handle<--> 699 * vnode pointer handling. 700 */ 701 static void 702 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, 703 int taglen, u_int32_t minorvers) 704 { 705 int i, lktype, op, op0 = 0, rstat, statsinprog = 0; 706 u_int32_t *tl; 707 struct nfsclient *clp, *nclp; 708 int error = 0, igotlock, nextop, numops, savefhcnt; 709 u_int32_t retops = 0, *retopsp = NULL, *repp; 710 vnode_t vp, nvp, savevp; 711 struct nfsrvfh fh; 712 mount_t new_mp, temp_mp = NULL; 713 struct ucred *credanon; 714 struct nfsexstuff nes, vpnes, savevpnes; 715 fsid_t cur_fsid, save_fsid; 716 static u_int64_t compref = 0; 717 struct bintime start_time; 718 struct thread *p; 719 struct mbuf *mb, *md; 720 char *bpos, *dpos; 721 int bextpg, bextpgsiz; 722 723 p = curthread; 724 725 NFSVNO_EXINIT(&vpnes); 726 NFSVNO_EXINIT(&savevpnes); 727 /* 728 * Put the seq# of the current compound RPC in nfsrv_descript. 729 * (This is used by nfsrv_checkgetattr(), to see if the write 730 * delegation was created by the same compound RPC as the one 731 * with that Getattr in it.) 732 * Don't worry about the 64bit number wrapping around. It ain't 733 * gonna happen before this server gets shut down/rebooted. 734 */ 735 nd->nd_compref = compref++; 736 737 /* 738 * Check for and optionally get a lock on the root. This lock means that 739 * no nfsd will be fiddling with the V4 file system and state stuff. It 740 * is required when the V4 root is being changed, the stable storage 741 * restart file is being updated, or callbacks are being done. 742 * When any of the nfsd are processing an NFSv4 compound RPC, they must 743 * either hold a reference count (nfs_usecnt) or the lock. When 744 * nfsrv_unlock() is called to release the lock, it can optionally 745 * also get a reference count, which saves the need for a call to 746 * nfsrv_getref() after nfsrv_unlock(). 747 */ 748 /* 749 * First, check to see if we need to wait for an update lock. 750 */ 751 igotlock = 0; 752 NFSLOCKV4ROOTMUTEX(); 753 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK) 754 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 755 NFSV4ROOTLOCKMUTEXPTR, NULL); 756 else 757 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL, 758 NFSV4ROOTLOCKMUTEXPTR, NULL); 759 NFSUNLOCKV4ROOTMUTEX(); 760 if (igotlock) { 761 /* 762 * If I got the lock, I can update the stable storage file. 763 * Done when the grace period is over or a client has long 764 * since expired. 765 */ 766 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK; 767 if ((nfsrv_stablefirst.nsf_flags & 768 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER) 769 nfsrv_updatestable(p); 770 771 /* 772 * If at least one client has long since expired, search 773 * the client list for them, write a REVOKE record on the 774 * stable storage file and then remove them from the client 775 * list. 776 */ 777 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) { 778 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT; 779 for (i = 0; i < nfsrv_clienthashsize; i++) { 780 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, 781 nclp) { 782 if (clp->lc_flags & LCL_EXPIREIT) { 783 if (!LIST_EMPTY(&clp->lc_open) || 784 !LIST_EMPTY(&clp->lc_deleg)) 785 nfsrv_writestable(clp->lc_id, 786 clp->lc_idlen, NFSNST_REVOKE, p); 787 nfsrv_cleanclient(clp, p); 788 nfsrv_freedeleglist(&clp->lc_deleg); 789 nfsrv_freedeleglist(&clp->lc_olddeleg); 790 LIST_REMOVE(clp, lc_hash); 791 nfsrv_zapclient(clp, p); 792 } 793 } 794 } 795 } 796 NFSLOCKV4ROOTMUTEX(); 797 nfsv4_unlock(&nfsv4rootfs_lock, 1); 798 NFSUNLOCKV4ROOTMUTEX(); 799 } else { 800 /* 801 * If we didn't get the lock, we need to get a refcnt, 802 * which also checks for and waits for the lock. 803 */ 804 NFSLOCKV4ROOTMUTEX(); 805 nfsv4_getref(&nfsv4rootfs_lock, NULL, 806 NFSV4ROOTLOCKMUTEXPTR, NULL); 807 NFSUNLOCKV4ROOTMUTEX(); 808 } 809 810 /* 811 * If flagged, search for open owners that haven't had any opens 812 * for a long time. 813 */ 814 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) { 815 nfsrv_throwawayopens(p); 816 } 817 818 /* Do a CBLAYOUTRECALL callback if over the high water mark. */ 819 if (nfsrv_layoutcnt > nfsrv_layouthighwater) 820 nfsrv_recalloldlayout(p); 821 822 savevp = vp = NULL; 823 save_fsid.val[0] = save_fsid.val[1] = 0; 824 cur_fsid.val[0] = cur_fsid.val[1] = 0; 825 nextop = -1; 826 savefhcnt = 0; 827 828 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */ 829 if (taglen < 0) { 830 error = EBADRPC; 831 goto nfsmout; 832 } 833 834 (void) nfsm_strtom(nd, tag, taglen); 835 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED); 836 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 837 if ((minorvers != NFSV4_MINORVERSION && 838 minorvers != NFSV41_MINORVERSION && 839 minorvers != NFSV42_MINORVERSION) || 840 minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4) 841 nd->nd_repstat = NFSERR_MINORVERMISMATCH; 842 if (nd->nd_repstat) 843 numops = 0; 844 else 845 numops = fxdr_unsigned(int, *tl); 846 /* 847 * Loop around doing the sub ops. 848 * vp - is an unlocked vnode pointer for the CFH 849 * savevp - is an unlocked vnode pointer for the SAVEDFH 850 * (at some future date, it might turn out to be more appropriate 851 * to keep the file handles instead of vnode pointers?) 852 * savevpnes and vpnes - are the export flags for the above. 853 */ 854 for (i = 0; i < numops; i++) { 855 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED); 856 if (savefhcnt > 0) { 857 op = NFSV4OP_SAVEFH; 858 *repp = txdr_unsigned(op); 859 savefhcnt--; 860 } else if (nextop == -1) { 861 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 862 *repp = *tl; 863 op = fxdr_unsigned(int, *tl); 864 } else { 865 op = nextop; 866 *repp = txdr_unsigned(op); 867 nextop = -1; 868 } 869 NFSD_DEBUG(4, "op=%d\n", op); 870 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS || 871 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) || 872 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) { 873 nd->nd_repstat = NFSERR_OPILLEGAL; 874 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL); 875 *repp = nfsd_errmap(nd); 876 retops++; 877 break; 878 } else { 879 repp++; 880 } 881 882 binuptime(&start_time); 883 nfsrvd_statstart(op, &start_time); 884 statsinprog = 1; 885 886 if (i == 0) 887 op0 = op; 888 if (i == numops - 1) 889 nd->nd_flag |= ND_LASTOP; 890 891 /* 892 * Check for a referral on the current FH and, if so, return 893 * NFSERR_MOVED for all ops that allow it, except Getattr. 894 */ 895 if (vp != NULL && op != NFSV4OP_GETATTR && 896 nfsv4root_getreferral(vp, NULL, 0) != NULL && 897 nfsrv_errmoved(op)) { 898 nd->nd_repstat = NFSERR_MOVED; 899 *repp = nfsd_errmap(nd); 900 retops++; 901 break; 902 } 903 904 /* 905 * For NFSv4.1, check for a Sequence Operation being first 906 * or one of the other allowed operations by itself. 907 */ 908 if ((nd->nd_flag & ND_NFSV41) != 0) { 909 if (i != 0 && op == NFSV4OP_SEQUENCE) 910 nd->nd_repstat = NFSERR_SEQUENCEPOS; 911 else if (i == 0 && op != NFSV4OP_SEQUENCE && 912 op != NFSV4OP_EXCHANGEID && 913 op != NFSV4OP_CREATESESSION && 914 op != NFSV4OP_BINDCONNTOSESS && 915 op != NFSV4OP_DESTROYCLIENTID && 916 op != NFSV4OP_DESTROYSESSION) 917 nd->nd_repstat = NFSERR_OPNOTINSESS; 918 else if (i != 0 && op0 != NFSV4OP_SEQUENCE) 919 nd->nd_repstat = NFSERR_NOTONLYOP; 920 if (nd->nd_repstat != 0) { 921 *repp = nfsd_errmap(nd); 922 retops++; 923 break; 924 } 925 } 926 927 nd->nd_procnum = op; 928 /* 929 * If over flood level, reply NFSERR_RESOURCE, if at the first 930 * Op. (Since a client recovery from NFSERR_RESOURCE can get 931 * really nasty for certain Op sequences, I'll play it safe 932 * and only return the error at the beginning.) The cache 933 * will still function over flood level, but uses lots of 934 * mbufs.) 935 * If nfsrv_mallocmget_limit() returns True, the system is near 936 * to its limit for memory that malloc()/mget() can allocate. 937 */ 938 if (i == 0 && (nd->nd_rp == NULL || 939 nd->nd_rp->rc_refcnt == 0) && 940 (nfsrv_mallocmget_limit() || 941 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) { 942 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) 943 printf("nfsd server cache flooded, try " 944 "increasing vfs.nfsd.tcphighwater\n"); 945 nd->nd_repstat = NFSERR_RESOURCE; 946 *repp = nfsd_errmap(nd); 947 if (op == NFSV4OP_SETATTR) { 948 /* 949 * Setattr replies require a bitmap. 950 * even for errors like these. 951 */ 952 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 953 *tl = 0; 954 } 955 retops++; 956 break; 957 } 958 if (nfsv4_opflag[op].savereply) 959 nd->nd_flag |= ND_SAVEREPLY; 960 switch (op) { 961 case NFSV4OP_PUTFH: 962 error = nfsrv_mtofh(nd, &fh); 963 if (error) 964 goto nfsmout; 965 if ((nd->nd_flag & ND_LASTOP) == 0) { 966 /* 967 * Pre-parse the next op#. If it is 968 * SaveFH, count it and skip to the 969 * next op#, if not the last op#. 970 * nextop is used to determine if 971 * NFSERR_WRONGSEC can be returned, 972 * per RFC5661 Sec. 2.6. 973 */ 974 do { 975 NFSM_DISSECT(tl, uint32_t *, 976 NFSX_UNSIGNED); 977 nextop = fxdr_unsigned(int, *tl); 978 if (nextop == NFSV4OP_SAVEFH && 979 i < numops - 1) 980 savefhcnt++; 981 } while (nextop == NFSV4OP_SAVEFH && 982 i < numops - 1); 983 } 984 if (!nd->nd_repstat) 985 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, 986 NULL, 0, nextop); 987 /* For now, allow this for non-export FHs */ 988 if (!nd->nd_repstat) { 989 if (vp) 990 vrele(vp); 991 vp = nvp; 992 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 993 NFSVOPUNLOCK(vp); 994 vpnes = nes; 995 } 996 break; 997 case NFSV4OP_PUTPUBFH: 998 if (nfs_pubfhset) { 999 if ((nd->nd_flag & ND_LASTOP) == 0) { 1000 /* 1001 * Pre-parse the next op#. If it is 1002 * SaveFH, count it and skip to the 1003 * next op#, if not the last op#. 1004 * nextop is used to determine if 1005 * NFSERR_WRONGSEC can be returned, 1006 * per RFC5661 Sec. 2.6. 1007 */ 1008 do { 1009 NFSM_DISSECT(tl, uint32_t *, 1010 NFSX_UNSIGNED); 1011 nextop = fxdr_unsigned(int, 1012 *tl); 1013 if (nextop == NFSV4OP_SAVEFH && 1014 i < numops - 1) 1015 savefhcnt++; 1016 } while (nextop == NFSV4OP_SAVEFH && 1017 i < numops - 1); 1018 } 1019 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp, 1020 &nes, NULL, 0, nextop); 1021 } else 1022 nd->nd_repstat = NFSERR_NOFILEHANDLE; 1023 if (!nd->nd_repstat) { 1024 if (vp) 1025 vrele(vp); 1026 vp = nvp; 1027 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 1028 NFSVOPUNLOCK(vp); 1029 vpnes = nes; 1030 } 1031 break; 1032 case NFSV4OP_PUTROOTFH: 1033 if (nfs_rootfhset) { 1034 if ((nd->nd_flag & ND_LASTOP) == 0) { 1035 /* 1036 * Pre-parse the next op#. If it is 1037 * SaveFH, count it and skip to the 1038 * next op#, if not the last op#. 1039 * nextop is used to determine if 1040 * NFSERR_WRONGSEC can be returned, 1041 * per RFC5661 Sec. 2.6. 1042 */ 1043 do { 1044 NFSM_DISSECT(tl, uint32_t *, 1045 NFSX_UNSIGNED); 1046 nextop = fxdr_unsigned(int, 1047 *tl); 1048 if (nextop == NFSV4OP_SAVEFH && 1049 i < numops - 1) 1050 savefhcnt++; 1051 } while (nextop == NFSV4OP_SAVEFH && 1052 i < numops - 1); 1053 } 1054 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp, 1055 &nes, NULL, 0, nextop); 1056 if (!nd->nd_repstat) { 1057 if (vp) 1058 vrele(vp); 1059 vp = nvp; 1060 cur_fsid = vp->v_mount->mnt_stat.f_fsid; 1061 NFSVOPUNLOCK(vp); 1062 vpnes = nes; 1063 } 1064 } else 1065 nd->nd_repstat = NFSERR_NOFILEHANDLE; 1066 break; 1067 case NFSV4OP_SAVEFH: 1068 if (vp && NFSVNO_EXPORTED(&vpnes)) { 1069 nd->nd_repstat = 0; 1070 /* If vp == savevp, a no-op */ 1071 if (vp != savevp) { 1072 if (savevp) 1073 vrele(savevp); 1074 VREF(vp); 1075 savevp = vp; 1076 savevpnes = vpnes; 1077 save_fsid = cur_fsid; 1078 } 1079 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 1080 nd->nd_savedcurstateid = 1081 nd->nd_curstateid; 1082 nd->nd_flag |= ND_SAVEDCURSTATEID; 1083 } 1084 } else { 1085 nd->nd_repstat = NFSERR_NOFILEHANDLE; 1086 } 1087 break; 1088 case NFSV4OP_RESTOREFH: 1089 if (savevp) { 1090 if ((nd->nd_flag & ND_LASTOP) == 0) { 1091 /* 1092 * Pre-parse the next op#. If it is 1093 * SaveFH, count it and skip to the 1094 * next op#, if not the last op#. 1095 * nextop is used to determine if 1096 * NFSERR_WRONGSEC can be returned, 1097 * per RFC5661 Sec. 2.6. 1098 */ 1099 do { 1100 NFSM_DISSECT(tl, uint32_t *, 1101 NFSX_UNSIGNED); 1102 nextop = fxdr_unsigned(int, 1103 *tl); 1104 if (nextop == NFSV4OP_SAVEFH && 1105 i < numops - 1) 1106 savefhcnt++; 1107 } while (nextop == NFSV4OP_SAVEFH && 1108 i < numops - 1); 1109 } 1110 nd->nd_repstat = 0; 1111 /* If vp == savevp, a no-op */ 1112 if (vp != savevp) { 1113 if (nfsrv_checkwrongsec(nd, nextop, 1114 savevp->v_type)) 1115 nd->nd_repstat = 1116 nfsvno_testexp(nd, 1117 &savevpnes); 1118 if (nd->nd_repstat == 0) { 1119 VREF(savevp); 1120 vrele(vp); 1121 vp = savevp; 1122 vpnes = savevpnes; 1123 cur_fsid = save_fsid; 1124 } 1125 } 1126 if (nd->nd_repstat == 0 && 1127 (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) { 1128 nd->nd_curstateid = 1129 nd->nd_savedcurstateid; 1130 nd->nd_flag |= ND_CURSTATEID; 1131 } 1132 } else { 1133 nd->nd_repstat = NFSERR_RESTOREFH; 1134 } 1135 break; 1136 default: 1137 /* 1138 * Allow a Lookup, Getattr, GetFH, Secinfo on an 1139 * non-exported directory if 1140 * nfs_rootfhset. Do I need to allow any other Ops? 1141 * (You can only have a non-exported vpnes if 1142 * nfs_rootfhset is true. See nfsd_fhtovp()) 1143 * Allow AUTH_SYS to be used for file systems 1144 * exported GSS only for certain Ops, to allow 1145 * clients to do mounts more easily. 1146 */ 1147 if (nfsv4_opflag[op].needscfh && vp) { 1148 if (!NFSVNO_EXPORTED(&vpnes) && 1149 op != NFSV4OP_LOOKUP && 1150 op != NFSV4OP_GETATTR && 1151 op != NFSV4OP_GETFH && 1152 op != NFSV4OP_ACCESS && 1153 op != NFSV4OP_READLINK && 1154 op != NFSV4OP_SECINFO && 1155 op != NFSV4OP_SECINFONONAME) 1156 nd->nd_repstat = NFSERR_NOFILEHANDLE; 1157 if (nd->nd_repstat) { 1158 if (op == NFSV4OP_SETATTR) { 1159 /* 1160 * Setattr reply requires a bitmap 1161 * even for errors like these. 1162 */ 1163 NFSM_BUILD(tl, u_int32_t *, 1164 NFSX_UNSIGNED); 1165 *tl = 0; 1166 } 1167 break; 1168 } 1169 } 1170 1171 /* 1172 * Save the current positions in the mbuf lists so 1173 * that a rollback to this location can be done upon a 1174 * redo due to a ERELOOKUP return for a operation. 1175 */ 1176 mb = nd->nd_mb; 1177 bpos = nd->nd_bpos; 1178 bextpg = nd->nd_bextpg; 1179 bextpgsiz = nd->nd_bextpgsiz; 1180 md = nd->nd_md; 1181 dpos = nd->nd_dpos; 1182 tryagain: 1183 1184 if (nfsv4_opflag[op].retfh == 1) { 1185 if (!vp) { 1186 nd->nd_repstat = NFSERR_NOFILEHANDLE; 1187 break; 1188 } 1189 if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP || 1190 op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN && 1191 vp->v_type == VDIR))) { 1192 /* Check for wrong security. */ 1193 rstat = nfsvno_testexp(nd, &vpnes); 1194 if (rstat != 0) { 1195 nd->nd_repstat = rstat; 1196 break; 1197 } 1198 } 1199 VREF(vp); 1200 if (nfsv4_opflag[op].modifyfs) 1201 vn_start_write(vp, &temp_mp, V_WAIT); 1202 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp, 1203 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes); 1204 if (!error && !nd->nd_repstat) { 1205 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) { 1206 new_mp = nvp->v_mount; 1207 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) { 1208 /* crossed a server mount point */ 1209 nd->nd_repstat = nfsvno_checkexp(new_mp, 1210 nd->nd_nam, &nes, &credanon); 1211 if (!nd->nd_repstat) 1212 nd->nd_repstat = nfsd_excred(nd, 1213 &nes, credanon, true); 1214 if (credanon != NULL) 1215 crfree(credanon); 1216 if (!nd->nd_repstat) { 1217 vpnes = nes; 1218 cur_fsid = new_mp->mnt_stat.f_fsid; 1219 } 1220 } 1221 /* Lookup ops return a locked vnode */ 1222 NFSVOPUNLOCK(nvp); 1223 } 1224 if (!nd->nd_repstat) { 1225 vrele(vp); 1226 vp = nvp; 1227 } else 1228 vrele(nvp); 1229 } 1230 if (nfsv4_opflag[op].modifyfs) 1231 vn_finished_write(temp_mp); 1232 } else if (nfsv4_opflag[op].retfh == 2) { 1233 if (vp == NULL || savevp == NULL) { 1234 nd->nd_repstat = NFSERR_NOFILEHANDLE; 1235 break; 1236 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) { 1237 nd->nd_repstat = NFSERR_XDEV; 1238 break; 1239 } 1240 if (nfsv4_opflag[op].modifyfs) 1241 vn_start_write(savevp, &temp_mp, V_WAIT); 1242 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) { 1243 VREF(vp); 1244 VREF(savevp); 1245 error = (*(nfsrv4_ops2[op]))(nd, isdgram, 1246 savevp, vp, &savevpnes, &vpnes); 1247 } else 1248 nd->nd_repstat = NFSERR_PERM; 1249 if (nfsv4_opflag[op].modifyfs) 1250 vn_finished_write(temp_mp); 1251 } else { 1252 if (nfsv4_opflag[op].retfh != 0) 1253 panic("nfsrvd_compound"); 1254 if (nfsv4_opflag[op].needscfh) { 1255 if (vp != NULL) { 1256 lktype = nfsv4_opflag[op].lktype; 1257 if (nfsv4_opflag[op].modifyfs) { 1258 vn_start_write(vp, &temp_mp, 1259 V_WAIT); 1260 if (op == NFSV4OP_WRITE && 1261 MNT_SHARED_WRITES(temp_mp)) 1262 lktype = LK_SHARED; 1263 } 1264 if (NFSVOPLOCK(vp, lktype) == 0) 1265 VREF(vp); 1266 else 1267 nd->nd_repstat = NFSERR_PERM; 1268 } else { 1269 nd->nd_repstat = NFSERR_NOFILEHANDLE; 1270 if (op == NFSV4OP_SETATTR) { 1271 /* 1272 * Setattr reply requires a 1273 * bitmap even for errors like 1274 * these. 1275 */ 1276 NFSM_BUILD(tl, u_int32_t *, 1277 NFSX_UNSIGNED); 1278 *tl = 0; 1279 } 1280 break; 1281 } 1282 if (nd->nd_repstat == 0) { 1283 error = (*(nfsrv4_ops0[op]))(nd, 1284 isdgram, vp, &vpnes); 1285 if ((op == NFSV4OP_SECINFO || 1286 op == NFSV4OP_SECINFONONAME) && 1287 error == 0 && nd->nd_repstat == 0) { 1288 /* 1289 * Secinfo and Secinfo_no_name 1290 * consume the current FH. 1291 */ 1292 vrele(vp); 1293 vp = NULL; 1294 } 1295 } 1296 if (nfsv4_opflag[op].modifyfs) 1297 vn_finished_write(temp_mp); 1298 } else { 1299 error = (*(nfsrv4_ops0[op]))(nd, isdgram, 1300 NULL, &vpnes); 1301 } 1302 } 1303 } 1304 if (error) { 1305 if (error == EBADRPC || error == NFSERR_BADXDR) { 1306 nd->nd_repstat = NFSERR_BADXDR; 1307 } else { 1308 nd->nd_repstat = error; 1309 printf("nfsv4 comperr0=%d\n", error); 1310 } 1311 error = 0; 1312 } 1313 1314 if (nd->nd_repstat == ERELOOKUP) { 1315 /* 1316 * Roll back to the beginning of the operation 1317 * arguments. 1318 */ 1319 nd->nd_md = md; 1320 nd->nd_dpos = dpos; 1321 1322 /* 1323 * Trim off the bogus reply for this operation 1324 * and redo the operation. 1325 */ 1326 nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz); 1327 nd->nd_repstat = 0; 1328 nd->nd_flag |= ND_ERELOOKUP; 1329 goto tryagain; 1330 } 1331 nd->nd_flag &= ~ND_ERELOOKUP; 1332 1333 if (statsinprog != 0) { 1334 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL, 1335 /*then*/ &start_time); 1336 statsinprog = 0; 1337 } 1338 1339 retops++; 1340 if (nd->nd_repstat) { 1341 *repp = nfsd_errmap(nd); 1342 break; 1343 } else { 1344 *repp = 0; /* NFS4_OK */ 1345 } 1346 } 1347 nfsmout: 1348 if (statsinprog != 0) { 1349 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL, 1350 /*then*/ &start_time); 1351 statsinprog = 0; 1352 } 1353 if (error) { 1354 if (error == EBADRPC || error == NFSERR_BADXDR) 1355 nd->nd_repstat = NFSERR_BADXDR; 1356 else 1357 printf("nfsv4 comperr1=%d\n", error); 1358 } 1359 if (taglen == -1) { 1360 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1361 *tl++ = 0; 1362 *tl = 0; 1363 } else { 1364 *retopsp = txdr_unsigned(retops); 1365 } 1366 if (vp) 1367 vrele(vp); 1368 if (savevp) 1369 vrele(savevp); 1370 NFSLOCKV4ROOTMUTEX(); 1371 nfsv4_relref(&nfsv4rootfs_lock); 1372 NFSUNLOCKV4ROOTMUTEX(); 1373 1374 NFSEXITCODE2(0, nd); 1375 } 1376