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