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/capsicum.h> 37 #include <sys/extattr.h> 38 39 /* 40 * Functions that perform the vfs operations required by the routines in 41 * nfsd_serv.c. It is hoped that this change will make the server more 42 * portable. 43 */ 44 45 #include <fs/nfs/nfsport.h> 46 #include <security/mac/mac_framework.h> 47 #include <sys/callout.h> 48 #include <sys/filio.h> 49 #include <sys/hash.h> 50 #include <sys/osd.h> 51 #include <sys/sysctl.h> 52 #include <nlm/nlm_prot.h> 53 #include <nlm/nlm.h> 54 #include <vm/vm_param.h> 55 #include <vm/vnode_pager.h> 56 57 FEATURE(nfsd, "NFSv4 server"); 58 59 extern u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1; 60 extern int nfsrv_useacl; 61 extern int newnfs_numnfsd; 62 extern int nfsrv_sessionhashsize; 63 extern struct nfslayouthash *nfslayouthash; 64 extern int nfsrv_layouthashsize; 65 extern struct mtx nfsrv_dslock_mtx; 66 extern int nfs_pnfsiothreads; 67 extern volatile int nfsrv_devidcnt; 68 extern int nfsrv_maxpnfsmirror; 69 extern uint32_t nfs_srvmaxio; 70 extern int nfs_bufpackets; 71 extern u_long sb_max_adj; 72 73 NFSD_VNET_DECLARE(int, nfsrv_numnfsd); 74 NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst); 75 NFSD_VNET_DECLARE(SVCPOOL *, nfsrvd_pool); 76 NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash); 77 NFSD_VNET_DECLARE(struct nfslockhashhead *, nfslockhash); 78 NFSD_VNET_DECLARE(struct nfssessionhash *, nfssessionhash); 79 NFSD_VNET_DECLARE(struct nfsv4lock, nfsd_suspend_lock); 80 NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p); 81 82 NFSDLOCKMUTEX; 83 NFSSTATESPINLOCK; 84 struct mtx nfsrc_udpmtx; 85 struct mtx nfs_v4root_mutex; 86 struct mtx nfsrv_dontlistlock_mtx; 87 struct mtx nfsrv_recalllock_mtx; 88 struct nfsrvfh nfs_pubfh; 89 int nfs_pubfhset = 0; 90 int nfsd_debuglevel = 0; 91 static pid_t nfsd_master_pid = (pid_t)-1; 92 static char nfsd_master_comm[MAXCOMLEN + 1]; 93 static struct timeval nfsd_master_start; 94 static uint32_t nfsv4_sysid = 0; 95 static fhandle_t zerofh; 96 97 NFSD_VNET_DEFINE(struct proc *, nfsd_master_proc) = NULL; 98 NFSD_VNET_DEFINE(struct nfsrvhashhead *, nfsrvudphashtbl); 99 NFSD_VNET_DEFINE(struct nfsrchash_bucket *, nfsrchash_table); 100 NFSD_VNET_DEFINE(struct nfsrchash_bucket *, nfsrcahash_table); 101 NFSD_VNET_DEFINE(struct nfsrvfh, nfs_rootfh); 102 NFSD_VNET_DEFINE(int, nfs_rootfhset) = 0; 103 NFSD_VNET_DEFINE(struct callout, nfsd_callout); 104 NFSD_VNET_DEFINE_STATIC(struct mount *, nfsv4root_mnt); 105 NFSD_VNET_DEFINE_STATIC(struct vfsoptlist, nfsv4root_opt); 106 NFSD_VNET_DEFINE_STATIC(struct vfsoptlist, nfsv4root_newopt); 107 NFSD_VNET_DEFINE_STATIC(bool, nfsrv_suspend_nfsd) = false; 108 NFSD_VNET_DEFINE_STATIC(bool, nfsrv_mntinited) = false; 109 110 static int nfssvc_srvcall(struct thread *, struct nfssvc_args *, 111 struct ucred *); 112 static void nfsvno_updateds(struct vnode *, struct ucred *, struct thread *); 113 114 int nfsrv_enable_crossmntpt = 1; 115 static int nfs_commit_blks; 116 static int nfs_commit_miss; 117 extern int nfsrv_issuedelegs; 118 extern int nfsrv_dolocallocks; 119 extern struct nfsdevicehead nfsrv_devidhead; 120 121 /* Map d_type to vnode type. */ 122 static uint8_t dtype_to_vnode[DT_WHT + 1] = { VNON, VFIFO, VCHR, VNON, VDIR, 123 VNON, VBLK, VNON, VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON }; 124 #define NFS_DTYPETOVTYPE(t) ((t) <= DT_WHT ? dtype_to_vnode[(t)] : VNON) 125 126 static int nfsrv_createiovec(int, struct mbuf **, struct mbuf **, 127 struct iovec **); 128 static int nfsrv_createiovec_extpgs(int, int, struct mbuf **, 129 struct mbuf **, struct iovec **); 130 static int nfsrv_createiovecw(int, struct mbuf *, char *, struct iovec **, 131 int *); 132 static void nfsrv_pnfscreate(struct vnode *, struct vattr *, struct ucred *, 133 NFSPROC_T *); 134 static void nfsrv_pnfsremovesetup(struct vnode *, NFSPROC_T *, struct vnode **, 135 int *, char *, fhandle_t *); 136 static void nfsrv_pnfsremove(struct vnode **, int, char *, fhandle_t *, 137 NFSPROC_T *); 138 static int nfsrv_proxyds(struct vnode *, off_t, int, struct ucred *, 139 struct thread *, int, struct mbuf **, char *, struct mbuf **, 140 struct nfsvattr *, struct acl *, off_t *, int, bool *); 141 static int nfsrv_setextattr(struct vnode *, struct nfsvattr *, NFSPROC_T *); 142 static int nfsrv_readdsrpc(fhandle_t *, off_t, int, struct ucred *, 143 NFSPROC_T *, struct nfsmount *, struct mbuf **, struct mbuf **); 144 static int nfsrv_writedsrpc(fhandle_t *, off_t, int, struct ucred *, 145 NFSPROC_T *, struct vnode *, struct nfsmount **, int, struct mbuf **, 146 char *, int *); 147 static int nfsrv_allocatedsrpc(fhandle_t *, off_t, off_t, struct ucred *, 148 NFSPROC_T *, struct vnode *, struct nfsmount **, int, int *); 149 static int nfsrv_deallocatedsrpc(fhandle_t *, off_t, off_t, struct ucred *, 150 NFSPROC_T *, struct vnode *, struct nfsmount **, int, int *); 151 static int nfsrv_setacldsrpc(fhandle_t *, struct ucred *, NFSPROC_T *, 152 struct vnode *, struct nfsmount **, int, struct acl *, int *); 153 static int nfsrv_setattrdsrpc(fhandle_t *, struct ucred *, NFSPROC_T *, 154 struct vnode *, struct nfsmount **, int, struct nfsvattr *, int *); 155 static int nfsrv_getattrdsrpc(fhandle_t *, struct ucred *, NFSPROC_T *, 156 struct vnode *, struct nfsmount *, struct nfsvattr *); 157 static int nfsrv_seekdsrpc(fhandle_t *, off_t *, int, bool *, struct ucred *, 158 NFSPROC_T *, struct nfsmount *); 159 static int nfsrv_putfhname(fhandle_t *, char *); 160 static int nfsrv_pnfslookupds(struct vnode *, struct vnode *, 161 struct pnfsdsfile *, struct vnode **, NFSPROC_T *); 162 static void nfsrv_pnfssetfh(struct vnode *, struct pnfsdsfile *, char *, char *, 163 struct vnode *, NFSPROC_T *); 164 static int nfsrv_dsremove(struct vnode *, char *, struct ucred *, NFSPROC_T *); 165 static int nfsrv_dssetacl(struct vnode *, struct acl *, struct ucred *, 166 NFSPROC_T *); 167 static int nfsrv_pnfsstatfs(struct statfs *, struct mount *); 168 169 int nfs_pnfsio(task_fn_t *, void *); 170 171 SYSCTL_NODE(_vfs, OID_AUTO, nfsd, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 172 "NFS server"); 173 SYSCTL_INT(_vfs_nfsd, OID_AUTO, mirrormnt, CTLFLAG_RW, 174 &nfsrv_enable_crossmntpt, 0, "Enable nfsd to cross mount points"); 175 SYSCTL_INT(_vfs_nfsd, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 176 0, ""); 177 SYSCTL_INT(_vfs_nfsd, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 178 0, ""); 179 SYSCTL_INT(_vfs_nfsd, OID_AUTO, issue_delegations, CTLFLAG_RW, 180 &nfsrv_issuedelegs, 0, "Enable nfsd to issue delegations"); 181 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_locallocks, CTLFLAG_RW, 182 &nfsrv_dolocallocks, 0, "Enable nfsd to acquire local locks on files"); 183 SYSCTL_INT(_vfs_nfsd, OID_AUTO, debuglevel, CTLFLAG_RW, &nfsd_debuglevel, 184 0, "Debug level for NFS server"); 185 NFSD_VNET_DECLARE(int, nfsd_enable_stringtouid); 186 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_stringtouid, 187 CTLFLAG_NFSD_VNET | CTLFLAG_RW, &NFSD_VNET_NAME(nfsd_enable_stringtouid), 188 0, "Enable nfsd to accept numeric owner_names"); 189 static int nfsrv_pnfsgetdsattr = 1; 190 SYSCTL_INT(_vfs_nfsd, OID_AUTO, pnfsgetdsattr, CTLFLAG_RW, 191 &nfsrv_pnfsgetdsattr, 0, "When set getattr gets DS attributes via RPC"); 192 193 /* 194 * nfsrv_dsdirsize can only be increased and only when the nfsd threads are 195 * not running. 196 * The dsN subdirectories for the increased values must have been created 197 * on all DS servers before this increase is done. 198 */ 199 u_int nfsrv_dsdirsize = 20; 200 static int 201 sysctl_dsdirsize(SYSCTL_HANDLER_ARGS) 202 { 203 int error, newdsdirsize; 204 205 newdsdirsize = nfsrv_dsdirsize; 206 error = sysctl_handle_int(oidp, &newdsdirsize, 0, req); 207 if (error != 0 || req->newptr == NULL) 208 return (error); 209 if (newdsdirsize <= nfsrv_dsdirsize || newdsdirsize > 10000 || 210 newnfs_numnfsd != 0) 211 return (EINVAL); 212 nfsrv_dsdirsize = newdsdirsize; 213 return (0); 214 } 215 SYSCTL_PROC(_vfs_nfsd, OID_AUTO, dsdirsize, 216 CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RW, 0, sizeof(nfsrv_dsdirsize), 217 sysctl_dsdirsize, "IU", "Number of dsN subdirs on the DS servers"); 218 219 /* 220 * nfs_srvmaxio can only be increased and only when the nfsd threads are 221 * not running. The setting must be a power of 2, with the current limit of 222 * 1Mbyte. 223 */ 224 static int 225 sysctl_srvmaxio(SYSCTL_HANDLER_ARGS) 226 { 227 int error; 228 u_int newsrvmaxio; 229 uint64_t tval; 230 231 newsrvmaxio = nfs_srvmaxio; 232 error = sysctl_handle_int(oidp, &newsrvmaxio, 0, req); 233 if (error != 0 || req->newptr == NULL) 234 return (error); 235 if (newsrvmaxio == nfs_srvmaxio) 236 return (0); 237 if (newsrvmaxio < nfs_srvmaxio) { 238 printf("nfsd: vfs.nfsd.srvmaxio can only be increased\n"); 239 return (EINVAL); 240 } 241 if (newsrvmaxio > 1048576) { 242 printf("nfsd: vfs.nfsd.srvmaxio cannot be > 1Mbyte\n"); 243 return (EINVAL); 244 } 245 if ((newsrvmaxio & (newsrvmaxio - 1)) != 0) { 246 printf("nfsd: vfs.nfsd.srvmaxio must be a power of 2\n"); 247 return (EINVAL); 248 } 249 250 /* 251 * Check that kern.ipc.maxsockbuf is large enough for 252 * newsrviomax, given the setting of vfs.nfs.bufpackets. 253 */ 254 if ((newsrvmaxio + NFS_MAXXDR) * nfs_bufpackets > 255 sb_max_adj) { 256 /* 257 * Suggest vfs.nfs.bufpackets * maximum RPC message for 258 * sb_max_adj. 259 */ 260 tval = (newsrvmaxio + NFS_MAXXDR) * nfs_bufpackets; 261 262 /* 263 * Convert suggested sb_max_adj value to a suggested 264 * sb_max value, which is what is set via kern.ipc.maxsockbuf. 265 * Perform the inverse calculation of (from uipc_sockbuf.c): 266 * sb_max_adj = (u_quad_t)sb_max * MCLBYTES / 267 * (MSIZE + MCLBYTES); 268 * XXX If the calculation of sb_max_adj from sb_max changes, 269 * this calculation must be changed as well. 270 */ 271 tval *= (MSIZE + MCLBYTES); /* Brackets for readability. */ 272 tval += MCLBYTES - 1; /* Round up divide. */ 273 tval /= MCLBYTES; 274 printf("nfsd: set kern.ipc.maxsockbuf to a minimum of " 275 "%ju to support %ubyte NFS I/O\n", (uintmax_t)tval, 276 newsrvmaxio); 277 return (EINVAL); 278 } 279 280 NFSD_LOCK(); 281 if (newnfs_numnfsd != 0) { 282 NFSD_UNLOCK(); 283 printf("nfsd: cannot set vfs.nfsd.srvmaxio when nfsd " 284 "threads are running\n"); 285 return (EINVAL); 286 } 287 288 289 nfs_srvmaxio = newsrvmaxio; 290 NFSD_UNLOCK(); 291 return (0); 292 } 293 SYSCTL_PROC(_vfs_nfsd, OID_AUTO, srvmaxio, 294 CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RW, NULL, 0, 295 sysctl_srvmaxio, "IU", "Maximum I/O size in bytes"); 296 297 #define MAX_REORDERED_RPC 16 298 #define NUM_HEURISTIC 1031 299 #define NHUSE_INIT 64 300 #define NHUSE_INC 16 301 #define NHUSE_MAX 2048 302 303 static struct nfsheur { 304 struct vnode *nh_vp; /* vp to match (unreferenced pointer) */ 305 off_t nh_nextoff; /* next offset for sequential detection */ 306 int nh_use; /* use count for selection */ 307 int nh_seqcount; /* heuristic */ 308 } nfsheur[NUM_HEURISTIC]; 309 310 /* 311 * Heuristic to detect sequential operation. 312 */ 313 static struct nfsheur * 314 nfsrv_sequential_heuristic(struct uio *uio, struct vnode *vp) 315 { 316 struct nfsheur *nh; 317 int hi, try; 318 319 /* Locate best candidate. */ 320 try = 32; 321 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC; 322 nh = &nfsheur[hi]; 323 while (try--) { 324 if (nfsheur[hi].nh_vp == vp) { 325 nh = &nfsheur[hi]; 326 break; 327 } 328 if (nfsheur[hi].nh_use > 0) 329 --nfsheur[hi].nh_use; 330 hi = (hi + 1) % NUM_HEURISTIC; 331 if (nfsheur[hi].nh_use < nh->nh_use) 332 nh = &nfsheur[hi]; 333 } 334 335 /* Initialize hint if this is a new file. */ 336 if (nh->nh_vp != vp) { 337 nh->nh_vp = vp; 338 nh->nh_nextoff = uio->uio_offset; 339 nh->nh_use = NHUSE_INIT; 340 if (uio->uio_offset == 0) 341 nh->nh_seqcount = 4; 342 else 343 nh->nh_seqcount = 1; 344 } 345 346 /* Calculate heuristic. */ 347 if ((uio->uio_offset == 0 && nh->nh_seqcount > 0) || 348 uio->uio_offset == nh->nh_nextoff) { 349 /* See comments in vfs_vnops.c:sequential_heuristic(). */ 350 nh->nh_seqcount += howmany(uio->uio_resid, 16384); 351 if (nh->nh_seqcount > IO_SEQMAX) 352 nh->nh_seqcount = IO_SEQMAX; 353 } else if (qabs(uio->uio_offset - nh->nh_nextoff) <= MAX_REORDERED_RPC * 354 imax(vp->v_mount->mnt_stat.f_iosize, uio->uio_resid)) { 355 /* Probably a reordered RPC, leave seqcount alone. */ 356 } else if (nh->nh_seqcount > 1) { 357 nh->nh_seqcount /= 2; 358 } else { 359 nh->nh_seqcount = 0; 360 } 361 nh->nh_use += NHUSE_INC; 362 if (nh->nh_use > NHUSE_MAX) 363 nh->nh_use = NHUSE_MAX; 364 return (nh); 365 } 366 367 /* 368 * Get attributes into nfsvattr structure. 369 */ 370 int 371 nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap, 372 struct nfsrv_descript *nd, struct thread *p, int vpislocked, 373 nfsattrbit_t *attrbitp) 374 { 375 int error, gotattr, lockedit = 0; 376 struct nfsvattr na; 377 378 if (vpislocked == 0) { 379 /* 380 * When vpislocked == 0, the vnode is either exclusively 381 * locked by this thread or not locked by this thread. 382 * As such, shared lock it, if not exclusively locked. 383 */ 384 if (NFSVOPISLOCKED(vp) != LK_EXCLUSIVE) { 385 lockedit = 1; 386 NFSVOPLOCK(vp, LK_SHARED | LK_RETRY); 387 } 388 } 389 390 /* 391 * Acquire the Change, Size, TimeAccess, TimeModify and SpaceUsed 392 * attributes, as required. 393 * This needs to be done for regular files if: 394 * - non-NFSv4 RPCs or 395 * - when attrbitp == NULL or 396 * - an NFSv4 RPC with any of the above attributes in attrbitp. 397 * A return of 0 for nfsrv_proxyds() indicates that it has acquired 398 * these attributes. nfsrv_proxyds() will return an error if the 399 * server is not a pNFS one. 400 */ 401 gotattr = 0; 402 if (vp->v_type == VREG && nfsrv_devidcnt > 0 && (attrbitp == NULL || 403 (nd->nd_flag & ND_NFSV4) == 0 || 404 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_CHANGE) || 405 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) || 406 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESS) || 407 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFY) || 408 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACEUSED))) { 409 error = nfsrv_proxyds(vp, 0, 0, nd->nd_cred, p, 410 NFSPROC_GETATTR, NULL, NULL, NULL, &na, NULL, NULL, 0, 411 NULL); 412 if (error == 0) 413 gotattr = 1; 414 } 415 416 error = VOP_GETATTR(vp, &nvap->na_vattr, nd->nd_cred); 417 if (lockedit != 0) 418 NFSVOPUNLOCK(vp); 419 420 /* 421 * If we got the Change, Size and Modify Time from the DS, 422 * replace them. 423 */ 424 if (gotattr != 0) { 425 nvap->na_atime = na.na_atime; 426 nvap->na_mtime = na.na_mtime; 427 nvap->na_filerev = na.na_filerev; 428 nvap->na_size = na.na_size; 429 nvap->na_bytes = na.na_bytes; 430 } 431 NFSD_DEBUG(4, "nfsvno_getattr: gotattr=%d err=%d chg=%ju\n", gotattr, 432 error, (uintmax_t)na.na_filerev); 433 434 NFSEXITCODE(error); 435 return (error); 436 } 437 438 /* 439 * Get a file handle for a vnode. 440 */ 441 int 442 nfsvno_getfh(struct vnode *vp, fhandle_t *fhp, struct thread *p) 443 { 444 int error; 445 446 NFSBZERO((caddr_t)fhp, sizeof(fhandle_t)); 447 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 448 error = VOP_VPTOFH(vp, &fhp->fh_fid); 449 450 NFSEXITCODE(error); 451 return (error); 452 } 453 454 /* 455 * Perform access checking for vnodes obtained from file handles that would 456 * refer to files already opened by a Unix client. You cannot just use 457 * vn_writechk() and VOP_ACCESSX() for two reasons. 458 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write 459 * case. 460 * 2 - The owner is to be given access irrespective of mode bits for some 461 * operations, so that processes that chmod after opening a file don't 462 * break. 463 */ 464 int 465 nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred, 466 struct nfsexstuff *exp, struct thread *p, int override, int vpislocked, 467 u_int32_t *supportedtypep) 468 { 469 struct vattr vattr; 470 int error = 0, getret = 0; 471 472 if (vpislocked == 0) { 473 if (NFSVOPLOCK(vp, LK_SHARED) != 0) { 474 error = EPERM; 475 goto out; 476 } 477 } 478 if (accmode & VWRITE) { 479 /* Just vn_writechk() changed to check rdonly */ 480 /* 481 * Disallow write attempts on read-only file systems; 482 * unless the file is a socket or a block or character 483 * device resident on the file system. 484 */ 485 if (NFSVNO_EXRDONLY(exp) || 486 (vp->v_mount->mnt_flag & MNT_RDONLY)) { 487 switch (vp->v_type) { 488 case VREG: 489 case VDIR: 490 case VLNK: 491 error = EROFS; 492 default: 493 break; 494 } 495 } 496 /* 497 * If there's shared text associated with 498 * the inode, try to free it up once. If 499 * we fail, we can't allow writing. 500 */ 501 if (VOP_IS_TEXT(vp) && error == 0) 502 error = ETXTBSY; 503 } 504 if (error != 0) { 505 if (vpislocked == 0) 506 NFSVOPUNLOCK(vp); 507 goto out; 508 } 509 510 /* 511 * Should the override still be applied when ACLs are enabled? 512 */ 513 error = VOP_ACCESSX(vp, accmode, cred, p); 514 if (error != 0 && (accmode & (VDELETE | VDELETE_CHILD))) { 515 /* 516 * Try again with VEXPLICIT_DENY, to see if the test for 517 * deletion is supported. 518 */ 519 error = VOP_ACCESSX(vp, accmode | VEXPLICIT_DENY, cred, p); 520 if (error == 0) { 521 if (vp->v_type == VDIR) { 522 accmode &= ~(VDELETE | VDELETE_CHILD); 523 accmode |= VWRITE; 524 error = VOP_ACCESSX(vp, accmode, cred, p); 525 } else if (supportedtypep != NULL) { 526 *supportedtypep &= ~NFSACCESS_DELETE; 527 } 528 } 529 } 530 531 /* 532 * Allow certain operations for the owner (reads and writes 533 * on files that are already open). 534 */ 535 if (override != NFSACCCHK_NOOVERRIDE && 536 (error == EPERM || error == EACCES)) { 537 if (cred->cr_uid == 0 && (override & NFSACCCHK_ALLOWROOT)) 538 error = 0; 539 else if (override & NFSACCCHK_ALLOWOWNER) { 540 getret = VOP_GETATTR(vp, &vattr, cred); 541 if (getret == 0 && cred->cr_uid == vattr.va_uid) 542 error = 0; 543 } 544 } 545 if (vpislocked == 0) 546 NFSVOPUNLOCK(vp); 547 548 out: 549 NFSEXITCODE(error); 550 return (error); 551 } 552 553 /* 554 * Set attribute(s) vnop. 555 */ 556 int 557 nfsvno_setattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred, 558 struct thread *p, struct nfsexstuff *exp) 559 { 560 u_quad_t savsize = 0; 561 int error, savedit; 562 time_t savbtime; 563 564 /* 565 * If this is an exported file system and a pNFS service is running, 566 * don't VOP_SETATTR() of size for the MDS file system. 567 */ 568 savedit = 0; 569 error = 0; 570 if (vp->v_type == VREG && (vp->v_mount->mnt_flag & MNT_EXPORTED) != 0 && 571 nfsrv_devidcnt != 0 && nvap->na_vattr.va_size != VNOVAL && 572 nvap->na_vattr.va_size > 0) { 573 savsize = nvap->na_vattr.va_size; 574 nvap->na_vattr.va_size = VNOVAL; 575 if (nvap->na_vattr.va_uid != (uid_t)VNOVAL || 576 nvap->na_vattr.va_gid != (gid_t)VNOVAL || 577 nvap->na_vattr.va_mode != (mode_t)VNOVAL || 578 nvap->na_vattr.va_atime.tv_sec != VNOVAL || 579 nvap->na_vattr.va_mtime.tv_sec != VNOVAL) 580 savedit = 1; 581 else 582 savedit = 2; 583 } 584 if (savedit != 2) 585 error = VOP_SETATTR(vp, &nvap->na_vattr, cred); 586 if (savedit != 0) 587 nvap->na_vattr.va_size = savsize; 588 if (error == 0 && (nvap->na_vattr.va_uid != (uid_t)VNOVAL || 589 nvap->na_vattr.va_gid != (gid_t)VNOVAL || 590 nvap->na_vattr.va_size != VNOVAL || 591 nvap->na_vattr.va_mode != (mode_t)VNOVAL || 592 nvap->na_vattr.va_atime.tv_sec != VNOVAL || 593 nvap->na_vattr.va_mtime.tv_sec != VNOVAL)) { 594 /* Never modify birthtime on a DS file. */ 595 savbtime = nvap->na_vattr.va_birthtime.tv_sec; 596 nvap->na_vattr.va_birthtime.tv_sec = VNOVAL; 597 /* For a pNFS server, set the attributes on the DS file. */ 598 error = nfsrv_proxyds(vp, 0, 0, cred, p, NFSPROC_SETATTR, 599 NULL, NULL, NULL, nvap, NULL, NULL, 0, NULL); 600 nvap->na_vattr.va_birthtime.tv_sec = savbtime; 601 if (error == ENOENT) 602 error = 0; 603 } 604 NFSEXITCODE(error); 605 return (error); 606 } 607 608 /* 609 * Set up nameidata for a lookup() call and do it. 610 */ 611 int 612 nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp, 613 struct vnode *dp, int islocked, struct nfsexstuff *exp, 614 struct vnode **retdirp) 615 { 616 struct componentname *cnp = &ndp->ni_cnd; 617 int i; 618 struct iovec aiov; 619 struct uio auio; 620 int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0, linklen; 621 int error = 0; 622 char *cp; 623 624 *retdirp = NULL; 625 cnp->cn_nameptr = cnp->cn_pnbuf; 626 ndp->ni_lcf = 0; 627 /* 628 * Extract and set starting directory. 629 */ 630 if (dp->v_type != VDIR) { 631 if (islocked) 632 vput(dp); 633 else 634 vrele(dp); 635 nfsvno_relpathbuf(ndp); 636 error = ENOTDIR; 637 goto out1; 638 } 639 if (islocked) 640 NFSVOPUNLOCK(dp); 641 VREF(dp); 642 *retdirp = dp; 643 if (NFSVNO_EXRDONLY(exp)) 644 cnp->cn_flags |= RDONLY; 645 ndp->ni_segflg = UIO_SYSSPACE; 646 647 if (nd->nd_flag & ND_PUBLOOKUP) { 648 ndp->ni_loopcnt = 0; 649 if (cnp->cn_pnbuf[0] == '/') { 650 vrele(dp); 651 /* 652 * Check for degenerate pathnames here, since lookup() 653 * panics on them. 654 */ 655 for (i = 1; i < ndp->ni_pathlen; i++) 656 if (cnp->cn_pnbuf[i] != '/') 657 break; 658 if (i == ndp->ni_pathlen) { 659 error = NFSERR_ACCES; 660 goto out; 661 } 662 dp = rootvnode; 663 VREF(dp); 664 } 665 } else if ((nfsrv_enable_crossmntpt == 0 && NFSVNO_EXPORTED(exp)) || 666 (nd->nd_flag & ND_NFSV4) == 0) { 667 /* 668 * Only cross mount points for NFSv4 when doing a 669 * mount while traversing the file system above 670 * the mount point, unless nfsrv_enable_crossmntpt is set. 671 */ 672 cnp->cn_flags |= NOCROSSMOUNT; 673 } 674 675 /* 676 * Initialize for scan, set ni_startdir and bump ref on dp again 677 * because lookup() will dereference ni_startdir. 678 */ 679 680 ndp->ni_startdir = dp; 681 ndp->ni_rootdir = rootvnode; 682 ndp->ni_topdir = NULL; 683 684 if (!lockleaf) 685 cnp->cn_flags |= LOCKLEAF; 686 for (;;) { 687 cnp->cn_nameptr = cnp->cn_pnbuf; 688 /* 689 * Call lookup() to do the real work. If an error occurs, 690 * ndp->ni_vp and ni_dvp are left uninitialized or NULL and 691 * we do not have to dereference anything before returning. 692 * In either case ni_startdir will be dereferenced and NULLed 693 * out. 694 */ 695 error = vfs_lookup(ndp); 696 if (error) 697 break; 698 699 /* 700 * Check for encountering a symbolic link. Trivial 701 * termination occurs if no symlink encountered. 702 */ 703 if ((cnp->cn_flags & ISSYMLINK) == 0) { 704 if (ndp->ni_vp && !lockleaf) 705 NFSVOPUNLOCK(ndp->ni_vp); 706 break; 707 } 708 709 /* 710 * Validate symlink 711 */ 712 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 713 NFSVOPUNLOCK(ndp->ni_dvp); 714 if (!(nd->nd_flag & ND_PUBLOOKUP)) { 715 error = EINVAL; 716 goto badlink2; 717 } 718 719 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 720 error = ELOOP; 721 goto badlink2; 722 } 723 if (ndp->ni_pathlen > 1) 724 cp = uma_zalloc(namei_zone, M_WAITOK); 725 else 726 cp = cnp->cn_pnbuf; 727 aiov.iov_base = cp; 728 aiov.iov_len = MAXPATHLEN; 729 auio.uio_iov = &aiov; 730 auio.uio_iovcnt = 1; 731 auio.uio_offset = 0; 732 auio.uio_rw = UIO_READ; 733 auio.uio_segflg = UIO_SYSSPACE; 734 auio.uio_td = NULL; 735 auio.uio_resid = MAXPATHLEN; 736 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); 737 if (error) { 738 badlink1: 739 if (ndp->ni_pathlen > 1) 740 uma_zfree(namei_zone, cp); 741 badlink2: 742 vrele(ndp->ni_dvp); 743 vput(ndp->ni_vp); 744 break; 745 } 746 linklen = MAXPATHLEN - auio.uio_resid; 747 if (linklen == 0) { 748 error = ENOENT; 749 goto badlink1; 750 } 751 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 752 error = ENAMETOOLONG; 753 goto badlink1; 754 } 755 756 /* 757 * Adjust or replace path 758 */ 759 if (ndp->ni_pathlen > 1) { 760 NFSBCOPY(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 761 uma_zfree(namei_zone, cnp->cn_pnbuf); 762 cnp->cn_pnbuf = cp; 763 } else 764 cnp->cn_pnbuf[linklen] = '\0'; 765 ndp->ni_pathlen += linklen; 766 767 /* 768 * Cleanup refs for next loop and check if root directory 769 * should replace current directory. Normally ni_dvp 770 * becomes the new base directory and is cleaned up when 771 * we loop. Explicitly null pointers after invalidation 772 * to clarify operation. 773 */ 774 vput(ndp->ni_vp); 775 ndp->ni_vp = NULL; 776 777 if (cnp->cn_pnbuf[0] == '/') { 778 vrele(ndp->ni_dvp); 779 ndp->ni_dvp = ndp->ni_rootdir; 780 VREF(ndp->ni_dvp); 781 } 782 ndp->ni_startdir = ndp->ni_dvp; 783 ndp->ni_dvp = NULL; 784 } 785 if (!lockleaf) 786 cnp->cn_flags &= ~LOCKLEAF; 787 788 out: 789 if (error) { 790 nfsvno_relpathbuf(ndp); 791 ndp->ni_vp = NULL; 792 ndp->ni_dvp = NULL; 793 ndp->ni_startdir = NULL; 794 } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) { 795 ndp->ni_dvp = NULL; 796 } 797 798 out1: 799 NFSEXITCODE2(error, nd); 800 return (error); 801 } 802 803 /* 804 * Set up a pathname buffer and return a pointer to it and, optionally 805 * set a hash pointer. 806 */ 807 void 808 nfsvno_setpathbuf(struct nameidata *ndp, char **bufpp, u_long **hashpp) 809 { 810 struct componentname *cnp = &ndp->ni_cnd; 811 812 cnp->cn_flags |= (NOMACCHECK); 813 cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); 814 if (hashpp != NULL) 815 *hashpp = NULL; 816 *bufpp = cnp->cn_pnbuf; 817 } 818 819 /* 820 * Release the above path buffer, if not released by nfsvno_namei(). 821 */ 822 void 823 nfsvno_relpathbuf(struct nameidata *ndp) 824 { 825 826 uma_zfree(namei_zone, ndp->ni_cnd.cn_pnbuf); 827 ndp->ni_cnd.cn_pnbuf = NULL; 828 } 829 830 /* 831 * Readlink vnode op into an mbuf list. 832 */ 833 int 834 nfsvno_readlink(struct vnode *vp, struct ucred *cred, int maxextsiz, 835 struct thread *p, struct mbuf **mpp, struct mbuf **mpendp, int *lenp) 836 { 837 struct iovec *iv; 838 struct uio io, *uiop = &io; 839 struct mbuf *mp, *mp3; 840 int len, tlen, error = 0; 841 842 len = NFS_MAXPATHLEN; 843 if (maxextsiz > 0) 844 uiop->uio_iovcnt = nfsrv_createiovec_extpgs(len, maxextsiz, 845 &mp3, &mp, &iv); 846 else 847 uiop->uio_iovcnt = nfsrv_createiovec(len, &mp3, &mp, &iv); 848 uiop->uio_iov = iv; 849 uiop->uio_offset = 0; 850 uiop->uio_resid = len; 851 uiop->uio_rw = UIO_READ; 852 uiop->uio_segflg = UIO_SYSSPACE; 853 uiop->uio_td = NULL; 854 error = VOP_READLINK(vp, uiop, cred); 855 free(iv, M_TEMP); 856 if (error) { 857 m_freem(mp3); 858 *lenp = 0; 859 goto out; 860 } 861 if (uiop->uio_resid > 0) { 862 len -= uiop->uio_resid; 863 tlen = NFSM_RNDUP(len); 864 if (tlen == 0) { 865 m_freem(mp3); 866 mp3 = mp = NULL; 867 } else if (tlen != NFS_MAXPATHLEN || tlen != len) 868 mp = nfsrv_adj(mp3, NFS_MAXPATHLEN - tlen, 869 tlen - len); 870 } 871 *lenp = len; 872 *mpp = mp3; 873 *mpendp = mp; 874 875 out: 876 NFSEXITCODE(error); 877 return (error); 878 } 879 880 /* 881 * Create an mbuf chain and an associated iovec that can be used to Read 882 * or Getextattr of data. 883 * Upon success, return pointers to the first and last mbufs in the chain 884 * plus the malloc'd iovec and its iovlen. 885 */ 886 static int 887 nfsrv_createiovec(int len, struct mbuf **mpp, struct mbuf **mpendp, 888 struct iovec **ivp) 889 { 890 struct mbuf *m, *m2 = NULL, *m3; 891 struct iovec *iv; 892 int i, left, siz; 893 894 left = len; 895 m3 = NULL; 896 /* 897 * Generate the mbuf list with the uio_iov ref. to it. 898 */ 899 i = 0; 900 while (left > 0) { 901 NFSMGET(m); 902 MCLGET(m, M_WAITOK); 903 m->m_len = 0; 904 siz = min(M_TRAILINGSPACE(m), left); 905 left -= siz; 906 i++; 907 if (m3) 908 m2->m_next = m; 909 else 910 m3 = m; 911 m2 = m; 912 } 913 *ivp = iv = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK); 914 m = m3; 915 left = len; 916 i = 0; 917 while (left > 0) { 918 if (m == NULL) 919 panic("nfsrv_createiovec iov"); 920 siz = min(M_TRAILINGSPACE(m), left); 921 if (siz > 0) { 922 iv->iov_base = mtod(m, caddr_t) + m->m_len; 923 iv->iov_len = siz; 924 m->m_len += siz; 925 left -= siz; 926 iv++; 927 i++; 928 } 929 m = m->m_next; 930 } 931 *mpp = m3; 932 *mpendp = m2; 933 return (i); 934 } 935 936 /* 937 * Create an mbuf chain and an associated iovec that can be used to Read 938 * or Getextattr of data. 939 * Upon success, return pointers to the first and last mbufs in the chain 940 * plus the malloc'd iovec and its iovlen. 941 * Same as above, but creates ext_pgs mbuf(s). 942 */ 943 static int 944 nfsrv_createiovec_extpgs(int len, int maxextsiz, struct mbuf **mpp, 945 struct mbuf **mpendp, struct iovec **ivp) 946 { 947 struct mbuf *m, *m2 = NULL, *m3; 948 struct iovec *iv; 949 int i, left, pgno, siz; 950 951 left = len; 952 m3 = NULL; 953 /* 954 * Generate the mbuf list with the uio_iov ref. to it. 955 */ 956 i = 0; 957 while (left > 0) { 958 siz = min(left, maxextsiz); 959 m = mb_alloc_ext_plus_pages(siz, M_WAITOK); 960 left -= siz; 961 i += m->m_epg_npgs; 962 if (m3 != NULL) 963 m2->m_next = m; 964 else 965 m3 = m; 966 m2 = m; 967 } 968 *ivp = iv = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK); 969 m = m3; 970 left = len; 971 i = 0; 972 pgno = 0; 973 while (left > 0) { 974 if (m == NULL) 975 panic("nfsvno_createiovec_extpgs iov"); 976 siz = min(PAGE_SIZE, left); 977 if (siz > 0) { 978 iv->iov_base = (void *)PHYS_TO_DMAP(m->m_epg_pa[pgno]); 979 iv->iov_len = siz; 980 m->m_len += siz; 981 if (pgno == m->m_epg_npgs - 1) 982 m->m_epg_last_len = siz; 983 left -= siz; 984 iv++; 985 i++; 986 pgno++; 987 } 988 if (pgno == m->m_epg_npgs && left > 0) { 989 m = m->m_next; 990 if (m == NULL) 991 panic("nfsvno_createiovec_extpgs iov"); 992 pgno = 0; 993 } 994 } 995 *mpp = m3; 996 *mpendp = m2; 997 return (i); 998 } 999 1000 /* 1001 * Read vnode op call into mbuf list. 1002 */ 1003 int 1004 nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred, 1005 int maxextsiz, struct thread *p, struct mbuf **mpp, 1006 struct mbuf **mpendp) 1007 { 1008 struct mbuf *m; 1009 struct iovec *iv; 1010 int error = 0, len, tlen, ioflag = 0; 1011 struct mbuf *m3; 1012 struct uio io, *uiop = &io; 1013 struct nfsheur *nh; 1014 1015 /* 1016 * Attempt to read from a DS file. A return of ENOENT implies 1017 * there is no DS file to read. 1018 */ 1019 error = nfsrv_proxyds(vp, off, cnt, cred, p, NFSPROC_READDS, mpp, 1020 NULL, mpendp, NULL, NULL, NULL, 0, NULL); 1021 if (error != ENOENT) 1022 return (error); 1023 1024 len = NFSM_RNDUP(cnt); 1025 if (maxextsiz > 0) 1026 uiop->uio_iovcnt = nfsrv_createiovec_extpgs(len, maxextsiz, 1027 &m3, &m, &iv); 1028 else 1029 uiop->uio_iovcnt = nfsrv_createiovec(len, &m3, &m, &iv); 1030 uiop->uio_iov = iv; 1031 uiop->uio_offset = off; 1032 uiop->uio_resid = len; 1033 uiop->uio_rw = UIO_READ; 1034 uiop->uio_segflg = UIO_SYSSPACE; 1035 uiop->uio_td = NULL; 1036 nh = nfsrv_sequential_heuristic(uiop, vp); 1037 ioflag |= nh->nh_seqcount << IO_SEQSHIFT; 1038 /* XXX KDM make this more systematic? */ 1039 NFSD_VNET(nfsstatsv1_p)->srvbytes[NFSV4OP_READ] += uiop->uio_resid; 1040 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred); 1041 free(iv, M_TEMP); 1042 if (error) { 1043 m_freem(m3); 1044 *mpp = NULL; 1045 goto out; 1046 } 1047 nh->nh_nextoff = uiop->uio_offset; 1048 tlen = len - uiop->uio_resid; 1049 cnt = cnt < tlen ? cnt : tlen; 1050 tlen = NFSM_RNDUP(cnt); 1051 if (tlen == 0) { 1052 m_freem(m3); 1053 m3 = m = NULL; 1054 } else if (len != tlen || tlen != cnt) 1055 m = nfsrv_adj(m3, len - tlen, tlen - cnt); 1056 *mpp = m3; 1057 *mpendp = m; 1058 1059 out: 1060 NFSEXITCODE(error); 1061 return (error); 1062 } 1063 1064 /* 1065 * Create the iovec for the mbuf chain passed in as an argument. 1066 * The "cp" argument is where the data starts within the first mbuf in 1067 * the chain. It returns the iovec and the iovcnt. 1068 */ 1069 static int 1070 nfsrv_createiovecw(int retlen, struct mbuf *m, char *cp, struct iovec **ivpp, 1071 int *iovcntp) 1072 { 1073 struct mbuf *mp; 1074 struct iovec *ivp; 1075 int cnt, i, len; 1076 1077 /* 1078 * Loop through the mbuf chain, counting how many mbufs are a 1079 * part of this write operation, so the iovec size is known. 1080 */ 1081 cnt = 0; 1082 len = retlen; 1083 mp = m; 1084 i = mtod(mp, caddr_t) + mp->m_len - cp; 1085 while (len > 0) { 1086 if (i > 0) { 1087 len -= i; 1088 cnt++; 1089 } 1090 mp = mp->m_next; 1091 if (!mp) { 1092 if (len > 0) 1093 return (EBADRPC); 1094 } else 1095 i = mp->m_len; 1096 } 1097 1098 /* Now, create the iovec. */ 1099 mp = m; 1100 *ivpp = ivp = malloc(cnt * sizeof (struct iovec), M_TEMP, 1101 M_WAITOK); 1102 *iovcntp = cnt; 1103 i = mtod(mp, caddr_t) + mp->m_len - cp; 1104 len = retlen; 1105 while (len > 0) { 1106 if (mp == NULL) 1107 panic("nfsrv_createiovecw"); 1108 if (i > 0) { 1109 i = min(i, len); 1110 ivp->iov_base = cp; 1111 ivp->iov_len = i; 1112 ivp++; 1113 len -= i; 1114 } 1115 mp = mp->m_next; 1116 if (mp) { 1117 i = mp->m_len; 1118 cp = mtod(mp, caddr_t); 1119 } 1120 } 1121 return (0); 1122 } 1123 1124 /* 1125 * Write vnode op from an mbuf list. 1126 */ 1127 int 1128 nfsvno_write(struct vnode *vp, off_t off, int retlen, int *stable, 1129 struct mbuf *mp, char *cp, struct ucred *cred, struct thread *p) 1130 { 1131 struct iovec *iv; 1132 int cnt, ioflags, error; 1133 struct uio io, *uiop = &io; 1134 struct nfsheur *nh; 1135 1136 /* 1137 * Attempt to write to a DS file. A return of ENOENT implies 1138 * there is no DS file to write. 1139 */ 1140 error = nfsrv_proxyds(vp, off, retlen, cred, p, NFSPROC_WRITEDS, 1141 &mp, cp, NULL, NULL, NULL, NULL, 0, NULL); 1142 if (error != ENOENT) { 1143 *stable = NFSWRITE_FILESYNC; 1144 return (error); 1145 } 1146 1147 if (*stable == NFSWRITE_UNSTABLE) 1148 ioflags = IO_NODELOCKED; 1149 else 1150 ioflags = (IO_SYNC | IO_NODELOCKED); 1151 error = nfsrv_createiovecw(retlen, mp, cp, &iv, &cnt); 1152 if (error != 0) 1153 return (error); 1154 uiop->uio_iov = iv; 1155 uiop->uio_iovcnt = cnt; 1156 uiop->uio_resid = retlen; 1157 uiop->uio_rw = UIO_WRITE; 1158 uiop->uio_segflg = UIO_SYSSPACE; 1159 NFSUIOPROC(uiop, p); 1160 uiop->uio_offset = off; 1161 nh = nfsrv_sequential_heuristic(uiop, vp); 1162 ioflags |= nh->nh_seqcount << IO_SEQSHIFT; 1163 /* XXX KDM make this more systematic? */ 1164 NFSD_VNET(nfsstatsv1_p)->srvbytes[NFSV4OP_WRITE] += uiop->uio_resid; 1165 error = VOP_WRITE(vp, uiop, ioflags, cred); 1166 if (error == 0) 1167 nh->nh_nextoff = uiop->uio_offset; 1168 free(iv, M_TEMP); 1169 1170 NFSEXITCODE(error); 1171 return (error); 1172 } 1173 1174 /* 1175 * Common code for creating a regular file (plus special files for V2). 1176 */ 1177 int 1178 nfsvno_createsub(struct nfsrv_descript *nd, struct nameidata *ndp, 1179 struct vnode **vpp, struct nfsvattr *nvap, int *exclusive_flagp, 1180 int32_t *cverf, NFSDEV_T rdev, struct nfsexstuff *exp) 1181 { 1182 u_quad_t tempsize; 1183 int error; 1184 struct thread *p = curthread; 1185 1186 error = nd->nd_repstat; 1187 if (!error && ndp->ni_vp == NULL) { 1188 if (nvap->na_type == VREG || nvap->na_type == VSOCK) { 1189 error = VOP_CREATE(ndp->ni_dvp, 1190 &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr); 1191 /* For a pNFS server, create the data file on a DS. */ 1192 if (error == 0 && nvap->na_type == VREG) { 1193 /* 1194 * Create a data file on a DS for a pNFS server. 1195 * This function just returns if not 1196 * running a pNFS DS or the creation fails. 1197 */ 1198 nfsrv_pnfscreate(ndp->ni_vp, &nvap->na_vattr, 1199 nd->nd_cred, p); 1200 } 1201 VOP_VPUT_PAIR(ndp->ni_dvp, error == 0 ? &ndp->ni_vp : 1202 NULL, false); 1203 nfsvno_relpathbuf(ndp); 1204 if (!error) { 1205 if (*exclusive_flagp) { 1206 *exclusive_flagp = 0; 1207 NFSVNO_ATTRINIT(nvap); 1208 nvap->na_atime.tv_sec = cverf[0]; 1209 nvap->na_atime.tv_nsec = cverf[1]; 1210 error = VOP_SETATTR(ndp->ni_vp, 1211 &nvap->na_vattr, nd->nd_cred); 1212 if (error != 0) { 1213 vput(ndp->ni_vp); 1214 ndp->ni_vp = NULL; 1215 error = NFSERR_NOTSUPP; 1216 } 1217 } 1218 } 1219 /* 1220 * NFS V2 Only. nfsrvd_mknod() does this for V3. 1221 * (This implies, just get out on an error.) 1222 */ 1223 } else if (nvap->na_type == VCHR || nvap->na_type == VBLK || 1224 nvap->na_type == VFIFO) { 1225 if (nvap->na_type == VCHR && rdev == 0xffffffff) 1226 nvap->na_type = VFIFO; 1227 if (nvap->na_type != VFIFO && 1228 (error = priv_check_cred(nd->nd_cred, PRIV_VFS_MKNOD_DEV))) { 1229 nfsvno_relpathbuf(ndp); 1230 vput(ndp->ni_dvp); 1231 goto out; 1232 } 1233 nvap->na_rdev = rdev; 1234 error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp, 1235 &ndp->ni_cnd, &nvap->na_vattr); 1236 VOP_VPUT_PAIR(ndp->ni_dvp, error == 0 ? &ndp->ni_vp : 1237 NULL, false); 1238 nfsvno_relpathbuf(ndp); 1239 if (error) 1240 goto out; 1241 } else { 1242 nfsvno_relpathbuf(ndp); 1243 vput(ndp->ni_dvp); 1244 error = ENXIO; 1245 goto out; 1246 } 1247 *vpp = ndp->ni_vp; 1248 } else { 1249 /* 1250 * Handle cases where error is already set and/or 1251 * the file exists. 1252 * 1 - clean up the lookup 1253 * 2 - iff !error and na_size set, truncate it 1254 */ 1255 nfsvno_relpathbuf(ndp); 1256 *vpp = ndp->ni_vp; 1257 if (ndp->ni_dvp == *vpp) 1258 vrele(ndp->ni_dvp); 1259 else 1260 vput(ndp->ni_dvp); 1261 if (!error && nvap->na_size != VNOVAL) { 1262 error = nfsvno_accchk(*vpp, VWRITE, 1263 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 1264 NFSACCCHK_VPISLOCKED, NULL); 1265 if (!error) { 1266 tempsize = nvap->na_size; 1267 NFSVNO_ATTRINIT(nvap); 1268 nvap->na_size = tempsize; 1269 error = nfsvno_setattr(*vpp, nvap, 1270 nd->nd_cred, p, exp); 1271 } 1272 } 1273 if (error) 1274 vput(*vpp); 1275 } 1276 1277 out: 1278 NFSEXITCODE(error); 1279 return (error); 1280 } 1281 1282 /* 1283 * Do a mknod vnode op. 1284 */ 1285 int 1286 nfsvno_mknod(struct nameidata *ndp, struct nfsvattr *nvap, struct ucred *cred, 1287 struct thread *p) 1288 { 1289 int error = 0; 1290 __enum_uint8(vtype) vtyp; 1291 1292 vtyp = nvap->na_type; 1293 /* 1294 * Iff doesn't exist, create it. 1295 */ 1296 if (ndp->ni_vp) { 1297 nfsvno_relpathbuf(ndp); 1298 vput(ndp->ni_dvp); 1299 vrele(ndp->ni_vp); 1300 error = EEXIST; 1301 goto out; 1302 } 1303 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) { 1304 nfsvno_relpathbuf(ndp); 1305 vput(ndp->ni_dvp); 1306 error = NFSERR_BADTYPE; 1307 goto out; 1308 } 1309 if (vtyp == VSOCK) { 1310 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 1311 &ndp->ni_cnd, &nvap->na_vattr); 1312 VOP_VPUT_PAIR(ndp->ni_dvp, error == 0 ? &ndp->ni_vp : NULL, 1313 false); 1314 nfsvno_relpathbuf(ndp); 1315 } else { 1316 if (nvap->na_type != VFIFO && 1317 (error = priv_check_cred(cred, PRIV_VFS_MKNOD_DEV))) { 1318 nfsvno_relpathbuf(ndp); 1319 vput(ndp->ni_dvp); 1320 goto out; 1321 } 1322 error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp, 1323 &ndp->ni_cnd, &nvap->na_vattr); 1324 VOP_VPUT_PAIR(ndp->ni_dvp, error == 0 ? &ndp->ni_vp : NULL, 1325 false); 1326 nfsvno_relpathbuf(ndp); 1327 /* 1328 * Since VOP_MKNOD returns the ni_vp, I can't 1329 * see any reason to do the lookup. 1330 */ 1331 } 1332 1333 out: 1334 NFSEXITCODE(error); 1335 return (error); 1336 } 1337 1338 /* 1339 * Mkdir vnode op. 1340 */ 1341 int 1342 nfsvno_mkdir(struct nameidata *ndp, struct nfsvattr *nvap, uid_t saved_uid, 1343 struct ucred *cred, struct thread *p, struct nfsexstuff *exp) 1344 { 1345 int error = 0; 1346 1347 if (ndp->ni_vp != NULL) { 1348 if (ndp->ni_dvp == ndp->ni_vp) 1349 vrele(ndp->ni_dvp); 1350 else 1351 vput(ndp->ni_dvp); 1352 vrele(ndp->ni_vp); 1353 nfsvno_relpathbuf(ndp); 1354 error = EEXIST; 1355 goto out; 1356 } 1357 error = VOP_MKDIR(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, 1358 &nvap->na_vattr); 1359 VOP_VPUT_PAIR(ndp->ni_dvp, error == 0 ? &ndp->ni_vp : NULL, false); 1360 nfsvno_relpathbuf(ndp); 1361 1362 out: 1363 NFSEXITCODE(error); 1364 return (error); 1365 } 1366 1367 /* 1368 * symlink vnode op. 1369 */ 1370 int 1371 nfsvno_symlink(struct nameidata *ndp, struct nfsvattr *nvap, char *pathcp, 1372 int pathlen, int not_v2, uid_t saved_uid, struct ucred *cred, struct thread *p, 1373 struct nfsexstuff *exp) 1374 { 1375 int error = 0; 1376 1377 if (ndp->ni_vp) { 1378 nfsvno_relpathbuf(ndp); 1379 if (ndp->ni_dvp == ndp->ni_vp) 1380 vrele(ndp->ni_dvp); 1381 else 1382 vput(ndp->ni_dvp); 1383 vrele(ndp->ni_vp); 1384 error = EEXIST; 1385 goto out; 1386 } 1387 1388 error = VOP_SYMLINK(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, 1389 &nvap->na_vattr, pathcp); 1390 /* 1391 * Although FreeBSD still had the lookup code in 1392 * it for 7/current, there doesn't seem to be any 1393 * point, since VOP_SYMLINK() returns the ni_vp. 1394 * Just vput it for v2. 1395 */ 1396 VOP_VPUT_PAIR(ndp->ni_dvp, &ndp->ni_vp, !not_v2 && error == 0); 1397 nfsvno_relpathbuf(ndp); 1398 1399 out: 1400 NFSEXITCODE(error); 1401 return (error); 1402 } 1403 1404 /* 1405 * Parse symbolic link arguments. 1406 * This function has an ugly side effect. It will malloc() an area for 1407 * the symlink and set iov_base to point to it, only if it succeeds. 1408 * So, if it returns with uiop->uio_iov->iov_base != NULL, that must 1409 * be FREE'd later. 1410 */ 1411 int 1412 nfsvno_getsymlink(struct nfsrv_descript *nd, struct nfsvattr *nvap, 1413 struct thread *p, char **pathcpp, int *lenp) 1414 { 1415 u_int32_t *tl; 1416 char *pathcp = NULL; 1417 int error = 0, len; 1418 struct nfsv2_sattr *sp; 1419 1420 *pathcpp = NULL; 1421 *lenp = 0; 1422 if ((nd->nd_flag & ND_NFSV3) && 1423 (error = nfsrv_sattr(nd, NULL, nvap, NULL, NULL, p))) 1424 goto nfsmout; 1425 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1426 len = fxdr_unsigned(int, *tl); 1427 if (len > NFS_MAXPATHLEN || len <= 0) { 1428 error = EBADRPC; 1429 goto nfsmout; 1430 } 1431 pathcp = malloc(len + 1, M_TEMP, M_WAITOK); 1432 error = nfsrv_mtostr(nd, pathcp, len); 1433 if (error) 1434 goto nfsmout; 1435 if (nd->nd_flag & ND_NFSV2) { 1436 NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1437 nvap->na_mode = fxdr_unsigned(u_int16_t, sp->sa_mode); 1438 } 1439 *pathcpp = pathcp; 1440 *lenp = len; 1441 NFSEXITCODE2(0, nd); 1442 return (0); 1443 nfsmout: 1444 if (pathcp) 1445 free(pathcp, M_TEMP); 1446 NFSEXITCODE2(error, nd); 1447 return (error); 1448 } 1449 1450 /* 1451 * Remove a non-directory object. 1452 */ 1453 int 1454 nfsvno_removesub(struct nameidata *ndp, int is_v4, struct ucred *cred, 1455 struct thread *p, struct nfsexstuff *exp) 1456 { 1457 struct vnode *vp, *dsdvp[NFSDEV_MAXMIRRORS]; 1458 int error = 0, mirrorcnt; 1459 char fname[PNFS_FILENAME_LEN + 1]; 1460 fhandle_t fh; 1461 1462 vp = ndp->ni_vp; 1463 dsdvp[0] = NULL; 1464 if (vp->v_type == VDIR) 1465 error = NFSERR_ISDIR; 1466 else if (is_v4) 1467 error = nfsrv_checkremove(vp, 1, NULL, (nfsquad_t)((u_quad_t)0), 1468 p); 1469 if (error == 0) 1470 nfsrv_pnfsremovesetup(vp, p, dsdvp, &mirrorcnt, fname, &fh); 1471 if (!error) 1472 error = VOP_REMOVE(ndp->ni_dvp, vp, &ndp->ni_cnd); 1473 if (error == 0 && dsdvp[0] != NULL) 1474 nfsrv_pnfsremove(dsdvp, mirrorcnt, fname, &fh, p); 1475 if (ndp->ni_dvp == vp) 1476 vrele(ndp->ni_dvp); 1477 else 1478 vput(ndp->ni_dvp); 1479 vput(vp); 1480 nfsvno_relpathbuf(ndp); 1481 NFSEXITCODE(error); 1482 return (error); 1483 } 1484 1485 /* 1486 * Remove a directory. 1487 */ 1488 int 1489 nfsvno_rmdirsub(struct nameidata *ndp, int is_v4, struct ucred *cred, 1490 struct thread *p, struct nfsexstuff *exp) 1491 { 1492 struct vnode *vp; 1493 int error = 0; 1494 1495 vp = ndp->ni_vp; 1496 if (vp->v_type != VDIR) { 1497 error = ENOTDIR; 1498 goto out; 1499 } 1500 /* 1501 * No rmdir "." please. 1502 */ 1503 if (ndp->ni_dvp == vp) { 1504 error = EINVAL; 1505 goto out; 1506 } 1507 /* 1508 * The root of a mounted filesystem cannot be deleted. 1509 */ 1510 if (vp->v_vflag & VV_ROOT) 1511 error = EBUSY; 1512 out: 1513 if (!error) 1514 error = VOP_RMDIR(ndp->ni_dvp, vp, &ndp->ni_cnd); 1515 if (ndp->ni_dvp == vp) 1516 vrele(ndp->ni_dvp); 1517 else 1518 vput(ndp->ni_dvp); 1519 vput(vp); 1520 nfsvno_relpathbuf(ndp); 1521 NFSEXITCODE(error); 1522 return (error); 1523 } 1524 1525 /* 1526 * Rename vnode op. 1527 */ 1528 int 1529 nfsvno_rename(struct nameidata *fromndp, struct nameidata *tondp, 1530 u_int32_t ndstat, u_int32_t ndflag, struct ucred *cred, struct thread *p) 1531 { 1532 struct vnode *fvp, *tvp, *tdvp, *dsdvp[NFSDEV_MAXMIRRORS]; 1533 int error = 0, mirrorcnt; 1534 char fname[PNFS_FILENAME_LEN + 1]; 1535 fhandle_t fh; 1536 1537 dsdvp[0] = NULL; 1538 fvp = fromndp->ni_vp; 1539 if (ndstat) { 1540 vrele(fromndp->ni_dvp); 1541 vrele(fvp); 1542 error = ndstat; 1543 goto out1; 1544 } 1545 tdvp = tondp->ni_dvp; 1546 tvp = tondp->ni_vp; 1547 if (tvp != NULL) { 1548 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1549 error = (ndflag & ND_NFSV2) ? EISDIR : EEXIST; 1550 goto out; 1551 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1552 error = (ndflag & ND_NFSV2) ? ENOTDIR : EEXIST; 1553 goto out; 1554 } 1555 if (tvp->v_type == VDIR && tvp->v_mountedhere) { 1556 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1557 goto out; 1558 } 1559 1560 /* 1561 * A rename to '.' or '..' results in a prematurely 1562 * unlocked vnode on FreeBSD5, so I'm just going to fail that 1563 * here. 1564 */ 1565 if ((tondp->ni_cnd.cn_namelen == 1 && 1566 tondp->ni_cnd.cn_nameptr[0] == '.') || 1567 (tondp->ni_cnd.cn_namelen == 2 && 1568 tondp->ni_cnd.cn_nameptr[0] == '.' && 1569 tondp->ni_cnd.cn_nameptr[1] == '.')) { 1570 error = EINVAL; 1571 goto out; 1572 } 1573 } 1574 if (fvp->v_type == VDIR && fvp->v_mountedhere) { 1575 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1576 goto out; 1577 } 1578 if (fvp->v_mount != tdvp->v_mount) { 1579 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1580 goto out; 1581 } 1582 if (fvp == tdvp) { 1583 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EINVAL; 1584 goto out; 1585 } 1586 if (fvp == tvp) { 1587 /* 1588 * If source and destination are the same, there is nothing to 1589 * do. Set error to -1 to indicate this. 1590 */ 1591 error = -1; 1592 goto out; 1593 } 1594 if (ndflag & ND_NFSV4) { 1595 if (NFSVOPLOCK(fvp, LK_EXCLUSIVE) == 0) { 1596 error = nfsrv_checkremove(fvp, 0, NULL, 1597 (nfsquad_t)((u_quad_t)0), p); 1598 NFSVOPUNLOCK(fvp); 1599 } else 1600 error = EPERM; 1601 if (tvp && !error) 1602 error = nfsrv_checkremove(tvp, 1, NULL, 1603 (nfsquad_t)((u_quad_t)0), p); 1604 } else { 1605 /* 1606 * For NFSv2 and NFSv3, try to get rid of the delegation, so 1607 * that the NFSv4 client won't be confused by the rename. 1608 * Since nfsd_recalldelegation() can only be called on an 1609 * unlocked vnode at this point and fvp is the file that will 1610 * still exist after the rename, just do fvp. 1611 */ 1612 nfsd_recalldelegation(fvp, p); 1613 } 1614 if (error == 0 && tvp != NULL) { 1615 nfsrv_pnfsremovesetup(tvp, p, dsdvp, &mirrorcnt, fname, &fh); 1616 NFSD_DEBUG(4, "nfsvno_rename: pnfsremovesetup" 1617 " dsdvp=%p\n", dsdvp[0]); 1618 } 1619 out: 1620 if (!error) { 1621 error = VOP_RENAME(fromndp->ni_dvp, fromndp->ni_vp, 1622 &fromndp->ni_cnd, tondp->ni_dvp, tondp->ni_vp, 1623 &tondp->ni_cnd); 1624 } else { 1625 if (tdvp == tvp) 1626 vrele(tdvp); 1627 else 1628 vput(tdvp); 1629 if (tvp) 1630 vput(tvp); 1631 vrele(fromndp->ni_dvp); 1632 vrele(fvp); 1633 if (error == -1) 1634 error = 0; 1635 } 1636 1637 /* 1638 * If dsdvp[0] != NULL, it was set up by nfsrv_pnfsremovesetup() and 1639 * if the rename succeeded, the DS file for the tvp needs to be 1640 * removed. 1641 */ 1642 if (error == 0 && dsdvp[0] != NULL) { 1643 nfsrv_pnfsremove(dsdvp, mirrorcnt, fname, &fh, p); 1644 NFSD_DEBUG(4, "nfsvno_rename: pnfsremove\n"); 1645 } 1646 1647 nfsvno_relpathbuf(tondp); 1648 out1: 1649 nfsvno_relpathbuf(fromndp); 1650 NFSEXITCODE(error); 1651 return (error); 1652 } 1653 1654 /* 1655 * Link vnode op. 1656 */ 1657 int 1658 nfsvno_link(struct nameidata *ndp, struct vnode *vp, nfsquad_t clientid, 1659 struct ucred *cred, struct thread *p, struct nfsexstuff *exp) 1660 { 1661 struct vnode *xp; 1662 int error = 0; 1663 1664 xp = ndp->ni_vp; 1665 if (xp != NULL) { 1666 error = EEXIST; 1667 } else { 1668 xp = ndp->ni_dvp; 1669 if (vp->v_mount != xp->v_mount) 1670 error = EXDEV; 1671 } 1672 if (!error) { 1673 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 1674 if (!VN_IS_DOOMED(vp)) { 1675 error = nfsrv_checkremove(vp, 0, NULL, clientid, p); 1676 if (error == 0) 1677 error = VOP_LINK(ndp->ni_dvp, vp, &ndp->ni_cnd); 1678 } else 1679 error = EPERM; 1680 if (ndp->ni_dvp == vp) { 1681 vrele(ndp->ni_dvp); 1682 NFSVOPUNLOCK(vp); 1683 } else { 1684 vref(vp); 1685 VOP_VPUT_PAIR(ndp->ni_dvp, &vp, true); 1686 } 1687 } else { 1688 if (ndp->ni_dvp == ndp->ni_vp) 1689 vrele(ndp->ni_dvp); 1690 else 1691 vput(ndp->ni_dvp); 1692 if (ndp->ni_vp) 1693 vrele(ndp->ni_vp); 1694 } 1695 nfsvno_relpathbuf(ndp); 1696 NFSEXITCODE(error); 1697 return (error); 1698 } 1699 1700 /* 1701 * Do the fsync() appropriate for the commit. 1702 */ 1703 int 1704 nfsvno_fsync(struct vnode *vp, u_int64_t off, int cnt, struct ucred *cred, 1705 struct thread *td) 1706 { 1707 int error = 0; 1708 1709 /* 1710 * RFC 1813 3.3.21: if count is 0, a flush from offset to the end of 1711 * file is done. At this time VOP_FSYNC does not accept offset and 1712 * byte count parameters so call VOP_FSYNC the whole file for now. 1713 * The same is true for NFSv4: RFC 3530 Sec. 14.2.3. 1714 * File systems that do not use the buffer cache (as indicated 1715 * by MNTK_USES_BCACHE not being set) must use VOP_FSYNC(). 1716 */ 1717 if (cnt == 0 || cnt > MAX_COMMIT_COUNT || 1718 (vp->v_mount->mnt_kern_flag & MNTK_USES_BCACHE) == 0) { 1719 /* 1720 * Give up and do the whole thing 1721 */ 1722 vnode_pager_clean_sync(vp); 1723 error = VOP_FSYNC(vp, MNT_WAIT, td); 1724 } else { 1725 /* 1726 * Locate and synchronously write any buffers that fall 1727 * into the requested range. Note: we are assuming that 1728 * f_iosize is a power of 2. 1729 */ 1730 int iosize = vp->v_mount->mnt_stat.f_iosize; 1731 int iomask = iosize - 1; 1732 struct bufobj *bo; 1733 daddr_t lblkno; 1734 1735 /* 1736 * Align to iosize boundary, super-align to page boundary. 1737 */ 1738 if (off & iomask) { 1739 cnt += off & iomask; 1740 off &= ~(u_quad_t)iomask; 1741 } 1742 if (off & PAGE_MASK) { 1743 cnt += off & PAGE_MASK; 1744 off &= ~(u_quad_t)PAGE_MASK; 1745 } 1746 lblkno = off / iosize; 1747 1748 if (vp->v_object && vm_object_mightbedirty(vp->v_object)) { 1749 VM_OBJECT_WLOCK(vp->v_object); 1750 vm_object_page_clean(vp->v_object, off, off + cnt, 1751 OBJPC_SYNC); 1752 VM_OBJECT_WUNLOCK(vp->v_object); 1753 } 1754 1755 bo = &vp->v_bufobj; 1756 BO_LOCK(bo); 1757 while (cnt > 0) { 1758 struct buf *bp; 1759 1760 /* 1761 * If we have a buffer and it is marked B_DELWRI we 1762 * have to lock and write it. Otherwise the prior 1763 * write is assumed to have already been committed. 1764 * 1765 * gbincore() can return invalid buffers now so we 1766 * have to check that bit as well (though B_DELWRI 1767 * should not be set if B_INVAL is set there could be 1768 * a race here since we haven't locked the buffer). 1769 */ 1770 if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) { 1771 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL | 1772 LK_INTERLOCK, BO_LOCKPTR(bo)) == ENOLCK) { 1773 BO_LOCK(bo); 1774 continue; /* retry */ 1775 } 1776 if ((bp->b_flags & (B_DELWRI|B_INVAL)) == 1777 B_DELWRI) { 1778 bremfree(bp); 1779 bp->b_flags &= ~B_ASYNC; 1780 bwrite(bp); 1781 ++nfs_commit_miss; 1782 } else 1783 BUF_UNLOCK(bp); 1784 BO_LOCK(bo); 1785 } 1786 ++nfs_commit_blks; 1787 if (cnt < iosize) 1788 break; 1789 cnt -= iosize; 1790 ++lblkno; 1791 } 1792 BO_UNLOCK(bo); 1793 } 1794 NFSEXITCODE(error); 1795 return (error); 1796 } 1797 1798 /* 1799 * Statfs vnode op. 1800 */ 1801 int 1802 nfsvno_statfs(struct vnode *vp, struct statfs *sf) 1803 { 1804 struct statfs *tsf; 1805 int error; 1806 1807 tsf = NULL; 1808 if (nfsrv_devidcnt > 0) { 1809 /* For a pNFS service, get the DS numbers. */ 1810 tsf = malloc(sizeof(*tsf), M_TEMP, M_WAITOK | M_ZERO); 1811 error = nfsrv_pnfsstatfs(tsf, vp->v_mount); 1812 if (error != 0) { 1813 free(tsf, M_TEMP); 1814 tsf = NULL; 1815 } 1816 } 1817 error = VFS_STATFS(vp->v_mount, sf); 1818 if (error == 0) { 1819 if (tsf != NULL) { 1820 sf->f_blocks = tsf->f_blocks; 1821 sf->f_bavail = tsf->f_bavail; 1822 sf->f_bfree = tsf->f_bfree; 1823 sf->f_bsize = tsf->f_bsize; 1824 } 1825 /* 1826 * Since NFS handles these values as unsigned on the 1827 * wire, there is no way to represent negative values, 1828 * so set them to 0. Without this, they will appear 1829 * to be very large positive values for clients like 1830 * Solaris10. 1831 */ 1832 if (sf->f_bavail < 0) 1833 sf->f_bavail = 0; 1834 if (sf->f_ffree < 0) 1835 sf->f_ffree = 0; 1836 } 1837 free(tsf, M_TEMP); 1838 NFSEXITCODE(error); 1839 return (error); 1840 } 1841 1842 /* 1843 * Do the vnode op stuff for Open. Similar to nfsvno_createsub(), but 1844 * must handle nfsrv_opencheck() calls after any other access checks. 1845 */ 1846 void 1847 nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp, 1848 nfsquad_t clientid, nfsv4stateid_t *stateidp, struct nfsstate *stp, 1849 int *exclusive_flagp, struct nfsvattr *nvap, int32_t *cverf, int create, 1850 NFSACL_T *aclp, nfsattrbit_t *attrbitp, struct ucred *cred, bool done_namei, 1851 struct nfsexstuff *exp, struct vnode **vpp) 1852 { 1853 struct vnode *vp = NULL; 1854 u_quad_t tempsize; 1855 struct nfsexstuff nes; 1856 struct thread *p = curthread; 1857 uint32_t oldrepstat; 1858 1859 if (ndp->ni_vp == NULL) { 1860 /* 1861 * If nfsrv_opencheck() sets nd_repstat, done_namei needs to be 1862 * set true, since cleanup after nfsvno_namei() is needed. 1863 */ 1864 oldrepstat = nd->nd_repstat; 1865 nd->nd_repstat = nfsrv_opencheck(clientid, 1866 stateidp, stp, NULL, nd, p, nd->nd_repstat); 1867 if (nd->nd_repstat != 0 && oldrepstat == 0) 1868 done_namei = true; 1869 } 1870 if (!nd->nd_repstat) { 1871 if (ndp->ni_vp == NULL) { 1872 nd->nd_repstat = VOP_CREATE(ndp->ni_dvp, 1873 &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr); 1874 /* For a pNFS server, create the data file on a DS. */ 1875 if (nd->nd_repstat == 0) { 1876 /* 1877 * Create a data file on a DS for a pNFS server. 1878 * This function just returns if not 1879 * running a pNFS DS or the creation fails. 1880 */ 1881 nfsrv_pnfscreate(ndp->ni_vp, &nvap->na_vattr, 1882 cred, p); 1883 } 1884 VOP_VPUT_PAIR(ndp->ni_dvp, nd->nd_repstat == 0 ? 1885 &ndp->ni_vp : NULL, false); 1886 nfsvno_relpathbuf(ndp); 1887 if (!nd->nd_repstat) { 1888 if (*exclusive_flagp) { 1889 *exclusive_flagp = 0; 1890 NFSVNO_ATTRINIT(nvap); 1891 nvap->na_atime.tv_sec = cverf[0]; 1892 nvap->na_atime.tv_nsec = cverf[1]; 1893 nd->nd_repstat = VOP_SETATTR(ndp->ni_vp, 1894 &nvap->na_vattr, cred); 1895 if (nd->nd_repstat != 0) { 1896 vput(ndp->ni_vp); 1897 ndp->ni_vp = NULL; 1898 nd->nd_repstat = NFSERR_NOTSUPP; 1899 } else 1900 NFSSETBIT_ATTRBIT(attrbitp, 1901 NFSATTRBIT_TIMEACCESS); 1902 } else { 1903 nfsrv_fixattr(nd, ndp->ni_vp, nvap, 1904 aclp, p, attrbitp, exp); 1905 } 1906 } 1907 vp = ndp->ni_vp; 1908 } else { 1909 nfsvno_relpathbuf(ndp); 1910 vp = ndp->ni_vp; 1911 if (create == NFSV4OPEN_CREATE) { 1912 if (ndp->ni_dvp == vp) 1913 vrele(ndp->ni_dvp); 1914 else 1915 vput(ndp->ni_dvp); 1916 } 1917 if (NFSVNO_ISSETSIZE(nvap) && vp->v_type == VREG) { 1918 if (ndp->ni_cnd.cn_flags & RDONLY) 1919 NFSVNO_SETEXRDONLY(&nes); 1920 else 1921 NFSVNO_EXINIT(&nes); 1922 nd->nd_repstat = nfsvno_accchk(vp, 1923 VWRITE, cred, &nes, p, 1924 NFSACCCHK_NOOVERRIDE, 1925 NFSACCCHK_VPISLOCKED, NULL); 1926 nd->nd_repstat = nfsrv_opencheck(clientid, 1927 stateidp, stp, vp, nd, p, nd->nd_repstat); 1928 if (!nd->nd_repstat) { 1929 tempsize = nvap->na_size; 1930 NFSVNO_ATTRINIT(nvap); 1931 nvap->na_size = tempsize; 1932 nd->nd_repstat = nfsvno_setattr(vp, 1933 nvap, cred, p, exp); 1934 } 1935 } else if (vp->v_type == VREG) { 1936 nd->nd_repstat = nfsrv_opencheck(clientid, 1937 stateidp, stp, vp, nd, p, nd->nd_repstat); 1938 } 1939 } 1940 } else if (done_namei) { 1941 KASSERT(create == NFSV4OPEN_CREATE, 1942 ("nfsvno_open: not create")); 1943 /* 1944 * done_namei is set when nfsvno_namei() has completed 1945 * successfully, but a subsequent error was set in 1946 * nd_repstat. As such, cleanup of the nfsvno_namei() 1947 * results is required. 1948 */ 1949 nfsvno_relpathbuf(ndp); 1950 if (ndp->ni_dvp == ndp->ni_vp) 1951 vrele(ndp->ni_dvp); 1952 else 1953 vput(ndp->ni_dvp); 1954 if (ndp->ni_vp) 1955 vput(ndp->ni_vp); 1956 } 1957 *vpp = vp; 1958 1959 NFSEXITCODE2(0, nd); 1960 } 1961 1962 /* 1963 * Updates the file rev and sets the mtime and ctime 1964 * to the current clock time, returning the va_filerev and va_Xtime 1965 * values. 1966 * Return ESTALE to indicate the vnode is VIRF_DOOMED. 1967 */ 1968 int 1969 nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap, 1970 struct nfsrv_descript *nd, struct thread *p) 1971 { 1972 struct vattr va; 1973 1974 VATTR_NULL(&va); 1975 vfs_timestamp(&va.va_mtime); 1976 if (NFSVOPISLOCKED(vp) != LK_EXCLUSIVE) { 1977 NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); 1978 if (VN_IS_DOOMED(vp)) 1979 return (ESTALE); 1980 } 1981 (void) VOP_SETATTR(vp, &va, nd->nd_cred); 1982 (void) nfsvno_getattr(vp, nvap, nd, p, 1, NULL); 1983 return (0); 1984 } 1985 1986 /* 1987 * Glue routine to nfsv4_fillattr(). 1988 */ 1989 int 1990 nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp, 1991 struct nfsvattr *nvap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp, 1992 struct ucred *cred, struct thread *p, int isdgram, int reterr, 1993 int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno) 1994 { 1995 struct statfs *sf; 1996 int error; 1997 1998 sf = NULL; 1999 if (nfsrv_devidcnt > 0 && 2000 (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACEAVAIL) || 2001 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACEFREE) || 2002 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACETOTAL))) { 2003 sf = malloc(sizeof(*sf), M_TEMP, M_WAITOK | M_ZERO); 2004 error = nfsrv_pnfsstatfs(sf, mp); 2005 if (error != 0) { 2006 free(sf, M_TEMP); 2007 sf = NULL; 2008 } 2009 } 2010 error = nfsv4_fillattr(nd, mp, vp, NULL, &nvap->na_vattr, fhp, rderror, 2011 attrbitp, cred, p, isdgram, reterr, supports_nfsv4acls, at_root, 2012 mounted_on_fileno, sf); 2013 free(sf, M_TEMP); 2014 NFSEXITCODE2(0, nd); 2015 return (error); 2016 } 2017 2018 /* Since the Readdir vnode ops vary, put the entire functions in here. */ 2019 /* 2020 * nfs readdir service 2021 * - mallocs what it thinks is enough to read 2022 * count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR 2023 * - calls VOP_READDIR() 2024 * - loops around building the reply 2025 * if the output generated exceeds count break out of loop 2026 * The NFSM_CLGET macro is used here so that the reply will be packed 2027 * tightly in mbuf clusters. 2028 * - it trims out records with d_fileno == 0 2029 * this doesn't matter for Unix clients, but they might confuse clients 2030 * for other os'. 2031 * - it trims out records with d_type == DT_WHT 2032 * these cannot be seen through NFS (unless we extend the protocol) 2033 * The alternate call nfsrvd_readdirplus() does lookups as well. 2034 * PS: The NFS protocol spec. does not clarify what the "count" byte 2035 * argument is a count of.. just name strings and file id's or the 2036 * entire reply rpc or ... 2037 * I tried just file name and id sizes and it confused the Sun client, 2038 * so I am using the full rpc size now. The "paranoia.." comment refers 2039 * to including the status longwords that are not a part of the dir. 2040 * "entry" structures, but are in the rpc. 2041 */ 2042 int 2043 nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram, 2044 struct vnode *vp, struct nfsexstuff *exp) 2045 { 2046 struct dirent *dp; 2047 u_int32_t *tl; 2048 int dirlen; 2049 char *cpos, *cend, *rbuf; 2050 struct nfsvattr at; 2051 int nlen, error = 0, getret = 1; 2052 int siz, cnt, fullsiz, eofflag, ncookies; 2053 u_int64_t off, toff, verf __unused; 2054 uint64_t *cookies = NULL, *cookiep; 2055 struct uio io; 2056 struct iovec iv; 2057 int is_ufs; 2058 struct thread *p = curthread; 2059 2060 if (nd->nd_repstat) { 2061 nfsrv_postopattr(nd, getret, &at); 2062 goto out; 2063 } 2064 if (nd->nd_flag & ND_NFSV2) { 2065 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2066 off = fxdr_unsigned(u_quad_t, *tl++); 2067 } else { 2068 NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2069 off = fxdr_hyper(tl); 2070 tl += 2; 2071 verf = fxdr_hyper(tl); 2072 tl += 2; 2073 } 2074 toff = off; 2075 cnt = fxdr_unsigned(int, *tl); 2076 if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0) 2077 cnt = NFS_SRVMAXDATA(nd); 2078 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 2079 fullsiz = siz; 2080 if (nd->nd_flag & ND_NFSV3) { 2081 nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd, p, 1, 2082 NULL); 2083 #if 0 2084 /* 2085 * va_filerev is not sufficient as a cookie verifier, 2086 * since it is not supposed to change when entries are 2087 * removed/added unless that offset cookies returned to 2088 * the client are no longer valid. 2089 */ 2090 if (!nd->nd_repstat && toff && verf != at.na_filerev) 2091 nd->nd_repstat = NFSERR_BAD_COOKIE; 2092 #endif 2093 } 2094 if (!nd->nd_repstat && vp->v_type != VDIR) 2095 nd->nd_repstat = NFSERR_NOTDIR; 2096 if (nd->nd_repstat == 0 && cnt == 0) { 2097 if (nd->nd_flag & ND_NFSV2) 2098 /* NFSv2 does not have NFSERR_TOOSMALL */ 2099 nd->nd_repstat = EPERM; 2100 else 2101 nd->nd_repstat = NFSERR_TOOSMALL; 2102 } 2103 if (!nd->nd_repstat) 2104 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 2105 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 2106 NFSACCCHK_VPISLOCKED, NULL); 2107 if (nd->nd_repstat) { 2108 vput(vp); 2109 if (nd->nd_flag & ND_NFSV3) 2110 nfsrv_postopattr(nd, getret, &at); 2111 goto out; 2112 } 2113 is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0; 2114 rbuf = malloc(siz, M_TEMP, M_WAITOK); 2115 again: 2116 eofflag = 0; 2117 if (cookies) { 2118 free(cookies, M_TEMP); 2119 cookies = NULL; 2120 } 2121 2122 iv.iov_base = rbuf; 2123 iv.iov_len = siz; 2124 io.uio_iov = &iv; 2125 io.uio_iovcnt = 1; 2126 io.uio_offset = (off_t)off; 2127 io.uio_resid = siz; 2128 io.uio_segflg = UIO_SYSSPACE; 2129 io.uio_rw = UIO_READ; 2130 io.uio_td = NULL; 2131 nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies, 2132 &cookies); 2133 off = (u_int64_t)io.uio_offset; 2134 if (io.uio_resid) 2135 siz -= io.uio_resid; 2136 2137 if (!cookies && !nd->nd_repstat) 2138 nd->nd_repstat = NFSERR_PERM; 2139 if (nd->nd_flag & ND_NFSV3) { 2140 getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL); 2141 if (!nd->nd_repstat) 2142 nd->nd_repstat = getret; 2143 } 2144 2145 /* 2146 * Handles the failed cases. nd->nd_repstat == 0 past here. 2147 */ 2148 if (nd->nd_repstat) { 2149 vput(vp); 2150 free(rbuf, M_TEMP); 2151 if (cookies) 2152 free(cookies, M_TEMP); 2153 if (nd->nd_flag & ND_NFSV3) 2154 nfsrv_postopattr(nd, getret, &at); 2155 goto out; 2156 } 2157 /* 2158 * If nothing read, return eof 2159 * rpc reply 2160 */ 2161 if (siz == 0) { 2162 vput(vp); 2163 if (nd->nd_flag & ND_NFSV2) { 2164 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2165 } else { 2166 nfsrv_postopattr(nd, getret, &at); 2167 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 2168 txdr_hyper(at.na_filerev, tl); 2169 tl += 2; 2170 } 2171 *tl++ = newnfs_false; 2172 *tl = newnfs_true; 2173 free(rbuf, M_TEMP); 2174 free(cookies, M_TEMP); 2175 goto out; 2176 } 2177 2178 /* 2179 * Check for degenerate cases of nothing useful read. 2180 * If so go try again 2181 */ 2182 cpos = rbuf; 2183 cend = rbuf + siz; 2184 dp = (struct dirent *)cpos; 2185 cookiep = cookies; 2186 2187 /* 2188 * For some reason FreeBSD's ufs_readdir() chooses to back the 2189 * directory offset up to a block boundary, so it is necessary to 2190 * skip over the records that precede the requested offset. This 2191 * requires the assumption that file offset cookies monotonically 2192 * increase. 2193 */ 2194 while (cpos < cend && ncookies > 0 && 2195 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 2196 (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff))) { 2197 cpos += dp->d_reclen; 2198 dp = (struct dirent *)cpos; 2199 cookiep++; 2200 ncookies--; 2201 } 2202 if (cpos >= cend || ncookies == 0) { 2203 siz = fullsiz; 2204 toff = off; 2205 goto again; 2206 } 2207 vput(vp); 2208 2209 /* 2210 * If cnt > MCLBYTES and the reply will not be saved, use 2211 * ext_pgs mbufs for TLS. 2212 * For NFSv4.0, we do not know for sure if the reply will 2213 * be saved, so do not use ext_pgs mbufs for NFSv4.0. 2214 */ 2215 if (cnt > MCLBYTES && siz > MCLBYTES && 2216 (nd->nd_flag & (ND_TLS | ND_EXTPG | ND_SAVEREPLY)) == ND_TLS && 2217 (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4) 2218 nd->nd_flag |= ND_EXTPG; 2219 2220 /* 2221 * dirlen is the size of the reply, including all XDR and must 2222 * not exceed cnt. For NFSv2, RFC1094 didn't clearly indicate 2223 * if the XDR should be included in "count", but to be safe, we do. 2224 * (Include the two booleans at the end of the reply in dirlen now.) 2225 */ 2226 if (nd->nd_flag & ND_NFSV3) { 2227 nfsrv_postopattr(nd, getret, &at); 2228 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2229 txdr_hyper(at.na_filerev, tl); 2230 dirlen = NFSX_V3POSTOPATTR + NFSX_VERF + 2 * NFSX_UNSIGNED; 2231 } else { 2232 dirlen = 2 * NFSX_UNSIGNED; 2233 } 2234 2235 /* Loop through the records and build reply */ 2236 while (cpos < cend && ncookies > 0) { 2237 nlen = dp->d_namlen; 2238 if (dp->d_fileno != 0 && dp->d_type != DT_WHT && 2239 nlen <= NFS_MAXNAMLEN) { 2240 if (nd->nd_flag & ND_NFSV3) 2241 dirlen += (6*NFSX_UNSIGNED + NFSM_RNDUP(nlen)); 2242 else 2243 dirlen += (4*NFSX_UNSIGNED + NFSM_RNDUP(nlen)); 2244 if (dirlen > cnt) { 2245 eofflag = 0; 2246 break; 2247 } 2248 2249 /* 2250 * Build the directory record xdr from 2251 * the dirent entry. 2252 */ 2253 if (nd->nd_flag & ND_NFSV3) { 2254 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2255 *tl++ = newnfs_true; 2256 txdr_hyper(dp->d_fileno, tl); 2257 } else { 2258 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2259 *tl++ = newnfs_true; 2260 *tl = txdr_unsigned(dp->d_fileno); 2261 } 2262 (void) nfsm_strtom(nd, dp->d_name, nlen); 2263 if (nd->nd_flag & ND_NFSV3) { 2264 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2265 txdr_hyper(*cookiep, tl); 2266 } else { 2267 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 2268 *tl = txdr_unsigned(*cookiep); 2269 } 2270 } 2271 cpos += dp->d_reclen; 2272 dp = (struct dirent *)cpos; 2273 cookiep++; 2274 ncookies--; 2275 } 2276 if (cpos < cend) 2277 eofflag = 0; 2278 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2279 *tl++ = newnfs_false; 2280 if (eofflag) 2281 *tl = newnfs_true; 2282 else 2283 *tl = newnfs_false; 2284 free(rbuf, M_TEMP); 2285 free(cookies, M_TEMP); 2286 2287 out: 2288 NFSEXITCODE2(0, nd); 2289 return (0); 2290 nfsmout: 2291 vput(vp); 2292 NFSEXITCODE2(error, nd); 2293 return (error); 2294 } 2295 2296 /* 2297 * Readdirplus for V3 and Readdir for V4. 2298 */ 2299 int 2300 nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, 2301 struct vnode *vp, struct nfsexstuff *exp) 2302 { 2303 struct dirent *dp; 2304 u_int32_t *tl; 2305 int dirlen; 2306 char *cpos, *cend, *rbuf; 2307 struct vnode *nvp; 2308 fhandle_t nfh; 2309 struct nfsvattr nva, at, *nvap = &nva; 2310 struct mbuf *mb0, *mb1; 2311 struct nfsreferral *refp; 2312 int nlen, r, error = 0, getret = 1, usevget = 1; 2313 int siz, cnt, fullsiz, eofflag, ncookies, entrycnt; 2314 caddr_t bpos0, bpos1; 2315 u_int64_t off, toff, verf __unused; 2316 uint64_t *cookies = NULL, *cookiep; 2317 nfsattrbit_t attrbits, rderrbits, savbits, refbits; 2318 struct uio io; 2319 struct iovec iv; 2320 struct componentname cn; 2321 int at_root, is_ufs, is_zfs, needs_unbusy, supports_nfsv4acls; 2322 struct mount *mp, *new_mp; 2323 uint64_t mounted_on_fileno; 2324 struct thread *p = curthread; 2325 int bextpg0, bextpg1, bextpgsiz0, bextpgsiz1; 2326 2327 if (nd->nd_repstat) { 2328 nfsrv_postopattr(nd, getret, &at); 2329 goto out; 2330 } 2331 NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 2332 off = fxdr_hyper(tl); 2333 toff = off; 2334 tl += 2; 2335 verf = fxdr_hyper(tl); 2336 tl += 2; 2337 siz = fxdr_unsigned(int, *tl++); 2338 cnt = fxdr_unsigned(int, *tl); 2339 2340 /* 2341 * Use the server's maximum data transfer size as the upper bound 2342 * on reply datalen. 2343 */ 2344 if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0) 2345 cnt = NFS_SRVMAXDATA(nd); 2346 2347 /* 2348 * siz is a "hint" of how much directory information (name, fileid, 2349 * cookie) should be in the reply. At least one client "hints" 0, 2350 * so I set it to cnt for that case. I also round it up to the 2351 * next multiple of DIRBLKSIZ. 2352 * Since the size of a Readdirplus directory entry reply will always 2353 * be greater than a directory entry returned by VOP_READDIR(), it 2354 * does not make sense to read more than NFS_SRVMAXDATA() via 2355 * VOP_READDIR(). 2356 */ 2357 if (siz <= 0) 2358 siz = cnt; 2359 else if (siz > NFS_SRVMAXDATA(nd)) 2360 siz = NFS_SRVMAXDATA(nd); 2361 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 2362 2363 if (nd->nd_flag & ND_NFSV4) { 2364 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL); 2365 if (error) 2366 goto nfsmout; 2367 NFSSET_ATTRBIT(&savbits, &attrbits); 2368 NFSSET_ATTRBIT(&refbits, &attrbits); 2369 NFSCLRNOTFILLABLE_ATTRBIT(&attrbits, nd); 2370 NFSZERO_ATTRBIT(&rderrbits); 2371 NFSSETBIT_ATTRBIT(&rderrbits, NFSATTRBIT_RDATTRERROR); 2372 /* 2373 * If these 4 bits are the only attributes requested by the 2374 * client, they can be satisfied without acquiring the vnode 2375 * for the file object unless it is a directory. 2376 * This will be indicated by savbits being all 0s. 2377 */ 2378 NFSCLRBIT_ATTRBIT(&savbits, NFSATTRBIT_TYPE); 2379 NFSCLRBIT_ATTRBIT(&savbits, NFSATTRBIT_FILEID); 2380 NFSCLRBIT_ATTRBIT(&savbits, NFSATTRBIT_MOUNTEDONFILEID); 2381 NFSCLRBIT_ATTRBIT(&savbits, NFSATTRBIT_RDATTRERROR); 2382 } else { 2383 NFSZERO_ATTRBIT(&attrbits); 2384 } 2385 fullsiz = siz; 2386 nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL); 2387 #if 0 2388 if (!nd->nd_repstat) { 2389 if (off && verf != at.na_filerev) { 2390 /* 2391 * va_filerev is not sufficient as a cookie verifier, 2392 * since it is not supposed to change when entries are 2393 * removed/added unless that offset cookies returned to 2394 * the client are no longer valid. 2395 */ 2396 if (nd->nd_flag & ND_NFSV4) { 2397 nd->nd_repstat = NFSERR_NOTSAME; 2398 } else { 2399 nd->nd_repstat = NFSERR_BAD_COOKIE; 2400 } 2401 } 2402 } 2403 #endif 2404 if (!nd->nd_repstat && vp->v_type != VDIR) 2405 nd->nd_repstat = NFSERR_NOTDIR; 2406 if (!nd->nd_repstat && cnt == 0) 2407 nd->nd_repstat = NFSERR_TOOSMALL; 2408 if (!nd->nd_repstat) 2409 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 2410 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 2411 NFSACCCHK_VPISLOCKED, NULL); 2412 if (nd->nd_repstat) { 2413 vput(vp); 2414 if (nd->nd_flag & ND_NFSV3) 2415 nfsrv_postopattr(nd, getret, &at); 2416 goto out; 2417 } 2418 is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0; 2419 is_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs") == 0; 2420 2421 rbuf = malloc(siz, M_TEMP, M_WAITOK); 2422 again: 2423 eofflag = 0; 2424 if (cookies) { 2425 free(cookies, M_TEMP); 2426 cookies = NULL; 2427 } 2428 2429 iv.iov_base = rbuf; 2430 iv.iov_len = siz; 2431 io.uio_iov = &iv; 2432 io.uio_iovcnt = 1; 2433 io.uio_offset = (off_t)off; 2434 io.uio_resid = siz; 2435 io.uio_segflg = UIO_SYSSPACE; 2436 io.uio_rw = UIO_READ; 2437 io.uio_td = NULL; 2438 nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies, 2439 &cookies); 2440 off = (u_int64_t)io.uio_offset; 2441 if (io.uio_resid) 2442 siz -= io.uio_resid; 2443 2444 getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL); 2445 2446 if (!cookies && !nd->nd_repstat) 2447 nd->nd_repstat = NFSERR_PERM; 2448 if (!nd->nd_repstat) 2449 nd->nd_repstat = getret; 2450 if (nd->nd_repstat) { 2451 vput(vp); 2452 if (cookies) 2453 free(cookies, M_TEMP); 2454 free(rbuf, M_TEMP); 2455 if (nd->nd_flag & ND_NFSV3) 2456 nfsrv_postopattr(nd, getret, &at); 2457 goto out; 2458 } 2459 /* 2460 * If nothing read, return eof 2461 * rpc reply 2462 */ 2463 if (siz == 0) { 2464 vput(vp); 2465 if (nd->nd_flag & ND_NFSV3) 2466 nfsrv_postopattr(nd, getret, &at); 2467 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 2468 txdr_hyper(at.na_filerev, tl); 2469 tl += 2; 2470 *tl++ = newnfs_false; 2471 *tl = newnfs_true; 2472 free(cookies, M_TEMP); 2473 free(rbuf, M_TEMP); 2474 goto out; 2475 } 2476 2477 /* 2478 * Check for degenerate cases of nothing useful read. 2479 * If so go try again 2480 */ 2481 cpos = rbuf; 2482 cend = rbuf + siz; 2483 dp = (struct dirent *)cpos; 2484 cookiep = cookies; 2485 2486 /* 2487 * For some reason FreeBSD's ufs_readdir() chooses to back the 2488 * directory offset up to a block boundary, so it is necessary to 2489 * skip over the records that precede the requested offset. This 2490 * requires the assumption that file offset cookies monotonically 2491 * increase. 2492 */ 2493 while (cpos < cend && ncookies > 0 && 2494 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 2495 (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff) || 2496 ((nd->nd_flag & ND_NFSV4) && 2497 ((dp->d_namlen == 1 && dp->d_name[0] == '.') || 2498 (dp->d_namlen==2 && dp->d_name[0]=='.' && dp->d_name[1]=='.'))))) { 2499 cpos += dp->d_reclen; 2500 dp = (struct dirent *)cpos; 2501 cookiep++; 2502 ncookies--; 2503 } 2504 if (cpos >= cend || ncookies == 0) { 2505 siz = fullsiz; 2506 toff = off; 2507 goto again; 2508 } 2509 2510 /* 2511 * Busy the file system so that the mount point won't go away 2512 * and, as such, VFS_VGET() can be used safely. 2513 */ 2514 mp = vp->v_mount; 2515 vfs_ref(mp); 2516 NFSVOPUNLOCK(vp); 2517 nd->nd_repstat = vfs_busy(mp, 0); 2518 vfs_rel(mp); 2519 if (nd->nd_repstat != 0) { 2520 vrele(vp); 2521 free(cookies, M_TEMP); 2522 free(rbuf, M_TEMP); 2523 if (nd->nd_flag & ND_NFSV3) 2524 nfsrv_postopattr(nd, getret, &at); 2525 goto out; 2526 } 2527 2528 /* 2529 * Check to see if entries in this directory can be safely acquired 2530 * via VFS_VGET() or if a switch to VOP_LOOKUP() is required. 2531 * ZFS snapshot directories need VOP_LOOKUP(), so that any 2532 * automount of the snapshot directory that is required will 2533 * be done. 2534 * This needs to be done here for NFSv4, since NFSv4 never does 2535 * a VFS_VGET() for "." or "..". 2536 */ 2537 if (is_zfs == 1) { 2538 r = VFS_VGET(mp, at.na_fileid, LK_SHARED, &nvp); 2539 if (r == EOPNOTSUPP) { 2540 usevget = 0; 2541 cn.cn_nameiop = LOOKUP; 2542 cn.cn_lkflags = LK_SHARED | LK_RETRY; 2543 cn.cn_cred = nd->nd_cred; 2544 } else if (r == 0) 2545 vput(nvp); 2546 } 2547 2548 /* 2549 * If the reply is likely to exceed MCLBYTES and the reply will 2550 * not be saved, use ext_pgs mbufs for TLS. 2551 * It is difficult to predict how large each entry will be and 2552 * how many entries have been read, so just assume the directory 2553 * entries grow by a factor of 4 when attributes are included. 2554 * For NFSv4.0, we do not know for sure if the reply will 2555 * be saved, so do not use ext_pgs mbufs for NFSv4.0. 2556 */ 2557 if (cnt > MCLBYTES && siz > MCLBYTES / 4 && 2558 (nd->nd_flag & (ND_TLS | ND_EXTPG | ND_SAVEREPLY)) == ND_TLS && 2559 (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4) 2560 nd->nd_flag |= ND_EXTPG; 2561 2562 /* 2563 * Save this position, in case there is an error before one entry 2564 * is created. 2565 */ 2566 mb0 = nd->nd_mb; 2567 bpos0 = nd->nd_bpos; 2568 bextpg0 = nd->nd_bextpg; 2569 bextpgsiz0 = nd->nd_bextpgsiz; 2570 2571 /* 2572 * Fill in the first part of the reply. 2573 * dirlen is the reply length in bytes and cannot exceed cnt. 2574 * (Include the two booleans at the end of the reply in dirlen now, 2575 * so we recognize when we have exceeded cnt.) 2576 */ 2577 if (nd->nd_flag & ND_NFSV3) { 2578 dirlen = NFSX_V3POSTOPATTR + NFSX_VERF + 2 * NFSX_UNSIGNED; 2579 nfsrv_postopattr(nd, getret, &at); 2580 } else { 2581 dirlen = NFSX_VERF + 2 * NFSX_UNSIGNED; 2582 } 2583 NFSM_BUILD(tl, u_int32_t *, NFSX_VERF); 2584 txdr_hyper(at.na_filerev, tl); 2585 2586 /* 2587 * Save this position, in case there is an empty reply needed. 2588 */ 2589 mb1 = nd->nd_mb; 2590 bpos1 = nd->nd_bpos; 2591 bextpg1 = nd->nd_bextpg; 2592 bextpgsiz1 = nd->nd_bextpgsiz; 2593 2594 /* Loop through the records and build reply */ 2595 entrycnt = 0; 2596 while (cpos < cend && ncookies > 0 && dirlen < cnt) { 2597 nlen = dp->d_namlen; 2598 if (dp->d_fileno != 0 && dp->d_type != DT_WHT && 2599 nlen <= NFS_MAXNAMLEN && 2600 ((nd->nd_flag & ND_NFSV3) || nlen > 2 || 2601 (nlen==2 && (dp->d_name[0]!='.' || dp->d_name[1]!='.')) 2602 || (nlen == 1 && dp->d_name[0] != '.'))) { 2603 /* 2604 * Save the current position in the reply, in case 2605 * this entry exceeds cnt. 2606 */ 2607 mb1 = nd->nd_mb; 2608 bpos1 = nd->nd_bpos; 2609 bextpg1 = nd->nd_bextpg; 2610 bextpgsiz1 = nd->nd_bextpgsiz; 2611 2612 /* 2613 * For readdir_and_lookup get the vnode using 2614 * the file number. 2615 */ 2616 nvp = NULL; 2617 refp = NULL; 2618 r = 0; 2619 at_root = 0; 2620 needs_unbusy = 0; 2621 new_mp = mp; 2622 mounted_on_fileno = (uint64_t)dp->d_fileno; 2623 if ((nd->nd_flag & ND_NFSV3) || 2624 NFSNONZERO_ATTRBIT(&savbits) || 2625 dp->d_type == DT_UNKNOWN || 2626 (dp->d_type == DT_DIR && 2627 nfsrv_enable_crossmntpt != 0)) { 2628 if (nd->nd_flag & ND_NFSV4) 2629 refp = nfsv4root_getreferral(NULL, 2630 vp, dp->d_fileno); 2631 if (refp == NULL) { 2632 if (usevget) 2633 r = VFS_VGET(mp, dp->d_fileno, 2634 LK_SHARED, &nvp); 2635 else 2636 r = EOPNOTSUPP; 2637 if (r == EOPNOTSUPP) { 2638 if (usevget) { 2639 usevget = 0; 2640 cn.cn_nameiop = LOOKUP; 2641 cn.cn_lkflags = 2642 LK_SHARED | 2643 LK_RETRY; 2644 cn.cn_cred = 2645 nd->nd_cred; 2646 } 2647 cn.cn_nameptr = dp->d_name; 2648 cn.cn_namelen = nlen; 2649 cn.cn_flags = ISLASTCN | 2650 NOFOLLOW | LOCKLEAF; 2651 if (nlen == 2 && 2652 dp->d_name[0] == '.' && 2653 dp->d_name[1] == '.') 2654 cn.cn_flags |= 2655 ISDOTDOT; 2656 if (NFSVOPLOCK(vp, LK_SHARED) 2657 != 0) { 2658 nd->nd_repstat = EPERM; 2659 break; 2660 } 2661 if ((vp->v_vflag & VV_ROOT) != 0 2662 && (cn.cn_flags & ISDOTDOT) 2663 != 0) { 2664 vref(vp); 2665 nvp = vp; 2666 r = 0; 2667 } else { 2668 r = VOP_LOOKUP(vp, &nvp, 2669 &cn); 2670 if (vp != nvp) 2671 NFSVOPUNLOCK(vp); 2672 } 2673 } 2674 2675 /* 2676 * For NFSv4, check to see if nvp is 2677 * a mount point and get the mount 2678 * point vnode, as required. 2679 */ 2680 if (r == 0 && 2681 nfsrv_enable_crossmntpt != 0 && 2682 (nd->nd_flag & ND_NFSV4) != 0 && 2683 nvp->v_type == VDIR && 2684 nvp->v_mountedhere != NULL) { 2685 new_mp = nvp->v_mountedhere; 2686 r = vfs_busy(new_mp, 0); 2687 vput(nvp); 2688 nvp = NULL; 2689 if (r == 0) { 2690 r = VFS_ROOT(new_mp, 2691 LK_SHARED, &nvp); 2692 needs_unbusy = 1; 2693 if (r == 0) 2694 at_root = 1; 2695 } 2696 } 2697 } 2698 2699 /* 2700 * If we failed to look up the entry, then it 2701 * has become invalid, most likely removed. 2702 */ 2703 if (r != 0) { 2704 if (needs_unbusy) 2705 vfs_unbusy(new_mp); 2706 goto invalid; 2707 } 2708 KASSERT(refp != NULL || nvp != NULL, 2709 ("%s: undetected lookup error", __func__)); 2710 2711 if (refp == NULL && 2712 ((nd->nd_flag & ND_NFSV3) || 2713 NFSNONZERO_ATTRBIT(&attrbits))) { 2714 r = nfsvno_getfh(nvp, &nfh, p); 2715 if (!r) 2716 r = nfsvno_getattr(nvp, nvap, nd, p, 2717 1, &attrbits); 2718 if (r == 0 && is_zfs == 1 && 2719 nfsrv_enable_crossmntpt != 0 && 2720 (nd->nd_flag & ND_NFSV4) != 0 && 2721 nvp->v_type == VDIR && 2722 vp->v_mount != nvp->v_mount) { 2723 /* 2724 * For a ZFS snapshot, there is a 2725 * pseudo mount that does not set 2726 * v_mountedhere, so it needs to 2727 * be detected via a different 2728 * mount structure. 2729 */ 2730 at_root = 1; 2731 if (new_mp == mp) 2732 new_mp = nvp->v_mount; 2733 } 2734 } 2735 2736 /* 2737 * If we failed to get attributes of the entry, 2738 * then just skip it for NFSv3 (the traditional 2739 * behavior in the old NFS server). 2740 * For NFSv4 the behavior is controlled by 2741 * RDATTRERROR: we either ignore the error or 2742 * fail the request. 2743 * The exception is EOPNOTSUPP, which can be 2744 * returned by nfsvno_getfh() for certain 2745 * file systems, such as devfs. This indicates 2746 * that the file system cannot be exported, 2747 * so just skip over the entry. 2748 * Note that RDATTRERROR is never set for NFSv3. 2749 */ 2750 if (r != 0) { 2751 if (!NFSISSET_ATTRBIT(&attrbits, 2752 NFSATTRBIT_RDATTRERROR) || 2753 r == EOPNOTSUPP) { 2754 vput(nvp); 2755 if (needs_unbusy != 0) 2756 vfs_unbusy(new_mp); 2757 if ((nd->nd_flag & ND_NFSV3) || 2758 r == EOPNOTSUPP) 2759 goto invalid; 2760 nd->nd_repstat = r; 2761 break; 2762 } 2763 } 2764 } else if (NFSNONZERO_ATTRBIT(&attrbits)) { 2765 /* Only need Type and/or Fileid. */ 2766 VATTR_NULL(&nvap->na_vattr); 2767 nvap->na_fileid = dp->d_fileno; 2768 nvap->na_type = NFS_DTYPETOVTYPE(dp->d_type); 2769 } 2770 2771 /* 2772 * Build the directory record xdr 2773 */ 2774 if (nd->nd_flag & ND_NFSV3) { 2775 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2776 *tl++ = newnfs_true; 2777 txdr_hyper(dp->d_fileno, tl); 2778 dirlen += nfsm_strtom(nd, dp->d_name, nlen); 2779 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2780 txdr_hyper(*cookiep, tl); 2781 nfsrv_postopattr(nd, 0, nvap); 2782 dirlen += nfsm_fhtom(NULL, nd, (u_int8_t *)&nfh, 2783 0, 1); 2784 dirlen += (5*NFSX_UNSIGNED+NFSX_V3POSTOPATTR); 2785 if (nvp != NULL) 2786 vput(nvp); 2787 } else { 2788 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2789 *tl++ = newnfs_true; 2790 txdr_hyper(*cookiep, tl); 2791 dirlen += nfsm_strtom(nd, dp->d_name, nlen); 2792 if (nvp != NULL) { 2793 supports_nfsv4acls = 2794 nfs_supportsnfsv4acls(nvp); 2795 NFSVOPUNLOCK(nvp); 2796 } else 2797 supports_nfsv4acls = 0; 2798 if (refp != NULL) { 2799 dirlen += nfsrv_putreferralattr(nd, 2800 &refbits, refp, 0, 2801 &nd->nd_repstat); 2802 if (nd->nd_repstat) { 2803 if (nvp != NULL) 2804 vrele(nvp); 2805 if (needs_unbusy != 0) 2806 vfs_unbusy(new_mp); 2807 break; 2808 } 2809 } else if (r) { 2810 dirlen += nfsvno_fillattr(nd, new_mp, 2811 nvp, nvap, &nfh, r, &rderrbits, 2812 nd->nd_cred, p, isdgram, 0, 2813 supports_nfsv4acls, at_root, 2814 mounted_on_fileno); 2815 } else { 2816 dirlen += nfsvno_fillattr(nd, new_mp, 2817 nvp, nvap, &nfh, r, &attrbits, 2818 nd->nd_cred, p, isdgram, 0, 2819 supports_nfsv4acls, at_root, 2820 mounted_on_fileno); 2821 } 2822 if (nvp != NULL) 2823 vrele(nvp); 2824 dirlen += (3 * NFSX_UNSIGNED); 2825 } 2826 if (needs_unbusy != 0) 2827 vfs_unbusy(new_mp); 2828 if (dirlen <= cnt) 2829 entrycnt++; 2830 } 2831 invalid: 2832 cpos += dp->d_reclen; 2833 dp = (struct dirent *)cpos; 2834 cookiep++; 2835 ncookies--; 2836 } 2837 vrele(vp); 2838 vfs_unbusy(mp); 2839 2840 /* 2841 * If dirlen > cnt, we must strip off the last entry. If that 2842 * results in an empty reply, report NFSERR_TOOSMALL. 2843 */ 2844 if (dirlen > cnt || nd->nd_repstat) { 2845 if (!nd->nd_repstat && entrycnt == 0) 2846 nd->nd_repstat = NFSERR_TOOSMALL; 2847 if (nd->nd_repstat) { 2848 nfsm_trimtrailing(nd, mb0, bpos0, bextpg0, bextpgsiz0); 2849 if (nd->nd_flag & ND_NFSV3) 2850 nfsrv_postopattr(nd, getret, &at); 2851 } else 2852 nfsm_trimtrailing(nd, mb1, bpos1, bextpg1, bextpgsiz1); 2853 eofflag = 0; 2854 } else if (cpos < cend) 2855 eofflag = 0; 2856 if (!nd->nd_repstat) { 2857 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2858 *tl++ = newnfs_false; 2859 if (eofflag) 2860 *tl = newnfs_true; 2861 else 2862 *tl = newnfs_false; 2863 } 2864 free(cookies, M_TEMP); 2865 free(rbuf, M_TEMP); 2866 2867 out: 2868 NFSEXITCODE2(0, nd); 2869 return (0); 2870 nfsmout: 2871 vput(vp); 2872 NFSEXITCODE2(error, nd); 2873 return (error); 2874 } 2875 2876 /* 2877 * Get the settable attributes out of the mbuf list. 2878 * (Return 0 or EBADRPC) 2879 */ 2880 int 2881 nfsrv_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap, 2882 nfsattrbit_t *attrbitp, NFSACL_T *aclp, struct thread *p) 2883 { 2884 u_int32_t *tl; 2885 struct nfsv2_sattr *sp; 2886 int error = 0, toclient = 0; 2887 2888 switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) { 2889 case ND_NFSV2: 2890 NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 2891 /* 2892 * Some old clients didn't fill in the high order 16bits. 2893 * --> check the low order 2 bytes for 0xffff 2894 */ 2895 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 2896 nvap->na_mode = nfstov_mode(sp->sa_mode); 2897 if (sp->sa_uid != newnfs_xdrneg1) 2898 nvap->na_uid = fxdr_unsigned(uid_t, sp->sa_uid); 2899 if (sp->sa_gid != newnfs_xdrneg1) 2900 nvap->na_gid = fxdr_unsigned(gid_t, sp->sa_gid); 2901 if (sp->sa_size != newnfs_xdrneg1) 2902 nvap->na_size = fxdr_unsigned(u_quad_t, sp->sa_size); 2903 if (sp->sa_atime.nfsv2_sec != newnfs_xdrneg1) { 2904 #ifdef notyet 2905 fxdr_nfsv2time(&sp->sa_atime, &nvap->na_atime); 2906 #else 2907 nvap->na_atime.tv_sec = 2908 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec); 2909 nvap->na_atime.tv_nsec = 0; 2910 #endif 2911 } 2912 if (sp->sa_mtime.nfsv2_sec != newnfs_xdrneg1) 2913 fxdr_nfsv2time(&sp->sa_mtime, &nvap->na_mtime); 2914 break; 2915 case ND_NFSV3: 2916 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2917 if (*tl == newnfs_true) { 2918 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2919 nvap->na_mode = nfstov_mode(*tl); 2920 } 2921 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2922 if (*tl == newnfs_true) { 2923 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2924 nvap->na_uid = fxdr_unsigned(uid_t, *tl); 2925 } 2926 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2927 if (*tl == newnfs_true) { 2928 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2929 nvap->na_gid = fxdr_unsigned(gid_t, *tl); 2930 } 2931 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2932 if (*tl == newnfs_true) { 2933 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2934 nvap->na_size = fxdr_hyper(tl); 2935 } 2936 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2937 switch (fxdr_unsigned(int, *tl)) { 2938 case NFSV3SATTRTIME_TOCLIENT: 2939 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2940 fxdr_nfsv3time(tl, &nvap->na_atime); 2941 toclient = 1; 2942 break; 2943 case NFSV3SATTRTIME_TOSERVER: 2944 vfs_timestamp(&nvap->na_atime); 2945 nvap->na_vaflags |= VA_UTIMES_NULL; 2946 break; 2947 } 2948 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2949 switch (fxdr_unsigned(int, *tl)) { 2950 case NFSV3SATTRTIME_TOCLIENT: 2951 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2952 fxdr_nfsv3time(tl, &nvap->na_mtime); 2953 nvap->na_vaflags &= ~VA_UTIMES_NULL; 2954 break; 2955 case NFSV3SATTRTIME_TOSERVER: 2956 vfs_timestamp(&nvap->na_mtime); 2957 if (!toclient) 2958 nvap->na_vaflags |= VA_UTIMES_NULL; 2959 break; 2960 } 2961 break; 2962 case ND_NFSV4: 2963 error = nfsv4_sattr(nd, vp, nvap, attrbitp, aclp, p); 2964 } 2965 nfsmout: 2966 NFSEXITCODE2(error, nd); 2967 return (error); 2968 } 2969 2970 /* 2971 * Handle the setable attributes for V4. 2972 * Returns NFSERR_BADXDR if it can't be parsed, 0 otherwise. 2973 */ 2974 int 2975 nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap, 2976 nfsattrbit_t *attrbitp, NFSACL_T *aclp, struct thread *p) 2977 { 2978 u_int32_t *tl; 2979 int attrsum = 0; 2980 int i, j; 2981 int error, attrsize, bitpos, aclsize, aceerr, retnotsup = 0; 2982 int moderet, toclient = 0; 2983 u_char *cp, namestr[NFSV4_SMALLSTR + 1]; 2984 uid_t uid; 2985 gid_t gid; 2986 u_short mode, mask; /* Same type as va_mode. */ 2987 struct vattr va; 2988 2989 error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup); 2990 if (error) 2991 goto nfsmout; 2992 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2993 attrsize = fxdr_unsigned(int, *tl); 2994 2995 /* 2996 * Loop around getting the setable attributes. If an unsupported 2997 * one is found, set nd_repstat == NFSERR_ATTRNOTSUPP and return. 2998 */ 2999 if (retnotsup) { 3000 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 3001 bitpos = NFSATTRBIT_MAX; 3002 } else { 3003 bitpos = 0; 3004 } 3005 moderet = 0; 3006 for (; bitpos < NFSATTRBIT_MAX; bitpos++) { 3007 if (attrsum > attrsize) { 3008 error = NFSERR_BADXDR; 3009 goto nfsmout; 3010 } 3011 if (NFSISSET_ATTRBIT(attrbitp, bitpos)) 3012 switch (bitpos) { 3013 case NFSATTRBIT_SIZE: 3014 NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER); 3015 if (vp != NULL && vp->v_type != VREG) { 3016 error = (vp->v_type == VDIR) ? NFSERR_ISDIR : 3017 NFSERR_INVAL; 3018 goto nfsmout; 3019 } 3020 nvap->na_size = fxdr_hyper(tl); 3021 attrsum += NFSX_HYPER; 3022 break; 3023 case NFSATTRBIT_ACL: 3024 error = nfsrv_dissectacl(nd, aclp, true, &aceerr, 3025 &aclsize, p); 3026 if (error) 3027 goto nfsmout; 3028 if (aceerr && !nd->nd_repstat) 3029 nd->nd_repstat = aceerr; 3030 attrsum += aclsize; 3031 break; 3032 case NFSATTRBIT_ARCHIVE: 3033 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3034 if (!nd->nd_repstat) 3035 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 3036 attrsum += NFSX_UNSIGNED; 3037 break; 3038 case NFSATTRBIT_HIDDEN: 3039 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3040 if (!nd->nd_repstat) 3041 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 3042 attrsum += NFSX_UNSIGNED; 3043 break; 3044 case NFSATTRBIT_MIMETYPE: 3045 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3046 i = fxdr_unsigned(int, *tl); 3047 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 3048 if (error) 3049 goto nfsmout; 3050 if (!nd->nd_repstat) 3051 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 3052 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i)); 3053 break; 3054 case NFSATTRBIT_MODE: 3055 moderet = NFSERR_INVAL; /* Can't do MODESETMASKED. */ 3056 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3057 nvap->na_mode = nfstov_mode(*tl); 3058 attrsum += NFSX_UNSIGNED; 3059 break; 3060 case NFSATTRBIT_OWNER: 3061 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3062 j = fxdr_unsigned(int, *tl); 3063 if (j < 0) { 3064 error = NFSERR_BADXDR; 3065 goto nfsmout; 3066 } 3067 if (j > NFSV4_SMALLSTR) 3068 cp = malloc(j + 1, M_NFSSTRING, M_WAITOK); 3069 else 3070 cp = namestr; 3071 error = nfsrv_mtostr(nd, cp, j); 3072 if (error) { 3073 if (j > NFSV4_SMALLSTR) 3074 free(cp, M_NFSSTRING); 3075 goto nfsmout; 3076 } 3077 if (!nd->nd_repstat) { 3078 nd->nd_repstat = nfsv4_strtouid(nd, cp, j, 3079 &uid); 3080 if (!nd->nd_repstat) 3081 nvap->na_uid = uid; 3082 } 3083 if (j > NFSV4_SMALLSTR) 3084 free(cp, M_NFSSTRING); 3085 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j)); 3086 break; 3087 case NFSATTRBIT_OWNERGROUP: 3088 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3089 j = fxdr_unsigned(int, *tl); 3090 if (j < 0) { 3091 error = NFSERR_BADXDR; 3092 goto nfsmout; 3093 } 3094 if (j > NFSV4_SMALLSTR) 3095 cp = malloc(j + 1, M_NFSSTRING, M_WAITOK); 3096 else 3097 cp = namestr; 3098 error = nfsrv_mtostr(nd, cp, j); 3099 if (error) { 3100 if (j > NFSV4_SMALLSTR) 3101 free(cp, M_NFSSTRING); 3102 goto nfsmout; 3103 } 3104 if (!nd->nd_repstat) { 3105 nd->nd_repstat = nfsv4_strtogid(nd, cp, j, 3106 &gid); 3107 if (!nd->nd_repstat) 3108 nvap->na_gid = gid; 3109 } 3110 if (j > NFSV4_SMALLSTR) 3111 free(cp, M_NFSSTRING); 3112 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j)); 3113 break; 3114 case NFSATTRBIT_SYSTEM: 3115 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3116 if (!nd->nd_repstat) 3117 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 3118 attrsum += NFSX_UNSIGNED; 3119 break; 3120 case NFSATTRBIT_TIMEACCESSSET: 3121 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3122 attrsum += NFSX_UNSIGNED; 3123 if (fxdr_unsigned(int, *tl)==NFSV4SATTRTIME_TOCLIENT) { 3124 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 3125 fxdr_nfsv4time(tl, &nvap->na_atime); 3126 toclient = 1; 3127 attrsum += NFSX_V4TIME; 3128 } else { 3129 vfs_timestamp(&nvap->na_atime); 3130 nvap->na_vaflags |= VA_UTIMES_NULL; 3131 } 3132 break; 3133 case NFSATTRBIT_TIMEBACKUP: 3134 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 3135 if (!nd->nd_repstat) 3136 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 3137 attrsum += NFSX_V4TIME; 3138 break; 3139 case NFSATTRBIT_TIMECREATE: 3140 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 3141 fxdr_nfsv4time(tl, &nvap->na_btime); 3142 attrsum += NFSX_V4TIME; 3143 break; 3144 case NFSATTRBIT_TIMEMODIFYSET: 3145 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3146 attrsum += NFSX_UNSIGNED; 3147 if (fxdr_unsigned(int, *tl)==NFSV4SATTRTIME_TOCLIENT) { 3148 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 3149 fxdr_nfsv4time(tl, &nvap->na_mtime); 3150 nvap->na_vaflags &= ~VA_UTIMES_NULL; 3151 attrsum += NFSX_V4TIME; 3152 } else { 3153 vfs_timestamp(&nvap->na_mtime); 3154 if (!toclient) 3155 nvap->na_vaflags |= VA_UTIMES_NULL; 3156 } 3157 break; 3158 case NFSATTRBIT_MODESETMASKED: 3159 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 3160 mode = fxdr_unsigned(u_short, *tl++); 3161 mask = fxdr_unsigned(u_short, *tl); 3162 /* 3163 * vp == NULL implies an Open/Create operation. 3164 * This attribute can only be used for Setattr and 3165 * only for NFSv4.1 or higher. 3166 * If moderet != 0, a mode attribute has also been 3167 * specified and this attribute cannot be done in the 3168 * same Setattr operation. 3169 */ 3170 if ((nd->nd_flag & ND_NFSV41) == 0) 3171 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 3172 else if ((mode & ~07777) != 0 || (mask & ~07777) != 0 || 3173 vp == NULL) 3174 nd->nd_repstat = NFSERR_INVAL; 3175 else if (moderet == 0) 3176 moderet = VOP_GETATTR(vp, &va, nd->nd_cred); 3177 if (moderet == 0) 3178 nvap->na_mode = (mode & mask) | 3179 (va.va_mode & ~mask); 3180 else 3181 nd->nd_repstat = moderet; 3182 attrsum += 2 * NFSX_UNSIGNED; 3183 break; 3184 default: 3185 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 3186 /* 3187 * set bitpos so we drop out of the loop. 3188 */ 3189 bitpos = NFSATTRBIT_MAX; 3190 break; 3191 } 3192 } 3193 3194 /* 3195 * some clients pad the attrlist, so we need to skip over the 3196 * padding. 3197 */ 3198 if (attrsum > attrsize) { 3199 error = NFSERR_BADXDR; 3200 } else { 3201 attrsize = NFSM_RNDUP(attrsize); 3202 if (attrsum < attrsize) 3203 error = nfsm_advance(nd, attrsize - attrsum, -1); 3204 } 3205 nfsmout: 3206 NFSEXITCODE2(error, nd); 3207 return (error); 3208 } 3209 3210 /* 3211 * Check/setup export credentials. 3212 */ 3213 int 3214 nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, 3215 struct ucred *credanon, bool testsec) 3216 { 3217 int error; 3218 3219 /* 3220 * Check/setup credentials. 3221 */ 3222 if (nd->nd_flag & ND_GSS) 3223 exp->nes_exflag &= ~MNT_EXPORTANON; 3224 3225 /* 3226 * Check to see if the operation is allowed for this security flavor. 3227 */ 3228 error = 0; 3229 if (testsec) { 3230 error = nfsvno_testexp(nd, exp); 3231 if (error != 0) 3232 goto out; 3233 } 3234 3235 /* 3236 * Check to see if the file system is exported V4 only. 3237 */ 3238 if (NFSVNO_EXV4ONLY(exp) && !(nd->nd_flag & ND_NFSV4)) { 3239 error = NFSERR_PROGNOTV4; 3240 goto out; 3241 } 3242 3243 /* 3244 * Now, map the user credentials. 3245 * (Note that ND_AUTHNONE will only be set for an NFSv3 3246 * Fsinfo RPC. If set for anything else, this code might need 3247 * to change.) 3248 */ 3249 if (NFSVNO_EXPORTED(exp)) { 3250 if (((nd->nd_flag & ND_GSS) == 0 && nd->nd_cred->cr_uid == 0) || 3251 NFSVNO_EXPORTANON(exp) || 3252 (nd->nd_flag & ND_AUTHNONE) != 0) { 3253 nd->nd_cred->cr_uid = credanon->cr_uid; 3254 nd->nd_cred->cr_gid = credanon->cr_gid; 3255 crsetgroups(nd->nd_cred, credanon->cr_ngroups, 3256 credanon->cr_groups); 3257 } else if ((nd->nd_flag & ND_GSS) == 0) { 3258 /* 3259 * If using AUTH_SYS, call nfsrv_getgrpscred() to see 3260 * if there is a replacement credential with a group 3261 * list set up by "nfsuserd -manage-gids". 3262 * If there is no replacement, nfsrv_getgrpscred() 3263 * simply returns its argument. 3264 */ 3265 nd->nd_cred = nfsrv_getgrpscred(nd->nd_cred); 3266 } 3267 } 3268 3269 out: 3270 NFSEXITCODE2(error, nd); 3271 return (error); 3272 } 3273 3274 /* 3275 * Check exports. 3276 */ 3277 int 3278 nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp, 3279 struct ucred **credp) 3280 { 3281 int error; 3282 3283 error = 0; 3284 *credp = NULL; 3285 MNT_ILOCK(mp); 3286 if (mp->mnt_exjail == NULL || 3287 mp->mnt_exjail->cr_prison != curthread->td_ucred->cr_prison) 3288 error = EACCES; 3289 MNT_IUNLOCK(mp); 3290 if (error == 0) 3291 error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, 3292 &exp->nes_numsecflavor, exp->nes_secflavors); 3293 if (error) { 3294 if (NFSD_VNET(nfs_rootfhset)) { 3295 exp->nes_exflag = 0; 3296 exp->nes_numsecflavor = 0; 3297 error = 0; 3298 } 3299 } else if (exp->nes_numsecflavor < 1 || exp->nes_numsecflavor > 3300 MAXSECFLAVORS) { 3301 printf("nfsvno_checkexp: numsecflavors out of range\n"); 3302 exp->nes_numsecflavor = 0; 3303 error = EACCES; 3304 } 3305 NFSEXITCODE(error); 3306 return (error); 3307 } 3308 3309 /* 3310 * Get a vnode for a file handle and export stuff. 3311 */ 3312 int 3313 nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam, 3314 int lktype, struct vnode **vpp, struct nfsexstuff *exp, 3315 struct ucred **credp) 3316 { 3317 int error; 3318 3319 *credp = NULL; 3320 exp->nes_numsecflavor = 0; 3321 error = VFS_FHTOVP(mp, &fhp->fh_fid, lktype, vpp); 3322 if (error != 0) 3323 /* Make sure the server replies ESTALE to the client. */ 3324 error = ESTALE; 3325 if (nam && !error) { 3326 MNT_ILOCK(mp); 3327 if (mp->mnt_exjail == NULL || 3328 mp->mnt_exjail->cr_prison != curthread->td_ucred->cr_prison) 3329 error = EACCES; 3330 MNT_IUNLOCK(mp); 3331 if (error == 0) 3332 error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, 3333 &exp->nes_numsecflavor, exp->nes_secflavors); 3334 if (error) { 3335 if (NFSD_VNET(nfs_rootfhset)) { 3336 exp->nes_exflag = 0; 3337 exp->nes_numsecflavor = 0; 3338 error = 0; 3339 } else { 3340 vput(*vpp); 3341 } 3342 } else if (exp->nes_numsecflavor < 1 || exp->nes_numsecflavor > 3343 MAXSECFLAVORS) { 3344 printf("nfsvno_fhtovp: numsecflavors out of range\n"); 3345 exp->nes_numsecflavor = 0; 3346 error = EACCES; 3347 vput(*vpp); 3348 } 3349 } 3350 NFSEXITCODE(error); 3351 return (error); 3352 } 3353 3354 /* 3355 * nfsd_fhtovp() - convert a fh to a vnode ptr 3356 * - look up fsid in mount list (if not found ret error) 3357 * - get vp and export rights by calling nfsvno_fhtovp() 3358 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 3359 * for AUTH_SYS 3360 * - if mpp != NULL, return the mount point so that it can 3361 * be used for vn_finished_write() by the caller 3362 */ 3363 void 3364 nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype, 3365 struct vnode **vpp, struct nfsexstuff *exp, 3366 struct mount **mpp, int startwrite, int nextop) 3367 { 3368 struct mount *mp, *mpw; 3369 struct ucred *credanon; 3370 fhandle_t *fhp; 3371 int error; 3372 3373 if (mpp != NULL) 3374 *mpp = NULL; 3375 *vpp = NULL; 3376 fhp = (fhandle_t *)nfp->nfsrvfh_data; 3377 mp = vfs_busyfs(&fhp->fh_fsid); 3378 if (mp == NULL) { 3379 nd->nd_repstat = ESTALE; 3380 goto out; 3381 } 3382 3383 if (startwrite) { 3384 mpw = mp; 3385 error = vn_start_write(NULL, &mpw, V_WAIT); 3386 if (error != 0) { 3387 mpw = NULL; 3388 vfs_unbusy(mp); 3389 nd->nd_repstat = ESTALE; 3390 goto out; 3391 } 3392 if (lktype == LK_SHARED && !(MNT_SHARED_WRITES(mp))) 3393 lktype = LK_EXCLUSIVE; 3394 } else 3395 mpw = NULL; 3396 3397 nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, lktype, vpp, exp, 3398 &credanon); 3399 vfs_unbusy(mp); 3400 3401 /* 3402 * For NFSv4 without a pseudo root fs, unexported file handles 3403 * can be returned, so that Lookup works everywhere. 3404 */ 3405 if (!nd->nd_repstat && exp->nes_exflag == 0 && 3406 !(nd->nd_flag & ND_NFSV4)) { 3407 vput(*vpp); 3408 *vpp = NULL; 3409 nd->nd_repstat = EACCES; 3410 } 3411 3412 /* 3413 * Personally, I've never seen any point in requiring a 3414 * reserved port#, since only in the rare case where the 3415 * clients are all boxes with secure system privileges, 3416 * does it provide any enhanced security, but... some people 3417 * believe it to be useful and keep putting this code back in. 3418 * (There is also some "security checker" out there that 3419 * complains if the nfs server doesn't enforce this.) 3420 * However, note the following: 3421 * RFC3530 (NFSv4) specifies that a reserved port# not be 3422 * required. 3423 * RFC2623 recommends that, if a reserved port# is checked for, 3424 * that there be a way to turn that off--> ifdef'd. 3425 */ 3426 #ifdef NFS_REQRSVPORT 3427 if (!nd->nd_repstat) { 3428 struct sockaddr_in *saddr; 3429 struct sockaddr_in6 *saddr6; 3430 3431 saddr = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); 3432 saddr6 = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in6 *); 3433 if (!(nd->nd_flag & ND_NFSV4) && 3434 ((saddr->sin_family == AF_INET && 3435 ntohs(saddr->sin_port) >= IPPORT_RESERVED) || 3436 (saddr6->sin6_family == AF_INET6 && 3437 ntohs(saddr6->sin6_port) >= IPPORT_RESERVED))) { 3438 vput(*vpp); 3439 nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK); 3440 } 3441 } 3442 #endif /* NFS_REQRSVPORT */ 3443 3444 /* 3445 * Check/setup credentials. 3446 */ 3447 if (!nd->nd_repstat) { 3448 nd->nd_saveduid = nd->nd_cred->cr_uid; 3449 nd->nd_repstat = nfsd_excred(nd, exp, credanon, 3450 nfsrv_checkwrongsec(nd, nextop, (*vpp)->v_type)); 3451 if (nd->nd_repstat) 3452 vput(*vpp); 3453 } 3454 if (credanon != NULL) 3455 crfree(credanon); 3456 if (nd->nd_repstat) { 3457 vn_finished_write(mpw); 3458 *vpp = NULL; 3459 } else if (mpp != NULL) { 3460 *mpp = mpw; 3461 } 3462 3463 out: 3464 NFSEXITCODE2(0, nd); 3465 } 3466 3467 /* 3468 * glue for fp. 3469 */ 3470 static int 3471 fp_getfvp(struct thread *p, int fd, struct file **fpp, struct vnode **vpp) 3472 { 3473 struct filedesc *fdp; 3474 struct file *fp; 3475 int error = 0; 3476 3477 fdp = p->td_proc->p_fd; 3478 if (fd < 0 || fd >= fdp->fd_nfiles || 3479 (fp = fdp->fd_ofiles[fd].fde_file) == NULL) { 3480 error = EBADF; 3481 goto out; 3482 } 3483 *fpp = fp; 3484 3485 out: 3486 NFSEXITCODE(error); 3487 return (error); 3488 } 3489 3490 /* 3491 * Called from nfssvc() to update the exports list. Just call 3492 * vfs_export(). This has to be done, since the v4 root fake fs isn't 3493 * in the mount list. 3494 */ 3495 int 3496 nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p) 3497 { 3498 struct nfsex_args *nfsexargp = (struct nfsex_args *)argp; 3499 int error = 0; 3500 struct nameidata nd; 3501 fhandle_t fh; 3502 3503 error = vfs_export(NFSD_VNET(nfsv4root_mnt), &nfsexargp->export, false); 3504 if ((nfsexargp->export.ex_flags & MNT_DELEXPORT) != 0) 3505 NFSD_VNET(nfs_rootfhset) = 0; 3506 else if (error == 0) { 3507 if (nfsexargp->fspec == NULL) { 3508 error = EPERM; 3509 goto out; 3510 } 3511 /* 3512 * If fspec != NULL, this is the v4root path. 3513 */ 3514 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, nfsexargp->fspec); 3515 if ((error = namei(&nd)) != 0) 3516 goto out; 3517 error = nfsvno_getfh(nd.ni_vp, &fh, p); 3518 vrele(nd.ni_vp); 3519 if (!error) { 3520 NFSD_VNET(nfs_rootfh).nfsrvfh_len = NFSX_MYFH; 3521 NFSBCOPY((caddr_t)&fh, 3522 NFSD_VNET(nfs_rootfh).nfsrvfh_data, 3523 sizeof (fhandle_t)); 3524 NFSD_VNET(nfs_rootfhset) = 1; 3525 } 3526 } 3527 3528 out: 3529 NFSEXITCODE(error); 3530 return (error); 3531 } 3532 3533 /* 3534 * This function needs to test to see if the system is near its limit 3535 * for memory allocation via malloc() or mget() and return True iff 3536 * either of these resources are near their limit. 3537 * XXX (For now, this is just a stub.) 3538 */ 3539 int nfsrv_testmalloclimit = 0; 3540 int 3541 nfsrv_mallocmget_limit(void) 3542 { 3543 static int printmesg = 0; 3544 static int testval = 1; 3545 3546 if (nfsrv_testmalloclimit && (testval++ % 1000) == 0) { 3547 if ((printmesg++ % 100) == 0) 3548 printf("nfsd: malloc/mget near limit\n"); 3549 return (1); 3550 } 3551 return (0); 3552 } 3553 3554 /* 3555 * BSD specific initialization of a mount point. 3556 */ 3557 void 3558 nfsd_mntinit(void) 3559 { 3560 3561 NFSD_LOCK(); 3562 if (NFSD_VNET(nfsrv_mntinited)) { 3563 NFSD_UNLOCK(); 3564 return; 3565 } 3566 NFSD_VNET(nfsrv_mntinited) = true; 3567 nfsrvd_init(0); 3568 NFSD_UNLOCK(); 3569 3570 NFSD_VNET(nfsv4root_mnt) = malloc(sizeof(struct mount), M_TEMP, 3571 M_WAITOK | M_ZERO); 3572 NFSD_VNET(nfsv4root_mnt)->mnt_flag = (MNT_RDONLY | MNT_EXPORTED); 3573 mtx_init(&NFSD_VNET(nfsv4root_mnt)->mnt_mtx, "nfs4mnt", NULL, MTX_DEF); 3574 lockinit(&NFSD_VNET(nfsv4root_mnt)->mnt_explock, PVFS, "explock", 0, 0); 3575 TAILQ_INIT(&NFSD_VNET(nfsv4root_mnt)->mnt_nvnodelist); 3576 TAILQ_INIT(&NFSD_VNET(nfsv4root_mnt)->mnt_lazyvnodelist); 3577 NFSD_VNET(nfsv4root_mnt)->mnt_export = NULL; 3578 TAILQ_INIT(&NFSD_VNET(nfsv4root_opt)); 3579 TAILQ_INIT(&NFSD_VNET(nfsv4root_newopt)); 3580 NFSD_VNET(nfsv4root_mnt)->mnt_opt = &NFSD_VNET(nfsv4root_opt); 3581 NFSD_VNET(nfsv4root_mnt)->mnt_optnew = &NFSD_VNET(nfsv4root_newopt); 3582 NFSD_VNET(nfsv4root_mnt)->mnt_nvnodelistsize = 0; 3583 NFSD_VNET(nfsv4root_mnt)->mnt_lazyvnodelistsize = 0; 3584 callout_init(&NFSD_VNET(nfsd_callout), 1); 3585 3586 nfsrvd_initcache(); 3587 nfsd_init(); 3588 } 3589 3590 static void 3591 nfsd_timer(void *arg) 3592 { 3593 struct vnet *vnetp; 3594 3595 vnetp = (struct vnet *)arg; 3596 NFSD_CURVNET_SET_QUIET(vnetp); 3597 nfsrv_servertimer(vnetp); 3598 callout_reset_sbt(&NFSD_VNET(nfsd_callout), SBT_1S, SBT_1S, nfsd_timer, 3599 arg, 0); 3600 NFSD_CURVNET_RESTORE(); 3601 } 3602 3603 /* 3604 * Get a vnode for a file handle, without checking exports, etc. 3605 */ 3606 struct vnode * 3607 nfsvno_getvp(fhandle_t *fhp) 3608 { 3609 struct mount *mp; 3610 struct vnode *vp; 3611 int error; 3612 3613 mp = vfs_busyfs(&fhp->fh_fsid); 3614 if (mp == NULL) 3615 return (NULL); 3616 error = VFS_FHTOVP(mp, &fhp->fh_fid, LK_EXCLUSIVE, &vp); 3617 vfs_unbusy(mp); 3618 if (error) 3619 return (NULL); 3620 return (vp); 3621 } 3622 3623 /* 3624 * Do a local VOP_ADVLOCK(). 3625 */ 3626 int 3627 nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first, 3628 u_int64_t end, struct thread *td) 3629 { 3630 int error = 0; 3631 struct flock fl; 3632 u_int64_t tlen; 3633 3634 if (nfsrv_dolocallocks == 0) 3635 goto out; 3636 ASSERT_VOP_UNLOCKED(vp, "nfsvno_advlock: vp locked"); 3637 3638 fl.l_whence = SEEK_SET; 3639 fl.l_type = ftype; 3640 fl.l_start = (off_t)first; 3641 if (end == NFS64BITSSET) { 3642 fl.l_len = 0; 3643 } else { 3644 tlen = end - first; 3645 fl.l_len = (off_t)tlen; 3646 } 3647 /* 3648 * For FreeBSD8, the l_pid and l_sysid must be set to the same 3649 * values for all calls, so that all locks will be held by the 3650 * nfsd server. (The nfsd server handles conflicts between the 3651 * various clients.) 3652 * Since an NFSv4 lockowner is a ClientID plus an array of up to 1024 3653 * bytes, so it can't be put in l_sysid. 3654 */ 3655 if (nfsv4_sysid == 0) 3656 nfsv4_sysid = nlm_acquire_next_sysid(); 3657 fl.l_pid = (pid_t)0; 3658 fl.l_sysid = (int)nfsv4_sysid; 3659 3660 if (ftype == F_UNLCK) 3661 error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_UNLCK, &fl, 3662 (F_POSIX | F_REMOTE)); 3663 else 3664 error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_SETLK, &fl, 3665 (F_POSIX | F_REMOTE)); 3666 3667 out: 3668 NFSEXITCODE(error); 3669 return (error); 3670 } 3671 3672 /* 3673 * Check the nfsv4 root exports. 3674 */ 3675 int 3676 nfsvno_v4rootexport(struct nfsrv_descript *nd) 3677 { 3678 struct ucred *credanon; 3679 int error = 0, numsecflavor, secflavors[MAXSECFLAVORS], i; 3680 uint64_t exflags; 3681 3682 error = vfs_stdcheckexp(NFSD_VNET(nfsv4root_mnt), nd->nd_nam, &exflags, 3683 &credanon, &numsecflavor, secflavors); 3684 if (error) { 3685 error = NFSERR_PROGUNAVAIL; 3686 goto out; 3687 } 3688 if (credanon != NULL) 3689 crfree(credanon); 3690 for (i = 0; i < numsecflavor; i++) { 3691 if (secflavors[i] == AUTH_SYS) 3692 nd->nd_flag |= ND_EXAUTHSYS; 3693 else if (secflavors[i] == RPCSEC_GSS_KRB5) 3694 nd->nd_flag |= ND_EXGSS; 3695 else if (secflavors[i] == RPCSEC_GSS_KRB5I) 3696 nd->nd_flag |= ND_EXGSSINTEGRITY; 3697 else if (secflavors[i] == RPCSEC_GSS_KRB5P) 3698 nd->nd_flag |= ND_EXGSSPRIVACY; 3699 } 3700 3701 /* And set ND_EXxx flags for TLS. */ 3702 if ((exflags & MNT_EXTLS) != 0) { 3703 nd->nd_flag |= ND_EXTLS; 3704 if ((exflags & MNT_EXTLSCERT) != 0) 3705 nd->nd_flag |= ND_EXTLSCERT; 3706 if ((exflags & MNT_EXTLSCERTUSER) != 0) 3707 nd->nd_flag |= ND_EXTLSCERTUSER; 3708 } 3709 3710 out: 3711 NFSEXITCODE(error); 3712 return (error); 3713 } 3714 3715 /* 3716 * Nfs server pseudo system call for the nfsd's 3717 */ 3718 /* 3719 * MPSAFE 3720 */ 3721 static int 3722 nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap) 3723 { 3724 struct file *fp; 3725 struct nfsd_addsock_args sockarg; 3726 struct nfsd_nfsd_args nfsdarg; 3727 struct nfsd_nfsd_oargs onfsdarg; 3728 struct nfsd_pnfsd_args pnfsdarg; 3729 struct vnode *vp, *nvp, *curdvp; 3730 struct pnfsdsfile *pf; 3731 struct nfsdevice *ds, *fds; 3732 cap_rights_t rights; 3733 int buflen, error, ret; 3734 char *buf, *cp, *cp2, *cp3; 3735 char fname[PNFS_FILENAME_LEN + 1]; 3736 3737 NFSD_CURVNET_SET(NFSD_TD_TO_VNET(td)); 3738 if (uap->flag & NFSSVC_NFSDADDSOCK) { 3739 error = copyin(uap->argp, (caddr_t)&sockarg, sizeof (sockarg)); 3740 if (error) 3741 goto out; 3742 /* 3743 * Since we don't know what rights might be required, 3744 * pretend that we need them all. It is better to be too 3745 * careful than too reckless. 3746 */ 3747 error = fget(td, sockarg.sock, 3748 cap_rights_init_one(&rights, CAP_SOCK_SERVER), &fp); 3749 if (error != 0) 3750 goto out; 3751 if (fp->f_type != DTYPE_SOCKET) { 3752 fdrop(fp, td); 3753 error = EPERM; 3754 goto out; 3755 } 3756 error = nfsrvd_addsock(fp); 3757 fdrop(fp, td); 3758 } else if (uap->flag & NFSSVC_NFSDNFSD) { 3759 if (uap->argp == NULL) { 3760 error = EINVAL; 3761 goto out; 3762 } 3763 if ((uap->flag & NFSSVC_NEWSTRUCT) == 0) { 3764 error = copyin(uap->argp, &onfsdarg, sizeof(onfsdarg)); 3765 if (error == 0) { 3766 nfsdarg.principal = onfsdarg.principal; 3767 nfsdarg.minthreads = onfsdarg.minthreads; 3768 nfsdarg.maxthreads = onfsdarg.maxthreads; 3769 nfsdarg.version = 1; 3770 nfsdarg.addr = NULL; 3771 nfsdarg.addrlen = 0; 3772 nfsdarg.dnshost = NULL; 3773 nfsdarg.dnshostlen = 0; 3774 nfsdarg.dspath = NULL; 3775 nfsdarg.dspathlen = 0; 3776 nfsdarg.mdspath = NULL; 3777 nfsdarg.mdspathlen = 0; 3778 nfsdarg.mirrorcnt = 1; 3779 } 3780 } else 3781 error = copyin(uap->argp, &nfsdarg, sizeof(nfsdarg)); 3782 if (error) 3783 goto out; 3784 if (nfsdarg.addrlen > 0 && nfsdarg.addrlen < 10000 && 3785 nfsdarg.dnshostlen > 0 && nfsdarg.dnshostlen < 10000 && 3786 nfsdarg.dspathlen > 0 && nfsdarg.dspathlen < 10000 && 3787 nfsdarg.mdspathlen > 0 && nfsdarg.mdspathlen < 10000 && 3788 nfsdarg.mirrorcnt >= 1 && 3789 nfsdarg.mirrorcnt <= NFSDEV_MAXMIRRORS && 3790 nfsdarg.addr != NULL && nfsdarg.dnshost != NULL && 3791 nfsdarg.dspath != NULL && nfsdarg.mdspath != NULL) { 3792 NFSD_DEBUG(1, "addrlen=%d dspathlen=%d dnslen=%d" 3793 " mdspathlen=%d mirrorcnt=%d\n", nfsdarg.addrlen, 3794 nfsdarg.dspathlen, nfsdarg.dnshostlen, 3795 nfsdarg.mdspathlen, nfsdarg.mirrorcnt); 3796 cp = malloc(nfsdarg.addrlen + 1, M_TEMP, M_WAITOK); 3797 error = copyin(nfsdarg.addr, cp, nfsdarg.addrlen); 3798 if (error != 0) { 3799 free(cp, M_TEMP); 3800 goto out; 3801 } 3802 cp[nfsdarg.addrlen] = '\0'; /* Ensure nul term. */ 3803 nfsdarg.addr = cp; 3804 cp = malloc(nfsdarg.dnshostlen + 1, M_TEMP, M_WAITOK); 3805 error = copyin(nfsdarg.dnshost, cp, nfsdarg.dnshostlen); 3806 if (error != 0) { 3807 free(nfsdarg.addr, M_TEMP); 3808 free(cp, M_TEMP); 3809 goto out; 3810 } 3811 cp[nfsdarg.dnshostlen] = '\0'; /* Ensure nul term. */ 3812 nfsdarg.dnshost = cp; 3813 cp = malloc(nfsdarg.dspathlen + 1, M_TEMP, M_WAITOK); 3814 error = copyin(nfsdarg.dspath, cp, nfsdarg.dspathlen); 3815 if (error != 0) { 3816 free(nfsdarg.addr, M_TEMP); 3817 free(nfsdarg.dnshost, M_TEMP); 3818 free(cp, M_TEMP); 3819 goto out; 3820 } 3821 cp[nfsdarg.dspathlen] = '\0'; /* Ensure nul term. */ 3822 nfsdarg.dspath = cp; 3823 cp = malloc(nfsdarg.mdspathlen + 1, M_TEMP, M_WAITOK); 3824 error = copyin(nfsdarg.mdspath, cp, nfsdarg.mdspathlen); 3825 if (error != 0) { 3826 free(nfsdarg.addr, M_TEMP); 3827 free(nfsdarg.dnshost, M_TEMP); 3828 free(nfsdarg.dspath, M_TEMP); 3829 free(cp, M_TEMP); 3830 goto out; 3831 } 3832 cp[nfsdarg.mdspathlen] = '\0'; /* Ensure nul term. */ 3833 nfsdarg.mdspath = cp; 3834 } else { 3835 nfsdarg.addr = NULL; 3836 nfsdarg.addrlen = 0; 3837 nfsdarg.dnshost = NULL; 3838 nfsdarg.dnshostlen = 0; 3839 nfsdarg.dspath = NULL; 3840 nfsdarg.dspathlen = 0; 3841 nfsdarg.mdspath = NULL; 3842 nfsdarg.mdspathlen = 0; 3843 nfsdarg.mirrorcnt = 1; 3844 } 3845 nfsd_timer(NFSD_TD_TO_VNET(td)); 3846 error = nfsrvd_nfsd(td, &nfsdarg); 3847 callout_drain(&NFSD_VNET(nfsd_callout)); 3848 free(nfsdarg.addr, M_TEMP); 3849 free(nfsdarg.dnshost, M_TEMP); 3850 free(nfsdarg.dspath, M_TEMP); 3851 free(nfsdarg.mdspath, M_TEMP); 3852 } else if (uap->flag & NFSSVC_PNFSDS) { 3853 error = copyin(uap->argp, &pnfsdarg, sizeof(pnfsdarg)); 3854 if (error == 0 && (pnfsdarg.op == PNFSDOP_DELDSSERVER || 3855 pnfsdarg.op == PNFSDOP_FORCEDELDS)) { 3856 cp = malloc(PATH_MAX + 1, M_TEMP, M_WAITOK); 3857 error = copyinstr(pnfsdarg.dspath, cp, PATH_MAX + 1, 3858 NULL); 3859 if (error == 0) 3860 error = nfsrv_deldsserver(pnfsdarg.op, cp, td); 3861 free(cp, M_TEMP); 3862 } else if (error == 0 && pnfsdarg.op == PNFSDOP_COPYMR) { 3863 cp = malloc(PATH_MAX + 1, M_TEMP, M_WAITOK); 3864 buflen = sizeof(*pf) * NFSDEV_MAXMIRRORS; 3865 buf = malloc(buflen, M_TEMP, M_WAITOK); 3866 error = copyinstr(pnfsdarg.mdspath, cp, PATH_MAX + 1, 3867 NULL); 3868 NFSD_DEBUG(4, "pnfsdcopymr cp mdspath=%d\n", error); 3869 if (error == 0 && pnfsdarg.dspath != NULL) { 3870 cp2 = malloc(PATH_MAX + 1, M_TEMP, M_WAITOK); 3871 error = copyinstr(pnfsdarg.dspath, cp2, 3872 PATH_MAX + 1, NULL); 3873 NFSD_DEBUG(4, "pnfsdcopymr cp dspath=%d\n", 3874 error); 3875 } else 3876 cp2 = NULL; 3877 if (error == 0 && pnfsdarg.curdspath != NULL) { 3878 cp3 = malloc(PATH_MAX + 1, M_TEMP, M_WAITOK); 3879 error = copyinstr(pnfsdarg.curdspath, cp3, 3880 PATH_MAX + 1, NULL); 3881 NFSD_DEBUG(4, "pnfsdcopymr cp curdspath=%d\n", 3882 error); 3883 } else 3884 cp3 = NULL; 3885 curdvp = NULL; 3886 fds = NULL; 3887 if (error == 0) 3888 error = nfsrv_mdscopymr(cp, cp2, cp3, buf, 3889 &buflen, fname, td, &vp, &nvp, &pf, &ds, 3890 &fds); 3891 NFSD_DEBUG(4, "nfsrv_mdscopymr=%d\n", error); 3892 if (error == 0) { 3893 if (pf->dsf_dir >= nfsrv_dsdirsize) { 3894 printf("copymr: dsdir out of range\n"); 3895 pf->dsf_dir = 0; 3896 } 3897 NFSD_DEBUG(4, "copymr: buflen=%d\n", buflen); 3898 error = nfsrv_copymr(vp, nvp, 3899 ds->nfsdev_dsdir[pf->dsf_dir], ds, pf, 3900 (struct pnfsdsfile *)buf, 3901 buflen / sizeof(*pf), td->td_ucred, td); 3902 vput(vp); 3903 vput(nvp); 3904 if (fds != NULL && error == 0) { 3905 curdvp = fds->nfsdev_dsdir[pf->dsf_dir]; 3906 ret = vn_lock(curdvp, LK_EXCLUSIVE); 3907 if (ret == 0) { 3908 nfsrv_dsremove(curdvp, fname, 3909 td->td_ucred, td); 3910 NFSVOPUNLOCK(curdvp); 3911 } 3912 } 3913 NFSD_DEBUG(4, "nfsrv_copymr=%d\n", error); 3914 } 3915 free(cp, M_TEMP); 3916 free(cp2, M_TEMP); 3917 free(cp3, M_TEMP); 3918 free(buf, M_TEMP); 3919 } 3920 } else { 3921 error = nfssvc_srvcall(td, uap, td->td_ucred); 3922 } 3923 3924 out: 3925 NFSD_CURVNET_RESTORE(); 3926 NFSEXITCODE(error); 3927 return (error); 3928 } 3929 3930 static int 3931 nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) 3932 { 3933 struct nfsex_args export; 3934 struct nfsex_oldargs oexp; 3935 struct file *fp = NULL; 3936 int stablefd, i, len; 3937 struct nfsd_clid adminrevoke; 3938 struct nfsd_dumplist dumplist; 3939 struct nfsd_dumpclients *dumpclients; 3940 struct nfsd_dumplocklist dumplocklist; 3941 struct nfsd_dumplocks *dumplocks; 3942 struct nameidata nd; 3943 vnode_t vp; 3944 int error = EINVAL, igotlock; 3945 struct proc *procp; 3946 gid_t *grps; 3947 3948 if (uap->flag & NFSSVC_PUBLICFH) { 3949 NFSBZERO((caddr_t)&nfs_pubfh.nfsrvfh_data, 3950 sizeof (fhandle_t)); 3951 error = copyin(uap->argp, 3952 &nfs_pubfh.nfsrvfh_data, sizeof (fhandle_t)); 3953 if (!error) 3954 nfs_pubfhset = 1; 3955 } else if ((uap->flag & (NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT)) == 3956 (NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT)) { 3957 error = copyin(uap->argp,(caddr_t)&export, 3958 sizeof (struct nfsex_args)); 3959 if (!error) { 3960 grps = NULL; 3961 if (export.export.ex_ngroups > NGROUPS_MAX || 3962 export.export.ex_ngroups < 0) 3963 error = EINVAL; 3964 else if (export.export.ex_ngroups > 0) { 3965 grps = malloc(export.export.ex_ngroups * 3966 sizeof(gid_t), M_TEMP, M_WAITOK); 3967 error = copyin(export.export.ex_groups, grps, 3968 export.export.ex_ngroups * sizeof(gid_t)); 3969 export.export.ex_groups = grps; 3970 } else 3971 export.export.ex_groups = NULL; 3972 if (!error) 3973 error = nfsrv_v4rootexport(&export, cred, p); 3974 free(grps, M_TEMP); 3975 } 3976 } else if ((uap->flag & (NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT)) == 3977 NFSSVC_V4ROOTEXPORT) { 3978 error = copyin(uap->argp,(caddr_t)&oexp, 3979 sizeof (struct nfsex_oldargs)); 3980 if (!error) { 3981 memset(&export.export, 0, sizeof(export.export)); 3982 export.export.ex_flags = (uint64_t)oexp.export.ex_flags; 3983 export.export.ex_root = oexp.export.ex_root; 3984 export.export.ex_uid = oexp.export.ex_anon.cr_uid; 3985 export.export.ex_ngroups = 3986 oexp.export.ex_anon.cr_ngroups; 3987 export.export.ex_groups = NULL; 3988 if (export.export.ex_ngroups > XU_NGROUPS || 3989 export.export.ex_ngroups < 0) 3990 error = EINVAL; 3991 else if (export.export.ex_ngroups > 0) { 3992 export.export.ex_groups = malloc( 3993 export.export.ex_ngroups * sizeof(gid_t), 3994 M_TEMP, M_WAITOK); 3995 for (i = 0; i < export.export.ex_ngroups; i++) 3996 export.export.ex_groups[i] = 3997 oexp.export.ex_anon.cr_groups[i]; 3998 } 3999 export.export.ex_addr = oexp.export.ex_addr; 4000 export.export.ex_addrlen = oexp.export.ex_addrlen; 4001 export.export.ex_mask = oexp.export.ex_mask; 4002 export.export.ex_masklen = oexp.export.ex_masklen; 4003 export.export.ex_indexfile = oexp.export.ex_indexfile; 4004 export.export.ex_numsecflavors = 4005 oexp.export.ex_numsecflavors; 4006 if (export.export.ex_numsecflavors >= MAXSECFLAVORS || 4007 export.export.ex_numsecflavors < 0) 4008 error = EINVAL; 4009 else { 4010 for (i = 0; i < export.export.ex_numsecflavors; 4011 i++) 4012 export.export.ex_secflavors[i] = 4013 oexp.export.ex_secflavors[i]; 4014 } 4015 export.fspec = oexp.fspec; 4016 if (error == 0) 4017 error = nfsrv_v4rootexport(&export, cred, p); 4018 free(export.export.ex_groups, M_TEMP); 4019 } 4020 } else if (uap->flag & NFSSVC_NOPUBLICFH) { 4021 nfs_pubfhset = 0; 4022 error = 0; 4023 } else if (uap->flag & NFSSVC_STABLERESTART) { 4024 error = copyin(uap->argp, (caddr_t)&stablefd, 4025 sizeof (int)); 4026 if (!error) 4027 error = fp_getfvp(p, stablefd, &fp, &vp); 4028 if (!error && (NFSFPFLAG(fp) & (FREAD | FWRITE)) != (FREAD | FWRITE)) 4029 error = EBADF; 4030 if (!error && NFSD_VNET(nfsrv_numnfsd) != 0) 4031 error = ENXIO; 4032 if (!error) { 4033 NFSD_VNET(nfsrv_stablefirst).nsf_fp = fp; 4034 nfsrv_setupstable(p); 4035 } 4036 } else if (uap->flag & NFSSVC_ADMINREVOKE) { 4037 error = copyin(uap->argp, (caddr_t)&adminrevoke, 4038 sizeof (struct nfsd_clid)); 4039 if (!error) 4040 error = nfsrv_adminrevoke(&adminrevoke, p); 4041 } else if (uap->flag & NFSSVC_DUMPCLIENTS) { 4042 error = copyin(uap->argp, (caddr_t)&dumplist, 4043 sizeof (struct nfsd_dumplist)); 4044 if (!error && (dumplist.ndl_size < 1 || 4045 dumplist.ndl_size > NFSRV_MAXDUMPLIST)) 4046 error = EPERM; 4047 if (!error) { 4048 len = sizeof (struct nfsd_dumpclients) * dumplist.ndl_size; 4049 dumpclients = malloc(len, M_TEMP, M_WAITOK | M_ZERO); 4050 nfsrv_dumpclients(dumpclients, dumplist.ndl_size); 4051 error = copyout(dumpclients, dumplist.ndl_list, len); 4052 free(dumpclients, M_TEMP); 4053 } 4054 } else if (uap->flag & NFSSVC_DUMPLOCKS) { 4055 error = copyin(uap->argp, (caddr_t)&dumplocklist, 4056 sizeof (struct nfsd_dumplocklist)); 4057 if (!error && (dumplocklist.ndllck_size < 1 || 4058 dumplocklist.ndllck_size > NFSRV_MAXDUMPLIST)) 4059 error = EPERM; 4060 if (!error) 4061 error = nfsrv_lookupfilename(&nd, 4062 dumplocklist.ndllck_fname, p); 4063 if (!error) { 4064 len = sizeof (struct nfsd_dumplocks) * 4065 dumplocklist.ndllck_size; 4066 dumplocks = malloc(len, M_TEMP, M_WAITOK | M_ZERO); 4067 nfsrv_dumplocks(nd.ni_vp, dumplocks, 4068 dumplocklist.ndllck_size, p); 4069 vput(nd.ni_vp); 4070 error = copyout(dumplocks, dumplocklist.ndllck_list, 4071 len); 4072 free(dumplocks, M_TEMP); 4073 } 4074 } else if (uap->flag & NFSSVC_BACKUPSTABLE) { 4075 procp = p->td_proc; 4076 PROC_LOCK(procp); 4077 nfsd_master_pid = procp->p_pid; 4078 bcopy(procp->p_comm, nfsd_master_comm, MAXCOMLEN + 1); 4079 nfsd_master_start = procp->p_stats->p_start; 4080 NFSD_VNET(nfsd_master_proc) = procp; 4081 PROC_UNLOCK(procp); 4082 } else if ((uap->flag & NFSSVC_SUSPENDNFSD) != 0) { 4083 NFSLOCKV4ROOTMUTEX(); 4084 if (!NFSD_VNET(nfsrv_suspend_nfsd)) { 4085 /* Lock out all nfsd threads */ 4086 do { 4087 igotlock = nfsv4_lock( 4088 &NFSD_VNET(nfsd_suspend_lock), 1, NULL, 4089 NFSV4ROOTLOCKMUTEXPTR, NULL); 4090 } while (igotlock == 0 && 4091 !NFSD_VNET(nfsrv_suspend_nfsd)); 4092 NFSD_VNET(nfsrv_suspend_nfsd) = true; 4093 } 4094 NFSUNLOCKV4ROOTMUTEX(); 4095 error = 0; 4096 } else if ((uap->flag & NFSSVC_RESUMENFSD) != 0) { 4097 NFSLOCKV4ROOTMUTEX(); 4098 if (NFSD_VNET(nfsrv_suspend_nfsd)) { 4099 nfsv4_unlock(&NFSD_VNET(nfsd_suspend_lock), 0); 4100 NFSD_VNET(nfsrv_suspend_nfsd) = false; 4101 } 4102 NFSUNLOCKV4ROOTMUTEX(); 4103 error = 0; 4104 } 4105 4106 NFSEXITCODE(error); 4107 return (error); 4108 } 4109 4110 /* 4111 * Check exports. 4112 * Returns 0 if ok, 1 otherwise. 4113 */ 4114 int 4115 nfsvno_testexp(struct nfsrv_descript *nd, struct nfsexstuff *exp) 4116 { 4117 int i; 4118 4119 if ((NFSVNO_EXTLS(exp) && (nd->nd_flag & ND_TLS) == 0) || 4120 (NFSVNO_EXTLSCERT(exp) && 4121 (nd->nd_flag & ND_TLSCERT) == 0) || 4122 (NFSVNO_EXTLSCERTUSER(exp) && 4123 (nd->nd_flag & ND_TLSCERTUSER) == 0)) { 4124 if ((nd->nd_flag & ND_NFSV4) != 0) 4125 return (NFSERR_WRONGSEC); 4126 #ifdef notnow 4127 /* There is currently no auth_stat for this. */ 4128 else if ((nd->nd_flag & ND_TLS) == 0) 4129 return (NFSERR_AUTHERR | AUTH_NEEDS_TLS); 4130 else 4131 return (NFSERR_AUTHERR | AUTH_NEEDS_TLS_MUTUAL_HOST); 4132 #endif 4133 else 4134 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 4135 } 4136 4137 /* 4138 * RFC2623 suggests that the NFSv3 Fsinfo RPC be allowed to use 4139 * AUTH_NONE or AUTH_SYS for file systems requiring RPCSEC_GSS. 4140 */ 4141 if ((nd->nd_flag & ND_NFSV3) != 0 && nd->nd_procnum == NFSPROC_FSINFO) 4142 return (0); 4143 4144 /* 4145 * This seems odd, but allow the case where the security flavor 4146 * list is empty. This happens when NFSv4 is traversing non-exported 4147 * file systems. Exported file systems should always have a non-empty 4148 * security flavor list. 4149 */ 4150 if (exp->nes_numsecflavor == 0) 4151 return (0); 4152 4153 for (i = 0; i < exp->nes_numsecflavor; i++) { 4154 /* 4155 * The tests for privacy and integrity must be first, 4156 * since ND_GSS is set for everything but AUTH_SYS. 4157 */ 4158 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5P && 4159 (nd->nd_flag & ND_GSSPRIVACY)) 4160 return (0); 4161 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5I && 4162 (nd->nd_flag & ND_GSSINTEGRITY)) 4163 return (0); 4164 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5 && 4165 (nd->nd_flag & ND_GSS)) 4166 return (0); 4167 if (exp->nes_secflavors[i] == AUTH_SYS && 4168 (nd->nd_flag & ND_GSS) == 0) 4169 return (0); 4170 } 4171 if ((nd->nd_flag & ND_NFSV4) != 0) 4172 return (NFSERR_WRONGSEC); 4173 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 4174 } 4175 4176 /* 4177 * Calculate a hash value for the fid in a file handle. 4178 */ 4179 uint32_t 4180 nfsrv_hashfh(fhandle_t *fhp) 4181 { 4182 uint32_t hashval; 4183 4184 hashval = hash32_buf(&fhp->fh_fid, sizeof(struct fid), 0); 4185 return (hashval); 4186 } 4187 4188 /* 4189 * Calculate a hash value for the sessionid. 4190 */ 4191 uint32_t 4192 nfsrv_hashsessionid(uint8_t *sessionid) 4193 { 4194 uint32_t hashval; 4195 4196 hashval = hash32_buf(sessionid, NFSX_V4SESSIONID, 0); 4197 return (hashval); 4198 } 4199 4200 /* 4201 * Signal the userland master nfsd to backup the stable restart file. 4202 */ 4203 void 4204 nfsrv_backupstable(void) 4205 { 4206 struct proc *procp; 4207 4208 if (NFSD_VNET(nfsd_master_proc) != NULL) { 4209 procp = pfind(nfsd_master_pid); 4210 /* Try to make sure it is the correct process. */ 4211 if (procp == NFSD_VNET(nfsd_master_proc) && 4212 procp->p_stats->p_start.tv_sec == 4213 nfsd_master_start.tv_sec && 4214 procp->p_stats->p_start.tv_usec == 4215 nfsd_master_start.tv_usec && 4216 strcmp(procp->p_comm, nfsd_master_comm) == 0) 4217 kern_psignal(procp, SIGUSR2); 4218 else 4219 NFSD_VNET(nfsd_master_proc) = NULL; 4220 4221 if (procp != NULL) 4222 PROC_UNLOCK(procp); 4223 } 4224 } 4225 4226 /* 4227 * Create a DS data file for nfsrv_pnfscreate(). Called for each mirror. 4228 * The arguments are in a structure, so that they can be passed through 4229 * taskqueue for a kernel process to execute this function. 4230 */ 4231 struct nfsrvdscreate { 4232 int done; 4233 int inprog; 4234 struct task tsk; 4235 struct ucred *tcred; 4236 struct vnode *dvp; 4237 NFSPROC_T *p; 4238 struct pnfsdsfile *pf; 4239 int err; 4240 fhandle_t fh; 4241 struct vattr va; 4242 struct vattr createva; 4243 }; 4244 4245 int 4246 nfsrv_dscreate(struct vnode *dvp, struct vattr *vap, struct vattr *nvap, 4247 fhandle_t *fhp, struct pnfsdsfile *pf, struct pnfsdsattr *dsa, 4248 char *fnamep, struct ucred *tcred, NFSPROC_T *p, struct vnode **nvpp) 4249 { 4250 struct vnode *nvp; 4251 struct nameidata named; 4252 struct vattr va; 4253 char *bufp; 4254 u_long *hashp; 4255 struct nfsnode *np; 4256 struct nfsmount *nmp; 4257 int error; 4258 4259 NFSNAMEICNDSET(&named.ni_cnd, tcred, CREATE, 4260 LOCKPARENT | LOCKLEAF | NOCACHE); 4261 nfsvno_setpathbuf(&named, &bufp, &hashp); 4262 named.ni_cnd.cn_lkflags = LK_EXCLUSIVE; 4263 named.ni_cnd.cn_nameptr = bufp; 4264 if (fnamep != NULL) { 4265 strlcpy(bufp, fnamep, PNFS_FILENAME_LEN + 1); 4266 named.ni_cnd.cn_namelen = strlen(bufp); 4267 } else 4268 named.ni_cnd.cn_namelen = nfsrv_putfhname(fhp, bufp); 4269 NFSD_DEBUG(4, "nfsrv_dscreate: dvp=%p fname=%s\n", dvp, bufp); 4270 4271 /* Create the date file in the DS mount. */ 4272 error = NFSVOPLOCK(dvp, LK_EXCLUSIVE); 4273 if (error == 0) { 4274 error = VOP_CREATE(dvp, &nvp, &named.ni_cnd, vap); 4275 vref(dvp); 4276 VOP_VPUT_PAIR(dvp, error == 0 ? &nvp : NULL, false); 4277 if (error == 0) { 4278 /* Set the ownership of the file. */ 4279 error = VOP_SETATTR(nvp, nvap, tcred); 4280 NFSD_DEBUG(4, "nfsrv_dscreate:" 4281 " setattr-uid=%d\n", error); 4282 if (error != 0) 4283 vput(nvp); 4284 } 4285 if (error != 0) 4286 printf("pNFS: pnfscreate failed=%d\n", error); 4287 } else 4288 printf("pNFS: pnfscreate vnlock=%d\n", error); 4289 if (error == 0) { 4290 np = VTONFS(nvp); 4291 nmp = VFSTONFS(nvp->v_mount); 4292 if (strcmp(nvp->v_mount->mnt_vfc->vfc_name, "nfs") 4293 != 0 || nmp->nm_nam->sa_len > sizeof( 4294 struct sockaddr_in6) || 4295 np->n_fhp->nfh_len != NFSX_MYFH) { 4296 printf("Bad DS file: fstype=%s salen=%d" 4297 " fhlen=%d\n", 4298 nvp->v_mount->mnt_vfc->vfc_name, 4299 nmp->nm_nam->sa_len, np->n_fhp->nfh_len); 4300 error = ENOENT; 4301 } 4302 4303 /* Set extattrs for the DS on the MDS file. */ 4304 if (error == 0) { 4305 if (dsa != NULL) { 4306 error = VOP_GETATTR(nvp, &va, tcred); 4307 if (error == 0) { 4308 dsa->dsa_filerev = va.va_filerev; 4309 dsa->dsa_size = va.va_size; 4310 dsa->dsa_atime = va.va_atime; 4311 dsa->dsa_mtime = va.va_mtime; 4312 dsa->dsa_bytes = va.va_bytes; 4313 } 4314 } 4315 if (error == 0) { 4316 NFSBCOPY(np->n_fhp->nfh_fh, &pf->dsf_fh, 4317 NFSX_MYFH); 4318 NFSBCOPY(nmp->nm_nam, &pf->dsf_sin, 4319 nmp->nm_nam->sa_len); 4320 NFSBCOPY(named.ni_cnd.cn_nameptr, 4321 pf->dsf_filename, 4322 sizeof(pf->dsf_filename)); 4323 } 4324 } else 4325 printf("pNFS: pnfscreate can't get DS" 4326 " attr=%d\n", error); 4327 if (nvpp != NULL && error == 0) 4328 *nvpp = nvp; 4329 else 4330 vput(nvp); 4331 } 4332 nfsvno_relpathbuf(&named); 4333 return (error); 4334 } 4335 4336 /* 4337 * Start up the thread that will execute nfsrv_dscreate(). 4338 */ 4339 static void 4340 start_dscreate(void *arg, int pending) 4341 { 4342 struct nfsrvdscreate *dsc; 4343 4344 dsc = (struct nfsrvdscreate *)arg; 4345 dsc->err = nfsrv_dscreate(dsc->dvp, &dsc->createva, &dsc->va, &dsc->fh, 4346 dsc->pf, NULL, NULL, dsc->tcred, dsc->p, NULL); 4347 dsc->done = 1; 4348 NFSD_DEBUG(4, "start_dscreate: err=%d\n", dsc->err); 4349 } 4350 4351 /* 4352 * Create a pNFS data file on the Data Server(s). 4353 */ 4354 static void 4355 nfsrv_pnfscreate(struct vnode *vp, struct vattr *vap, struct ucred *cred, 4356 NFSPROC_T *p) 4357 { 4358 struct nfsrvdscreate *dsc, *tdsc = NULL; 4359 struct nfsdevice *ds, *tds, *fds; 4360 struct mount *mp; 4361 struct pnfsdsfile *pf, *tpf; 4362 struct pnfsdsattr dsattr; 4363 struct vattr va; 4364 struct vnode *dvp[NFSDEV_MAXMIRRORS]; 4365 struct nfsmount *nmp; 4366 fhandle_t fh; 4367 uid_t vauid; 4368 gid_t vagid; 4369 u_short vamode; 4370 struct ucred *tcred; 4371 int dsdir[NFSDEV_MAXMIRRORS], error, i, mirrorcnt, ret; 4372 int failpos, timo; 4373 4374 /* Get a DS server directory in a round-robin order. */ 4375 mirrorcnt = 1; 4376 mp = vp->v_mount; 4377 ds = fds = NULL; 4378 NFSDDSLOCK(); 4379 /* 4380 * Search for the first entry that handles this MDS fs, but use the 4381 * first entry for all MDS fs's otherwise. 4382 */ 4383 TAILQ_FOREACH(tds, &nfsrv_devidhead, nfsdev_list) { 4384 if (tds->nfsdev_nmp != NULL) { 4385 if (tds->nfsdev_mdsisset == 0 && ds == NULL) 4386 ds = tds; 4387 else if (tds->nfsdev_mdsisset != 0 && fsidcmp( 4388 &mp->mnt_stat.f_fsid, &tds->nfsdev_mdsfsid) == 0) { 4389 ds = fds = tds; 4390 break; 4391 } 4392 } 4393 } 4394 if (ds == NULL) { 4395 NFSDDSUNLOCK(); 4396 NFSD_DEBUG(4, "nfsrv_pnfscreate: no srv\n"); 4397 return; 4398 } 4399 i = dsdir[0] = ds->nfsdev_nextdir; 4400 ds->nfsdev_nextdir = (ds->nfsdev_nextdir + 1) % nfsrv_dsdirsize; 4401 dvp[0] = ds->nfsdev_dsdir[i]; 4402 tds = TAILQ_NEXT(ds, nfsdev_list); 4403 if (nfsrv_maxpnfsmirror > 1 && tds != NULL) { 4404 TAILQ_FOREACH_FROM(tds, &nfsrv_devidhead, nfsdev_list) { 4405 if (tds->nfsdev_nmp != NULL && 4406 ((tds->nfsdev_mdsisset == 0 && fds == NULL) || 4407 (tds->nfsdev_mdsisset != 0 && fds != NULL && 4408 fsidcmp(&mp->mnt_stat.f_fsid, 4409 &tds->nfsdev_mdsfsid) == 0))) { 4410 dsdir[mirrorcnt] = i; 4411 dvp[mirrorcnt] = tds->nfsdev_dsdir[i]; 4412 mirrorcnt++; 4413 if (mirrorcnt >= nfsrv_maxpnfsmirror) 4414 break; 4415 } 4416 } 4417 } 4418 /* Put at end of list to implement round-robin usage. */ 4419 TAILQ_REMOVE(&nfsrv_devidhead, ds, nfsdev_list); 4420 TAILQ_INSERT_TAIL(&nfsrv_devidhead, ds, nfsdev_list); 4421 NFSDDSUNLOCK(); 4422 dsc = NULL; 4423 if (mirrorcnt > 1) 4424 tdsc = dsc = malloc(sizeof(*dsc) * (mirrorcnt - 1), M_TEMP, 4425 M_WAITOK | M_ZERO); 4426 tpf = pf = malloc(sizeof(*pf) * nfsrv_maxpnfsmirror, M_TEMP, M_WAITOK | 4427 M_ZERO); 4428 4429 error = nfsvno_getfh(vp, &fh, p); 4430 if (error == 0) 4431 error = VOP_GETATTR(vp, &va, cred); 4432 if (error == 0) { 4433 /* Set the attributes for "vp" to Setattr the DS vp. */ 4434 vauid = va.va_uid; 4435 vagid = va.va_gid; 4436 vamode = va.va_mode; 4437 VATTR_NULL(&va); 4438 va.va_uid = vauid; 4439 va.va_gid = vagid; 4440 va.va_mode = vamode; 4441 va.va_size = 0; 4442 } else 4443 printf("pNFS: pnfscreate getfh+attr=%d\n", error); 4444 4445 NFSD_DEBUG(4, "nfsrv_pnfscreate: cruid=%d crgid=%d\n", cred->cr_uid, 4446 cred->cr_gid); 4447 /* Make data file name based on FH. */ 4448 tcred = newnfs_getcred(); 4449 4450 /* 4451 * Create the file on each DS mirror, using kernel process(es) for the 4452 * additional mirrors. 4453 */ 4454 failpos = -1; 4455 for (i = 0; i < mirrorcnt - 1 && error == 0; i++, tpf++, tdsc++) { 4456 tpf->dsf_dir = dsdir[i]; 4457 tdsc->tcred = tcred; 4458 tdsc->p = p; 4459 tdsc->pf = tpf; 4460 tdsc->createva = *vap; 4461 NFSBCOPY(&fh, &tdsc->fh, sizeof(fh)); 4462 tdsc->va = va; 4463 tdsc->dvp = dvp[i]; 4464 tdsc->done = 0; 4465 tdsc->inprog = 0; 4466 tdsc->err = 0; 4467 ret = EIO; 4468 if (nfs_pnfsiothreads != 0) { 4469 ret = nfs_pnfsio(start_dscreate, tdsc); 4470 NFSD_DEBUG(4, "nfsrv_pnfscreate: nfs_pnfsio=%d\n", ret); 4471 } 4472 if (ret != 0) { 4473 ret = nfsrv_dscreate(dvp[i], vap, &va, &fh, tpf, NULL, 4474 NULL, tcred, p, NULL); 4475 if (ret != 0) { 4476 KASSERT(error == 0, ("nfsrv_dscreate err=%d", 4477 error)); 4478 if (failpos == -1 && nfsds_failerr(ret)) 4479 failpos = i; 4480 else 4481 error = ret; 4482 } 4483 } 4484 } 4485 if (error == 0) { 4486 tpf->dsf_dir = dsdir[mirrorcnt - 1]; 4487 error = nfsrv_dscreate(dvp[mirrorcnt - 1], vap, &va, &fh, tpf, 4488 &dsattr, NULL, tcred, p, NULL); 4489 if (failpos == -1 && mirrorcnt > 1 && nfsds_failerr(error)) { 4490 failpos = mirrorcnt - 1; 4491 error = 0; 4492 } 4493 } 4494 timo = hz / 50; /* Wait for 20msec. */ 4495 if (timo < 1) 4496 timo = 1; 4497 /* Wait for kernel task(s) to complete. */ 4498 for (tdsc = dsc, i = 0; i < mirrorcnt - 1; i++, tdsc++) { 4499 while (tdsc->inprog != 0 && tdsc->done == 0) 4500 tsleep(&tdsc->tsk, PVFS, "srvdcr", timo); 4501 if (tdsc->err != 0) { 4502 if (failpos == -1 && nfsds_failerr(tdsc->err)) 4503 failpos = i; 4504 else if (error == 0) 4505 error = tdsc->err; 4506 } 4507 } 4508 4509 /* 4510 * If failpos has been set, that mirror has failed, so it needs 4511 * to be disabled. 4512 */ 4513 if (failpos >= 0) { 4514 nmp = VFSTONFS(dvp[failpos]->v_mount); 4515 NFSLOCKMNT(nmp); 4516 if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM | 4517 NFSMNTP_CANCELRPCS)) == 0) { 4518 nmp->nm_privflag |= NFSMNTP_CANCELRPCS; 4519 NFSUNLOCKMNT(nmp); 4520 ds = nfsrv_deldsnmp(PNFSDOP_DELDSSERVER, nmp, p); 4521 NFSD_DEBUG(4, "dscreatfail fail=%d ds=%p\n", failpos, 4522 ds); 4523 if (ds != NULL) 4524 nfsrv_killrpcs(nmp); 4525 NFSLOCKMNT(nmp); 4526 nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS; 4527 wakeup(nmp); 4528 } 4529 NFSUNLOCKMNT(nmp); 4530 } 4531 4532 NFSFREECRED(tcred); 4533 if (error == 0) { 4534 ASSERT_VOP_ELOCKED(vp, "nfsrv_pnfscreate vp"); 4535 4536 NFSD_DEBUG(4, "nfsrv_pnfscreate: mirrorcnt=%d maxmirror=%d\n", 4537 mirrorcnt, nfsrv_maxpnfsmirror); 4538 /* 4539 * For all mirrors that couldn't be created, fill in the 4540 * *pf structure, but with an IP address == 0.0.0.0. 4541 */ 4542 tpf = pf + mirrorcnt; 4543 for (i = mirrorcnt; i < nfsrv_maxpnfsmirror; i++, tpf++) { 4544 *tpf = *pf; 4545 tpf->dsf_sin.sin_family = AF_INET; 4546 tpf->dsf_sin.sin_len = sizeof(struct sockaddr_in); 4547 tpf->dsf_sin.sin_addr.s_addr = 0; 4548 tpf->dsf_sin.sin_port = 0; 4549 } 4550 4551 error = vn_extattr_set(vp, IO_NODELOCKED, 4552 EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile", 4553 sizeof(*pf) * nfsrv_maxpnfsmirror, (char *)pf, p); 4554 if (error == 0) 4555 error = vn_extattr_set(vp, IO_NODELOCKED, 4556 EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsattr", 4557 sizeof(dsattr), (char *)&dsattr, p); 4558 if (error != 0) 4559 printf("pNFS: pnfscreate setextattr=%d\n", 4560 error); 4561 } else 4562 printf("pNFS: pnfscreate=%d\n", error); 4563 free(pf, M_TEMP); 4564 free(dsc, M_TEMP); 4565 } 4566 4567 /* 4568 * Get the information needed to remove the pNFS Data Server file from the 4569 * Metadata file. Upon success, ddvp is set non-NULL to the locked 4570 * DS directory vnode. The caller must unlock *ddvp when done with it. 4571 */ 4572 static void 4573 nfsrv_pnfsremovesetup(struct vnode *vp, NFSPROC_T *p, struct vnode **dvpp, 4574 int *mirrorcntp, char *fname, fhandle_t *fhp) 4575 { 4576 struct vattr va; 4577 struct ucred *tcred; 4578 char *buf; 4579 int buflen, error; 4580 4581 dvpp[0] = NULL; 4582 /* If not an exported regular file or not a pNFS server, just return. */ 4583 if (vp->v_type != VREG || (vp->v_mount->mnt_flag & MNT_EXPORTED) == 0 || 4584 nfsrv_devidcnt == 0) 4585 return; 4586 4587 /* Check to see if this is the last hard link. */ 4588 tcred = newnfs_getcred(); 4589 error = VOP_GETATTR(vp, &va, tcred); 4590 NFSFREECRED(tcred); 4591 if (error != 0) { 4592 printf("pNFS: nfsrv_pnfsremovesetup getattr=%d\n", error); 4593 return; 4594 } 4595 if (va.va_nlink > 1) 4596 return; 4597 4598 error = nfsvno_getfh(vp, fhp, p); 4599 if (error != 0) { 4600 printf("pNFS: nfsrv_pnfsremovesetup getfh=%d\n", error); 4601 return; 4602 } 4603 4604 buflen = 1024; 4605 buf = malloc(buflen, M_TEMP, M_WAITOK); 4606 /* Get the directory vnode for the DS mount and the file handle. */ 4607 error = nfsrv_dsgetsockmnt(vp, 0, buf, &buflen, mirrorcntp, p, dvpp, 4608 NULL, NULL, fname, NULL, NULL, NULL, NULL, NULL); 4609 free(buf, M_TEMP); 4610 if (error != 0) 4611 printf("pNFS: nfsrv_pnfsremovesetup getsockmnt=%d\n", error); 4612 } 4613 4614 /* 4615 * Remove a DS data file for nfsrv_pnfsremove(). Called for each mirror. 4616 * The arguments are in a structure, so that they can be passed through 4617 * taskqueue for a kernel process to execute this function. 4618 */ 4619 struct nfsrvdsremove { 4620 int done; 4621 int inprog; 4622 struct task tsk; 4623 struct ucred *tcred; 4624 struct vnode *dvp; 4625 NFSPROC_T *p; 4626 int err; 4627 char fname[PNFS_FILENAME_LEN + 1]; 4628 }; 4629 4630 static int 4631 nfsrv_dsremove(struct vnode *dvp, char *fname, struct ucred *tcred, 4632 NFSPROC_T *p) 4633 { 4634 struct nameidata named; 4635 struct vnode *nvp; 4636 char *bufp; 4637 u_long *hashp; 4638 int error; 4639 4640 error = NFSVOPLOCK(dvp, LK_EXCLUSIVE); 4641 if (error != 0) 4642 return (error); 4643 named.ni_cnd.cn_nameiop = DELETE; 4644 named.ni_cnd.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; 4645 named.ni_cnd.cn_cred = tcred; 4646 named.ni_cnd.cn_flags = ISLASTCN | LOCKPARENT | LOCKLEAF; 4647 nfsvno_setpathbuf(&named, &bufp, &hashp); 4648 named.ni_cnd.cn_nameptr = bufp; 4649 named.ni_cnd.cn_namelen = strlen(fname); 4650 strlcpy(bufp, fname, NAME_MAX); 4651 NFSD_DEBUG(4, "nfsrv_pnfsremove: filename=%s\n", bufp); 4652 error = VOP_LOOKUP(dvp, &nvp, &named.ni_cnd); 4653 NFSD_DEBUG(4, "nfsrv_pnfsremove: aft LOOKUP=%d\n", error); 4654 if (error == 0) { 4655 error = VOP_REMOVE(dvp, nvp, &named.ni_cnd); 4656 vput(nvp); 4657 } 4658 NFSVOPUNLOCK(dvp); 4659 nfsvno_relpathbuf(&named); 4660 if (error != 0) 4661 printf("pNFS: nfsrv_pnfsremove failed=%d\n", error); 4662 return (error); 4663 } 4664 4665 /* 4666 * Start up the thread that will execute nfsrv_dsremove(). 4667 */ 4668 static void 4669 start_dsremove(void *arg, int pending) 4670 { 4671 struct nfsrvdsremove *dsrm; 4672 4673 dsrm = (struct nfsrvdsremove *)arg; 4674 dsrm->err = nfsrv_dsremove(dsrm->dvp, dsrm->fname, dsrm->tcred, 4675 dsrm->p); 4676 dsrm->done = 1; 4677 NFSD_DEBUG(4, "start_dsremove: err=%d\n", dsrm->err); 4678 } 4679 4680 /* 4681 * Remove a pNFS data file from a Data Server. 4682 * nfsrv_pnfsremovesetup() must have been called before the MDS file was 4683 * removed to set up the dvp and fill in the FH. 4684 */ 4685 static void 4686 nfsrv_pnfsremove(struct vnode **dvp, int mirrorcnt, char *fname, fhandle_t *fhp, 4687 NFSPROC_T *p) 4688 { 4689 struct ucred *tcred; 4690 struct nfsrvdsremove *dsrm, *tdsrm; 4691 struct nfsdevice *ds; 4692 struct nfsmount *nmp; 4693 int failpos, i, ret, timo; 4694 4695 tcred = newnfs_getcred(); 4696 dsrm = NULL; 4697 if (mirrorcnt > 1) 4698 dsrm = malloc(sizeof(*dsrm) * mirrorcnt - 1, M_TEMP, M_WAITOK); 4699 /* 4700 * Remove the file on each DS mirror, using kernel process(es) for the 4701 * additional mirrors. 4702 */ 4703 failpos = -1; 4704 for (tdsrm = dsrm, i = 0; i < mirrorcnt - 1; i++, tdsrm++) { 4705 tdsrm->tcred = tcred; 4706 tdsrm->p = p; 4707 tdsrm->dvp = dvp[i]; 4708 strlcpy(tdsrm->fname, fname, PNFS_FILENAME_LEN + 1); 4709 tdsrm->inprog = 0; 4710 tdsrm->done = 0; 4711 tdsrm->err = 0; 4712 ret = EIO; 4713 if (nfs_pnfsiothreads != 0) { 4714 ret = nfs_pnfsio(start_dsremove, tdsrm); 4715 NFSD_DEBUG(4, "nfsrv_pnfsremove: nfs_pnfsio=%d\n", ret); 4716 } 4717 if (ret != 0) { 4718 ret = nfsrv_dsremove(dvp[i], fname, tcred, p); 4719 if (failpos == -1 && nfsds_failerr(ret)) 4720 failpos = i; 4721 } 4722 } 4723 ret = nfsrv_dsremove(dvp[mirrorcnt - 1], fname, tcred, p); 4724 if (failpos == -1 && mirrorcnt > 1 && nfsds_failerr(ret)) 4725 failpos = mirrorcnt - 1; 4726 timo = hz / 50; /* Wait for 20msec. */ 4727 if (timo < 1) 4728 timo = 1; 4729 /* Wait for kernel task(s) to complete. */ 4730 for (tdsrm = dsrm, i = 0; i < mirrorcnt - 1; i++, tdsrm++) { 4731 while (tdsrm->inprog != 0 && tdsrm->done == 0) 4732 tsleep(&tdsrm->tsk, PVFS, "srvdsrm", timo); 4733 if (failpos == -1 && nfsds_failerr(tdsrm->err)) 4734 failpos = i; 4735 } 4736 4737 /* 4738 * If failpos has been set, that mirror has failed, so it needs 4739 * to be disabled. 4740 */ 4741 if (failpos >= 0) { 4742 nmp = VFSTONFS(dvp[failpos]->v_mount); 4743 NFSLOCKMNT(nmp); 4744 if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM | 4745 NFSMNTP_CANCELRPCS)) == 0) { 4746 nmp->nm_privflag |= NFSMNTP_CANCELRPCS; 4747 NFSUNLOCKMNT(nmp); 4748 ds = nfsrv_deldsnmp(PNFSDOP_DELDSSERVER, nmp, p); 4749 NFSD_DEBUG(4, "dsremovefail fail=%d ds=%p\n", failpos, 4750 ds); 4751 if (ds != NULL) 4752 nfsrv_killrpcs(nmp); 4753 NFSLOCKMNT(nmp); 4754 nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS; 4755 wakeup(nmp); 4756 } 4757 NFSUNLOCKMNT(nmp); 4758 } 4759 4760 /* Get rid all layouts for the file. */ 4761 nfsrv_freefilelayouts(fhp); 4762 4763 NFSFREECRED(tcred); 4764 free(dsrm, M_TEMP); 4765 } 4766 4767 /* 4768 * Generate a file name based on the file handle and put it in *bufp. 4769 * Return the number of bytes generated. 4770 */ 4771 static int 4772 nfsrv_putfhname(fhandle_t *fhp, char *bufp) 4773 { 4774 int i; 4775 uint8_t *cp; 4776 const uint8_t *hexdigits = "0123456789abcdef"; 4777 4778 cp = (uint8_t *)fhp; 4779 for (i = 0; i < sizeof(*fhp); i++) { 4780 bufp[2 * i] = hexdigits[(*cp >> 4) & 0xf]; 4781 bufp[2 * i + 1] = hexdigits[*cp++ & 0xf]; 4782 } 4783 bufp[2 * i] = '\0'; 4784 return (2 * i); 4785 } 4786 4787 /* 4788 * Update the Metadata file's attributes from the DS file when a Read/Write 4789 * layout is returned. 4790 * Basically just call nfsrv_proxyds() with procedure == NFSPROC_LAYOUTRETURN 4791 * so that it does a nfsrv_getattrdsrpc() and nfsrv_setextattr() on the DS file. 4792 */ 4793 int 4794 nfsrv_updatemdsattr(struct vnode *vp, struct nfsvattr *nap, NFSPROC_T *p) 4795 { 4796 struct ucred *tcred; 4797 int error; 4798 4799 /* Do this as root so that it won't fail with EACCES. */ 4800 tcred = newnfs_getcred(); 4801 error = nfsrv_proxyds(vp, 0, 0, tcred, p, NFSPROC_LAYOUTRETURN, 4802 NULL, NULL, NULL, nap, NULL, NULL, 0, NULL); 4803 NFSFREECRED(tcred); 4804 return (error); 4805 } 4806 4807 /* 4808 * Set the NFSv4 ACL on the DS file to the same ACL as the MDS file. 4809 */ 4810 static int 4811 nfsrv_dssetacl(struct vnode *vp, struct acl *aclp, struct ucred *cred, 4812 NFSPROC_T *p) 4813 { 4814 int error; 4815 4816 error = nfsrv_proxyds(vp, 0, 0, cred, p, NFSPROC_SETACL, 4817 NULL, NULL, NULL, NULL, aclp, NULL, 0, NULL); 4818 return (error); 4819 } 4820 4821 static int 4822 nfsrv_proxyds(struct vnode *vp, off_t off, int cnt, struct ucred *cred, 4823 struct thread *p, int ioproc, struct mbuf **mpp, char *cp, 4824 struct mbuf **mpp2, struct nfsvattr *nap, struct acl *aclp, 4825 off_t *offp, int content, bool *eofp) 4826 { 4827 struct nfsmount *nmp[NFSDEV_MAXMIRRORS], *failnmp; 4828 fhandle_t fh[NFSDEV_MAXMIRRORS]; 4829 struct vnode *dvp[NFSDEV_MAXMIRRORS]; 4830 struct nfsdevice *ds; 4831 struct pnfsdsattr dsattr; 4832 struct opnfsdsattr odsattr; 4833 char *buf; 4834 int buflen, error, failpos, i, mirrorcnt, origmircnt, trycnt; 4835 4836 NFSD_DEBUG(4, "in nfsrv_proxyds\n"); 4837 /* 4838 * If not a regular file, not exported or not a pNFS server, 4839 * just return ENOENT. 4840 */ 4841 if (vp->v_type != VREG || (vp->v_mount->mnt_flag & MNT_EXPORTED) == 0 || 4842 nfsrv_devidcnt == 0) 4843 return (ENOENT); 4844 4845 buflen = 1024; 4846 buf = malloc(buflen, M_TEMP, M_WAITOK); 4847 error = 0; 4848 4849 /* 4850 * For Getattr, get the Change attribute (va_filerev) and size (va_size) 4851 * from the MetaData file's extended attribute. 4852 */ 4853 if (ioproc == NFSPROC_GETATTR) { 4854 error = vn_extattr_get(vp, IO_NODELOCKED, 4855 EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsattr", &buflen, buf, 4856 p); 4857 if (error == 0) { 4858 if (buflen == sizeof(odsattr)) { 4859 NFSBCOPY(buf, &odsattr, buflen); 4860 nap->na_filerev = odsattr.dsa_filerev; 4861 nap->na_size = odsattr.dsa_size; 4862 nap->na_atime = odsattr.dsa_atime; 4863 nap->na_mtime = odsattr.dsa_mtime; 4864 /* 4865 * Fake na_bytes by rounding up na_size. 4866 * Since we don't know the block size, just 4867 * use BLKDEV_IOSIZE. 4868 */ 4869 nap->na_bytes = (odsattr.dsa_size + 4870 BLKDEV_IOSIZE - 1) & ~(BLKDEV_IOSIZE - 1); 4871 } else if (buflen == sizeof(dsattr)) { 4872 NFSBCOPY(buf, &dsattr, buflen); 4873 nap->na_filerev = dsattr.dsa_filerev; 4874 nap->na_size = dsattr.dsa_size; 4875 nap->na_atime = dsattr.dsa_atime; 4876 nap->na_mtime = dsattr.dsa_mtime; 4877 nap->na_bytes = dsattr.dsa_bytes; 4878 } else 4879 error = ENXIO; 4880 } 4881 if (error == 0) { 4882 /* 4883 * If nfsrv_pnfsgetdsattr is 0 or nfsrv_checkdsattr() 4884 * returns 0, just return now. nfsrv_checkdsattr() 4885 * returns 0 if there is no Read/Write layout 4886 * plus either an Open/Write_access or Write 4887 * delegation issued to a client for the file. 4888 */ 4889 if (nfsrv_pnfsgetdsattr == 0 || 4890 nfsrv_checkdsattr(vp, p) == 0) { 4891 free(buf, M_TEMP); 4892 return (error); 4893 } 4894 } 4895 4896 /* 4897 * Clear ENOATTR so the code below will attempt to do a 4898 * nfsrv_getattrdsrpc() to get the attributes and (re)create 4899 * the extended attribute. 4900 */ 4901 if (error == ENOATTR) 4902 error = 0; 4903 } 4904 4905 origmircnt = -1; 4906 trycnt = 0; 4907 tryagain: 4908 if (error == 0) { 4909 buflen = 1024; 4910 if (ioproc == NFSPROC_READDS && NFSVOPISLOCKED(vp) == 4911 LK_EXCLUSIVE) 4912 printf("nfsrv_proxyds: Readds vp exclusively locked\n"); 4913 error = nfsrv_dsgetsockmnt(vp, LK_SHARED, buf, &buflen, 4914 &mirrorcnt, p, dvp, fh, NULL, NULL, NULL, NULL, NULL, 4915 NULL, NULL); 4916 if (error == 0) { 4917 for (i = 0; i < mirrorcnt; i++) 4918 nmp[i] = VFSTONFS(dvp[i]->v_mount); 4919 } else 4920 printf("pNFS: proxy getextattr sockaddr=%d\n", error); 4921 } else 4922 printf("pNFS: nfsrv_dsgetsockmnt=%d\n", error); 4923 if (error == 0) { 4924 failpos = -1; 4925 if (origmircnt == -1) 4926 origmircnt = mirrorcnt; 4927 /* 4928 * If failpos is set to a mirror#, then that mirror has 4929 * failed and will be disabled. For Read, Getattr and Seek, the 4930 * function only tries one mirror, so if that mirror has 4931 * failed, it will need to be retried. As such, increment 4932 * tryitagain for these cases. 4933 * For Write, Setattr and Setacl, the function tries all 4934 * mirrors and will not return an error for the case where 4935 * one mirror has failed. For these cases, the functioning 4936 * mirror(s) will have been modified, so a retry isn't 4937 * necessary. These functions will set failpos for the 4938 * failed mirror#. 4939 */ 4940 if (ioproc == NFSPROC_READDS) { 4941 error = nfsrv_readdsrpc(fh, off, cnt, cred, p, nmp[0], 4942 mpp, mpp2); 4943 if (nfsds_failerr(error) && mirrorcnt > 1) { 4944 /* 4945 * Setting failpos will cause the mirror 4946 * to be disabled and then a retry of this 4947 * read is required. 4948 */ 4949 failpos = 0; 4950 error = 0; 4951 trycnt++; 4952 } 4953 } else if (ioproc == NFSPROC_WRITEDS) 4954 error = nfsrv_writedsrpc(fh, off, cnt, cred, p, vp, 4955 &nmp[0], mirrorcnt, mpp, cp, &failpos); 4956 else if (ioproc == NFSPROC_SETATTR) 4957 error = nfsrv_setattrdsrpc(fh, cred, p, vp, &nmp[0], 4958 mirrorcnt, nap, &failpos); 4959 else if (ioproc == NFSPROC_SETACL) 4960 error = nfsrv_setacldsrpc(fh, cred, p, vp, &nmp[0], 4961 mirrorcnt, aclp, &failpos); 4962 else if (ioproc == NFSPROC_SEEKDS) { 4963 error = nfsrv_seekdsrpc(fh, offp, content, eofp, cred, 4964 p, nmp[0]); 4965 if (nfsds_failerr(error) && mirrorcnt > 1) { 4966 /* 4967 * Setting failpos will cause the mirror 4968 * to be disabled and then a retry of this 4969 * read is required. 4970 */ 4971 failpos = 0; 4972 error = 0; 4973 trycnt++; 4974 } 4975 } else if (ioproc == NFSPROC_ALLOCATE) 4976 error = nfsrv_allocatedsrpc(fh, off, *offp, cred, p, vp, 4977 &nmp[0], mirrorcnt, &failpos); 4978 else if (ioproc == NFSPROC_DEALLOCATE) 4979 error = nfsrv_deallocatedsrpc(fh, off, *offp, cred, p, 4980 vp, &nmp[0], mirrorcnt, &failpos); 4981 else { 4982 error = nfsrv_getattrdsrpc(&fh[mirrorcnt - 1], cred, p, 4983 vp, nmp[mirrorcnt - 1], nap); 4984 if (nfsds_failerr(error) && mirrorcnt > 1) { 4985 /* 4986 * Setting failpos will cause the mirror 4987 * to be disabled and then a retry of this 4988 * getattr is required. 4989 */ 4990 failpos = mirrorcnt - 1; 4991 error = 0; 4992 trycnt++; 4993 } 4994 } 4995 ds = NULL; 4996 if (failpos >= 0) { 4997 failnmp = nmp[failpos]; 4998 NFSLOCKMNT(failnmp); 4999 if ((failnmp->nm_privflag & (NFSMNTP_FORCEDISM | 5000 NFSMNTP_CANCELRPCS)) == 0) { 5001 failnmp->nm_privflag |= NFSMNTP_CANCELRPCS; 5002 NFSUNLOCKMNT(failnmp); 5003 ds = nfsrv_deldsnmp(PNFSDOP_DELDSSERVER, 5004 failnmp, p); 5005 NFSD_DEBUG(4, "dsldsnmp fail=%d ds=%p\n", 5006 failpos, ds); 5007 if (ds != NULL) 5008 nfsrv_killrpcs(failnmp); 5009 NFSLOCKMNT(failnmp); 5010 failnmp->nm_privflag &= ~NFSMNTP_CANCELRPCS; 5011 wakeup(failnmp); 5012 } 5013 NFSUNLOCKMNT(failnmp); 5014 } 5015 for (i = 0; i < mirrorcnt; i++) 5016 NFSVOPUNLOCK(dvp[i]); 5017 NFSD_DEBUG(4, "nfsrv_proxyds: aft RPC=%d trya=%d\n", error, 5018 trycnt); 5019 /* Try the Read/Getattr again if a mirror was deleted. */ 5020 if (ds != NULL && trycnt > 0 && trycnt < origmircnt) 5021 goto tryagain; 5022 } else { 5023 /* Return ENOENT for any Extended Attribute error. */ 5024 error = ENOENT; 5025 } 5026 free(buf, M_TEMP); 5027 NFSD_DEBUG(4, "nfsrv_proxyds: error=%d\n", error); 5028 return (error); 5029 } 5030 5031 /* 5032 * Get the DS mount point, fh and directory from the "pnfsd.dsfile" extended 5033 * attribute. 5034 * newnmpp - If it points to a non-NULL nmp, that is the destination and needs 5035 * to be checked. If it points to a NULL nmp, then it returns 5036 * a suitable destination. 5037 * curnmp - If non-NULL, it is the source mount for the copy. 5038 */ 5039 int 5040 nfsrv_dsgetsockmnt(struct vnode *vp, int lktype, char *buf, int *buflenp, 5041 int *mirrorcntp, NFSPROC_T *p, struct vnode **dvpp, fhandle_t *fhp, 5042 char *devid, char *fnamep, struct vnode **nvpp, struct nfsmount **newnmpp, 5043 struct nfsmount *curnmp, int *ippos, int *dsdirp) 5044 { 5045 struct vnode *dvp, *nvp = NULL, **tdvpp; 5046 struct mount *mp; 5047 struct nfsmount *nmp, *newnmp; 5048 struct sockaddr *sad; 5049 struct sockaddr_in *sin; 5050 struct nfsdevice *ds, *tds, *fndds; 5051 struct pnfsdsfile *pf; 5052 uint32_t dsdir; 5053 int error, fhiszero, fnd, gotone, i, mirrorcnt; 5054 5055 ASSERT_VOP_LOCKED(vp, "nfsrv_dsgetsockmnt vp"); 5056 *mirrorcntp = 1; 5057 tdvpp = dvpp; 5058 if (nvpp != NULL) 5059 *nvpp = NULL; 5060 if (dvpp != NULL) 5061 *dvpp = NULL; 5062 if (ippos != NULL) 5063 *ippos = -1; 5064 if (newnmpp != NULL) 5065 newnmp = *newnmpp; 5066 else 5067 newnmp = NULL; 5068 mp = vp->v_mount; 5069 error = vn_extattr_get(vp, IO_NODELOCKED, EXTATTR_NAMESPACE_SYSTEM, 5070 "pnfsd.dsfile", buflenp, buf, p); 5071 mirrorcnt = *buflenp / sizeof(*pf); 5072 if (error == 0 && (mirrorcnt < 1 || mirrorcnt > NFSDEV_MAXMIRRORS || 5073 *buflenp != sizeof(*pf) * mirrorcnt)) 5074 error = ENOATTR; 5075 5076 pf = (struct pnfsdsfile *)buf; 5077 /* If curnmp != NULL, check for a match in the mirror list. */ 5078 if (curnmp != NULL && error == 0) { 5079 fnd = 0; 5080 for (i = 0; i < mirrorcnt; i++, pf++) { 5081 sad = (struct sockaddr *)&pf->dsf_sin; 5082 if (nfsaddr2_match(sad, curnmp->nm_nam)) { 5083 if (ippos != NULL) 5084 *ippos = i; 5085 fnd = 1; 5086 break; 5087 } 5088 } 5089 if (fnd == 0) 5090 error = ENXIO; 5091 } 5092 5093 gotone = 0; 5094 pf = (struct pnfsdsfile *)buf; 5095 NFSD_DEBUG(4, "nfsrv_dsgetsockmnt: mirrorcnt=%d err=%d\n", mirrorcnt, 5096 error); 5097 for (i = 0; i < mirrorcnt && error == 0; i++, pf++) { 5098 fhiszero = 0; 5099 sad = (struct sockaddr *)&pf->dsf_sin; 5100 sin = &pf->dsf_sin; 5101 dsdir = pf->dsf_dir; 5102 if (dsdir >= nfsrv_dsdirsize) { 5103 printf("nfsrv_dsgetsockmnt: dsdir=%d\n", dsdir); 5104 error = ENOATTR; 5105 } else if (nvpp != NULL && newnmp != NULL && 5106 nfsaddr2_match(sad, newnmp->nm_nam)) 5107 error = EEXIST; 5108 if (error == 0) { 5109 if (ippos != NULL && curnmp == NULL && 5110 sad->sa_family == AF_INET && 5111 sin->sin_addr.s_addr == 0) 5112 *ippos = i; 5113 if (NFSBCMP(&zerofh, &pf->dsf_fh, sizeof(zerofh)) == 0) 5114 fhiszero = 1; 5115 /* Use the socket address to find the mount point. */ 5116 fndds = NULL; 5117 NFSDDSLOCK(); 5118 /* Find a match for the IP address. */ 5119 TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) { 5120 if (ds->nfsdev_nmp != NULL) { 5121 dvp = ds->nfsdev_dvp; 5122 nmp = VFSTONFS(dvp->v_mount); 5123 if (nmp != ds->nfsdev_nmp) 5124 printf("different2 nmp %p %p\n", 5125 nmp, ds->nfsdev_nmp); 5126 if (nfsaddr2_match(sad, nmp->nm_nam)) { 5127 fndds = ds; 5128 break; 5129 } 5130 } 5131 } 5132 if (fndds != NULL && newnmpp != NULL && 5133 newnmp == NULL) { 5134 /* Search for a place to make a mirror copy. */ 5135 TAILQ_FOREACH(tds, &nfsrv_devidhead, 5136 nfsdev_list) { 5137 if (tds->nfsdev_nmp != NULL && 5138 fndds != tds && 5139 ((tds->nfsdev_mdsisset == 0 && 5140 fndds->nfsdev_mdsisset == 0) || 5141 (tds->nfsdev_mdsisset != 0 && 5142 fndds->nfsdev_mdsisset != 0 && 5143 fsidcmp(&tds->nfsdev_mdsfsid, 5144 &mp->mnt_stat.f_fsid) == 0))) { 5145 *newnmpp = tds->nfsdev_nmp; 5146 break; 5147 } 5148 } 5149 if (tds != NULL) { 5150 /* 5151 * Move this entry to the end of the 5152 * list, so it won't be selected as 5153 * easily the next time. 5154 */ 5155 TAILQ_REMOVE(&nfsrv_devidhead, tds, 5156 nfsdev_list); 5157 TAILQ_INSERT_TAIL(&nfsrv_devidhead, tds, 5158 nfsdev_list); 5159 } 5160 } 5161 NFSDDSUNLOCK(); 5162 if (fndds != NULL) { 5163 dvp = fndds->nfsdev_dsdir[dsdir]; 5164 if (lktype != 0 || fhiszero != 0 || 5165 (nvpp != NULL && *nvpp == NULL)) { 5166 if (fhiszero != 0) 5167 error = vn_lock(dvp, 5168 LK_EXCLUSIVE); 5169 else if (lktype != 0) 5170 error = vn_lock(dvp, lktype); 5171 else 5172 error = vn_lock(dvp, LK_SHARED); 5173 /* 5174 * If the file handle is all 0's, try to 5175 * do a Lookup against the DS to acquire 5176 * it. 5177 * If dvpp == NULL or the Lookup fails, 5178 * unlock dvp after the call. 5179 */ 5180 if (error == 0 && (fhiszero != 0 || 5181 (nvpp != NULL && *nvpp == NULL))) { 5182 error = nfsrv_pnfslookupds(vp, 5183 dvp, pf, &nvp, p); 5184 if (error == 0) { 5185 if (fhiszero != 0) 5186 nfsrv_pnfssetfh( 5187 vp, pf, 5188 devid, 5189 fnamep, 5190 nvp, p); 5191 if (nvpp != NULL && 5192 *nvpp == NULL) { 5193 *nvpp = nvp; 5194 *dsdirp = dsdir; 5195 } else 5196 vput(nvp); 5197 } 5198 if (error != 0 || lktype == 0) 5199 NFSVOPUNLOCK(dvp); 5200 } 5201 } 5202 if (error == 0) { 5203 gotone++; 5204 NFSD_DEBUG(4, "gotone=%d\n", gotone); 5205 if (devid != NULL) { 5206 NFSBCOPY(fndds->nfsdev_deviceid, 5207 devid, NFSX_V4DEVICEID); 5208 devid += NFSX_V4DEVICEID; 5209 } 5210 if (dvpp != NULL) 5211 *tdvpp++ = dvp; 5212 if (fhp != NULL) 5213 NFSBCOPY(&pf->dsf_fh, fhp++, 5214 NFSX_MYFH); 5215 if (fnamep != NULL && gotone == 1) 5216 strlcpy(fnamep, 5217 pf->dsf_filename, 5218 sizeof(pf->dsf_filename)); 5219 } else 5220 NFSD_DEBUG(4, "nfsrv_dsgetsockmnt " 5221 "err=%d\n", error); 5222 } 5223 } 5224 } 5225 if (error == 0 && gotone == 0) 5226 error = ENOENT; 5227 5228 NFSD_DEBUG(4, "eo nfsrv_dsgetsockmnt: gotone=%d err=%d\n", gotone, 5229 error); 5230 if (error == 0) 5231 *mirrorcntp = gotone; 5232 else { 5233 if (gotone > 0 && dvpp != NULL) { 5234 /* 5235 * If the error didn't occur on the first one and 5236 * dvpp != NULL, the one(s) prior to the failure will 5237 * have locked dvp's that need to be unlocked. 5238 */ 5239 for (i = 0; i < gotone; i++) { 5240 NFSVOPUNLOCK(*dvpp); 5241 *dvpp++ = NULL; 5242 } 5243 } 5244 /* 5245 * If it found the vnode to be copied from before a failure, 5246 * it needs to be vput()'d. 5247 */ 5248 if (nvpp != NULL && *nvpp != NULL) { 5249 vput(*nvpp); 5250 *nvpp = NULL; 5251 } 5252 } 5253 return (error); 5254 } 5255 5256 /* 5257 * Set the extended attribute for the Change attribute. 5258 */ 5259 static int 5260 nfsrv_setextattr(struct vnode *vp, struct nfsvattr *nap, NFSPROC_T *p) 5261 { 5262 struct pnfsdsattr dsattr; 5263 int error; 5264 5265 ASSERT_VOP_ELOCKED(vp, "nfsrv_setextattr vp"); 5266 dsattr.dsa_filerev = nap->na_filerev; 5267 dsattr.dsa_size = nap->na_size; 5268 dsattr.dsa_atime = nap->na_atime; 5269 dsattr.dsa_mtime = nap->na_mtime; 5270 dsattr.dsa_bytes = nap->na_bytes; 5271 error = vn_extattr_set(vp, IO_NODELOCKED, EXTATTR_NAMESPACE_SYSTEM, 5272 "pnfsd.dsattr", sizeof(dsattr), (char *)&dsattr, p); 5273 if (error != 0) 5274 printf("pNFS: setextattr=%d\n", error); 5275 return (error); 5276 } 5277 5278 static int 5279 nfsrv_readdsrpc(fhandle_t *fhp, off_t off, int len, struct ucred *cred, 5280 NFSPROC_T *p, struct nfsmount *nmp, struct mbuf **mpp, struct mbuf **mpendp) 5281 { 5282 uint32_t *tl; 5283 struct nfsrv_descript *nd; 5284 nfsv4stateid_t st; 5285 struct mbuf *m, *m2; 5286 int error = 0, retlen, tlen, trimlen; 5287 5288 NFSD_DEBUG(4, "in nfsrv_readdsrpc\n"); 5289 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 5290 *mpp = NULL; 5291 /* 5292 * Use a stateid where other is an alternating 01010 pattern and 5293 * seqid is 0xffffffff. This value is not defined as special by 5294 * the RFC and is used by the FreeBSD NFS server to indicate an 5295 * MDS->DS proxy operation. 5296 */ 5297 st.other[0] = 0x55555555; 5298 st.other[1] = 0x55555555; 5299 st.other[2] = 0x55555555; 5300 st.seqid = 0xffffffff; 5301 nfscl_reqstart(nd, NFSPROC_READDS, nmp, (u_int8_t *)fhp, sizeof(*fhp), 5302 NULL, NULL, 0, 0, cred); 5303 nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID); 5304 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED * 3); 5305 txdr_hyper(off, tl); 5306 *(tl + 2) = txdr_unsigned(len); 5307 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred, 5308 NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); 5309 if (error != 0) { 5310 free(nd, M_TEMP); 5311 return (error); 5312 } 5313 if (nd->nd_repstat == 0) { 5314 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 5315 NFSM_STRSIZ(retlen, len); 5316 if (retlen > 0) { 5317 /* Trim off the pre-data XDR from the mbuf chain. */ 5318 m = nd->nd_mrep; 5319 while (m != NULL && m != nd->nd_md) { 5320 if (m->m_next == nd->nd_md) { 5321 m->m_next = NULL; 5322 m_freem(nd->nd_mrep); 5323 nd->nd_mrep = m = nd->nd_md; 5324 } else 5325 m = m->m_next; 5326 } 5327 if (m == NULL) { 5328 printf("nfsrv_readdsrpc: busted mbuf list\n"); 5329 error = ENOENT; 5330 goto nfsmout; 5331 } 5332 5333 /* 5334 * Now, adjust first mbuf so that any XDR before the 5335 * read data is skipped over. 5336 */ 5337 trimlen = nd->nd_dpos - mtod(m, char *); 5338 if (trimlen > 0) { 5339 m->m_len -= trimlen; 5340 NFSM_DATAP(m, trimlen); 5341 } 5342 5343 /* 5344 * Truncate the mbuf chain at retlen bytes of data, 5345 * plus XDR padding that brings the length up to a 5346 * multiple of 4. 5347 */ 5348 tlen = NFSM_RNDUP(retlen); 5349 do { 5350 if (m->m_len >= tlen) { 5351 m->m_len = tlen; 5352 tlen = 0; 5353 m2 = m->m_next; 5354 m->m_next = NULL; 5355 m_freem(m2); 5356 break; 5357 } 5358 tlen -= m->m_len; 5359 m = m->m_next; 5360 } while (m != NULL); 5361 if (tlen > 0) { 5362 printf("nfsrv_readdsrpc: busted mbuf list\n"); 5363 error = ENOENT; 5364 goto nfsmout; 5365 } 5366 *mpp = nd->nd_mrep; 5367 *mpendp = m; 5368 nd->nd_mrep = NULL; 5369 } 5370 } else 5371 error = nd->nd_repstat; 5372 nfsmout: 5373 /* If nd->nd_mrep is already NULL, this is a no-op. */ 5374 m_freem(nd->nd_mrep); 5375 free(nd, M_TEMP); 5376 NFSD_DEBUG(4, "nfsrv_readdsrpc error=%d\n", error); 5377 return (error); 5378 } 5379 5380 /* 5381 * Do a write RPC on a DS data file, using this structure for the arguments, 5382 * so that this function can be executed by a separate kernel process. 5383 */ 5384 struct nfsrvwritedsdorpc { 5385 int done; 5386 int inprog; 5387 struct task tsk; 5388 fhandle_t fh; 5389 off_t off; 5390 int len; 5391 struct nfsmount *nmp; 5392 struct ucred *cred; 5393 NFSPROC_T *p; 5394 struct mbuf *m; 5395 int err; 5396 }; 5397 5398 static int 5399 nfsrv_writedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off, int len, 5400 struct nfsvattr *nap, struct mbuf *m, struct ucred *cred, NFSPROC_T *p) 5401 { 5402 uint32_t *tl; 5403 struct nfsrv_descript *nd; 5404 nfsattrbit_t attrbits; 5405 nfsv4stateid_t st; 5406 int commit, error, retlen; 5407 5408 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 5409 nfscl_reqstart(nd, NFSPROC_WRITE, nmp, (u_int8_t *)fhp, 5410 sizeof(fhandle_t), NULL, NULL, 0, 0, cred); 5411 5412 /* 5413 * Use a stateid where other is an alternating 01010 pattern and 5414 * seqid is 0xffffffff. This value is not defined as special by 5415 * the RFC and is used by the FreeBSD NFS server to indicate an 5416 * MDS->DS proxy operation. 5417 */ 5418 st.other[0] = 0x55555555; 5419 st.other[1] = 0x55555555; 5420 st.other[2] = 0x55555555; 5421 st.seqid = 0xffffffff; 5422 nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID); 5423 NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED); 5424 txdr_hyper(off, tl); 5425 tl += 2; 5426 /* 5427 * Do all writes FileSync, since the server doesn't hold onto dirty 5428 * buffers. Since clients should be accessing the DS servers directly 5429 * using the pNFS layouts, this just needs to work correctly as a 5430 * fallback. 5431 */ 5432 *tl++ = txdr_unsigned(NFSWRITE_FILESYNC); 5433 *tl = txdr_unsigned(len); 5434 NFSD_DEBUG(4, "nfsrv_writedsdorpc: len=%d\n", len); 5435 5436 /* Put data in mbuf chain. */ 5437 nd->nd_mb->m_next = m; 5438 5439 /* Set nd_mb and nd_bpos to end of data. */ 5440 while (m->m_next != NULL) 5441 m = m->m_next; 5442 nd->nd_mb = m; 5443 nfsm_set(nd, m->m_len); 5444 NFSD_DEBUG(4, "nfsrv_writedsdorpc: lastmb len=%d\n", m->m_len); 5445 5446 /* Do a Getattr for the attributes that change upon writing. */ 5447 NFSZERO_ATTRBIT(&attrbits); 5448 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE); 5449 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE); 5450 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS); 5451 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY); 5452 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED); 5453 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 5454 *tl = txdr_unsigned(NFSV4OP_GETATTR); 5455 (void) nfsrv_putattrbit(nd, &attrbits); 5456 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, 5457 cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); 5458 if (error != 0) { 5459 free(nd, M_TEMP); 5460 return (error); 5461 } 5462 NFSD_DEBUG(4, "nfsrv_writedsdorpc: aft writerpc=%d\n", nd->nd_repstat); 5463 /* Get rid of weak cache consistency data for now. */ 5464 if ((nd->nd_flag & (ND_NOMOREDATA | ND_NFSV4 | ND_V4WCCATTR)) == 5465 (ND_NFSV4 | ND_V4WCCATTR)) { 5466 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, 5467 NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 5468 NFSD_DEBUG(4, "nfsrv_writedsdorpc: wcc attr=%d\n", error); 5469 if (error != 0) 5470 goto nfsmout; 5471 /* 5472 * Get rid of Op# and status for next op. 5473 */ 5474 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 5475 if (*++tl != 0) 5476 nd->nd_flag |= ND_NOMOREDATA; 5477 } 5478 if (nd->nd_repstat == 0) { 5479 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_VERF); 5480 retlen = fxdr_unsigned(int, *tl++); 5481 commit = fxdr_unsigned(int, *tl); 5482 if (commit != NFSWRITE_FILESYNC) 5483 error = NFSERR_IO; 5484 NFSD_DEBUG(4, "nfsrv_writedsdorpc:retlen=%d commit=%d err=%d\n", 5485 retlen, commit, error); 5486 } else 5487 error = nd->nd_repstat; 5488 /* We have no use for the Write Verifier since we use FileSync. */ 5489 5490 /* 5491 * Get the Change, Size, Access Time and Modify Time attributes and set 5492 * on the Metadata file, so its attributes will be what the file's 5493 * would be if it had been written. 5494 */ 5495 if (error == 0) { 5496 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 5497 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, 5498 NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 5499 } 5500 NFSD_DEBUG(4, "nfsrv_writedsdorpc: aft loadattr=%d\n", error); 5501 nfsmout: 5502 m_freem(nd->nd_mrep); 5503 free(nd, M_TEMP); 5504 NFSD_DEBUG(4, "nfsrv_writedsdorpc error=%d\n", error); 5505 return (error); 5506 } 5507 5508 /* 5509 * Start up the thread that will execute nfsrv_writedsdorpc(). 5510 */ 5511 static void 5512 start_writedsdorpc(void *arg, int pending) 5513 { 5514 struct nfsrvwritedsdorpc *drpc; 5515 5516 drpc = (struct nfsrvwritedsdorpc *)arg; 5517 drpc->err = nfsrv_writedsdorpc(drpc->nmp, &drpc->fh, drpc->off, 5518 drpc->len, NULL, drpc->m, drpc->cred, drpc->p); 5519 drpc->done = 1; 5520 NFSD_DEBUG(4, "start_writedsdorpc: err=%d\n", drpc->err); 5521 } 5522 5523 static int 5524 nfsrv_writedsrpc(fhandle_t *fhp, off_t off, int len, struct ucred *cred, 5525 NFSPROC_T *p, struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt, 5526 struct mbuf **mpp, char *cp, int *failposp) 5527 { 5528 struct nfsrvwritedsdorpc *drpc, *tdrpc = NULL; 5529 struct nfsvattr na; 5530 struct mbuf *m; 5531 int error, i, offs, ret, timo; 5532 5533 NFSD_DEBUG(4, "in nfsrv_writedsrpc\n"); 5534 KASSERT(*mpp != NULL, ("nfsrv_writedsrpc: NULL mbuf chain")); 5535 drpc = NULL; 5536 if (mirrorcnt > 1) 5537 tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP, 5538 M_WAITOK); 5539 5540 /* Calculate offset in mbuf chain that data starts. */ 5541 offs = cp - mtod(*mpp, char *); 5542 NFSD_DEBUG(4, "nfsrv_writedsrpc: mcopy offs=%d len=%d\n", offs, len); 5543 5544 /* 5545 * Do the write RPC for every DS, using a separate kernel process 5546 * for every DS except the last one. 5547 */ 5548 error = 0; 5549 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 5550 tdrpc->done = 0; 5551 NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp)); 5552 tdrpc->off = off; 5553 tdrpc->len = len; 5554 tdrpc->nmp = *nmpp; 5555 tdrpc->cred = cred; 5556 tdrpc->p = p; 5557 tdrpc->inprog = 0; 5558 tdrpc->err = 0; 5559 tdrpc->m = m_copym(*mpp, offs, NFSM_RNDUP(len), M_WAITOK); 5560 ret = EIO; 5561 if (nfs_pnfsiothreads != 0) { 5562 ret = nfs_pnfsio(start_writedsdorpc, tdrpc); 5563 NFSD_DEBUG(4, "nfsrv_writedsrpc: nfs_pnfsio=%d\n", 5564 ret); 5565 } 5566 if (ret != 0) { 5567 ret = nfsrv_writedsdorpc(*nmpp, fhp, off, len, NULL, 5568 tdrpc->m, cred, p); 5569 if (nfsds_failerr(ret) && *failposp == -1) 5570 *failposp = i; 5571 else if (error == 0 && ret != 0) 5572 error = ret; 5573 } 5574 nmpp++; 5575 fhp++; 5576 } 5577 m = m_copym(*mpp, offs, NFSM_RNDUP(len), M_WAITOK); 5578 ret = nfsrv_writedsdorpc(*nmpp, fhp, off, len, &na, m, cred, p); 5579 if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1) 5580 *failposp = mirrorcnt - 1; 5581 else if (error == 0 && ret != 0) 5582 error = ret; 5583 if (error == 0) 5584 error = nfsrv_setextattr(vp, &na, p); 5585 NFSD_DEBUG(4, "nfsrv_writedsrpc: aft setextat=%d\n", error); 5586 tdrpc = drpc; 5587 timo = hz / 50; /* Wait for 20msec. */ 5588 if (timo < 1) 5589 timo = 1; 5590 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 5591 /* Wait for RPCs on separate threads to complete. */ 5592 while (tdrpc->inprog != 0 && tdrpc->done == 0) 5593 tsleep(&tdrpc->tsk, PVFS, "srvwrds", timo); 5594 if (nfsds_failerr(tdrpc->err) && *failposp == -1) 5595 *failposp = i; 5596 else if (error == 0 && tdrpc->err != 0) 5597 error = tdrpc->err; 5598 } 5599 free(drpc, M_TEMP); 5600 return (error); 5601 } 5602 5603 /* 5604 * Do a allocate RPC on a DS data file, using this structure for the arguments, 5605 * so that this function can be executed by a separate kernel process. 5606 */ 5607 struct nfsrvallocatedsdorpc { 5608 int done; 5609 int inprog; 5610 struct task tsk; 5611 fhandle_t fh; 5612 off_t off; 5613 off_t len; 5614 struct nfsmount *nmp; 5615 struct ucred *cred; 5616 NFSPROC_T *p; 5617 int err; 5618 }; 5619 5620 static int 5621 nfsrv_allocatedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off, 5622 off_t len, struct nfsvattr *nap, struct ucred *cred, NFSPROC_T *p) 5623 { 5624 uint32_t *tl; 5625 struct nfsrv_descript *nd; 5626 nfsattrbit_t attrbits; 5627 nfsv4stateid_t st; 5628 int error; 5629 5630 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 5631 nfscl_reqstart(nd, NFSPROC_ALLOCATE, nmp, (u_int8_t *)fhp, 5632 sizeof(fhandle_t), NULL, NULL, 0, 0, cred); 5633 5634 /* 5635 * Use a stateid where other is an alternating 01010 pattern and 5636 * seqid is 0xffffffff. This value is not defined as special by 5637 * the RFC and is used by the FreeBSD NFS server to indicate an 5638 * MDS->DS proxy operation. 5639 */ 5640 st.other[0] = 0x55555555; 5641 st.other[1] = 0x55555555; 5642 st.other[2] = 0x55555555; 5643 st.seqid = 0xffffffff; 5644 nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID); 5645 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED); 5646 txdr_hyper(off, tl); tl += 2; 5647 txdr_hyper(len, tl); tl += 2; 5648 NFSD_DEBUG(4, "nfsrv_allocatedsdorpc: len=%jd\n", (intmax_t)len); 5649 5650 *tl = txdr_unsigned(NFSV4OP_GETATTR); 5651 NFSGETATTR_ATTRBIT(&attrbits); 5652 nfsrv_putattrbit(nd, &attrbits); 5653 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, 5654 cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); 5655 if (error != 0) { 5656 free(nd, M_TEMP); 5657 return (error); 5658 } 5659 NFSD_DEBUG(4, "nfsrv_allocatedsdorpc: aft allocaterpc=%d\n", 5660 nd->nd_repstat); 5661 if (nd->nd_repstat == 0) { 5662 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 5663 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, 5664 NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 5665 } else 5666 error = nd->nd_repstat; 5667 NFSD_DEBUG(4, "nfsrv_allocatedsdorpc: aft loadattr=%d\n", error); 5668 nfsmout: 5669 m_freem(nd->nd_mrep); 5670 free(nd, M_TEMP); 5671 NFSD_DEBUG(4, "nfsrv_allocatedsdorpc error=%d\n", error); 5672 return (error); 5673 } 5674 5675 /* 5676 * Start up the thread that will execute nfsrv_allocatedsdorpc(). 5677 */ 5678 static void 5679 start_allocatedsdorpc(void *arg, int pending) 5680 { 5681 struct nfsrvallocatedsdorpc *drpc; 5682 5683 drpc = (struct nfsrvallocatedsdorpc *)arg; 5684 drpc->err = nfsrv_allocatedsdorpc(drpc->nmp, &drpc->fh, drpc->off, 5685 drpc->len, NULL, drpc->cred, drpc->p); 5686 drpc->done = 1; 5687 NFSD_DEBUG(4, "start_allocatedsdorpc: err=%d\n", drpc->err); 5688 } 5689 5690 static int 5691 nfsrv_allocatedsrpc(fhandle_t *fhp, off_t off, off_t len, struct ucred *cred, 5692 NFSPROC_T *p, struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt, 5693 int *failposp) 5694 { 5695 struct nfsrvallocatedsdorpc *drpc, *tdrpc = NULL; 5696 struct nfsvattr na; 5697 int error, i, ret, timo; 5698 5699 NFSD_DEBUG(4, "in nfsrv_allocatedsrpc\n"); 5700 drpc = NULL; 5701 if (mirrorcnt > 1) 5702 tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP, 5703 M_WAITOK); 5704 5705 /* 5706 * Do the allocate RPC for every DS, using a separate kernel process 5707 * for every DS except the last one. 5708 */ 5709 error = 0; 5710 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 5711 tdrpc->done = 0; 5712 NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp)); 5713 tdrpc->off = off; 5714 tdrpc->len = len; 5715 tdrpc->nmp = *nmpp; 5716 tdrpc->cred = cred; 5717 tdrpc->p = p; 5718 tdrpc->inprog = 0; 5719 tdrpc->err = 0; 5720 ret = EIO; 5721 if (nfs_pnfsiothreads != 0) { 5722 ret = nfs_pnfsio(start_allocatedsdorpc, tdrpc); 5723 NFSD_DEBUG(4, "nfsrv_allocatedsrpc: nfs_pnfsio=%d\n", 5724 ret); 5725 } 5726 if (ret != 0) { 5727 ret = nfsrv_allocatedsdorpc(*nmpp, fhp, off, len, NULL, 5728 cred, p); 5729 if (nfsds_failerr(ret) && *failposp == -1) 5730 *failposp = i; 5731 else if (error == 0 && ret != 0) 5732 error = ret; 5733 } 5734 nmpp++; 5735 fhp++; 5736 } 5737 ret = nfsrv_allocatedsdorpc(*nmpp, fhp, off, len, &na, cred, p); 5738 if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1) 5739 *failposp = mirrorcnt - 1; 5740 else if (error == 0 && ret != 0) 5741 error = ret; 5742 if (error == 0) 5743 error = nfsrv_setextattr(vp, &na, p); 5744 NFSD_DEBUG(4, "nfsrv_allocatedsrpc: aft setextat=%d\n", error); 5745 tdrpc = drpc; 5746 timo = hz / 50; /* Wait for 20msec. */ 5747 if (timo < 1) 5748 timo = 1; 5749 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 5750 /* Wait for RPCs on separate threads to complete. */ 5751 while (tdrpc->inprog != 0 && tdrpc->done == 0) 5752 tsleep(&tdrpc->tsk, PVFS, "srvalds", timo); 5753 if (nfsds_failerr(tdrpc->err) && *failposp == -1) 5754 *failposp = i; 5755 else if (error == 0 && tdrpc->err != 0) 5756 error = tdrpc->err; 5757 } 5758 free(drpc, M_TEMP); 5759 return (error); 5760 } 5761 5762 /* 5763 * Do a deallocate RPC on a DS data file, using this structure for the 5764 * arguments, so that this function can be executed by a separate kernel 5765 * process. 5766 */ 5767 struct nfsrvdeallocatedsdorpc { 5768 int done; 5769 int inprog; 5770 struct task tsk; 5771 fhandle_t fh; 5772 off_t off; 5773 off_t len; 5774 struct nfsmount *nmp; 5775 struct ucred *cred; 5776 NFSPROC_T *p; 5777 int err; 5778 }; 5779 5780 static int 5781 nfsrv_deallocatedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off, 5782 off_t len, struct nfsvattr *nap, struct ucred *cred, NFSPROC_T *p) 5783 { 5784 uint32_t *tl; 5785 struct nfsrv_descript *nd; 5786 nfsattrbit_t attrbits; 5787 nfsv4stateid_t st; 5788 int error; 5789 5790 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 5791 nfscl_reqstart(nd, NFSPROC_DEALLOCATE, nmp, (u_int8_t *)fhp, 5792 sizeof(fhandle_t), NULL, NULL, 0, 0, cred); 5793 5794 /* 5795 * Use a stateid where other is an alternating 01010 pattern and 5796 * seqid is 0xffffffff. This value is not defined as special by 5797 * the RFC and is used by the FreeBSD NFS server to indicate an 5798 * MDS->DS proxy operation. 5799 */ 5800 st.other[0] = 0x55555555; 5801 st.other[1] = 0x55555555; 5802 st.other[2] = 0x55555555; 5803 st.seqid = 0xffffffff; 5804 nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID); 5805 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED); 5806 txdr_hyper(off, tl); tl += 2; 5807 txdr_hyper(len, tl); tl += 2; 5808 NFSD_DEBUG(4, "nfsrv_deallocatedsdorpc: len=%jd\n", (intmax_t)len); 5809 5810 /* Do a Getattr for the attributes that change upon writing. */ 5811 NFSZERO_ATTRBIT(&attrbits); 5812 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE); 5813 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE); 5814 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS); 5815 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY); 5816 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED); 5817 *tl = txdr_unsigned(NFSV4OP_GETATTR); 5818 nfsrv_putattrbit(nd, &attrbits); 5819 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, 5820 cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); 5821 if (error != 0) { 5822 free(nd, M_TEMP); 5823 return (error); 5824 } 5825 NFSD_DEBUG(4, "nfsrv_deallocatedsdorpc: aft deallocaterpc=%d\n", 5826 nd->nd_repstat); 5827 /* Get rid of weak cache consistency data for now. */ 5828 if ((nd->nd_flag & (ND_NOMOREDATA | ND_NFSV4 | ND_V4WCCATTR)) == 5829 (ND_NFSV4 | ND_V4WCCATTR)) { 5830 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, 5831 NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 5832 NFSD_DEBUG(4, "nfsrv_deallocatedsdorpc: wcc attr=%d\n", error); 5833 if (error != 0) 5834 goto nfsmout; 5835 /* 5836 * Get rid of Op# and status for next op. 5837 */ 5838 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 5839 if (*++tl != 0) 5840 nd->nd_flag |= ND_NOMOREDATA; 5841 } 5842 if (nd->nd_repstat == 0) { 5843 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 5844 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL, 5845 NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 5846 } else 5847 error = nd->nd_repstat; 5848 NFSD_DEBUG(4, "nfsrv_deallocatedsdorpc: aft loadattr=%d\n", error); 5849 nfsmout: 5850 m_freem(nd->nd_mrep); 5851 free(nd, M_TEMP); 5852 NFSD_DEBUG(4, "nfsrv_deallocatedsdorpc error=%d\n", error); 5853 return (error); 5854 } 5855 5856 /* 5857 * Start up the thread that will execute nfsrv_deallocatedsdorpc(). 5858 */ 5859 static void 5860 start_deallocatedsdorpc(void *arg, int pending) 5861 { 5862 struct nfsrvdeallocatedsdorpc *drpc; 5863 5864 drpc = (struct nfsrvdeallocatedsdorpc *)arg; 5865 drpc->err = nfsrv_deallocatedsdorpc(drpc->nmp, &drpc->fh, drpc->off, 5866 drpc->len, NULL, drpc->cred, drpc->p); 5867 drpc->done = 1; 5868 NFSD_DEBUG(4, "start_deallocatedsdorpc: err=%d\n", drpc->err); 5869 } 5870 5871 static int 5872 nfsrv_deallocatedsrpc(fhandle_t *fhp, off_t off, off_t len, struct ucred *cred, 5873 NFSPROC_T *p, struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt, 5874 int *failposp) 5875 { 5876 struct nfsrvdeallocatedsdorpc *drpc, *tdrpc = NULL; 5877 struct nfsvattr na; 5878 int error, i, ret, timo; 5879 5880 NFSD_DEBUG(4, "in nfsrv_deallocatedsrpc\n"); 5881 drpc = NULL; 5882 if (mirrorcnt > 1) 5883 tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP, 5884 M_WAITOK); 5885 5886 /* 5887 * Do the deallocate RPC for every DS, using a separate kernel process 5888 * for every DS except the last one. 5889 */ 5890 error = 0; 5891 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 5892 tdrpc->done = 0; 5893 NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp)); 5894 tdrpc->off = off; 5895 tdrpc->len = len; 5896 tdrpc->nmp = *nmpp; 5897 tdrpc->cred = cred; 5898 tdrpc->p = p; 5899 tdrpc->inprog = 0; 5900 tdrpc->err = 0; 5901 ret = EIO; 5902 if (nfs_pnfsiothreads != 0) { 5903 ret = nfs_pnfsio(start_deallocatedsdorpc, tdrpc); 5904 NFSD_DEBUG(4, "nfsrv_deallocatedsrpc: nfs_pnfsio=%d\n", 5905 ret); 5906 } 5907 if (ret != 0) { 5908 ret = nfsrv_deallocatedsdorpc(*nmpp, fhp, off, len, 5909 NULL, cred, p); 5910 if (nfsds_failerr(ret) && *failposp == -1) 5911 *failposp = i; 5912 else if (error == 0 && ret != 0) 5913 error = ret; 5914 } 5915 nmpp++; 5916 fhp++; 5917 } 5918 ret = nfsrv_deallocatedsdorpc(*nmpp, fhp, off, len, &na, cred, p); 5919 if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1) 5920 *failposp = mirrorcnt - 1; 5921 else if (error == 0 && ret != 0) 5922 error = ret; 5923 if (error == 0) 5924 error = nfsrv_setextattr(vp, &na, p); 5925 NFSD_DEBUG(4, "nfsrv_deallocatedsrpc: aft setextat=%d\n", error); 5926 tdrpc = drpc; 5927 timo = hz / 50; /* Wait for 20msec. */ 5928 if (timo < 1) 5929 timo = 1; 5930 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 5931 /* Wait for RPCs on separate threads to complete. */ 5932 while (tdrpc->inprog != 0 && tdrpc->done == 0) 5933 tsleep(&tdrpc->tsk, PVFS, "srvalds", timo); 5934 if (nfsds_failerr(tdrpc->err) && *failposp == -1) 5935 *failposp = i; 5936 else if (error == 0 && tdrpc->err != 0) 5937 error = tdrpc->err; 5938 } 5939 free(drpc, M_TEMP); 5940 return (error); 5941 } 5942 5943 static int 5944 nfsrv_setattrdsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p, 5945 struct vnode *vp, struct nfsmount *nmp, struct nfsvattr *nap, 5946 struct nfsvattr *dsnap) 5947 { 5948 uint32_t *tl; 5949 struct nfsrv_descript *nd; 5950 nfsv4stateid_t st; 5951 nfsattrbit_t attrbits; 5952 int error; 5953 5954 NFSD_DEBUG(4, "in nfsrv_setattrdsdorpc\n"); 5955 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 5956 /* 5957 * Use a stateid where other is an alternating 01010 pattern and 5958 * seqid is 0xffffffff. This value is not defined as special by 5959 * the RFC and is used by the FreeBSD NFS server to indicate an 5960 * MDS->DS proxy operation. 5961 */ 5962 st.other[0] = 0x55555555; 5963 st.other[1] = 0x55555555; 5964 st.other[2] = 0x55555555; 5965 st.seqid = 0xffffffff; 5966 nfscl_reqstart(nd, NFSPROC_SETATTR, nmp, (u_int8_t *)fhp, sizeof(*fhp), 5967 NULL, NULL, 0, 0, cred); 5968 nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID); 5969 nfscl_fillsattr(nd, &nap->na_vattr, vp, NFSSATTR_FULL, 0); 5970 5971 /* Do a Getattr for the attributes that change due to writing. */ 5972 NFSZERO_ATTRBIT(&attrbits); 5973 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE); 5974 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE); 5975 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS); 5976 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY); 5977 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED); 5978 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 5979 *tl = txdr_unsigned(NFSV4OP_GETATTR); 5980 (void) nfsrv_putattrbit(nd, &attrbits); 5981 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred, 5982 NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); 5983 if (error != 0) { 5984 free(nd, M_TEMP); 5985 return (error); 5986 } 5987 NFSD_DEBUG(4, "nfsrv_setattrdsdorpc: aft setattrrpc=%d\n", 5988 nd->nd_repstat); 5989 /* Get rid of weak cache consistency data for now. */ 5990 if ((nd->nd_flag & (ND_NOMOREDATA | ND_NFSV4 | ND_V4WCCATTR)) == 5991 (ND_NFSV4 | ND_V4WCCATTR)) { 5992 error = nfsv4_loadattr(nd, NULL, dsnap, NULL, NULL, 0, NULL, 5993 NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 5994 NFSD_DEBUG(4, "nfsrv_setattrdsdorpc: wcc attr=%d\n", error); 5995 if (error != 0) 5996 goto nfsmout; 5997 /* 5998 * Get rid of Op# and status for next op. 5999 */ 6000 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 6001 if (*++tl != 0) 6002 nd->nd_flag |= ND_NOMOREDATA; 6003 } 6004 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL); 6005 if (error != 0) 6006 goto nfsmout; 6007 if (nd->nd_repstat != 0) 6008 error = nd->nd_repstat; 6009 /* 6010 * Get the Change, Size, Access Time and Modify Time attributes and set 6011 * on the Metadata file, so its attributes will be what the file's 6012 * would be if it had been written. 6013 */ 6014 if (error == 0) { 6015 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 6016 error = nfsv4_loadattr(nd, NULL, dsnap, NULL, NULL, 0, NULL, 6017 NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 6018 } 6019 NFSD_DEBUG(4, "nfsrv_setattrdsdorpc: aft setattr loadattr=%d\n", error); 6020 nfsmout: 6021 m_freem(nd->nd_mrep); 6022 free(nd, M_TEMP); 6023 NFSD_DEBUG(4, "nfsrv_setattrdsdorpc error=%d\n", error); 6024 return (error); 6025 } 6026 6027 struct nfsrvsetattrdsdorpc { 6028 int done; 6029 int inprog; 6030 struct task tsk; 6031 fhandle_t fh; 6032 struct nfsmount *nmp; 6033 struct vnode *vp; 6034 struct ucred *cred; 6035 NFSPROC_T *p; 6036 struct nfsvattr na; 6037 struct nfsvattr dsna; 6038 int err; 6039 }; 6040 6041 /* 6042 * Start up the thread that will execute nfsrv_setattrdsdorpc(). 6043 */ 6044 static void 6045 start_setattrdsdorpc(void *arg, int pending) 6046 { 6047 struct nfsrvsetattrdsdorpc *drpc; 6048 6049 drpc = (struct nfsrvsetattrdsdorpc *)arg; 6050 drpc->err = nfsrv_setattrdsdorpc(&drpc->fh, drpc->cred, drpc->p, 6051 drpc->vp, drpc->nmp, &drpc->na, &drpc->dsna); 6052 drpc->done = 1; 6053 } 6054 6055 static int 6056 nfsrv_setattrdsrpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p, 6057 struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt, 6058 struct nfsvattr *nap, int *failposp) 6059 { 6060 struct nfsrvsetattrdsdorpc *drpc, *tdrpc = NULL; 6061 struct nfsvattr na; 6062 int error, i, ret, timo; 6063 6064 NFSD_DEBUG(4, "in nfsrv_setattrdsrpc\n"); 6065 drpc = NULL; 6066 if (mirrorcnt > 1) 6067 tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP, 6068 M_WAITOK); 6069 6070 /* 6071 * Do the setattr RPC for every DS, using a separate kernel process 6072 * for every DS except the last one. 6073 */ 6074 error = 0; 6075 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 6076 tdrpc->done = 0; 6077 tdrpc->inprog = 0; 6078 NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp)); 6079 tdrpc->nmp = *nmpp; 6080 tdrpc->vp = vp; 6081 tdrpc->cred = cred; 6082 tdrpc->p = p; 6083 tdrpc->na = *nap; 6084 tdrpc->err = 0; 6085 ret = EIO; 6086 if (nfs_pnfsiothreads != 0) { 6087 ret = nfs_pnfsio(start_setattrdsdorpc, tdrpc); 6088 NFSD_DEBUG(4, "nfsrv_setattrdsrpc: nfs_pnfsio=%d\n", 6089 ret); 6090 } 6091 if (ret != 0) { 6092 ret = nfsrv_setattrdsdorpc(fhp, cred, p, vp, *nmpp, nap, 6093 &na); 6094 if (nfsds_failerr(ret) && *failposp == -1) 6095 *failposp = i; 6096 else if (error == 0 && ret != 0) 6097 error = ret; 6098 } 6099 nmpp++; 6100 fhp++; 6101 } 6102 ret = nfsrv_setattrdsdorpc(fhp, cred, p, vp, *nmpp, nap, &na); 6103 if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1) 6104 *failposp = mirrorcnt - 1; 6105 else if (error == 0 && ret != 0) 6106 error = ret; 6107 if (error == 0) 6108 error = nfsrv_setextattr(vp, &na, p); 6109 NFSD_DEBUG(4, "nfsrv_setattrdsrpc: aft setextat=%d\n", error); 6110 tdrpc = drpc; 6111 timo = hz / 50; /* Wait for 20msec. */ 6112 if (timo < 1) 6113 timo = 1; 6114 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 6115 /* Wait for RPCs on separate threads to complete. */ 6116 while (tdrpc->inprog != 0 && tdrpc->done == 0) 6117 tsleep(&tdrpc->tsk, PVFS, "srvsads", timo); 6118 if (nfsds_failerr(tdrpc->err) && *failposp == -1) 6119 *failposp = i; 6120 else if (error == 0 && tdrpc->err != 0) 6121 error = tdrpc->err; 6122 } 6123 free(drpc, M_TEMP); 6124 return (error); 6125 } 6126 6127 /* 6128 * Do a Setattr of an NFSv4 ACL on the DS file. 6129 */ 6130 static int 6131 nfsrv_setacldsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p, 6132 struct vnode *vp, struct nfsmount *nmp, struct acl *aclp) 6133 { 6134 struct nfsrv_descript *nd; 6135 nfsv4stateid_t st; 6136 nfsattrbit_t attrbits; 6137 int error; 6138 6139 NFSD_DEBUG(4, "in nfsrv_setacldsdorpc\n"); 6140 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 6141 /* 6142 * Use a stateid where other is an alternating 01010 pattern and 6143 * seqid is 0xffffffff. This value is not defined as special by 6144 * the RFC and is used by the FreeBSD NFS server to indicate an 6145 * MDS->DS proxy operation. 6146 */ 6147 st.other[0] = 0x55555555; 6148 st.other[1] = 0x55555555; 6149 st.other[2] = 0x55555555; 6150 st.seqid = 0xffffffff; 6151 nfscl_reqstart(nd, NFSPROC_SETACL, nmp, (u_int8_t *)fhp, sizeof(*fhp), 6152 NULL, NULL, 0, 0, cred); 6153 nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID); 6154 NFSZERO_ATTRBIT(&attrbits); 6155 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL); 6156 /* 6157 * The "vp" argument to nfsv4_fillattr() is only used for vnode_type(), 6158 * so passing in the metadata "vp" will be ok, since it is of 6159 * the same type (VREG). 6160 */ 6161 nfsv4_fillattr(nd, NULL, vp, aclp, NULL, NULL, 0, &attrbits, NULL, 6162 NULL, 0, 0, 0, 0, 0, NULL); 6163 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred, 6164 NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); 6165 if (error != 0) { 6166 free(nd, M_TEMP); 6167 return (error); 6168 } 6169 NFSD_DEBUG(4, "nfsrv_setacldsdorpc: aft setaclrpc=%d\n", 6170 nd->nd_repstat); 6171 error = nd->nd_repstat; 6172 m_freem(nd->nd_mrep); 6173 free(nd, M_TEMP); 6174 return (error); 6175 } 6176 6177 struct nfsrvsetacldsdorpc { 6178 int done; 6179 int inprog; 6180 struct task tsk; 6181 fhandle_t fh; 6182 struct nfsmount *nmp; 6183 struct vnode *vp; 6184 struct ucred *cred; 6185 NFSPROC_T *p; 6186 struct acl *aclp; 6187 int err; 6188 }; 6189 6190 /* 6191 * Start up the thread that will execute nfsrv_setacldsdorpc(). 6192 */ 6193 static void 6194 start_setacldsdorpc(void *arg, int pending) 6195 { 6196 struct nfsrvsetacldsdorpc *drpc; 6197 6198 drpc = (struct nfsrvsetacldsdorpc *)arg; 6199 drpc->err = nfsrv_setacldsdorpc(&drpc->fh, drpc->cred, drpc->p, 6200 drpc->vp, drpc->nmp, drpc->aclp); 6201 drpc->done = 1; 6202 } 6203 6204 static int 6205 nfsrv_setacldsrpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p, 6206 struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt, struct acl *aclp, 6207 int *failposp) 6208 { 6209 struct nfsrvsetacldsdorpc *drpc, *tdrpc = NULL; 6210 int error, i, ret, timo; 6211 6212 NFSD_DEBUG(4, "in nfsrv_setacldsrpc\n"); 6213 drpc = NULL; 6214 if (mirrorcnt > 1) 6215 tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP, 6216 M_WAITOK); 6217 6218 /* 6219 * Do the setattr RPC for every DS, using a separate kernel process 6220 * for every DS except the last one. 6221 */ 6222 error = 0; 6223 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 6224 tdrpc->done = 0; 6225 tdrpc->inprog = 0; 6226 NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp)); 6227 tdrpc->nmp = *nmpp; 6228 tdrpc->vp = vp; 6229 tdrpc->cred = cred; 6230 tdrpc->p = p; 6231 tdrpc->aclp = aclp; 6232 tdrpc->err = 0; 6233 ret = EIO; 6234 if (nfs_pnfsiothreads != 0) { 6235 ret = nfs_pnfsio(start_setacldsdorpc, tdrpc); 6236 NFSD_DEBUG(4, "nfsrv_setacldsrpc: nfs_pnfsio=%d\n", 6237 ret); 6238 } 6239 if (ret != 0) { 6240 ret = nfsrv_setacldsdorpc(fhp, cred, p, vp, *nmpp, 6241 aclp); 6242 if (nfsds_failerr(ret) && *failposp == -1) 6243 *failposp = i; 6244 else if (error == 0 && ret != 0) 6245 error = ret; 6246 } 6247 nmpp++; 6248 fhp++; 6249 } 6250 ret = nfsrv_setacldsdorpc(fhp, cred, p, vp, *nmpp, aclp); 6251 if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1) 6252 *failposp = mirrorcnt - 1; 6253 else if (error == 0 && ret != 0) 6254 error = ret; 6255 NFSD_DEBUG(4, "nfsrv_setacldsrpc: aft setextat=%d\n", error); 6256 tdrpc = drpc; 6257 timo = hz / 50; /* Wait for 20msec. */ 6258 if (timo < 1) 6259 timo = 1; 6260 for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) { 6261 /* Wait for RPCs on separate threads to complete. */ 6262 while (tdrpc->inprog != 0 && tdrpc->done == 0) 6263 tsleep(&tdrpc->tsk, PVFS, "srvacds", timo); 6264 if (nfsds_failerr(tdrpc->err) && *failposp == -1) 6265 *failposp = i; 6266 else if (error == 0 && tdrpc->err != 0) 6267 error = tdrpc->err; 6268 } 6269 free(drpc, M_TEMP); 6270 return (error); 6271 } 6272 6273 /* 6274 * Getattr call to the DS for the attributes that change due to writing. 6275 */ 6276 static int 6277 nfsrv_getattrdsrpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p, 6278 struct vnode *vp, struct nfsmount *nmp, struct nfsvattr *nap) 6279 { 6280 struct nfsrv_descript *nd; 6281 int error; 6282 nfsattrbit_t attrbits; 6283 6284 NFSD_DEBUG(4, "in nfsrv_getattrdsrpc\n"); 6285 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 6286 nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, (u_int8_t *)fhp, 6287 sizeof(fhandle_t), NULL, NULL, 0, 0, cred); 6288 NFSZERO_ATTRBIT(&attrbits); 6289 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE); 6290 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE); 6291 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS); 6292 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY); 6293 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED); 6294 (void) nfsrv_putattrbit(nd, &attrbits); 6295 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred, 6296 NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); 6297 if (error != 0) { 6298 free(nd, M_TEMP); 6299 return (error); 6300 } 6301 NFSD_DEBUG(4, "nfsrv_getattrdsrpc: aft getattrrpc=%d\n", 6302 nd->nd_repstat); 6303 if (nd->nd_repstat == 0) { 6304 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, 6305 NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 6306 NULL, NULL); 6307 /* 6308 * We can only save the updated values in the extended 6309 * attribute if the vp is exclusively locked. 6310 * This should happen when any of the following operations 6311 * occur on the vnode: 6312 * Close, Delegreturn, LayoutCommit, LayoutReturn 6313 * As such, the updated extended attribute should get saved 6314 * before nfsrv_checkdsattr() returns 0 and allows the cached 6315 * attributes to be returned without calling this function. 6316 */ 6317 if (error == 0 && VOP_ISLOCKED(vp) == LK_EXCLUSIVE) { 6318 error = nfsrv_setextattr(vp, nap, p); 6319 NFSD_DEBUG(4, "nfsrv_getattrdsrpc: aft setextat=%d\n", 6320 error); 6321 } 6322 } else 6323 error = nd->nd_repstat; 6324 m_freem(nd->nd_mrep); 6325 free(nd, M_TEMP); 6326 NFSD_DEBUG(4, "nfsrv_getattrdsrpc error=%d\n", error); 6327 return (error); 6328 } 6329 6330 /* 6331 * Seek call to a DS. 6332 */ 6333 static int 6334 nfsrv_seekdsrpc(fhandle_t *fhp, off_t *offp, int content, bool *eofp, 6335 struct ucred *cred, NFSPROC_T *p, struct nfsmount *nmp) 6336 { 6337 uint32_t *tl; 6338 struct nfsrv_descript *nd; 6339 nfsv4stateid_t st; 6340 int error; 6341 6342 NFSD_DEBUG(4, "in nfsrv_seekdsrpc\n"); 6343 /* 6344 * Use a stateid where other is an alternating 01010 pattern and 6345 * seqid is 0xffffffff. This value is not defined as special by 6346 * the RFC and is used by the FreeBSD NFS server to indicate an 6347 * MDS->DS proxy operation. 6348 */ 6349 st.other[0] = 0x55555555; 6350 st.other[1] = 0x55555555; 6351 st.other[2] = 0x55555555; 6352 st.seqid = 0xffffffff; 6353 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 6354 nfscl_reqstart(nd, NFSPROC_SEEKDS, nmp, (u_int8_t *)fhp, 6355 sizeof(fhandle_t), NULL, NULL, 0, 0, cred); 6356 nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID); 6357 NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED); 6358 txdr_hyper(*offp, tl); tl += 2; 6359 *tl = txdr_unsigned(content); 6360 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred, 6361 NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); 6362 if (error != 0) { 6363 free(nd, M_TEMP); 6364 return (error); 6365 } 6366 NFSD_DEBUG(4, "nfsrv_seekdsrpc: aft seekrpc=%d\n", nd->nd_repstat); 6367 if (nd->nd_repstat == 0) { 6368 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER); 6369 if (*tl++ == newnfs_true) 6370 *eofp = true; 6371 else 6372 *eofp = false; 6373 *offp = fxdr_hyper(tl); 6374 } else 6375 error = nd->nd_repstat; 6376 nfsmout: 6377 m_freem(nd->nd_mrep); 6378 free(nd, M_TEMP); 6379 NFSD_DEBUG(4, "nfsrv_seekdsrpc error=%d\n", error); 6380 return (error); 6381 } 6382 6383 /* 6384 * Get the device id and file handle for a DS file. 6385 */ 6386 int 6387 nfsrv_dsgetdevandfh(struct vnode *vp, NFSPROC_T *p, int *mirrorcntp, 6388 fhandle_t *fhp, char *devid) 6389 { 6390 int buflen, error; 6391 char *buf; 6392 6393 buflen = 1024; 6394 buf = malloc(buflen, M_TEMP, M_WAITOK); 6395 error = nfsrv_dsgetsockmnt(vp, 0, buf, &buflen, mirrorcntp, p, NULL, 6396 fhp, devid, NULL, NULL, NULL, NULL, NULL, NULL); 6397 free(buf, M_TEMP); 6398 return (error); 6399 } 6400 6401 /* 6402 * Do a Lookup against the DS for the filename. 6403 */ 6404 static int 6405 nfsrv_pnfslookupds(struct vnode *vp, struct vnode *dvp, struct pnfsdsfile *pf, 6406 struct vnode **nvpp, NFSPROC_T *p) 6407 { 6408 struct nameidata named; 6409 struct ucred *tcred; 6410 char *bufp; 6411 u_long *hashp; 6412 struct vnode *nvp; 6413 int error; 6414 6415 tcred = newnfs_getcred(); 6416 named.ni_cnd.cn_nameiop = LOOKUP; 6417 named.ni_cnd.cn_lkflags = LK_SHARED | LK_RETRY; 6418 named.ni_cnd.cn_cred = tcred; 6419 named.ni_cnd.cn_flags = ISLASTCN | LOCKPARENT | LOCKLEAF; 6420 nfsvno_setpathbuf(&named, &bufp, &hashp); 6421 named.ni_cnd.cn_nameptr = bufp; 6422 named.ni_cnd.cn_namelen = strlen(pf->dsf_filename); 6423 strlcpy(bufp, pf->dsf_filename, NAME_MAX); 6424 NFSD_DEBUG(4, "nfsrv_pnfslookupds: filename=%s\n", bufp); 6425 error = VOP_LOOKUP(dvp, &nvp, &named.ni_cnd); 6426 NFSD_DEBUG(4, "nfsrv_pnfslookupds: aft LOOKUP=%d\n", error); 6427 NFSFREECRED(tcred); 6428 nfsvno_relpathbuf(&named); 6429 if (error == 0) 6430 *nvpp = nvp; 6431 NFSD_DEBUG(4, "eo nfsrv_pnfslookupds=%d\n", error); 6432 return (error); 6433 } 6434 6435 /* 6436 * Set the file handle to the correct one. 6437 */ 6438 static void 6439 nfsrv_pnfssetfh(struct vnode *vp, struct pnfsdsfile *pf, char *devid, 6440 char *fnamep, struct vnode *nvp, NFSPROC_T *p) 6441 { 6442 struct nfsnode *np; 6443 int ret = 0; 6444 6445 np = VTONFS(nvp); 6446 NFSBCOPY(np->n_fhp->nfh_fh, &pf->dsf_fh, NFSX_MYFH); 6447 /* 6448 * We can only do a vn_set_extattr() if the vnode is exclusively 6449 * locked and vn_start_write() has been done. If devid != NULL or 6450 * fnamep != NULL or the vnode is shared locked, vn_start_write() 6451 * may not have been done. 6452 * If not done now, it will be done on a future call. 6453 */ 6454 if (devid == NULL && fnamep == NULL && NFSVOPISLOCKED(vp) == 6455 LK_EXCLUSIVE) 6456 ret = vn_extattr_set(vp, IO_NODELOCKED, 6457 EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile", sizeof(*pf), 6458 (char *)pf, p); 6459 NFSD_DEBUG(4, "eo nfsrv_pnfssetfh=%d\n", ret); 6460 } 6461 6462 /* 6463 * Cause RPCs waiting on "nmp" to fail. This is called for a DS mount point 6464 * when the DS has failed. 6465 */ 6466 void 6467 nfsrv_killrpcs(struct nfsmount *nmp) 6468 { 6469 6470 /* 6471 * Call newnfs_nmcancelreqs() to cause 6472 * any RPCs in progress on the mount point to 6473 * fail. 6474 * This will cause any process waiting for an 6475 * RPC to complete while holding a vnode lock 6476 * on the mounted-on vnode (such as "df" or 6477 * a non-forced "umount") to fail. 6478 * This will unlock the mounted-on vnode so 6479 * a forced dismount can succeed. 6480 * The NFSMNTP_CANCELRPCS flag should be set when this function is 6481 * called. 6482 */ 6483 newnfs_nmcancelreqs(nmp); 6484 } 6485 6486 /* 6487 * Sum up the statfs info for each of the DSs, so that the client will 6488 * receive the total for all DSs. 6489 */ 6490 static int 6491 nfsrv_pnfsstatfs(struct statfs *sf, struct mount *mp) 6492 { 6493 struct statfs *tsf; 6494 struct nfsdevice *ds; 6495 struct vnode **dvpp, **tdvpp, *dvp; 6496 uint64_t tot; 6497 int cnt, error = 0, i; 6498 6499 if (nfsrv_devidcnt <= 0) 6500 return (ENXIO); 6501 dvpp = mallocarray(nfsrv_devidcnt, sizeof(*dvpp), M_TEMP, M_WAITOK); 6502 tsf = malloc(sizeof(*tsf), M_TEMP, M_WAITOK); 6503 6504 /* Get an array of the dvps for the DSs. */ 6505 tdvpp = dvpp; 6506 i = 0; 6507 NFSDDSLOCK(); 6508 /* First, search for matches for same file system. */ 6509 TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) { 6510 if (ds->nfsdev_nmp != NULL && ds->nfsdev_mdsisset != 0 && 6511 fsidcmp(&ds->nfsdev_mdsfsid, &mp->mnt_stat.f_fsid) == 0) { 6512 if (++i > nfsrv_devidcnt) 6513 break; 6514 *tdvpp++ = ds->nfsdev_dvp; 6515 } 6516 } 6517 /* 6518 * If no matches for same file system, total all servers not assigned 6519 * to a file system. 6520 */ 6521 if (i == 0) { 6522 TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) { 6523 if (ds->nfsdev_nmp != NULL && 6524 ds->nfsdev_mdsisset == 0) { 6525 if (++i > nfsrv_devidcnt) 6526 break; 6527 *tdvpp++ = ds->nfsdev_dvp; 6528 } 6529 } 6530 } 6531 NFSDDSUNLOCK(); 6532 cnt = i; 6533 6534 /* Do a VFS_STATFS() for each of the DSs and sum them up. */ 6535 tdvpp = dvpp; 6536 for (i = 0; i < cnt && error == 0; i++) { 6537 dvp = *tdvpp++; 6538 error = VFS_STATFS(dvp->v_mount, tsf); 6539 if (error == 0) { 6540 if (sf->f_bsize == 0) { 6541 if (tsf->f_bsize > 0) 6542 sf->f_bsize = tsf->f_bsize; 6543 else 6544 sf->f_bsize = 8192; 6545 } 6546 if (tsf->f_blocks > 0) { 6547 if (sf->f_bsize != tsf->f_bsize) { 6548 tot = tsf->f_blocks * tsf->f_bsize; 6549 sf->f_blocks += (tot / sf->f_bsize); 6550 } else 6551 sf->f_blocks += tsf->f_blocks; 6552 } 6553 if (tsf->f_bfree > 0) { 6554 if (sf->f_bsize != tsf->f_bsize) { 6555 tot = tsf->f_bfree * tsf->f_bsize; 6556 sf->f_bfree += (tot / sf->f_bsize); 6557 } else 6558 sf->f_bfree += tsf->f_bfree; 6559 } 6560 if (tsf->f_bavail > 0) { 6561 if (sf->f_bsize != tsf->f_bsize) { 6562 tot = tsf->f_bavail * tsf->f_bsize; 6563 sf->f_bavail += (tot / sf->f_bsize); 6564 } else 6565 sf->f_bavail += tsf->f_bavail; 6566 } 6567 } 6568 } 6569 free(tsf, M_TEMP); 6570 free(dvpp, M_TEMP); 6571 return (error); 6572 } 6573 6574 /* 6575 * Set an NFSv4 acl. 6576 */ 6577 int 6578 nfsrv_setacl(struct vnode *vp, NFSACL_T *aclp, struct ucred *cred, NFSPROC_T *p) 6579 { 6580 int error; 6581 6582 if (nfsrv_useacl == 0 || nfs_supportsnfsv4acls(vp) == 0) { 6583 error = NFSERR_ATTRNOTSUPP; 6584 goto out; 6585 } 6586 /* 6587 * With NFSv4 ACLs, chmod(2) may need to add additional entries. 6588 * Make sure it has enough room for that - splitting every entry 6589 * into two and appending "canonical six" entries at the end. 6590 * Cribbed out of kern/vfs_acl.c - Rick M. 6591 */ 6592 if (aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2) { 6593 error = NFSERR_ATTRNOTSUPP; 6594 goto out; 6595 } 6596 error = VOP_SETACL(vp, ACL_TYPE_NFS4, aclp, cred, p); 6597 if (error == 0) { 6598 error = nfsrv_dssetacl(vp, aclp, cred, p); 6599 if (error == ENOENT) 6600 error = 0; 6601 } 6602 6603 out: 6604 NFSEXITCODE(error); 6605 return (error); 6606 } 6607 6608 /* 6609 * Seek vnode op call (actually it is a VOP_IOCTL()). 6610 * This function is called with the vnode locked, but unlocks and vrele()s 6611 * the vp before returning. 6612 */ 6613 int 6614 nfsvno_seek(struct nfsrv_descript *nd, struct vnode *vp, u_long cmd, 6615 off_t *offp, int content, bool *eofp, struct ucred *cred, NFSPROC_T *p) 6616 { 6617 struct nfsvattr at; 6618 int error, ret; 6619 6620 ASSERT_VOP_LOCKED(vp, "nfsvno_seek vp"); 6621 /* 6622 * Attempt to seek on a DS file. A return of ENOENT implies 6623 * there is no DS file to seek on. 6624 */ 6625 error = nfsrv_proxyds(vp, 0, 0, cred, p, NFSPROC_SEEKDS, NULL, 6626 NULL, NULL, NULL, NULL, offp, content, eofp); 6627 if (error != ENOENT) { 6628 vput(vp); 6629 return (error); 6630 } 6631 6632 /* 6633 * Do the VOP_IOCTL() call. For the case where *offp == file_size, 6634 * VOP_IOCTL() will return ENXIO. However, the correct reply for 6635 * NFSv4.2 is *eofp == true and error == 0 for this case. 6636 */ 6637 NFSVOPUNLOCK(vp); 6638 error = VOP_IOCTL(vp, cmd, offp, 0, cred, p); 6639 *eofp = false; 6640 if (error == ENXIO || (error == 0 && cmd == FIOSEEKHOLE)) { 6641 /* Handle the cases where we might be at EOF. */ 6642 ret = nfsvno_getattr(vp, &at, nd, p, 0, NULL); 6643 if (ret == 0 && *offp == at.na_size) { 6644 *eofp = true; 6645 error = 0; 6646 } 6647 if (ret != 0 && error == 0) 6648 error = ret; 6649 } 6650 vrele(vp); 6651 NFSEXITCODE(error); 6652 return (error); 6653 } 6654 6655 /* 6656 * Allocate vnode op call. 6657 */ 6658 int 6659 nfsvno_allocate(struct vnode *vp, off_t off, off_t len, struct ucred *cred, 6660 NFSPROC_T *p) 6661 { 6662 int error; 6663 off_t olen; 6664 6665 ASSERT_VOP_ELOCKED(vp, "nfsvno_allocate vp"); 6666 /* 6667 * Attempt to allocate on a DS file. A return of ENOENT implies 6668 * there is no DS file to allocate on. 6669 */ 6670 error = nfsrv_proxyds(vp, off, 0, cred, p, NFSPROC_ALLOCATE, NULL, 6671 NULL, NULL, NULL, NULL, &len, 0, NULL); 6672 if (error != ENOENT) 6673 return (error); 6674 6675 /* 6676 * Do the actual VOP_ALLOCATE(), looping so long as 6677 * progress is being made, to achieve completion. 6678 */ 6679 do { 6680 olen = len; 6681 error = VOP_ALLOCATE(vp, &off, &len, IO_SYNC, cred); 6682 if (error == 0 && len > 0 && olen > len) 6683 maybe_yield(); 6684 } while (error == 0 && len > 0 && olen > len); 6685 if (error == 0 && len > 0) 6686 error = NFSERR_IO; 6687 NFSEXITCODE(error); 6688 return (error); 6689 } 6690 6691 /* 6692 * Deallocate vnode op call. 6693 */ 6694 int 6695 nfsvno_deallocate(struct vnode *vp, off_t off, off_t len, struct ucred *cred, 6696 NFSPROC_T *p) 6697 { 6698 int error; 6699 off_t olen; 6700 6701 ASSERT_VOP_ELOCKED(vp, "nfsvno_deallocate vp"); 6702 /* 6703 * Attempt to deallocate on a DS file. A return of ENOENT implies 6704 * there is no DS file to deallocate on. 6705 */ 6706 error = nfsrv_proxyds(vp, off, 0, cred, p, NFSPROC_DEALLOCATE, NULL, 6707 NULL, NULL, NULL, NULL, &len, 0, NULL); 6708 if (error != ENOENT) 6709 return (error); 6710 6711 /* 6712 * Do the actual VOP_DEALLOCATE(), looping so long as 6713 * progress is being made, to achieve completion. 6714 */ 6715 do { 6716 olen = len; 6717 error = VOP_DEALLOCATE(vp, &off, &len, 0, IO_SYNC, cred); 6718 if (error == 0 && len > 0 && olen > len) 6719 maybe_yield(); 6720 } while (error == 0 && len > 0 && olen > len); 6721 if (error == 0 && len > 0) 6722 error = NFSERR_IO; 6723 NFSEXITCODE(error); 6724 return (error); 6725 } 6726 6727 /* 6728 * Get Extended Atribute vnode op into an mbuf list. 6729 */ 6730 int 6731 nfsvno_getxattr(struct vnode *vp, char *name, uint32_t maxresp, 6732 struct ucred *cred, uint64_t flag, int maxextsiz, struct thread *p, 6733 struct mbuf **mpp, struct mbuf **mpendp, int *lenp) 6734 { 6735 struct iovec *iv; 6736 struct uio io, *uiop = &io; 6737 struct mbuf *m, *m2; 6738 int alen, error, len, tlen; 6739 size_t siz; 6740 6741 /* First, find out the size of the extended attribute. */ 6742 error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL, 6743 &siz, cred, p); 6744 if (error != 0) 6745 return (NFSERR_NOXATTR); 6746 if (siz > maxresp - NFS_MAXXDR) 6747 return (NFSERR_XATTR2BIG); 6748 len = siz; 6749 tlen = NFSM_RNDUP(len); 6750 if (tlen > 0) { 6751 /* 6752 * If cnt > MCLBYTES and the reply will not be saved, use 6753 * ext_pgs mbufs for TLS. 6754 * For NFSv4.0, we do not know for sure if the reply will 6755 * be saved, so do not use ext_pgs mbufs for NFSv4.0. 6756 * Always use ext_pgs mbufs if ND_EXTPG is set. 6757 */ 6758 if ((flag & ND_EXTPG) != 0 || (tlen > MCLBYTES && 6759 (flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS && 6760 (flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4)) 6761 uiop->uio_iovcnt = nfsrv_createiovec_extpgs(tlen, 6762 maxextsiz, &m, &m2, &iv); 6763 else 6764 uiop->uio_iovcnt = nfsrv_createiovec(tlen, &m, &m2, 6765 &iv); 6766 uiop->uio_iov = iv; 6767 } else { 6768 uiop->uio_iovcnt = 0; 6769 uiop->uio_iov = iv = NULL; 6770 m = m2 = NULL; 6771 } 6772 uiop->uio_offset = 0; 6773 uiop->uio_resid = tlen; 6774 uiop->uio_rw = UIO_READ; 6775 uiop->uio_segflg = UIO_SYSSPACE; 6776 uiop->uio_td = p; 6777 #ifdef MAC 6778 error = mac_vnode_check_getextattr(cred, vp, EXTATTR_NAMESPACE_USER, 6779 name); 6780 if (error != 0) 6781 goto out; 6782 #endif 6783 6784 if (tlen > 0) 6785 error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop, 6786 NULL, cred, p); 6787 if (error != 0) 6788 goto out; 6789 if (uiop->uio_resid > 0) { 6790 alen = tlen; 6791 len = tlen - uiop->uio_resid; 6792 tlen = NFSM_RNDUP(len); 6793 if (alen != tlen) 6794 printf("nfsvno_getxattr: weird size read\n"); 6795 if (tlen == 0) { 6796 m_freem(m); 6797 m = m2 = NULL; 6798 } else if (alen != tlen || tlen != len) 6799 m2 = nfsrv_adj(m, alen - tlen, tlen - len); 6800 } 6801 *lenp = len; 6802 *mpp = m; 6803 *mpendp = m2; 6804 6805 out: 6806 if (error != 0) { 6807 if (m != NULL) 6808 m_freem(m); 6809 *lenp = 0; 6810 } 6811 free(iv, M_TEMP); 6812 NFSEXITCODE(error); 6813 return (error); 6814 } 6815 6816 /* 6817 * Set Extended attribute vnode op from an mbuf list. 6818 */ 6819 int 6820 nfsvno_setxattr(struct vnode *vp, char *name, int len, struct mbuf *m, 6821 char *cp, struct ucred *cred, struct thread *p) 6822 { 6823 struct iovec *iv; 6824 struct uio uio, *uiop = &uio; 6825 int cnt, error; 6826 6827 error = 0; 6828 #ifdef MAC 6829 error = mac_vnode_check_setextattr(cred, vp, EXTATTR_NAMESPACE_USER, 6830 name); 6831 #endif 6832 if (error != 0) 6833 goto out; 6834 6835 uiop->uio_rw = UIO_WRITE; 6836 uiop->uio_segflg = UIO_SYSSPACE; 6837 uiop->uio_td = p; 6838 uiop->uio_offset = 0; 6839 uiop->uio_resid = len; 6840 if (len > 0) { 6841 error = nfsrv_createiovecw(len, m, cp, &iv, &cnt); 6842 uiop->uio_iov = iv; 6843 uiop->uio_iovcnt = cnt; 6844 } else { 6845 uiop->uio_iov = iv = NULL; 6846 uiop->uio_iovcnt = 0; 6847 } 6848 if (error == 0) { 6849 error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop, 6850 cred, p); 6851 if (error == 0) { 6852 if (vp->v_type == VREG && nfsrv_devidcnt != 0) 6853 nfsvno_updateds(vp, cred, p); 6854 error = VOP_FSYNC(vp, MNT_WAIT, p); 6855 } 6856 free(iv, M_TEMP); 6857 } 6858 6859 out: 6860 NFSEXITCODE(error); 6861 return (error); 6862 } 6863 6864 /* 6865 * For a pNFS server, the DS file's ctime and 6866 * va_filerev (TimeMetadata and Change) needs to 6867 * be updated. This is a hack, but works by 6868 * flipping the S_ISGID bit in va_mode and then 6869 * flipping it back. 6870 * It does result in two MDS->DS RPCs, but creating 6871 * a custom RPC just to do this seems overkill, since 6872 * Setxattr/Rmxattr will not be done that frequently. 6873 * If it fails part way through, that is not too 6874 * serious, since the DS file is never executed. 6875 */ 6876 static void 6877 nfsvno_updateds(struct vnode *vp, struct ucred *cred, NFSPROC_T *p) 6878 { 6879 struct nfsvattr nva; 6880 int ret; 6881 u_short tmode; 6882 6883 ret = VOP_GETATTR(vp, &nva.na_vattr, cred); 6884 if (ret == 0) { 6885 tmode = nva.na_mode; 6886 NFSVNO_ATTRINIT(&nva); 6887 tmode ^= S_ISGID; 6888 NFSVNO_SETATTRVAL(&nva, mode, tmode); 6889 ret = nfsrv_proxyds(vp, 0, 0, cred, p, 6890 NFSPROC_SETATTR, NULL, NULL, NULL, &nva, 6891 NULL, NULL, 0, NULL); 6892 if (ret == 0) { 6893 tmode ^= S_ISGID; 6894 NFSVNO_SETATTRVAL(&nva, mode, tmode); 6895 ret = nfsrv_proxyds(vp, 0, 0, cred, p, 6896 NFSPROC_SETATTR, NULL, NULL, NULL, 6897 &nva, NULL, NULL, 0, NULL); 6898 } 6899 } 6900 } 6901 6902 /* 6903 * Remove Extended attribute vnode op. 6904 */ 6905 int 6906 nfsvno_rmxattr(struct nfsrv_descript *nd, struct vnode *vp, char *name, 6907 struct ucred *cred, struct thread *p) 6908 { 6909 int error; 6910 6911 /* 6912 * Get rid of any delegations. I am not sure why this is required, 6913 * but RFC-8276 says so. 6914 */ 6915 error = nfsrv_checkremove(vp, 0, nd, nd->nd_clientid, p); 6916 if (error != 0) 6917 goto out; 6918 #ifdef MAC 6919 error = mac_vnode_check_deleteextattr(cred, vp, EXTATTR_NAMESPACE_USER, 6920 name); 6921 if (error != 0) 6922 goto out; 6923 #endif 6924 6925 error = VOP_DELETEEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, cred, p); 6926 if (error == EOPNOTSUPP) 6927 error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL, 6928 cred, p); 6929 if (error == 0) { 6930 if (vp->v_type == VREG && nfsrv_devidcnt != 0) 6931 nfsvno_updateds(vp, cred, p); 6932 error = VOP_FSYNC(vp, MNT_WAIT, p); 6933 } 6934 out: 6935 NFSEXITCODE(error); 6936 return (error); 6937 } 6938 6939 /* 6940 * List Extended Atribute vnode op into an mbuf list. 6941 */ 6942 int 6943 nfsvno_listxattr(struct vnode *vp, uint64_t cookie, struct ucred *cred, 6944 struct thread *p, u_char **bufp, uint32_t *lenp, bool *eofp) 6945 { 6946 struct iovec iv; 6947 struct uio io; 6948 int error; 6949 size_t siz; 6950 6951 *bufp = NULL; 6952 /* First, find out the size of the extended attribute. */ 6953 error = VOP_LISTEXTATTR(vp, EXTATTR_NAMESPACE_USER, NULL, &siz, cred, 6954 p); 6955 if (error != 0) 6956 return (NFSERR_NOXATTR); 6957 if (siz <= cookie) { 6958 *lenp = 0; 6959 *eofp = true; 6960 goto out; 6961 } 6962 if (siz > cookie + *lenp) { 6963 siz = cookie + *lenp; 6964 *eofp = false; 6965 } else 6966 *eofp = true; 6967 /* Just choose a sanity limit of 10Mbytes for malloc(M_TEMP). */ 6968 if (siz > 10 * 1024 * 1024) { 6969 error = NFSERR_XATTR2BIG; 6970 goto out; 6971 } 6972 *bufp = malloc(siz, M_TEMP, M_WAITOK); 6973 iv.iov_base = *bufp; 6974 iv.iov_len = siz; 6975 io.uio_iovcnt = 1; 6976 io.uio_iov = &iv; 6977 io.uio_offset = 0; 6978 io.uio_resid = siz; 6979 io.uio_rw = UIO_READ; 6980 io.uio_segflg = UIO_SYSSPACE; 6981 io.uio_td = p; 6982 #ifdef MAC 6983 error = mac_vnode_check_listextattr(cred, vp, EXTATTR_NAMESPACE_USER); 6984 if (error != 0) 6985 goto out; 6986 #endif 6987 6988 error = VOP_LISTEXTATTR(vp, EXTATTR_NAMESPACE_USER, &io, NULL, cred, 6989 p); 6990 if (error != 0) 6991 goto out; 6992 if (io.uio_resid > 0) 6993 siz -= io.uio_resid; 6994 *lenp = siz; 6995 6996 out: 6997 if (error != 0) { 6998 free(*bufp, M_TEMP); 6999 *bufp = NULL; 7000 } 7001 NFSEXITCODE(error); 7002 return (error); 7003 } 7004 7005 /* 7006 * Trim trailing data off the mbuf list being built. 7007 */ 7008 void 7009 nfsm_trimtrailing(struct nfsrv_descript *nd, struct mbuf *mb, char *bpos, 7010 int bextpg, int bextpgsiz) 7011 { 7012 vm_page_t pg; 7013 int fullpgsiz, i; 7014 7015 if (mb->m_next != NULL) { 7016 m_freem(mb->m_next); 7017 mb->m_next = NULL; 7018 } 7019 if ((mb->m_flags & M_EXTPG) != 0) { 7020 KASSERT(bextpg >= 0 && bextpg < mb->m_epg_npgs, 7021 ("nfsm_trimtrailing: bextpg out of range")); 7022 KASSERT(bpos == (char *)(void *) 7023 PHYS_TO_DMAP(mb->m_epg_pa[bextpg]) + PAGE_SIZE - bextpgsiz, 7024 ("nfsm_trimtrailing: bextpgsiz bad!")); 7025 7026 /* First, get rid of any pages after this position. */ 7027 for (i = mb->m_epg_npgs - 1; i > bextpg; i--) { 7028 pg = PHYS_TO_VM_PAGE(mb->m_epg_pa[i]); 7029 vm_page_unwire_noq(pg); 7030 vm_page_free(pg); 7031 } 7032 mb->m_epg_npgs = bextpg + 1; 7033 if (bextpg == 0) 7034 fullpgsiz = PAGE_SIZE - mb->m_epg_1st_off; 7035 else 7036 fullpgsiz = PAGE_SIZE; 7037 mb->m_epg_last_len = fullpgsiz - bextpgsiz; 7038 mb->m_len = m_epg_pagelen(mb, 0, mb->m_epg_1st_off); 7039 for (i = 1; i < mb->m_epg_npgs; i++) 7040 mb->m_len += m_epg_pagelen(mb, i, 0); 7041 nd->nd_bextpgsiz = bextpgsiz; 7042 nd->nd_bextpg = bextpg; 7043 } else 7044 mb->m_len = bpos - mtod(mb, char *); 7045 nd->nd_mb = mb; 7046 nd->nd_bpos = bpos; 7047 } 7048 7049 7050 /* 7051 * Check to see if a put file handle operation should test for 7052 * NFSERR_WRONGSEC, although NFSv3 actually returns NFSERR_AUTHERR. 7053 * When Open is the next operation, NFSERR_WRONGSEC cannot be 7054 * replied for the Open cases that use a component. This can 7055 * be identified by the fact that the file handle's type is VDIR. 7056 */ 7057 bool 7058 nfsrv_checkwrongsec(struct nfsrv_descript *nd, int nextop, __enum_uint8(vtype) vtyp) 7059 { 7060 7061 if ((nd->nd_flag & ND_NFSV4) == 0) 7062 return (true); 7063 7064 if ((nd->nd_flag & ND_LASTOP) != 0) 7065 return (false); 7066 7067 if (nextop == NFSV4OP_PUTROOTFH || nextop == NFSV4OP_PUTFH || 7068 nextop == NFSV4OP_PUTPUBFH || nextop == NFSV4OP_RESTOREFH || 7069 nextop == NFSV4OP_LOOKUP || nextop == NFSV4OP_LOOKUPP || 7070 nextop == NFSV4OP_SECINFO || nextop == NFSV4OP_SECINFONONAME) 7071 return (false); 7072 if (nextop == NFSV4OP_OPEN && vtyp == VDIR) 7073 return (false); 7074 return (true); 7075 } 7076 7077 /* 7078 * Check DSs marked no space. 7079 */ 7080 void 7081 nfsrv_checknospc(void) 7082 { 7083 struct statfs *tsf; 7084 struct nfsdevice *ds; 7085 struct vnode **dvpp, **tdvpp, *dvp; 7086 char *devid, *tdevid; 7087 int cnt, error = 0, i; 7088 7089 if (nfsrv_devidcnt <= 0) 7090 return; 7091 dvpp = mallocarray(nfsrv_devidcnt, sizeof(*dvpp), M_TEMP, M_WAITOK); 7092 devid = malloc(nfsrv_devidcnt * NFSX_V4DEVICEID, M_TEMP, M_WAITOK); 7093 tsf = malloc(sizeof(*tsf), M_TEMP, M_WAITOK); 7094 7095 /* Get an array of the dvps for the DSs. */ 7096 tdvpp = dvpp; 7097 tdevid = devid; 7098 i = 0; 7099 NFSDDSLOCK(); 7100 /* First, search for matches for same file system. */ 7101 TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) { 7102 if (ds->nfsdev_nmp != NULL && ds->nfsdev_nospc) { 7103 if (++i > nfsrv_devidcnt) 7104 break; 7105 *tdvpp++ = ds->nfsdev_dvp; 7106 NFSBCOPY(ds->nfsdev_deviceid, tdevid, NFSX_V4DEVICEID); 7107 tdevid += NFSX_V4DEVICEID; 7108 } 7109 } 7110 NFSDDSUNLOCK(); 7111 7112 /* Do a VFS_STATFS() for each of the DSs and clear no space. */ 7113 cnt = i; 7114 tdvpp = dvpp; 7115 tdevid = devid; 7116 for (i = 0; i < cnt && error == 0; i++) { 7117 dvp = *tdvpp++; 7118 error = VFS_STATFS(dvp->v_mount, tsf); 7119 if (error == 0 && tsf->f_bavail > 0) { 7120 NFSD_DEBUG(1, "nfsrv_checknospc: reset nospc\n"); 7121 nfsrv_marknospc(tdevid, false); 7122 } 7123 tdevid += NFSX_V4DEVICEID; 7124 } 7125 free(tsf, M_TEMP); 7126 free(dvpp, M_TEMP); 7127 free(devid, M_TEMP); 7128 } 7129 7130 /* 7131 * Initialize everything that needs to be initialized for a vnet. 7132 */ 7133 static void 7134 nfsrv_vnetinit(const void *unused __unused) 7135 { 7136 7137 nfsd_mntinit(); 7138 } 7139 VNET_SYSINIT(nfsrv_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY, 7140 nfsrv_vnetinit, NULL); 7141 7142 /* 7143 * Clean up everything that is in a vnet and needs to be 7144 * done when the jail is destroyed or the module unloaded. 7145 */ 7146 static void 7147 nfsrv_cleanup(const void *unused __unused) 7148 { 7149 int i; 7150 7151 NFSD_LOCK(); 7152 if (!NFSD_VNET(nfsrv_mntinited)) { 7153 NFSD_UNLOCK(); 7154 return; 7155 } 7156 NFSD_VNET(nfsrv_mntinited) = false; 7157 NFSD_UNLOCK(); 7158 7159 /* Clean out all NFSv4 state. */ 7160 nfsrv_throwawayallstate(curthread); 7161 7162 /* Clean the NFS server reply cache */ 7163 nfsrvd_cleancache(); 7164 7165 /* Clean out v4root exports. */ 7166 if (NFSD_VNET(nfsv4root_mnt)->mnt_export != NULL) { 7167 vfs_free_addrlist(NFSD_VNET(nfsv4root_mnt)->mnt_export); 7168 free(NFSD_VNET(nfsv4root_mnt)->mnt_export, M_MOUNT); 7169 NFSD_VNET(nfsv4root_mnt)->mnt_export = NULL; 7170 } 7171 7172 /* Free up the krpc server pool. */ 7173 if (NFSD_VNET(nfsrvd_pool) != NULL) 7174 svcpool_destroy(NFSD_VNET(nfsrvd_pool)); 7175 7176 /* and get rid of the locks */ 7177 for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { 7178 mtx_destroy(&NFSD_VNET(nfsrchash_table)[i].mtx); 7179 mtx_destroy(&NFSD_VNET(nfsrcahash_table)[i].mtx); 7180 } 7181 mtx_destroy(&NFSD_VNET(nfsv4root_mnt)->mnt_mtx); 7182 for (i = 0; i < nfsrv_sessionhashsize; i++) 7183 mtx_destroy(&NFSD_VNET(nfssessionhash)[i].mtx); 7184 lockdestroy(&NFSD_VNET(nfsv4root_mnt)->mnt_explock); 7185 free(NFSD_VNET(nfsrvudphashtbl), M_NFSRVCACHE); 7186 free(NFSD_VNET(nfsrchash_table), M_NFSRVCACHE); 7187 free(NFSD_VNET(nfsrcahash_table), M_NFSRVCACHE); 7188 free(NFSD_VNET(nfsclienthash), M_NFSDCLIENT); 7189 free(NFSD_VNET(nfslockhash), M_NFSDLOCKFILE); 7190 free(NFSD_VNET(nfssessionhash), M_NFSDSESSION); 7191 free(NFSD_VNET(nfsv4root_mnt), M_TEMP); 7192 NFSD_VNET(nfsv4root_mnt) = NULL; 7193 } 7194 VNET_SYSUNINIT(nfsrv_cleanup, SI_SUB_VNET_DONE, SI_ORDER_ANY, 7195 nfsrv_cleanup, NULL); 7196 7197 extern int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *); 7198 7199 /* 7200 * Called once to initialize data structures... 7201 */ 7202 static int 7203 nfsd_modevent(module_t mod, int type, void *data) 7204 { 7205 int error = 0, i; 7206 static int loaded = 0; 7207 7208 switch (type) { 7209 case MOD_LOAD: 7210 if (loaded) 7211 goto out; 7212 newnfs_portinit(); 7213 mtx_init(&nfsrc_udpmtx, "nfsuc", NULL, MTX_DEF); 7214 mtx_init(&nfs_v4root_mutex, "nfs4rt", NULL, MTX_DEF); 7215 mtx_init(&nfsrv_dontlistlock_mtx, "nfs4dnl", NULL, MTX_DEF); 7216 mtx_init(&nfsrv_recalllock_mtx, "nfs4rec", NULL, MTX_DEF); 7217 #ifdef VV_DISABLEDELEG 7218 vn_deleg_ops.vndeleg_recall = nfsd_recalldelegation; 7219 vn_deleg_ops.vndeleg_disable = nfsd_disabledelegation; 7220 #endif 7221 nfsd_call_nfsd = nfssvc_nfsd; 7222 loaded = 1; 7223 break; 7224 7225 case MOD_UNLOAD: 7226 if (newnfs_numnfsd != 0) { 7227 error = EBUSY; 7228 break; 7229 } 7230 7231 #ifdef VV_DISABLEDELEG 7232 vn_deleg_ops.vndeleg_recall = NULL; 7233 vn_deleg_ops.vndeleg_disable = NULL; 7234 #endif 7235 nfsd_call_nfsd = NULL; 7236 mtx_destroy(&nfsrc_udpmtx); 7237 mtx_destroy(&nfs_v4root_mutex); 7238 mtx_destroy(&nfsrv_dontlistlock_mtx); 7239 mtx_destroy(&nfsrv_recalllock_mtx); 7240 if (nfslayouthash != NULL) { 7241 for (i = 0; i < nfsrv_layouthashsize; i++) 7242 mtx_destroy(&nfslayouthash[i].mtx); 7243 free(nfslayouthash, M_NFSDSESSION); 7244 } 7245 loaded = 0; 7246 break; 7247 default: 7248 error = EOPNOTSUPP; 7249 break; 7250 } 7251 7252 out: 7253 NFSEXITCODE(error); 7254 return (error); 7255 } 7256 static moduledata_t nfsd_mod = { 7257 "nfsd", 7258 nfsd_modevent, 7259 NULL, 7260 }; 7261 DECLARE_MODULE(nfsd, nfsd_mod, SI_SUB_VFS, SI_ORDER_ANY); 7262 7263 /* So that loader and kldload(2) can find us, wherever we are.. */ 7264 MODULE_VERSION(nfsd, 1); 7265 MODULE_DEPEND(nfsd, nfscommon, 1, 1, 1); 7266 MODULE_DEPEND(nfsd, nfslockd, 1, 1, 1); 7267 MODULE_DEPEND(nfsd, krpc, 1, 1, 1); 7268 MODULE_DEPEND(nfsd, nfssvc, 1, 1, 1); 7269