1/*- 2 * Copyright (c) 2010-2012 Semihalf 3 * Copyright (c) 2008, 2009 Reinoud Zandijk 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * From: NetBSD: nilfs_vnops.c,v 1.2 2009/08/26 03:40:48 elad 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: stable/11/sys/fs/nandfs/nandfs_vnops.c 346032 2019-04-08 15:52:13Z sjg $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/conf.h> 35#include <sys/kernel.h> 36#include <sys/lock.h> 37#include <sys/lockf.h> 38#include <sys/malloc.h> 39#include <sys/mount.h> 40#include <sys/mutex.h> 41#include <sys/namei.h> 42#include <sys/sysctl.h> 43#include <sys/unistd.h> 44#include <sys/vnode.h> 45#include <sys/buf.h> 46#include <sys/bio.h> 47#include <sys/fcntl.h> 48#include <sys/dirent.h> 49#include <sys/rwlock.h> 50#include <sys/stat.h> 51#include <sys/priv.h> 52 53#include <vm/vm.h> 54#include <vm/vm_extern.h> 55#include <vm/vm_object.h> 56#include <vm/vnode_pager.h> 57 58#include <machine/_inttypes.h> 59 60#include <fs/nandfs/nandfs_mount.h> 61#include <fs/nandfs/nandfs.h> 62#include <fs/nandfs/nandfs_subr.h> 63 64extern uma_zone_t nandfs_node_zone; 65static void nandfs_read_filebuf(struct nandfs_node *, struct buf *); 66static void nandfs_itimes_locked(struct vnode *); 67static int nandfs_truncate(struct vnode *, uint64_t); 68 69static vop_pathconf_t nandfs_pathconf; 70 71#define UPDATE_CLOSE 0 72#define UPDATE_WAIT 0 73 74static int 75nandfs_inactive(struct vop_inactive_args *ap) 76{ 77 struct vnode *vp = ap->a_vp; 78 struct nandfs_node *node = VTON(vp); 79 int error = 0; 80 81 DPRINTF(VNCALL, ("%s: vp:%p node:%p\n", __func__, vp, node)); 82 83 if (node == NULL) { 84 DPRINTF(NODE, ("%s: inactive NULL node\n", __func__)); 85 return (0); 86 } 87 88 if (node->nn_inode.i_mode != 0 && !(node->nn_inode.i_links_count)) { 89 nandfs_truncate(vp, 0); 90 error = nandfs_node_destroy(node); 91 if (error) 92 nandfs_error("%s: destroy node: %p\n", __func__, node); 93 node->nn_flags = 0; 94 vrecycle(vp); 95 } 96 97 return (error); 98} 99 100static int 101nandfs_reclaim(struct vop_reclaim_args *ap) 102{ 103 struct vnode *vp = ap->a_vp; 104 struct nandfs_node *nandfs_node = VTON(vp); 105 struct nandfs_device *fsdev = nandfs_node->nn_nandfsdev; 106 uint64_t ino = nandfs_node->nn_ino; 107 108 DPRINTF(VNCALL, ("%s: vp:%p node:%p\n", __func__, vp, nandfs_node)); 109 110 /* Invalidate all entries to a particular vnode. */ 111 cache_purge(vp); 112 113 /* Destroy the vm object and flush associated pages. */ 114 vnode_destroy_vobject(vp); 115 116 /* Remove from vfs hash if not system vnode */ 117 if (!NANDFS_SYS_NODE(nandfs_node->nn_ino)) 118 vfs_hash_remove(vp); 119 120 /* Dispose all node knowledge */ 121 nandfs_dispose_node(&nandfs_node); 122 123 if (!NANDFS_SYS_NODE(ino)) 124 NANDFS_WRITEUNLOCK(fsdev); 125 126 return (0); 127} 128 129static int 130nandfs_read(struct vop_read_args *ap) 131{ 132 struct vnode *vp = ap->a_vp; 133 struct nandfs_node *node = VTON(vp); 134 struct nandfs_device *nandfsdev = node->nn_nandfsdev; 135 struct uio *uio = ap->a_uio; 136 struct buf *bp; 137 uint64_t size; 138 uint32_t blocksize; 139 off_t bytesinfile; 140 ssize_t toread, off; 141 daddr_t lbn; 142 ssize_t resid; 143 int error = 0; 144 145 if (uio->uio_resid == 0) 146 return (0); 147 148 size = node->nn_inode.i_size; 149 if (uio->uio_offset >= size) 150 return (0); 151 152 blocksize = nandfsdev->nd_blocksize; 153 bytesinfile = size - uio->uio_offset; 154 155 resid = omin(uio->uio_resid, bytesinfile); 156 157 while (resid) { 158 lbn = uio->uio_offset / blocksize; 159 off = uio->uio_offset & (blocksize - 1); 160 161 toread = omin(resid, blocksize - off); 162 163 DPRINTF(READ, ("nandfs_read bn: 0x%jx toread: 0x%zx (0x%x)\n", 164 (uintmax_t)lbn, toread, blocksize)); 165 166 error = nandfs_bread(node, lbn, NOCRED, 0, &bp); 167 if (error) { 168 brelse(bp); 169 break; 170 } 171 172 error = uiomove(bp->b_data + off, toread, uio); 173 if (error) { 174 brelse(bp); 175 break; 176 } 177 178 brelse(bp); 179 resid -= toread; 180 } 181 182 return (error); 183} 184 185static int 186nandfs_write(struct vop_write_args *ap) 187{ 188 struct nandfs_device *fsdev; 189 struct nandfs_node *node; 190 struct vnode *vp; 191 struct uio *uio; 192 struct buf *bp; 193 uint64_t file_size, vblk; 194 uint32_t blocksize; 195 ssize_t towrite, off; 196 daddr_t lbn; 197 ssize_t resid; 198 int error, ioflag, modified; 199 200 vp = ap->a_vp; 201 uio = ap->a_uio; 202 ioflag = ap->a_ioflag; 203 node = VTON(vp); 204 fsdev = node->nn_nandfsdev; 205 206 if (nandfs_fs_full(fsdev)) 207 return (ENOSPC); 208 209 DPRINTF(WRITE, ("nandfs_write called %#zx at %#jx\n", 210 uio->uio_resid, (uintmax_t)uio->uio_offset)); 211 212 if (uio->uio_offset < 0) 213 return (EINVAL); 214 if (uio->uio_resid == 0) 215 return (0); 216 217 blocksize = fsdev->nd_blocksize; 218 file_size = node->nn_inode.i_size; 219 220 switch (vp->v_type) { 221 case VREG: 222 if (ioflag & IO_APPEND) 223 uio->uio_offset = file_size; 224 break; 225 case VDIR: 226 return (EISDIR); 227 case VLNK: 228 break; 229 default: 230 panic("%s: bad file type vp: %p", __func__, vp); 231 } 232 233 /* If explicitly asked to append, uio_offset can be wrong? */ 234 if (ioflag & IO_APPEND) 235 uio->uio_offset = file_size; 236 237 resid = uio->uio_resid; 238 modified = error = 0; 239 240 while (uio->uio_resid) { 241 lbn = uio->uio_offset / blocksize; 242 off = uio->uio_offset & (blocksize - 1); 243 244 towrite = omin(uio->uio_resid, blocksize - off); 245 246 DPRINTF(WRITE, ("%s: lbn: 0x%jd toread: 0x%zx (0x%x)\n", 247 __func__, (uintmax_t)lbn, towrite, blocksize)); 248 249 error = nandfs_bmap_lookup(node, lbn, &vblk); 250 if (error) 251 break; 252 253 DPRINTF(WRITE, ("%s: lbn: 0x%jd toread: 0x%zx (0x%x) " 254 "vblk=%jx\n", __func__, (uintmax_t)lbn, towrite, blocksize, 255 vblk)); 256 257 if (vblk != 0) 258 error = nandfs_bread(node, lbn, NOCRED, 0, &bp); 259 else 260 error = nandfs_bcreate(node, lbn, NOCRED, 0, &bp); 261 262 DPRINTF(WRITE, ("%s: vp %p bread bp %p lbn %#jx\n", __func__, 263 vp, bp, (uintmax_t)lbn)); 264 if (error) { 265 if (bp) 266 brelse(bp); 267 break; 268 } 269 270 error = uiomove((char *)bp->b_data + off, (int)towrite, uio); 271 if (error) 272 break; 273 274 error = nandfs_dirty_buf(bp, 0); 275 if (error) 276 break; 277 278 modified++; 279 } 280 281 /* XXX proper handling when only part of file was properly written */ 282 if (modified) { 283 if (resid > uio->uio_resid && ap->a_cred && 284 ap->a_cred->cr_uid != 0) 285 node->nn_inode.i_mode &= ~(ISUID | ISGID); 286 287 if (file_size < uio->uio_offset + uio->uio_resid) { 288 node->nn_inode.i_size = uio->uio_offset + 289 uio->uio_resid; 290 node->nn_flags |= IN_CHANGE | IN_UPDATE; 291 vnode_pager_setsize(vp, uio->uio_offset + 292 uio->uio_resid); 293 nandfs_itimes(vp); 294 } 295 } 296 297 DPRINTF(WRITE, ("%s: return:%d\n", __func__, error)); 298 299 return (error); 300} 301 302static int 303nandfs_lookup(struct vop_cachedlookup_args *ap) 304{ 305 struct vnode *dvp, **vpp; 306 struct componentname *cnp; 307 struct ucred *cred; 308 struct thread *td; 309 struct nandfs_node *dir_node, *node; 310 struct nandfsmount *nmp; 311 uint64_t ino, off; 312 const char *name; 313 int namelen, nameiop, islastcn, mounted_ro; 314 int error, found; 315 316 DPRINTF(VNCALL, ("%s\n", __func__)); 317 318 dvp = ap->a_dvp; 319 vpp = ap->a_vpp; 320 *vpp = NULL; 321 322 cnp = ap->a_cnp; 323 cred = cnp->cn_cred; 324 td = cnp->cn_thread; 325 326 dir_node = VTON(dvp); 327 nmp = dir_node->nn_nmp; 328 329 /* Simplify/clarification flags */ 330 nameiop = cnp->cn_nameiop; 331 islastcn = cnp->cn_flags & ISLASTCN; 332 mounted_ro = dvp->v_mount->mnt_flag & MNT_RDONLY; 333 334 /* 335 * If requesting a modify on the last path element on a read-only 336 * filingsystem, reject lookup; 337 */ 338 if (islastcn && mounted_ro && (nameiop == DELETE || nameiop == RENAME)) 339 return (EROFS); 340 341 if (dir_node->nn_inode.i_links_count == 0) 342 return (ENOENT); 343 344 /* 345 * Obviously, the file is not (anymore) in the namecache, we have to 346 * search for it. There are three basic cases: '.', '..' and others. 347 * 348 * Following the guidelines of VOP_LOOKUP manpage and tmpfs. 349 */ 350 error = 0; 351 if ((cnp->cn_namelen == 1) && (cnp->cn_nameptr[0] == '.')) { 352 DPRINTF(LOOKUP, ("\tlookup '.'\n")); 353 /* Special case 1 '.' */ 354 VREF(dvp); 355 *vpp = dvp; 356 /* Done */ 357 } else if (cnp->cn_flags & ISDOTDOT) { 358 /* Special case 2 '..' */ 359 DPRINTF(LOOKUP, ("\tlookup '..'\n")); 360 361 /* Get our node */ 362 name = ".."; 363 namelen = 2; 364 error = nandfs_lookup_name_in_dir(dvp, name, namelen, &ino, 365 &found, &off); 366 if (error) 367 goto out; 368 if (!found) 369 error = ENOENT; 370 371 /* First unlock parent */ 372 VOP_UNLOCK(dvp, 0); 373 374 if (error == 0) { 375 DPRINTF(LOOKUP, ("\tfound '..'\n")); 376 /* Try to create/reuse the node */ 377 error = nandfs_get_node(nmp, ino, &node); 378 379 if (!error) { 380 DPRINTF(LOOKUP, 381 ("\tnode retrieved/created OK\n")); 382 *vpp = NTOV(node); 383 } 384 } 385 386 /* Try to relock parent */ 387 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 388 } else { 389 DPRINTF(LOOKUP, ("\tlookup file\n")); 390 /* All other files */ 391 /* Look up filename in the directory returning its inode */ 392 name = cnp->cn_nameptr; 393 namelen = cnp->cn_namelen; 394 error = nandfs_lookup_name_in_dir(dvp, name, namelen, 395 &ino, &found, &off); 396 if (error) 397 goto out; 398 if (!found) { 399 DPRINTF(LOOKUP, ("\tNOT found\n")); 400 /* 401 * UGH, didn't find name. If we're creating or 402 * renaming on the last name this is OK and we ought 403 * to return EJUSTRETURN if its allowed to be created. 404 */ 405 error = ENOENT; 406 if ((nameiop == CREATE || nameiop == RENAME) && 407 islastcn) { 408 error = VOP_ACCESS(dvp, VWRITE, cred, td); 409 if (!error) { 410 /* keep the component name */ 411 cnp->cn_flags |= SAVENAME; 412 error = EJUSTRETURN; 413 } 414 } 415 /* Done */ 416 } else { 417 if (ino == NANDFS_WHT_INO) 418 cnp->cn_flags |= ISWHITEOUT; 419 420 if ((cnp->cn_flags & ISWHITEOUT) && 421 (nameiop == LOOKUP)) 422 return (ENOENT); 423 424 if ((nameiop == DELETE) && islastcn) { 425 if ((cnp->cn_flags & ISWHITEOUT) && 426 (cnp->cn_flags & DOWHITEOUT)) { 427 cnp->cn_flags |= SAVENAME; 428 dir_node->nn_diroff = off; 429 return (EJUSTRETURN); 430 } 431 432 error = VOP_ACCESS(dvp, VWRITE, cred, 433 cnp->cn_thread); 434 if (error) 435 return (error); 436 437 /* Try to create/reuse the node */ 438 error = nandfs_get_node(nmp, ino, &node); 439 if (!error) { 440 *vpp = NTOV(node); 441 node->nn_diroff = off; 442 } 443 444 if ((dir_node->nn_inode.i_mode & ISVTX) && 445 cred->cr_uid != 0 && 446 cred->cr_uid != dir_node->nn_inode.i_uid && 447 node->nn_inode.i_uid != cred->cr_uid) { 448 vput(*vpp); 449 *vpp = NULL; 450 return (EPERM); 451 } 452 } else if ((nameiop == RENAME) && islastcn) { 453 error = VOP_ACCESS(dvp, VWRITE, cred, 454 cnp->cn_thread); 455 if (error) 456 return (error); 457 458 /* Try to create/reuse the node */ 459 error = nandfs_get_node(nmp, ino, &node); 460 if (!error) { 461 *vpp = NTOV(node); 462 node->nn_diroff = off; 463 } 464 } else { 465 /* Try to create/reuse the node */ 466 error = nandfs_get_node(nmp, ino, &node); 467 if (!error) { 468 *vpp = NTOV(node); 469 node->nn_diroff = off; 470 } 471 } 472 } 473 } 474 475out: 476 /* 477 * Store result in the cache if requested. If we are creating a file, 478 * the file might not be found and thus putting it into the namecache 479 * might be seen as negative caching. 480 */ 481 if ((cnp->cn_flags & MAKEENTRY) != 0) 482 cache_enter(dvp, *vpp, cnp); 483 484 return (error); 485 486} 487 488static int 489nandfs_getattr(struct vop_getattr_args *ap) 490{ 491 struct vnode *vp = ap->a_vp; 492 struct vattr *vap = ap->a_vap; 493 struct nandfs_node *node = VTON(vp); 494 struct nandfs_inode *inode = &node->nn_inode; 495 496 DPRINTF(VNCALL, ("%s: vp: %p\n", __func__, vp)); 497 nandfs_itimes(vp); 498 499 /* Basic info */ 500 VATTR_NULL(vap); 501 vap->va_atime.tv_sec = inode->i_mtime; 502 vap->va_atime.tv_nsec = inode->i_mtime_nsec; 503 vap->va_mtime.tv_sec = inode->i_mtime; 504 vap->va_mtime.tv_nsec = inode->i_mtime_nsec; 505 vap->va_ctime.tv_sec = inode->i_ctime; 506 vap->va_ctime.tv_nsec = inode->i_ctime_nsec; 507 vap->va_type = IFTOVT(inode->i_mode); 508 vap->va_mode = inode->i_mode & ~S_IFMT; 509 vap->va_nlink = inode->i_links_count; 510 vap->va_uid = inode->i_uid; 511 vap->va_gid = inode->i_gid; 512 vap->va_rdev = inode->i_special; 513 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 514 vap->va_fileid = node->nn_ino; 515 vap->va_size = inode->i_size; 516 vap->va_blocksize = node->nn_nandfsdev->nd_blocksize; 517 vap->va_gen = 0; 518 vap->va_flags = inode->i_flags; 519 vap->va_bytes = inode->i_blocks * vap->va_blocksize; 520 vap->va_filerev = 0; 521 vap->va_vaflags = 0; 522 523 return (0); 524} 525 526static int 527nandfs_vtruncbuf(struct vnode *vp, uint64_t nblks) 528{ 529 struct nandfs_device *nffsdev; 530 struct bufobj *bo; 531 struct buf *bp, *nbp; 532 533 bo = &vp->v_bufobj; 534 nffsdev = VTON(vp)->nn_nandfsdev; 535 536 ASSERT_VOP_LOCKED(vp, "nandfs_truncate"); 537restart: 538 BO_LOCK(bo); 539restart_locked: 540 TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, nbp) { 541 if (bp->b_lblkno < nblks) 542 continue; 543 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) 544 goto restart_locked; 545 546 bremfree(bp); 547 bp->b_flags |= (B_INVAL | B_RELBUF); 548 bp->b_flags &= ~(B_ASYNC | B_MANAGED); 549 BO_UNLOCK(bo); 550 brelse(bp); 551 BO_LOCK(bo); 552 } 553 554 TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { 555 if (bp->b_lblkno < nblks) 556 continue; 557 if (BUF_LOCK(bp, 558 LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, 559 BO_LOCKPTR(bo)) == ENOLCK) 560 goto restart; 561 bp->b_flags |= (B_INVAL | B_RELBUF); 562 bp->b_flags &= ~(B_ASYNC | B_MANAGED); 563 brelse(bp); 564 nandfs_dirty_bufs_decrement(nffsdev); 565 BO_LOCK(bo); 566 } 567 568 BO_UNLOCK(bo); 569 570 return (0); 571} 572 573static int 574nandfs_truncate(struct vnode *vp, uint64_t newsize) 575{ 576 struct nandfs_device *nffsdev; 577 struct nandfs_node *node; 578 struct nandfs_inode *inode; 579 struct buf *bp = NULL; 580 uint64_t oblks, nblks, vblk, size, rest; 581 int error; 582 583 node = VTON(vp); 584 nffsdev = node->nn_nandfsdev; 585 inode = &node->nn_inode; 586 587 /* Calculate end of file */ 588 size = inode->i_size; 589 590 if (newsize == size) { 591 node->nn_flags |= IN_CHANGE | IN_UPDATE; 592 nandfs_itimes(vp); 593 return (0); 594 } 595 596 if (newsize > size) { 597 inode->i_size = newsize; 598 vnode_pager_setsize(vp, newsize); 599 node->nn_flags |= IN_CHANGE | IN_UPDATE; 600 nandfs_itimes(vp); 601 return (0); 602 } 603 604 nblks = howmany(newsize, nffsdev->nd_blocksize); 605 oblks = howmany(size, nffsdev->nd_blocksize); 606 rest = newsize % nffsdev->nd_blocksize; 607 608 if (rest) { 609 error = nandfs_bmap_lookup(node, nblks - 1, &vblk); 610 if (error) 611 return (error); 612 613 if (vblk != 0) 614 error = nandfs_bread(node, nblks - 1, NOCRED, 0, &bp); 615 else 616 error = nandfs_bcreate(node, nblks - 1, NOCRED, 0, &bp); 617 618 if (error) { 619 if (bp) 620 brelse(bp); 621 return (error); 622 } 623 624 bzero((char *)bp->b_data + rest, 625 (u_int)(nffsdev->nd_blocksize - rest)); 626 error = nandfs_dirty_buf(bp, 0); 627 if (error) 628 return (error); 629 } 630 631 DPRINTF(VNCALL, ("%s: vp %p oblks %jx nblks %jx\n", __func__, vp, oblks, 632 nblks)); 633 634 error = nandfs_bmap_truncate_mapping(node, oblks - 1, nblks - 1); 635 if (error) { 636 if (bp) 637 nandfs_undirty_buf(bp); 638 return (error); 639 } 640 641 error = nandfs_vtruncbuf(vp, nblks); 642 if (error) { 643 if (bp) 644 nandfs_undirty_buf(bp); 645 return (error); 646 } 647 648 inode->i_size = newsize; 649 vnode_pager_setsize(vp, newsize); 650 node->nn_flags |= IN_CHANGE | IN_UPDATE; 651 nandfs_itimes(vp); 652 653 return (error); 654} 655 656static void 657nandfs_itimes_locked(struct vnode *vp) 658{ 659 struct nandfs_node *node; 660 struct nandfs_inode *inode; 661 struct timespec ts; 662 663 ASSERT_VI_LOCKED(vp, __func__); 664 665 node = VTON(vp); 666 inode = &node->nn_inode; 667 668 if ((node->nn_flags & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0) 669 return; 670 671 if (((vp->v_mount->mnt_kern_flag & 672 (MNTK_SUSPENDED | MNTK_SUSPEND)) == 0) || 673 (node->nn_flags & (IN_CHANGE | IN_UPDATE))) 674 node->nn_flags |= IN_MODIFIED; 675 676 vfs_timestamp(&ts); 677 if (node->nn_flags & IN_UPDATE) { 678 inode->i_mtime = ts.tv_sec; 679 inode->i_mtime_nsec = ts.tv_nsec; 680 } 681 if (node->nn_flags & IN_CHANGE) { 682 inode->i_ctime = ts.tv_sec; 683 inode->i_ctime_nsec = ts.tv_nsec; 684 } 685 686 node->nn_flags &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); 687} 688 689void 690nandfs_itimes(struct vnode *vp) 691{ 692 693 VI_LOCK(vp); 694 nandfs_itimes_locked(vp); 695 VI_UNLOCK(vp); 696} 697 698static int 699nandfs_chmod(struct vnode *vp, int mode, struct ucred *cred, struct thread *td) 700{ 701 struct nandfs_node *node = VTON(vp); 702 struct nandfs_inode *inode = &node->nn_inode; 703 uint16_t nmode; 704 int error = 0; 705 706 DPRINTF(VNCALL, ("%s: vp %p, mode %x, cred %p, td %p\n", __func__, vp, 707 mode, cred, td)); 708 /* 709 * To modify the permissions on a file, must possess VADMIN 710 * for that file. 711 */ 712 if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) 713 return (error); 714 715 /* 716 * Privileged processes may set the sticky bit on non-directories, 717 * as well as set the setgid bit on a file with a group that the 718 * process is not a member of. Both of these are allowed in 719 * jail(8). 720 */ 721 if (vp->v_type != VDIR && (mode & S_ISTXT)) { 722 if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0)) 723 return (EFTYPE); 724 } 725 if (!groupmember(inode->i_gid, cred) && (mode & ISGID)) { 726 error = priv_check_cred(cred, PRIV_VFS_SETGID, 0); 727 if (error) 728 return (error); 729 } 730 731 /* 732 * Deny setting setuid if we are not the file owner. 733 */ 734 if ((mode & ISUID) && inode->i_uid != cred->cr_uid) { 735 error = priv_check_cred(cred, PRIV_VFS_ADMIN, 0); 736 if (error) 737 return (error); 738 } 739 740 nmode = inode->i_mode; 741 nmode &= ~ALLPERMS; 742 nmode |= (mode & ALLPERMS); 743 inode->i_mode = nmode; 744 node->nn_flags |= IN_CHANGE; 745 746 DPRINTF(VNCALL, ("%s: to mode %x\n", __func__, nmode)); 747 748 return (error); 749} 750 751static int 752nandfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, 753 struct thread *td) 754{ 755 struct nandfs_node *node = VTON(vp); 756 struct nandfs_inode *inode = &node->nn_inode; 757 uid_t ouid; 758 gid_t ogid; 759 int error = 0; 760 761 if (uid == (uid_t)VNOVAL) 762 uid = inode->i_uid; 763 if (gid == (gid_t)VNOVAL) 764 gid = inode->i_gid; 765 /* 766 * To modify the ownership of a file, must possess VADMIN for that 767 * file. 768 */ 769 if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred, td))) 770 return (error); 771 /* 772 * To change the owner of a file, or change the group of a file to a 773 * group of which we are not a member, the caller must have 774 * privilege. 775 */ 776 if (((uid != inode->i_uid && uid != cred->cr_uid) || 777 (gid != inode->i_gid && !groupmember(gid, cred))) && 778 (error = priv_check_cred(cred, PRIV_VFS_CHOWN, 0))) 779 return (error); 780 ogid = inode->i_gid; 781 ouid = inode->i_uid; 782 783 inode->i_gid = gid; 784 inode->i_uid = uid; 785 786 node->nn_flags |= IN_CHANGE; 787 if ((inode->i_mode & (ISUID | ISGID)) && 788 (ouid != uid || ogid != gid)) { 789 if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0)) 790 inode->i_mode &= ~(ISUID | ISGID); 791 } 792 DPRINTF(VNCALL, ("%s: vp %p, cred %p, td %p - ret OK\n", __func__, vp, 793 cred, td)); 794 return (0); 795} 796 797static int 798nandfs_setattr(struct vop_setattr_args *ap) 799{ 800 struct vnode *vp = ap->a_vp; 801 struct nandfs_node *node = VTON(vp); 802 struct nandfs_inode *inode = &node->nn_inode; 803 struct vattr *vap = ap->a_vap; 804 struct ucred *cred = ap->a_cred; 805 struct thread *td = curthread; 806 uint32_t flags; 807 int error = 0; 808 809 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 810 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 811 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 812 (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 813 DPRINTF(VNCALL, ("%s: unsettable attribute\n", __func__)); 814 return (EINVAL); 815 } 816 817 if (vap->va_flags != VNOVAL) { 818 DPRINTF(VNCALL, ("%s: vp:%p td:%p flags:%lx\n", __func__, vp, 819 td, vap->va_flags)); 820 821 if (vp->v_mount->mnt_flag & MNT_RDONLY) 822 return (EROFS); 823 /* 824 * Callers may only modify the file flags on objects they 825 * have VADMIN rights for. 826 */ 827 if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) 828 return (error); 829 /* 830 * Unprivileged processes are not permitted to unset system 831 * flags, or modify flags if any system flags are set. 832 * Privileged non-jail processes may not modify system flags 833 * if securelevel > 0 and any existing system flags are set. 834 * Privileged jail processes behave like privileged non-jail 835 * processes if the security.jail.chflags_allowed sysctl is 836 * is non-zero; otherwise, they behave like unprivileged 837 * processes. 838 */ 839 840 flags = inode->i_flags; 841 if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) { 842 if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { 843 error = securelevel_gt(cred, 0); 844 if (error) 845 return (error); 846 } 847 /* Snapshot flag cannot be set or cleared */ 848 if (((vap->va_flags & SF_SNAPSHOT) != 0 && 849 (flags & SF_SNAPSHOT) == 0) || 850 ((vap->va_flags & SF_SNAPSHOT) == 0 && 851 (flags & SF_SNAPSHOT) != 0)) 852 return (EPERM); 853 854 inode->i_flags = vap->va_flags; 855 } else { 856 if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) || 857 (vap->va_flags & UF_SETTABLE) != vap->va_flags) 858 return (EPERM); 859 860 flags &= SF_SETTABLE; 861 flags |= (vap->va_flags & UF_SETTABLE); 862 inode->i_flags = flags; 863 } 864 node->nn_flags |= IN_CHANGE; 865 if (vap->va_flags & (IMMUTABLE | APPEND)) 866 return (0); 867 } 868 if (inode->i_flags & (IMMUTABLE | APPEND)) 869 return (EPERM); 870 871 if (vap->va_size != (u_quad_t)VNOVAL) { 872 DPRINTF(VNCALL, ("%s: vp:%p td:%p size:%jx\n", __func__, vp, td, 873 (uintmax_t)vap->va_size)); 874 875 switch (vp->v_type) { 876 case VDIR: 877 return (EISDIR); 878 case VLNK: 879 case VREG: 880 if (vp->v_mount->mnt_flag & MNT_RDONLY) 881 return (EROFS); 882 if ((inode->i_flags & SF_SNAPSHOT) != 0) 883 return (EPERM); 884 break; 885 default: 886 return (0); 887 } 888 889 if (vap->va_size > node->nn_nandfsdev->nd_maxfilesize) 890 return (EFBIG); 891 892 KASSERT((vp->v_type == VREG), ("Set size %d", vp->v_type)); 893 nandfs_truncate(vp, vap->va_size); 894 node->nn_flags |= IN_CHANGE; 895 896 return (0); 897 } 898 899 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 900 if (vp->v_mount->mnt_flag & MNT_RDONLY) 901 return (EROFS); 902 DPRINTF(VNCALL, ("%s: vp:%p td:%p uid/gid %x/%x\n", __func__, 903 vp, td, vap->va_uid, vap->va_gid)); 904 error = nandfs_chown(vp, vap->va_uid, vap->va_gid, cred, td); 905 if (error) 906 return (error); 907 } 908 909 if (vap->va_mode != (mode_t)VNOVAL) { 910 if (vp->v_mount->mnt_flag & MNT_RDONLY) 911 return (EROFS); 912 DPRINTF(VNCALL, ("%s: vp:%p td:%p mode %x\n", __func__, vp, td, 913 vap->va_mode)); 914 915 error = nandfs_chmod(vp, (int)vap->va_mode, cred, td); 916 if (error) 917 return (error); 918 } 919 if (vap->va_atime.tv_sec != VNOVAL || 920 vap->va_mtime.tv_sec != VNOVAL || 921 vap->va_birthtime.tv_sec != VNOVAL) { 922 DPRINTF(VNCALL, ("%s: vp:%p td:%p time a/m/b %jx/%jx/%jx\n", 923 __func__, vp, td, (uintmax_t)vap->va_atime.tv_sec, 924 (uintmax_t)vap->va_mtime.tv_sec, 925 (uintmax_t)vap->va_birthtime.tv_sec)); 926 927 if (vap->va_atime.tv_sec != VNOVAL) 928 node->nn_flags |= IN_ACCESS; 929 if (vap->va_mtime.tv_sec != VNOVAL) 930 node->nn_flags |= IN_CHANGE | IN_UPDATE; 931 if (vap->va_birthtime.tv_sec != VNOVAL) 932 node->nn_flags |= IN_MODIFIED; 933 nandfs_itimes(vp); 934 return (0); 935 } 936 937 return (0); 938} 939 940static int 941nandfs_open(struct vop_open_args *ap) 942{ 943 struct nandfs_node *node = VTON(ap->a_vp); 944 uint64_t filesize; 945 946 DPRINTF(VNCALL, ("nandfs_open called ap->a_mode %x\n", ap->a_mode)); 947 948 if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) 949 return (EOPNOTSUPP); 950 951 if ((node->nn_inode.i_flags & APPEND) && 952 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) 953 return (EPERM); 954 955 filesize = node->nn_inode.i_size; 956 vnode_create_vobject(ap->a_vp, filesize, ap->a_td); 957 958 return (0); 959} 960 961static int 962nandfs_close(struct vop_close_args *ap) 963{ 964 struct vnode *vp = ap->a_vp; 965 struct nandfs_node *node = VTON(vp); 966 967 DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node)); 968 969 mtx_lock(&vp->v_interlock); 970 if (vp->v_usecount > 1) 971 nandfs_itimes_locked(vp); 972 mtx_unlock(&vp->v_interlock); 973 974 return (0); 975} 976 977static int 978nandfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode) 979{ 980 981 /* Check if we are allowed to write */ 982 switch (vap->va_type) { 983 case VDIR: 984 case VLNK: 985 case VREG: 986 /* 987 * Normal nodes: check if we're on a read-only mounted 988 * filingsystem and bomb out if we're trying to write. 989 */ 990 if ((mode & VMODIFY_PERMS) && (vp->v_mount->mnt_flag & MNT_RDONLY)) 991 return (EROFS); 992 break; 993 case VBLK: 994 case VCHR: 995 case VSOCK: 996 case VFIFO: 997 /* 998 * Special nodes: even on read-only mounted filingsystems 999 * these are allowed to be written to if permissions allow. 1000 */ 1001 break; 1002 default: 1003 /* No idea what this is */ 1004 return (EINVAL); 1005 } 1006 1007 /* No one may write immutable files */ 1008 if ((mode & VWRITE) && (VTON(vp)->nn_inode.i_flags & IMMUTABLE)) 1009 return (EPERM); 1010 1011 return (0); 1012} 1013 1014static int 1015nandfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode, 1016 struct ucred *cred) 1017{ 1018 1019 return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, mode, 1020 cred, NULL)); 1021} 1022 1023static int 1024nandfs_advlock(struct vop_advlock_args *ap) 1025{ 1026 struct nandfs_node *nvp; 1027 quad_t size; 1028 1029 nvp = VTON(ap->a_vp); 1030 size = nvp->nn_inode.i_size; 1031 return (lf_advlock(ap, &(nvp->nn_lockf), size)); 1032} 1033 1034static int 1035nandfs_access(struct vop_access_args *ap) 1036{ 1037 struct vnode *vp = ap->a_vp; 1038 accmode_t accmode = ap->a_accmode; 1039 struct ucred *cred = ap->a_cred; 1040 struct vattr vap; 1041 int error; 1042 1043 DPRINTF(VNCALL, ("%s: vp:%p mode: %x\n", __func__, vp, accmode)); 1044 1045 error = VOP_GETATTR(vp, &vap, NULL); 1046 if (error) 1047 return (error); 1048 1049 error = nandfs_check_possible(vp, &vap, accmode); 1050 if (error) 1051 return (error); 1052 1053 error = nandfs_check_permitted(vp, &vap, accmode, cred); 1054 1055 return (error); 1056} 1057 1058static int 1059nandfs_print(struct vop_print_args *ap) 1060{ 1061 struct vnode *vp = ap->a_vp; 1062 struct nandfs_node *nvp = VTON(vp); 1063 1064 printf("\tvp=%p, nandfs_node=%p\n", vp, nvp); 1065 printf("nandfs inode %#jx\n", (uintmax_t)nvp->nn_ino); 1066 printf("flags = 0x%b\n", (u_int)nvp->nn_flags, PRINT_NODE_FLAGS); 1067 1068 return (0); 1069} 1070 1071static void 1072nandfs_read_filebuf(struct nandfs_node *node, struct buf *bp) 1073{ 1074 struct nandfs_device *nandfsdev = node->nn_nandfsdev; 1075 struct buf *nbp; 1076 nandfs_daddr_t vblk, pblk; 1077 nandfs_lbn_t from; 1078 uint32_t blocksize; 1079 int error = 0; 1080 int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE; 1081 1082 /* 1083 * Translate all the block sectors into a series of buffers to read 1084 * asynchronously from the nandfs device. Note that this lookup may 1085 * induce readin's too. 1086 */ 1087 1088 blocksize = nandfsdev->nd_blocksize; 1089 if (bp->b_bcount / blocksize != 1) 1090 panic("invalid b_count in bp %p\n", bp); 1091 1092 from = bp->b_blkno; 1093 1094 DPRINTF(READ, ("\tread in from inode %#jx blkno %#jx" 1095 " count %#lx\n", (uintmax_t)node->nn_ino, from, 1096 bp->b_bcount)); 1097 1098 /* Get virtual block numbers for the vnode's buffer span */ 1099 error = nandfs_bmap_lookup(node, from, &vblk); 1100 if (error) { 1101 bp->b_error = EINVAL; 1102 bp->b_ioflags |= BIO_ERROR; 1103 bufdone(bp); 1104 return; 1105 } 1106 1107 /* Translate virtual block numbers to physical block numbers */ 1108 error = nandfs_vtop(node, vblk, &pblk); 1109 if (error) { 1110 bp->b_error = EINVAL; 1111 bp->b_ioflags |= BIO_ERROR; 1112 bufdone(bp); 1113 return; 1114 } 1115 1116 /* Issue translated blocks */ 1117 bp->b_resid = bp->b_bcount; 1118 1119 /* Note virtual block 0 marks not mapped */ 1120 if (vblk == 0) { 1121 vfs_bio_clrbuf(bp); 1122 bufdone(bp); 1123 return; 1124 } 1125 1126 nbp = bp; 1127 nbp->b_blkno = pblk * blk2dev; 1128 bp->b_iooffset = dbtob(nbp->b_blkno); 1129 MPASS(bp->b_iooffset >= 0); 1130 BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, nbp); 1131 nandfs_vblk_set(bp, vblk); 1132 DPRINTF(READ, ("read_filebuf : ino %#jx blk %#jx -> " 1133 "%#jx -> %#jx [bp %p]\n", (uintmax_t)node->nn_ino, 1134 (uintmax_t)(from), (uintmax_t)vblk, 1135 (uintmax_t)pblk, nbp)); 1136} 1137 1138static void 1139nandfs_write_filebuf(struct nandfs_node *node, struct buf *bp) 1140{ 1141 struct nandfs_device *nandfsdev = node->nn_nandfsdev; 1142 1143 bp->b_iooffset = dbtob(bp->b_blkno); 1144 MPASS(bp->b_iooffset >= 0); 1145 BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, bp); 1146} 1147 1148static int 1149nandfs_strategy(struct vop_strategy_args *ap) 1150{ 1151 struct vnode *vp = ap->a_vp; 1152 struct buf *bp = ap->a_bp; 1153 struct nandfs_node *node = VTON(vp); 1154 1155 1156 /* check if we ought to be here */ 1157 KASSERT((vp->v_type != VBLK && vp->v_type != VCHR), 1158 ("nandfs_strategy on type %d", vp->v_type)); 1159 1160 /* Translate if needed and pass on */ 1161 if (bp->b_iocmd == BIO_READ) { 1162 nandfs_read_filebuf(node, bp); 1163 return (0); 1164 } 1165 1166 /* Send to segment collector */ 1167 nandfs_write_filebuf(node, bp); 1168 return (0); 1169} 1170 1171static int 1172nandfs_readdir(struct vop_readdir_args *ap) 1173{ 1174 struct uio *uio = ap->a_uio; 1175 struct vnode *vp = ap->a_vp; 1176 struct nandfs_node *node = VTON(vp); 1177 struct nandfs_dir_entry *ndirent; 1178 struct dirent dirent; 1179 struct buf *bp; 1180 uint64_t file_size, diroffset, transoffset, blkoff; 1181 uint64_t blocknr; 1182 uint32_t blocksize = node->nn_nandfsdev->nd_blocksize; 1183 uint8_t *pos, name_len; 1184 int error; 1185 1186 DPRINTF(READDIR, ("nandfs_readdir called\n")); 1187 1188 if (vp->v_type != VDIR) 1189 return (ENOTDIR); 1190 1191 file_size = node->nn_inode.i_size; 1192 DPRINTF(READDIR, ("nandfs_readdir filesize %jd resid %zd\n", 1193 (uintmax_t)file_size, uio->uio_resid )); 1194 1195 /* We are called just as long as we keep on pushing data in */ 1196 error = 0; 1197 if ((uio->uio_offset < file_size) && 1198 (uio->uio_resid >= sizeof(struct dirent))) { 1199 diroffset = uio->uio_offset; 1200 transoffset = diroffset; 1201 1202 blocknr = diroffset / blocksize; 1203 blkoff = diroffset % blocksize; 1204 error = nandfs_bread(node, blocknr, NOCRED, 0, &bp); 1205 if (error) { 1206 brelse(bp); 1207 return (EIO); 1208 } 1209 while (diroffset < file_size) { 1210 DPRINTF(READDIR, ("readdir : offset = %"PRIu64"\n", 1211 diroffset)); 1212 if (blkoff >= blocksize) { 1213 blkoff = 0; blocknr++; 1214 brelse(bp); 1215 error = nandfs_bread(node, blocknr, NOCRED, 0, 1216 &bp); 1217 if (error) { 1218 brelse(bp); 1219 return (EIO); 1220 } 1221 } 1222 1223 /* Read in one dirent */ 1224 pos = (uint8_t *)bp->b_data + blkoff; 1225 ndirent = (struct nandfs_dir_entry *)pos; 1226 1227 name_len = ndirent->name_len; 1228 memset(&dirent, 0, sizeof(dirent)); 1229 dirent.d_fileno = ndirent->inode; 1230 if (dirent.d_fileno) { 1231 dirent.d_type = ndirent->file_type; 1232 dirent.d_namlen = name_len; 1233 strncpy(dirent.d_name, ndirent->name, name_len); 1234 dirent.d_reclen = GENERIC_DIRSIZ(&dirent); 1235 dirent_terminate(&dirent); 1236 DPRINTF(READDIR, ("copying `%*.*s`\n", name_len, 1237 name_len, dirent.d_name)); 1238 } 1239 1240 /* 1241 * If there isn't enough space in the uio to return a 1242 * whole dirent, break off read 1243 */ 1244 if (uio->uio_resid < GENERIC_DIRSIZ(&dirent)) 1245 break; 1246 1247 /* Transfer */ 1248 if (dirent.d_fileno) 1249 uiomove(&dirent, dirent.d_reclen, uio); 1250 1251 /* Advance */ 1252 diroffset += ndirent->rec_len; 1253 blkoff += ndirent->rec_len; 1254 1255 /* Remember the last entry we transferred */ 1256 transoffset = diroffset; 1257 } 1258 brelse(bp); 1259 1260 /* Pass on last transferred offset */ 1261 uio->uio_offset = transoffset; 1262 } 1263 1264 if (ap->a_eofflag) 1265 *ap->a_eofflag = (uio->uio_offset >= file_size); 1266 1267 return (error); 1268} 1269 1270static int 1271nandfs_dirempty(struct vnode *dvp, uint64_t parentino, struct ucred *cred) 1272{ 1273 struct nandfs_node *dnode = VTON(dvp); 1274 struct nandfs_dir_entry *dirent; 1275 uint64_t file_size = dnode->nn_inode.i_size; 1276 uint64_t blockcount = dnode->nn_inode.i_blocks; 1277 uint64_t blocknr; 1278 uint32_t blocksize = dnode->nn_nandfsdev->nd_blocksize; 1279 uint32_t limit; 1280 uint32_t off; 1281 uint8_t *pos; 1282 struct buf *bp; 1283 int error; 1284 1285 DPRINTF(LOOKUP, ("%s: dvp %p parentino %#jx cred %p\n", __func__, dvp, 1286 (uintmax_t)parentino, cred)); 1287 1288 KASSERT((file_size != 0), ("nandfs_dirempty for NULL dir %p", dvp)); 1289 1290 blocknr = 0; 1291 while (blocknr < blockcount) { 1292 error = nandfs_bread(dnode, blocknr, NOCRED, 0, &bp); 1293 if (error) { 1294 brelse(bp); 1295 return (0); 1296 } 1297 1298 pos = (uint8_t *)bp->b_data; 1299 off = 0; 1300 1301 if (blocknr == (blockcount - 1)) 1302 limit = file_size % blocksize; 1303 else 1304 limit = blocksize; 1305 1306 while (off < limit) { 1307 dirent = (struct nandfs_dir_entry *)(pos + off); 1308 off += dirent->rec_len; 1309 1310 if (dirent->inode == 0) 1311 continue; 1312 1313 switch (dirent->name_len) { 1314 case 0: 1315 break; 1316 case 1: 1317 if (dirent->name[0] != '.') 1318 goto notempty; 1319 1320 KASSERT(dirent->inode == dnode->nn_ino, 1321 (".'s inode does not match dir")); 1322 break; 1323 case 2: 1324 if (dirent->name[0] != '.' && 1325 dirent->name[1] != '.') 1326 goto notempty; 1327 1328 KASSERT(dirent->inode == parentino, 1329 ("..'s inode does not match parent")); 1330 break; 1331 default: 1332 goto notempty; 1333 } 1334 } 1335 1336 brelse(bp); 1337 blocknr++; 1338 } 1339 1340 return (1); 1341notempty: 1342 brelse(bp); 1343 return (0); 1344} 1345 1346static int 1347nandfs_link(struct vop_link_args *ap) 1348{ 1349 struct vnode *tdvp = ap->a_tdvp; 1350 struct vnode *vp = ap->a_vp; 1351 struct componentname *cnp = ap->a_cnp; 1352 struct nandfs_node *node = VTON(vp); 1353 struct nandfs_inode *inode = &node->nn_inode; 1354 int error; 1355 1356 if (inode->i_links_count >= LINK_MAX) 1357 return (EMLINK); 1358 1359 if (inode->i_flags & (IMMUTABLE | APPEND)) 1360 return (EPERM); 1361 1362 /* Update link count */ 1363 inode->i_links_count++; 1364 1365 /* Add dir entry */ 1366 error = nandfs_add_dirent(tdvp, node->nn_ino, cnp->cn_nameptr, 1367 cnp->cn_namelen, IFTODT(inode->i_mode)); 1368 if (error) { 1369 inode->i_links_count--; 1370 } 1371 1372 node->nn_flags |= IN_CHANGE; 1373 nandfs_itimes(vp); 1374 DPRINTF(VNCALL, ("%s: tdvp %p vp %p cnp %p\n", 1375 __func__, tdvp, vp, cnp)); 1376 1377 return (0); 1378} 1379 1380static int 1381nandfs_create(struct vop_create_args *ap) 1382{ 1383 struct vnode *dvp = ap->a_dvp; 1384 struct vnode **vpp = ap->a_vpp; 1385 struct componentname *cnp = ap->a_cnp; 1386 uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 1387 struct nandfs_node *dir_node = VTON(dvp); 1388 struct nandfsmount *nmp = dir_node->nn_nmp; 1389 struct nandfs_node *node; 1390 int error; 1391 1392 DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp)); 1393 1394 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1395 return (ENOSPC); 1396 1397 /* Create new vnode/inode */ 1398 error = nandfs_node_create(nmp, &node, mode); 1399 if (error) 1400 return (error); 1401 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1402 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1403 1404 /* Add new dir entry */ 1405 error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1406 cnp->cn_namelen, IFTODT(mode)); 1407 if (error) { 1408 if (nandfs_node_destroy(node)) { 1409 nandfs_error("%s: error destroying node %p\n", 1410 __func__, node); 1411 } 1412 return (error); 1413 } 1414 *vpp = NTOV(node); 1415 if ((cnp->cn_flags & MAKEENTRY) != 0) 1416 cache_enter(dvp, *vpp, cnp); 1417 1418 DPRINTF(VNCALL, ("created file vp %p nandnode %p ino %jx\n", *vpp, node, 1419 (uintmax_t)node->nn_ino)); 1420 return (0); 1421} 1422 1423static int 1424nandfs_remove(struct vop_remove_args *ap) 1425{ 1426 struct vnode *vp = ap->a_vp; 1427 struct vnode *dvp = ap->a_dvp; 1428 struct nandfs_node *node = VTON(vp); 1429 struct nandfs_node *dnode = VTON(dvp); 1430 struct componentname *cnp = ap->a_cnp; 1431 1432 DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx link %d\n", 1433 __func__, dvp, vp, node, (uintmax_t)node->nn_ino, 1434 node->nn_inode.i_links_count)); 1435 1436 if (vp->v_type == VDIR) 1437 return (EISDIR); 1438 1439 /* Files marked as immutable or append-only cannot be deleted. */ 1440 if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) || 1441 (dnode->nn_inode.i_flags & APPEND)) 1442 return (EPERM); 1443 1444 nandfs_remove_dirent(dvp, node, cnp); 1445 node->nn_inode.i_links_count--; 1446 node->nn_flags |= IN_CHANGE; 1447 1448 return (0); 1449} 1450 1451/* 1452 * Check if source directory is in the path of the target directory. 1453 * Target is supplied locked, source is unlocked. 1454 * The target is always vput before returning. 1455 */ 1456static int 1457nandfs_checkpath(struct nandfs_node *src, struct nandfs_node *dest, 1458 struct ucred *cred) 1459{ 1460 struct vnode *vp; 1461 int error, rootino; 1462 struct nandfs_dir_entry dirent; 1463 1464 vp = NTOV(dest); 1465 if (src->nn_ino == dest->nn_ino) { 1466 error = EEXIST; 1467 goto out; 1468 } 1469 rootino = NANDFS_ROOT_INO; 1470 error = 0; 1471 if (dest->nn_ino == rootino) 1472 goto out; 1473 1474 for (;;) { 1475 if (vp->v_type != VDIR) { 1476 error = ENOTDIR; 1477 break; 1478 } 1479 1480 error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirent, 1481 NANDFS_DIR_REC_LEN(2), (off_t)0, UIO_SYSSPACE, 1482 IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, 1483 NULL, NULL); 1484 if (error != 0) 1485 break; 1486 if (dirent.name_len != 2 || 1487 dirent.name[0] != '.' || 1488 dirent.name[1] != '.') { 1489 error = ENOTDIR; 1490 break; 1491 } 1492 if (dirent.inode == src->nn_ino) { 1493 error = EINVAL; 1494 break; 1495 } 1496 if (dirent.inode == rootino) 1497 break; 1498 vput(vp); 1499 if ((error = VFS_VGET(vp->v_mount, dirent.inode, 1500 LK_EXCLUSIVE, &vp)) != 0) { 1501 vp = NULL; 1502 break; 1503 } 1504 } 1505 1506out: 1507 if (error == ENOTDIR) 1508 printf("checkpath: .. not a directory\n"); 1509 if (vp != NULL) 1510 vput(vp); 1511 return (error); 1512} 1513 1514static int 1515nandfs_rename(struct vop_rename_args *ap) 1516{ 1517 struct vnode *tvp = ap->a_tvp; 1518 struct vnode *tdvp = ap->a_tdvp; 1519 struct vnode *fvp = ap->a_fvp; 1520 struct vnode *fdvp = ap->a_fdvp; 1521 struct componentname *tcnp = ap->a_tcnp; 1522 struct componentname *fcnp = ap->a_fcnp; 1523 int doingdirectory = 0, oldparent = 0, newparent = 0; 1524 int error = 0; 1525 1526 struct nandfs_node *fdnode, *fnode, *fnode1; 1527 struct nandfs_node *tdnode = VTON(tdvp); 1528 struct nandfs_node *tnode; 1529 1530 uint32_t tdflags, fflags, fdflags; 1531 uint16_t mode; 1532 1533 DPRINTF(VNCALL, ("%s: fdvp:%p fvp:%p tdvp:%p tdp:%p\n", __func__, fdvp, 1534 fvp, tdvp, tvp)); 1535 1536 /* 1537 * Check for cross-device rename. 1538 */ 1539 if ((fvp->v_mount != tdvp->v_mount) || 1540 (tvp && (fvp->v_mount != tvp->v_mount))) { 1541 error = EXDEV; 1542abortit: 1543 if (tdvp == tvp) 1544 vrele(tdvp); 1545 else 1546 vput(tdvp); 1547 if (tvp) 1548 vput(tvp); 1549 vrele(fdvp); 1550 vrele(fvp); 1551 return (error); 1552 } 1553 1554 tdflags = tdnode->nn_inode.i_flags; 1555 if (tvp && 1556 ((VTON(tvp)->nn_inode.i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 1557 (tdflags & APPEND))) { 1558 error = EPERM; 1559 goto abortit; 1560 } 1561 1562 /* 1563 * Renaming a file to itself has no effect. The upper layers should 1564 * not call us in that case. Temporarily just warn if they do. 1565 */ 1566 if (fvp == tvp) { 1567 printf("nandfs_rename: fvp == tvp (can't happen)\n"); 1568 error = 0; 1569 goto abortit; 1570 } 1571 1572 if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) 1573 goto abortit; 1574 1575 fdnode = VTON(fdvp); 1576 fnode = VTON(fvp); 1577 1578 if (fnode->nn_inode.i_links_count >= LINK_MAX) { 1579 VOP_UNLOCK(fvp, 0); 1580 error = EMLINK; 1581 goto abortit; 1582 } 1583 1584 fflags = fnode->nn_inode.i_flags; 1585 fdflags = fdnode->nn_inode.i_flags; 1586 1587 if ((fflags & (NOUNLINK | IMMUTABLE | APPEND)) || 1588 (fdflags & APPEND)) { 1589 VOP_UNLOCK(fvp, 0); 1590 error = EPERM; 1591 goto abortit; 1592 } 1593 1594 mode = fnode->nn_inode.i_mode; 1595 if ((mode & S_IFMT) == S_IFDIR) { 1596 /* 1597 * Avoid ".", "..", and aliases of "." for obvious reasons. 1598 */ 1599 1600 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1601 (fdvp == fvp) || 1602 ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) || 1603 (fnode->nn_flags & IN_RENAME)) { 1604 VOP_UNLOCK(fvp, 0); 1605 error = EINVAL; 1606 goto abortit; 1607 } 1608 fnode->nn_flags |= IN_RENAME; 1609 doingdirectory = 1; 1610 DPRINTF(VNCALL, ("%s: doingdirectory dvp %p\n", __func__, 1611 tdvp)); 1612 oldparent = fdnode->nn_ino; 1613 } 1614 1615 vrele(fdvp); 1616 1617 tnode = NULL; 1618 if (tvp) 1619 tnode = VTON(tvp); 1620 1621 /* 1622 * Bump link count on fvp while we are moving stuff around. If we 1623 * crash before completing the work, the link count may be wrong 1624 * but correctable. 1625 */ 1626 fnode->nn_inode.i_links_count++; 1627 1628 /* Check for in path moving XXX */ 1629 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread); 1630 VOP_UNLOCK(fvp, 0); 1631 if (oldparent != tdnode->nn_ino) 1632 newparent = tdnode->nn_ino; 1633 if (doingdirectory && newparent) { 1634 if (error) /* write access check above */ 1635 goto bad; 1636 if (tnode != NULL) 1637 vput(tvp); 1638 1639 error = nandfs_checkpath(fnode, tdnode, tcnp->cn_cred); 1640 if (error) 1641 goto out; 1642 1643 VREF(tdvp); 1644 error = relookup(tdvp, &tvp, tcnp); 1645 if (error) 1646 goto out; 1647 vrele(tdvp); 1648 tdnode = VTON(tdvp); 1649 tnode = NULL; 1650 if (tvp) 1651 tnode = VTON(tvp); 1652 } 1653 1654 /* 1655 * If the target doesn't exist, link the target to the source and 1656 * unlink the source. Otherwise, rewrite the target directory to 1657 * reference the source and remove the original entry. 1658 */ 1659 1660 if (tvp == NULL) { 1661 /* 1662 * Account for ".." in new directory. 1663 */ 1664 if (doingdirectory && fdvp != tdvp) 1665 tdnode->nn_inode.i_links_count++; 1666 1667 DPRINTF(VNCALL, ("%s: new entry in dvp:%p\n", __func__, tdvp)); 1668 /* 1669 * Add name in new directory. 1670 */ 1671 error = nandfs_add_dirent(tdvp, fnode->nn_ino, tcnp->cn_nameptr, 1672 tcnp->cn_namelen, IFTODT(fnode->nn_inode.i_mode)); 1673 if (error) { 1674 if (doingdirectory && fdvp != tdvp) 1675 tdnode->nn_inode.i_links_count--; 1676 goto bad; 1677 } 1678 1679 vput(tdvp); 1680 } else { 1681 /* 1682 * If the parent directory is "sticky", then the user must 1683 * own the parent directory, or the destination of the rename, 1684 * otherwise the destination may not be changed (except by 1685 * root). This implements append-only directories. 1686 */ 1687 if ((tdnode->nn_inode.i_mode & S_ISTXT) && 1688 tcnp->cn_cred->cr_uid != 0 && 1689 tcnp->cn_cred->cr_uid != tdnode->nn_inode.i_uid && 1690 tnode->nn_inode.i_uid != tcnp->cn_cred->cr_uid) { 1691 error = EPERM; 1692 goto bad; 1693 } 1694 /* 1695 * Target must be empty if a directory and have no links 1696 * to it. Also, ensure source and target are compatible 1697 * (both directories, or both not directories). 1698 */ 1699 mode = tnode->nn_inode.i_mode; 1700 if ((mode & S_IFMT) == S_IFDIR) { 1701 if (!nandfs_dirempty(tvp, tdnode->nn_ino, 1702 tcnp->cn_cred)) { 1703 error = ENOTEMPTY; 1704 goto bad; 1705 } 1706 if (!doingdirectory) { 1707 error = ENOTDIR; 1708 goto bad; 1709 } 1710 /* 1711 * Update name cache since directory is going away. 1712 */ 1713 cache_purge(tdvp); 1714 } else if (doingdirectory) { 1715 error = EISDIR; 1716 goto bad; 1717 } 1718 1719 DPRINTF(VNCALL, ("%s: update entry dvp:%p\n", __func__, tdvp)); 1720 /* 1721 * Change name tcnp in tdvp to point at fvp. 1722 */ 1723 error = nandfs_update_dirent(tdvp, fnode, tnode); 1724 if (error) 1725 goto bad; 1726 1727 if (doingdirectory && !newparent) 1728 tdnode->nn_inode.i_links_count--; 1729 1730 vput(tdvp); 1731 1732 tnode->nn_inode.i_links_count--; 1733 vput(tvp); 1734 tnode = NULL; 1735 } 1736 1737 /* 1738 * Unlink the source. 1739 */ 1740 fcnp->cn_flags &= ~MODMASK; 1741 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 1742 VREF(fdvp); 1743 error = relookup(fdvp, &fvp, fcnp); 1744 if (error == 0) 1745 vrele(fdvp); 1746 if (fvp != NULL) { 1747 fnode1 = VTON(fvp); 1748 fdnode = VTON(fdvp); 1749 } else { 1750 /* 1751 * From name has disappeared. 1752 */ 1753 if (doingdirectory) 1754 panic("nandfs_rename: lost dir entry"); 1755 vrele(ap->a_fvp); 1756 return (0); 1757 } 1758 1759 DPRINTF(VNCALL, ("%s: unlink source fnode:%p\n", __func__, fnode)); 1760 1761 /* 1762 * Ensure that the directory entry still exists and has not 1763 * changed while the new name has been entered. If the source is 1764 * a file then the entry may have been unlinked or renamed. In 1765 * either case there is no further work to be done. If the source 1766 * is a directory then it cannot have been rmdir'ed; its link 1767 * count of three would cause a rmdir to fail with ENOTEMPTY. 1768 * The IN_RENAME flag ensures that it cannot be moved by another 1769 * rename. 1770 */ 1771 if (fnode != fnode1) { 1772 if (doingdirectory) 1773 panic("nandfs: lost dir entry"); 1774 } else { 1775 /* 1776 * If the source is a directory with a 1777 * new parent, the link count of the old 1778 * parent directory must be decremented 1779 * and ".." set to point to the new parent. 1780 */ 1781 if (doingdirectory && newparent) { 1782 DPRINTF(VNCALL, ("%s: new parent %#jx -> %#jx\n", 1783 __func__, (uintmax_t) oldparent, 1784 (uintmax_t) newparent)); 1785 error = nandfs_update_parent_dir(fvp, newparent); 1786 if (!error) { 1787 fdnode->nn_inode.i_links_count--; 1788 fdnode->nn_flags |= IN_CHANGE; 1789 } 1790 } 1791 error = nandfs_remove_dirent(fdvp, fnode, fcnp); 1792 if (!error) { 1793 fnode->nn_inode.i_links_count--; 1794 fnode->nn_flags |= IN_CHANGE; 1795 } 1796 fnode->nn_flags &= ~IN_RENAME; 1797 } 1798 if (fdnode) 1799 vput(fdvp); 1800 if (fnode) 1801 vput(fvp); 1802 vrele(ap->a_fvp); 1803 return (error); 1804 1805bad: 1806 DPRINTF(VNCALL, ("%s: error:%d\n", __func__, error)); 1807 if (tnode) 1808 vput(NTOV(tnode)); 1809 vput(NTOV(tdnode)); 1810out: 1811 if (doingdirectory) 1812 fnode->nn_flags &= ~IN_RENAME; 1813 if (vn_lock(fvp, LK_EXCLUSIVE) == 0) { 1814 fnode->nn_inode.i_links_count--; 1815 fnode->nn_flags |= IN_CHANGE; 1816 fnode->nn_flags &= ~IN_RENAME; 1817 vput(fvp); 1818 } else 1819 vrele(fvp); 1820 return (error); 1821} 1822 1823static int 1824nandfs_mkdir(struct vop_mkdir_args *ap) 1825{ 1826 struct vnode *dvp = ap->a_dvp; 1827 struct vnode **vpp = ap->a_vpp; 1828 struct componentname *cnp = ap->a_cnp; 1829 struct nandfs_node *dir_node = VTON(dvp); 1830 struct nandfs_inode *dir_inode = &dir_node->nn_inode; 1831 struct nandfs_node *node; 1832 struct nandfsmount *nmp = dir_node->nn_nmp; 1833 uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 1834 int error; 1835 1836 DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp)); 1837 1838 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1839 return (ENOSPC); 1840 1841 if (dir_inode->i_links_count >= LINK_MAX) 1842 return (EMLINK); 1843 1844 error = nandfs_node_create(nmp, &node, mode); 1845 if (error) 1846 return (error); 1847 1848 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1849 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1850 1851 *vpp = NTOV(node); 1852 1853 error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1854 cnp->cn_namelen, IFTODT(mode)); 1855 if (error) { 1856 vput(*vpp); 1857 return (error); 1858 } 1859 1860 dir_node->nn_inode.i_links_count++; 1861 dir_node->nn_flags |= IN_CHANGE; 1862 1863 error = nandfs_init_dir(NTOV(node), node->nn_ino, dir_node->nn_ino); 1864 if (error) { 1865 vput(NTOV(node)); 1866 return (error); 1867 } 1868 1869 DPRINTF(VNCALL, ("created dir vp %p nandnode %p ino %jx\n", *vpp, node, 1870 (uintmax_t)node->nn_ino)); 1871 return (0); 1872} 1873 1874static int 1875nandfs_mknod(struct vop_mknod_args *ap) 1876{ 1877 struct vnode *dvp = ap->a_dvp; 1878 struct vnode **vpp = ap->a_vpp; 1879 struct vattr *vap = ap->a_vap; 1880 uint16_t mode = MAKEIMODE(vap->va_type, vap->va_mode); 1881 struct componentname *cnp = ap->a_cnp; 1882 struct nandfs_node *dir_node = VTON(dvp); 1883 struct nandfsmount *nmp = dir_node->nn_nmp; 1884 struct nandfs_node *node; 1885 int error; 1886 1887 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1888 return (ENOSPC); 1889 1890 error = nandfs_node_create(nmp, &node, mode); 1891 if (error) 1892 return (error); 1893 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1894 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1895 if (vap->va_rdev != VNOVAL) 1896 node->nn_inode.i_special = vap->va_rdev; 1897 1898 *vpp = NTOV(node); 1899 1900 if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1901 cnp->cn_namelen, IFTODT(mode))) { 1902 vput(*vpp); 1903 return (ENOTDIR); 1904 } 1905 1906 node->nn_flags |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 1907 1908 return (0); 1909} 1910 1911static int 1912nandfs_symlink(struct vop_symlink_args *ap) 1913{ 1914 struct vnode **vpp = ap->a_vpp; 1915 struct vnode *dvp = ap->a_dvp; 1916 uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 1917 struct componentname *cnp = ap->a_cnp; 1918 struct nandfs_node *dir_node = VTON(dvp); 1919 struct nandfsmount *nmp = dir_node->nn_nmp; 1920 struct nandfs_node *node; 1921 int len, error; 1922 1923 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1924 return (ENOSPC); 1925 1926 error = nandfs_node_create(nmp, &node, S_IFLNK | mode); 1927 if (error) 1928 return (error); 1929 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1930 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1931 1932 *vpp = NTOV(node); 1933 1934 if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1935 cnp->cn_namelen, IFTODT(mode))) { 1936 vput(*vpp); 1937 return (ENOTDIR); 1938 } 1939 1940 1941 len = strlen(ap->a_target); 1942 error = vn_rdwr(UIO_WRITE, *vpp, ap->a_target, len, (off_t)0, 1943 UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, 1944 cnp->cn_cred, NOCRED, NULL, NULL); 1945 if (error) 1946 vput(*vpp); 1947 1948 return (error); 1949} 1950 1951static int 1952nandfs_readlink(struct vop_readlink_args *ap) 1953{ 1954 struct vnode *vp = ap->a_vp; 1955 1956 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); 1957} 1958 1959static int 1960nandfs_rmdir(struct vop_rmdir_args *ap) 1961{ 1962 struct vnode *vp = ap->a_vp; 1963 struct vnode *dvp = ap->a_dvp; 1964 struct componentname *cnp = ap->a_cnp; 1965 struct nandfs_node *node, *dnode; 1966 uint32_t dflag, flag; 1967 int error = 0; 1968 1969 node = VTON(vp); 1970 dnode = VTON(dvp); 1971 1972 /* Files marked as immutable or append-only cannot be deleted. */ 1973 if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) || 1974 (dnode->nn_inode.i_flags & APPEND)) 1975 return (EPERM); 1976 1977 DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx\n", __func__, 1978 dvp, vp, node, (uintmax_t)node->nn_ino)); 1979 1980 if (node->nn_inode.i_links_count < 2) 1981 return (EINVAL); 1982 1983 if (!nandfs_dirempty(vp, dnode->nn_ino, cnp->cn_cred)) 1984 return (ENOTEMPTY); 1985 1986 /* Files marked as immutable or append-only cannot be deleted. */ 1987 dflag = dnode->nn_inode.i_flags; 1988 flag = node->nn_inode.i_flags; 1989 if ((dflag & APPEND) || 1990 (flag & (NOUNLINK | IMMUTABLE | APPEND))) { 1991 return (EPERM); 1992 } 1993 1994 if (vp->v_mountedhere != 0) 1995 return (EINVAL); 1996 1997 nandfs_remove_dirent(dvp, node, cnp); 1998 dnode->nn_inode.i_links_count -= 1; 1999 dnode->nn_flags |= IN_CHANGE; 2000 2001 cache_purge(dvp); 2002 2003 error = nandfs_truncate(vp, (uint64_t)0); 2004 if (error) 2005 return (error); 2006 2007 node->nn_inode.i_links_count -= 2; 2008 node->nn_flags |= IN_CHANGE; 2009 2010 cache_purge(vp); 2011 2012 return (error); 2013} 2014 2015static int 2016nandfs_fsync(struct vop_fsync_args *ap) 2017{ 2018 struct vnode *vp = ap->a_vp; 2019 struct nandfs_node *node = VTON(vp); 2020 int locked; 2021 2022 DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp, 2023 node, (uintmax_t)node->nn_ino)); 2024 2025 /* 2026 * Start syncing vnode only if inode was modified or 2027 * there are some dirty buffers 2028 */ 2029 if (VTON(vp)->nn_flags & IN_MODIFIED || 2030 vp->v_bufobj.bo_dirty.bv_cnt) { 2031 locked = VOP_ISLOCKED(vp); 2032 VOP_UNLOCK(vp, 0); 2033 nandfs_wakeup_wait_sync(node->nn_nandfsdev, SYNCER_FSYNC); 2034 VOP_LOCK(vp, locked | LK_RETRY); 2035 } 2036 2037 return (0); 2038} 2039 2040static int 2041nandfs_bmap(struct vop_bmap_args *ap) 2042{ 2043 struct vnode *vp = ap->a_vp; 2044 struct nandfs_node *nnode = VTON(vp); 2045 struct nandfs_device *nandfsdev = nnode->nn_nandfsdev; 2046 nandfs_daddr_t l2vmap, v2pmap; 2047 int error; 2048 int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE; 2049 2050 DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp, 2051 nnode, (uintmax_t)nnode->nn_ino)); 2052 2053 if (ap->a_bop != NULL) 2054 *ap->a_bop = &nandfsdev->nd_devvp->v_bufobj; 2055 if (ap->a_bnp == NULL) 2056 return (0); 2057 if (ap->a_runp != NULL) 2058 *ap->a_runp = 0; 2059 if (ap->a_runb != NULL) 2060 *ap->a_runb = 0; 2061 2062 /* 2063 * Translate all the block sectors into a series of buffers to read 2064 * asynchronously from the nandfs device. Note that this lookup may 2065 * induce readin's too. 2066 */ 2067 2068 /* Get virtual block numbers for the vnode's buffer span */ 2069 error = nandfs_bmap_lookup(nnode, ap->a_bn, &l2vmap); 2070 if (error) 2071 return (-1); 2072 2073 /* Translate virtual block numbers to physical block numbers */ 2074 error = nandfs_vtop(nnode, l2vmap, &v2pmap); 2075 if (error) 2076 return (-1); 2077 2078 /* Note virtual block 0 marks not mapped */ 2079 if (l2vmap == 0) 2080 *ap->a_bnp = -1; 2081 else 2082 *ap->a_bnp = v2pmap * blk2dev; /* in DEV_BSIZE */ 2083 2084 DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx lblk %jx -> blk %jx\n", 2085 __func__, vp, nnode, (uintmax_t)nnode->nn_ino, (uintmax_t)ap->a_bn, 2086 (uintmax_t)*ap->a_bnp )); 2087 2088 return (0); 2089} 2090 2091static void 2092nandfs_force_syncer(struct nandfsmount *nmp) 2093{ 2094 2095 nmp->nm_flags |= NANDFS_FORCE_SYNCER; 2096 nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_FFORCE); 2097} 2098 2099static int 2100nandfs_ioctl(struct vop_ioctl_args *ap) 2101{ 2102 struct vnode *vp = ap->a_vp; 2103 u_long command = ap->a_command; 2104 caddr_t data = ap->a_data; 2105 struct nandfs_node *node = VTON(vp); 2106 struct nandfs_device *nandfsdev = node->nn_nandfsdev; 2107 struct nandfsmount *nmp = node->nn_nmp; 2108 uint64_t *tab, *cno; 2109 struct nandfs_seg_stat *nss; 2110 struct nandfs_cpmode *ncpm; 2111 struct nandfs_argv *nargv; 2112 struct nandfs_cpstat *ncp; 2113 int error; 2114 2115 DPRINTF(VNCALL, ("%s: %x\n", __func__, (uint32_t)command)); 2116 2117 error = priv_check(ap->a_td, PRIV_VFS_MOUNT); 2118 if (error) 2119 return (error); 2120 2121 if (nmp->nm_ronly) { 2122 switch (command) { 2123 case NANDFS_IOCTL_GET_FSINFO: 2124 case NANDFS_IOCTL_GET_SUSTAT: 2125 case NANDFS_IOCTL_GET_CPINFO: 2126 case NANDFS_IOCTL_GET_CPSTAT: 2127 case NANDFS_IOCTL_GET_SUINFO: 2128 case NANDFS_IOCTL_GET_VINFO: 2129 case NANDFS_IOCTL_GET_BDESCS: 2130 break; 2131 default: 2132 return (EROFS); 2133 } 2134 } 2135 2136 switch (command) { 2137 case NANDFS_IOCTL_GET_FSINFO: 2138 error = nandfs_get_fsinfo(nmp, (struct nandfs_fsinfo *)data); 2139 break; 2140 case NANDFS_IOCTL_GET_SUSTAT: 2141 nss = (struct nandfs_seg_stat *)data; 2142 error = nandfs_get_seg_stat(nandfsdev, nss); 2143 break; 2144 case NANDFS_IOCTL_CHANGE_CPMODE: 2145 ncpm = (struct nandfs_cpmode *)data; 2146 error = nandfs_chng_cpmode(nandfsdev->nd_cp_node, ncpm); 2147 nandfs_force_syncer(nmp); 2148 break; 2149 case NANDFS_IOCTL_GET_CPINFO: 2150 nargv = (struct nandfs_argv *)data; 2151 error = nandfs_get_cpinfo_ioctl(nandfsdev->nd_cp_node, nargv); 2152 break; 2153 case NANDFS_IOCTL_DELETE_CP: 2154 tab = (uint64_t *)data; 2155 error = nandfs_delete_cp(nandfsdev->nd_cp_node, tab[0], tab[1]); 2156 nandfs_force_syncer(nmp); 2157 break; 2158 case NANDFS_IOCTL_GET_CPSTAT: 2159 ncp = (struct nandfs_cpstat *)data; 2160 error = nandfs_get_cpstat(nandfsdev->nd_cp_node, ncp); 2161 break; 2162 case NANDFS_IOCTL_GET_SUINFO: 2163 nargv = (struct nandfs_argv *)data; 2164 error = nandfs_get_segment_info_ioctl(nandfsdev, nargv); 2165 break; 2166 case NANDFS_IOCTL_GET_VINFO: 2167 nargv = (struct nandfs_argv *)data; 2168 error = nandfs_get_dat_vinfo_ioctl(nandfsdev, nargv); 2169 break; 2170 case NANDFS_IOCTL_GET_BDESCS: 2171 nargv = (struct nandfs_argv *)data; 2172 error = nandfs_get_dat_bdescs_ioctl(nandfsdev, nargv); 2173 break; 2174 case NANDFS_IOCTL_SYNC: 2175 cno = (uint64_t *)data; 2176 nandfs_force_syncer(nmp); 2177 *cno = nandfsdev->nd_last_cno; 2178 error = 0; 2179 break; 2180 case NANDFS_IOCTL_MAKE_SNAP: 2181 cno = (uint64_t *)data; 2182 error = nandfs_make_snap(nandfsdev, cno); 2183 nandfs_force_syncer(nmp); 2184 break; 2185 case NANDFS_IOCTL_DELETE_SNAP: 2186 cno = (uint64_t *)data; 2187 error = nandfs_delete_snap(nandfsdev, *cno); 2188 nandfs_force_syncer(nmp); 2189 break; 2190 default: 2191 error = ENOTTY; 2192 break; 2193 } 2194 2195 return (error); 2196} 2197 2198/* 2199 * Whiteout vnode call 2200 */ 2201static int 2202nandfs_whiteout(struct vop_whiteout_args *ap) 2203{ 2204 struct vnode *dvp = ap->a_dvp; 2205 struct componentname *cnp = ap->a_cnp; 2206 int error = 0; 2207 2208 switch (ap->a_flags) { 2209 case LOOKUP: 2210 return (0); 2211 case CREATE: 2212 /* Create a new directory whiteout */ 2213#ifdef INVARIANTS 2214 if ((cnp->cn_flags & SAVENAME) == 0) 2215 panic("ufs_whiteout: missing name"); 2216#endif 2217 error = nandfs_add_dirent(dvp, NANDFS_WHT_INO, cnp->cn_nameptr, 2218 cnp->cn_namelen, DT_WHT); 2219 break; 2220 2221 case DELETE: 2222 /* Remove an existing directory whiteout */ 2223 cnp->cn_flags &= ~DOWHITEOUT; 2224 error = nandfs_remove_dirent(dvp, NULL, cnp); 2225 break; 2226 default: 2227 panic("nandf_whiteout: unknown op: %d", ap->a_flags); 2228 } 2229 2230 return (error); 2231} 2232 2233static int 2234nandfs_pathconf(struct vop_pathconf_args *ap) 2235{ 2236 int error; 2237 2238 error = 0; 2239 switch (ap->a_name) { 2240 case _PC_LINK_MAX: 2241 *ap->a_retval = LINK_MAX; 2242 break; 2243 case _PC_NAME_MAX: 2244 *ap->a_retval = NANDFS_NAME_LEN; 2245 break; 2246 case _PC_PIPE_BUF: 2247 if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO) 2248 *ap->a_retval = PIPE_BUF; 2249 else 2250 error = EINVAL; 2251 break; 2252 case _PC_CHOWN_RESTRICTED: 2253 *ap->a_retval = 1; 2254 break; 2255 case _PC_NO_TRUNC: 2256 *ap->a_retval = 1; 2257 break; 2258 case _PC_ALLOC_SIZE_MIN: 2259 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize; 2260 break; 2261 case _PC_FILESIZEBITS: 2262 *ap->a_retval = 64; 2263 break; 2264 case _PC_REC_INCR_XFER_SIZE: 2265 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize; 2266 break; 2267 case _PC_REC_MAX_XFER_SIZE: 2268 *ap->a_retval = -1; /* means ``unlimited'' */ 2269 break; 2270 case _PC_REC_MIN_XFER_SIZE: 2271 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize; 2272 break; 2273 default: 2274 error = vop_stdpathconf(ap); 2275 break; 2276 } 2277 return (error); 2278} 2279 2280static int 2281nandfs_vnlock1(struct vop_lock1_args *ap) 2282{ 2283 struct vnode *vp = ap->a_vp; 2284 struct nandfs_node *node = VTON(vp); 2285 int error, vi_locked; 2286 2287 /* 2288 * XXX can vnode go away while we are sleeping? 2289 */ 2290 vi_locked = mtx_owned(&vp->v_interlock); 2291 if (vi_locked) 2292 VI_UNLOCK(vp); 2293 error = NANDFS_WRITELOCKFLAGS(node->nn_nandfsdev, 2294 ap->a_flags & LK_NOWAIT); 2295 if (vi_locked && !error) 2296 VI_LOCK(vp); 2297 if (error) 2298 return (error); 2299 2300 error = vop_stdlock(ap); 2301 if (error) { 2302 NANDFS_WRITEUNLOCK(node->nn_nandfsdev); 2303 return (error); 2304 } 2305 2306 return (0); 2307} 2308 2309static int 2310nandfs_vnunlock(struct vop_unlock_args *ap) 2311{ 2312 struct vnode *vp = ap->a_vp; 2313 struct nandfs_node *node = VTON(vp); 2314 int error; 2315 2316 error = vop_stdunlock(ap); 2317 if (error) 2318 return (error); 2319 2320 NANDFS_WRITEUNLOCK(node->nn_nandfsdev); 2321 2322 return (0); 2323} 2324 2325/* 2326 * Global vfs data structures 2327 */ 2328struct vop_vector nandfs_vnodeops = { 2329 .vop_default = &default_vnodeops, 2330 .vop_access = nandfs_access, 2331 .vop_advlock = nandfs_advlock, 2332 .vop_bmap = nandfs_bmap, 2333 .vop_close = nandfs_close, 2334 .vop_create = nandfs_create, 2335 .vop_fsync = nandfs_fsync, 2336 .vop_getattr = nandfs_getattr, 2337 .vop_inactive = nandfs_inactive, 2338 .vop_cachedlookup = nandfs_lookup, 2339 .vop_ioctl = nandfs_ioctl, 2340 .vop_link = nandfs_link, 2341 .vop_lookup = vfs_cache_lookup, 2342 .vop_mkdir = nandfs_mkdir, 2343 .vop_mknod = nandfs_mknod, 2344 .vop_open = nandfs_open, 2345 .vop_pathconf = nandfs_pathconf, 2346 .vop_print = nandfs_print, 2347 .vop_read = nandfs_read, 2348 .vop_readdir = nandfs_readdir, 2349 .vop_readlink = nandfs_readlink, 2350 .vop_reclaim = nandfs_reclaim, 2351 .vop_remove = nandfs_remove, 2352 .vop_rename = nandfs_rename, 2353 .vop_rmdir = nandfs_rmdir, 2354 .vop_whiteout = nandfs_whiteout, 2355 .vop_write = nandfs_write, 2356 .vop_setattr = nandfs_setattr, 2357 .vop_strategy = nandfs_strategy, 2358 .vop_symlink = nandfs_symlink, 2359 .vop_lock1 = nandfs_vnlock1, 2360 .vop_unlock = nandfs_vnunlock, 2361}; 2362 2363struct vop_vector nandfs_system_vnodeops = { 2364 .vop_default = &default_vnodeops, 2365 .vop_close = nandfs_close, 2366 .vop_inactive = nandfs_inactive, 2367 .vop_reclaim = nandfs_reclaim, 2368 .vop_strategy = nandfs_strategy, 2369 .vop_fsync = nandfs_fsync, 2370 .vop_bmap = nandfs_bmap, 2371 .vop_access = VOP_PANIC, 2372 .vop_advlock = VOP_PANIC, 2373 .vop_create = VOP_PANIC, 2374 .vop_getattr = VOP_PANIC, 2375 .vop_cachedlookup = VOP_PANIC, 2376 .vop_ioctl = VOP_PANIC, 2377 .vop_link = VOP_PANIC, 2378 .vop_lookup = VOP_PANIC, 2379 .vop_mkdir = VOP_PANIC, 2380 .vop_mknod = VOP_PANIC, 2381 .vop_open = VOP_PANIC, 2382 .vop_pathconf = VOP_PANIC, 2383 .vop_print = VOP_PANIC, 2384 .vop_read = VOP_PANIC, 2385 .vop_readdir = VOP_PANIC, 2386 .vop_readlink = VOP_PANIC, 2387 .vop_remove = VOP_PANIC, 2388 .vop_rename = VOP_PANIC, 2389 .vop_rmdir = VOP_PANIC, 2390 .vop_whiteout = VOP_PANIC, 2391 .vop_write = VOP_PANIC, 2392 .vop_setattr = VOP_PANIC, 2393 .vop_symlink = VOP_PANIC, 2394}; 2395 2396static int 2397nandfsfifo_close(struct vop_close_args *ap) 2398{ 2399 struct vnode *vp = ap->a_vp; 2400 struct nandfs_node *node = VTON(vp); 2401 2402 DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node)); 2403 2404 mtx_lock(&vp->v_interlock); 2405 if (vp->v_usecount > 1) 2406 nandfs_itimes_locked(vp); 2407 mtx_unlock(&vp->v_interlock); 2408 2409 return (fifo_specops.vop_close(ap)); 2410} 2411 2412struct vop_vector nandfs_fifoops = { 2413 .vop_default = &fifo_specops, 2414 .vop_fsync = VOP_PANIC, 2415 .vop_access = nandfs_access, 2416 .vop_close = nandfsfifo_close, 2417 .vop_getattr = nandfs_getattr, 2418 .vop_inactive = nandfs_inactive, 2419 .vop_pathconf = nandfs_pathconf, 2420 .vop_print = nandfs_print, 2421 .vop_read = VOP_PANIC, 2422 .vop_reclaim = nandfs_reclaim, 2423 .vop_setattr = nandfs_setattr, 2424 .vop_write = VOP_PANIC, 2425 .vop_lock1 = nandfs_vnlock1, 2426 .vop_unlock = nandfs_vnunlock, 2427}; 2428 2429int 2430nandfs_vinit(struct vnode *vp, uint64_t ino) 2431{ 2432 struct nandfs_node *node; 2433 2434 ASSERT_VOP_LOCKED(vp, __func__); 2435 2436 node = VTON(vp); 2437 2438 /* Check if we're fetching the root */ 2439 if (ino == NANDFS_ROOT_INO) 2440 vp->v_vflag |= VV_ROOT; 2441 2442 if (ino != NANDFS_GC_INO) 2443 vp->v_type = IFTOVT(node->nn_inode.i_mode); 2444 else 2445 vp->v_type = VREG; 2446 2447 if (vp->v_type == VFIFO) 2448 vp->v_op = &nandfs_fifoops; 2449 2450 return (0); 2451} 2452