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