nandfs_vnops.c revision 269283
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/10/sys/fs/nandfs/nandfs_vnops.c 269283 2014-07-30 03:56:17Z kib $"); 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 register struct vnode *vp = ap->a_vp; 133 register 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, 409 td); 410 if (!error) { 411 /* keep the component name */ 412 cnp->cn_flags |= SAVENAME; 413 error = EJUSTRETURN; 414 } 415 } 416 /* Done */ 417 } else { 418 if (ino == NANDFS_WHT_INO) 419 cnp->cn_flags |= ISWHITEOUT; 420 421 if ((cnp->cn_flags & ISWHITEOUT) && 422 (nameiop == LOOKUP)) 423 return (ENOENT); 424 425 if ((nameiop == DELETE) && islastcn) { 426 if ((cnp->cn_flags & ISWHITEOUT) && 427 (cnp->cn_flags & DOWHITEOUT)) { 428 cnp->cn_flags |= SAVENAME; 429 dir_node->nn_diroff = off; 430 return (EJUSTRETURN); 431 } 432 433 error = VOP_ACCESS(dvp, VWRITE, cred, 434 cnp->cn_thread); 435 if (error) 436 return (error); 437 438 /* Try to create/reuse the node */ 439 error = nandfs_get_node(nmp, ino, &node); 440 if (!error) { 441 *vpp = NTOV(node); 442 node->nn_diroff = off; 443 } 444 445 if ((dir_node->nn_inode.i_mode & ISVTX) && 446 cred->cr_uid != 0 && 447 cred->cr_uid != dir_node->nn_inode.i_uid && 448 node->nn_inode.i_uid != cred->cr_uid) { 449 vput(*vpp); 450 *vpp = NULL; 451 return (EPERM); 452 } 453 } else if ((nameiop == RENAME) && islastcn) { 454 error = VOP_ACCESS(dvp, VWRITE, cred, 455 cnp->cn_thread); 456 if (error) 457 return (error); 458 459 /* Try to create/reuse the node */ 460 error = nandfs_get_node(nmp, ino, &node); 461 if (!error) { 462 *vpp = NTOV(node); 463 node->nn_diroff = off; 464 } 465 } else { 466 /* Try to create/reuse the node */ 467 error = nandfs_get_node(nmp, ino, &node); 468 if (!error) { 469 *vpp = NTOV(node); 470 node->nn_diroff = off; 471 } 472 } 473 } 474 } 475 476out: 477 /* 478 * Store result in the cache if requested. If we are creating a file, 479 * the file might not be found and thus putting it into the namecache 480 * might be seen as negative caching. 481 */ 482 if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) 483 cache_enter(dvp, *vpp, cnp); 484 485 return (error); 486 487} 488 489static int 490nandfs_getattr(struct vop_getattr_args *ap) 491{ 492 struct vnode *vp = ap->a_vp; 493 struct vattr *vap = ap->a_vap; 494 struct nandfs_node *node = VTON(vp); 495 struct nandfs_inode *inode = &node->nn_inode; 496 497 DPRINTF(VNCALL, ("%s: vp: %p\n", __func__, vp)); 498 nandfs_itimes(vp); 499 500 /* Basic info */ 501 VATTR_NULL(vap); 502 vap->va_atime.tv_sec = inode->i_mtime; 503 vap->va_atime.tv_nsec = inode->i_mtime_nsec; 504 vap->va_mtime.tv_sec = inode->i_mtime; 505 vap->va_mtime.tv_nsec = inode->i_mtime_nsec; 506 vap->va_ctime.tv_sec = inode->i_ctime; 507 vap->va_ctime.tv_nsec = inode->i_ctime_nsec; 508 vap->va_type = IFTOVT(inode->i_mode); 509 vap->va_mode = inode->i_mode & ~S_IFMT; 510 vap->va_nlink = inode->i_links_count; 511 vap->va_uid = inode->i_uid; 512 vap->va_gid = inode->i_gid; 513 vap->va_rdev = inode->i_special; 514 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 515 vap->va_fileid = node->nn_ino; 516 vap->va_size = inode->i_size; 517 vap->va_blocksize = node->nn_nandfsdev->nd_blocksize; 518 vap->va_gen = 0; 519 vap->va_flags = inode->i_flags; 520 vap->va_bytes = inode->i_blocks * vap->va_blocksize; 521 vap->va_filerev = 0; 522 vap->va_vaflags = 0; 523 524 return (0); 525} 526 527static int 528nandfs_vtruncbuf(struct vnode *vp, uint64_t nblks) 529{ 530 struct nandfs_device *nffsdev; 531 struct bufobj *bo; 532 struct buf *bp, *nbp; 533 534 bo = &vp->v_bufobj; 535 nffsdev = VTON(vp)->nn_nandfsdev; 536 537 ASSERT_VOP_LOCKED(vp, "nandfs_truncate"); 538restart: 539 BO_LOCK(bo); 540restart_locked: 541 TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, nbp) { 542 if (bp->b_lblkno < nblks) 543 continue; 544 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) 545 goto restart_locked; 546 547 bremfree(bp); 548 bp->b_flags |= (B_INVAL | B_RELBUF); 549 bp->b_flags &= ~(B_ASYNC | B_MANAGED); 550 BO_UNLOCK(bo); 551 brelse(bp); 552 BO_LOCK(bo); 553 } 554 555 TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { 556 if (bp->b_lblkno < nblks) 557 continue; 558 if (BUF_LOCK(bp, 559 LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, 560 BO_LOCKPTR(bo)) == ENOLCK) 561 goto restart; 562 bp->b_flags |= (B_INVAL | B_RELBUF); 563 bp->b_flags &= ~(B_ASYNC | B_MANAGED); 564 brelse(bp); 565 nandfs_dirty_bufs_decrement(nffsdev); 566 BO_LOCK(bo); 567 } 568 569 BO_UNLOCK(bo); 570 571 return (0); 572} 573 574static int 575nandfs_truncate(struct vnode *vp, uint64_t newsize) 576{ 577 struct nandfs_device *nffsdev; 578 struct nandfs_node *node; 579 struct nandfs_inode *inode; 580 struct buf *bp = NULL; 581 uint64_t oblks, nblks, vblk, size, rest; 582 int error; 583 584 node = VTON(vp); 585 nffsdev = node->nn_nandfsdev; 586 inode = &node->nn_inode; 587 588 /* Calculate end of file */ 589 size = inode->i_size; 590 591 if (newsize == size) { 592 node->nn_flags |= IN_CHANGE | IN_UPDATE; 593 nandfs_itimes(vp); 594 return (0); 595 } 596 597 if (newsize > size) { 598 inode->i_size = newsize; 599 vnode_pager_setsize(vp, newsize); 600 node->nn_flags |= IN_CHANGE | IN_UPDATE; 601 nandfs_itimes(vp); 602 return (0); 603 } 604 605 nblks = howmany(newsize, nffsdev->nd_blocksize); 606 oblks = howmany(size, nffsdev->nd_blocksize); 607 rest = newsize % nffsdev->nd_blocksize; 608 609 if (rest) { 610 error = nandfs_bmap_lookup(node, nblks - 1, &vblk); 611 if (error) 612 return (error); 613 614 if (vblk != 0) 615 error = nandfs_bread(node, nblks - 1, NOCRED, 0, &bp); 616 else 617 error = nandfs_bcreate(node, nblks - 1, NOCRED, 0, &bp); 618 619 if (error) { 620 if (bp) 621 brelse(bp); 622 return (error); 623 } 624 625 bzero((char *)bp->b_data + rest, 626 (u_int)(nffsdev->nd_blocksize - rest)); 627 error = nandfs_dirty_buf(bp, 0); 628 if (error) 629 return (error); 630 } 631 632 DPRINTF(VNCALL, ("%s: vp %p oblks %jx nblks %jx\n", __func__, vp, oblks, 633 nblks)); 634 635 error = nandfs_bmap_truncate_mapping(node, oblks - 1, nblks - 1); 636 if (error) { 637 if (bp) 638 nandfs_undirty_buf(bp); 639 return (error); 640 } 641 642 error = nandfs_vtruncbuf(vp, nblks); 643 if (error) { 644 if (bp) 645 nandfs_undirty_buf(bp); 646 return (error); 647 } 648 649 inode->i_size = newsize; 650 vnode_pager_setsize(vp, newsize); 651 node->nn_flags |= IN_CHANGE | IN_UPDATE; 652 nandfs_itimes(vp); 653 654 return (error); 655} 656 657static void 658nandfs_itimes_locked(struct vnode *vp) 659{ 660 struct nandfs_node *node; 661 struct nandfs_inode *inode; 662 struct timespec ts; 663 664 ASSERT_VI_LOCKED(vp, __func__); 665 666 node = VTON(vp); 667 inode = &node->nn_inode; 668 669 if ((node->nn_flags & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0) 670 return; 671 672 if (((vp->v_mount->mnt_kern_flag & 673 (MNTK_SUSPENDED | MNTK_SUSPEND)) == 0) || 674 (node->nn_flags & (IN_CHANGE | IN_UPDATE))) 675 node->nn_flags |= IN_MODIFIED; 676 677 vfs_timestamp(&ts); 678 if (node->nn_flags & IN_UPDATE) { 679 inode->i_mtime = ts.tv_sec; 680 inode->i_mtime_nsec = ts.tv_nsec; 681 } 682 if (node->nn_flags & IN_CHANGE) { 683 inode->i_ctime = ts.tv_sec; 684 inode->i_ctime_nsec = ts.tv_nsec; 685 } 686 687 node->nn_flags &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); 688} 689 690void 691nandfs_itimes(struct vnode *vp) 692{ 693 694 VI_LOCK(vp); 695 nandfs_itimes_locked(vp); 696 VI_UNLOCK(vp); 697} 698 699static int 700nandfs_chmod(struct vnode *vp, int mode, struct ucred *cred, struct thread *td) 701{ 702 struct nandfs_node *node = VTON(vp); 703 struct nandfs_inode *inode = &node->nn_inode; 704 uint16_t nmode; 705 int error = 0; 706 707 DPRINTF(VNCALL, ("%s: vp %p, mode %x, cred %p, td %p\n", __func__, vp, 708 mode, cred, td)); 709 /* 710 * To modify the permissions on a file, must possess VADMIN 711 * for that file. 712 */ 713 if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) 714 return (error); 715 716 /* 717 * Privileged processes may set the sticky bit on non-directories, 718 * as well as set the setgid bit on a file with a group that the 719 * process is not a member of. Both of these are allowed in 720 * jail(8). 721 */ 722 if (vp->v_type != VDIR && (mode & S_ISTXT)) { 723 if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0)) 724 return (EFTYPE); 725 } 726 if (!groupmember(inode->i_gid, cred) && (mode & ISGID)) { 727 error = priv_check_cred(cred, PRIV_VFS_SETGID, 0); 728 if (error) 729 return (error); 730 } 731 732 /* 733 * Deny setting setuid if we are not the file owner. 734 */ 735 if ((mode & ISUID) && inode->i_uid != cred->cr_uid) { 736 error = priv_check_cred(cred, PRIV_VFS_ADMIN, 0); 737 if (error) 738 return (error); 739 } 740 741 nmode = inode->i_mode; 742 nmode &= ~ALLPERMS; 743 nmode |= (mode & ALLPERMS); 744 inode->i_mode = nmode; 745 node->nn_flags |= IN_CHANGE; 746 747 DPRINTF(VNCALL, ("%s: to mode %x\n", __func__, nmode)); 748 749 return (error); 750} 751 752static int 753nandfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, 754 struct thread *td) 755{ 756 struct nandfs_node *node = VTON(vp); 757 struct nandfs_inode *inode = &node->nn_inode; 758 uid_t ouid; 759 gid_t ogid; 760 int error = 0; 761 762 if (uid == (uid_t)VNOVAL) 763 uid = inode->i_uid; 764 if (gid == (gid_t)VNOVAL) 765 gid = inode->i_gid; 766 /* 767 * To modify the ownership of a file, must possess VADMIN for that 768 * file. 769 */ 770 if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred, td))) 771 return (error); 772 /* 773 * To change the owner of a file, or change the group of a file to a 774 * group of which we are not a member, the caller must have 775 * privilege. 776 */ 777 if (((uid != inode->i_uid && uid != cred->cr_uid) || 778 (gid != inode->i_gid && !groupmember(gid, cred))) && 779 (error = priv_check_cred(cred, PRIV_VFS_CHOWN, 0))) 780 return (error); 781 ogid = inode->i_gid; 782 ouid = inode->i_uid; 783 784 inode->i_gid = gid; 785 inode->i_uid = uid; 786 787 node->nn_flags |= IN_CHANGE; 788 if ((inode->i_mode & (ISUID | ISGID)) && 789 (ouid != uid || ogid != gid)) { 790 if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0)) { 791 inode->i_mode &= ~(ISUID | ISGID); 792 } 793 } 794 DPRINTF(VNCALL, ("%s: vp %p, cred %p, td %p - ret OK\n", __func__, vp, 795 cred, td)); 796 return (0); 797} 798 799static int 800nandfs_setattr(struct vop_setattr_args *ap) 801{ 802 struct vnode *vp = ap->a_vp; 803 struct nandfs_node *node = VTON(vp); 804 struct nandfs_inode *inode = &node->nn_inode; 805 struct vattr *vap = ap->a_vap; 806 struct ucred *cred = ap->a_cred; 807 struct thread *td = curthread; 808 uint32_t flags; 809 int error = 0; 810 811 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 812 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 813 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 814 (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 815 DPRINTF(VNCALL, ("%s: unsettable attribute\n", __func__)); 816 return (EINVAL); 817 } 818 819 if (vap->va_flags != VNOVAL) { 820 DPRINTF(VNCALL, ("%s: vp:%p td:%p flags:%lx\n", __func__, vp, 821 td, vap->va_flags)); 822 823 if (vp->v_mount->mnt_flag & MNT_RDONLY) 824 return (EROFS); 825 /* 826 * Callers may only modify the file flags on objects they 827 * have VADMIN rights for. 828 */ 829 if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) 830 return (error); 831 /* 832 * Unprivileged processes are not permitted to unset system 833 * flags, or modify flags if any system flags are set. 834 * Privileged non-jail processes may not modify system flags 835 * if securelevel > 0 and any existing system flags are set. 836 * Privileged jail processes behave like privileged non-jail 837 * processes if the security.jail.chflags_allowed sysctl is 838 * is non-zero; otherwise, they behave like unprivileged 839 * processes. 840 */ 841 842 flags = inode->i_flags; 843 if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) { 844 if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { 845 error = securelevel_gt(cred, 0); 846 if (error) 847 return (error); 848 } 849 /* Snapshot flag cannot be set or cleared */ 850 if (((vap->va_flags & SF_SNAPSHOT) != 0 && 851 (flags & SF_SNAPSHOT) == 0) || 852 ((vap->va_flags & SF_SNAPSHOT) == 0 && 853 (flags & SF_SNAPSHOT) != 0)) 854 return (EPERM); 855 856 inode->i_flags = vap->va_flags; 857 } else { 858 if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) || 859 (vap->va_flags & UF_SETTABLE) != vap->va_flags) 860 return (EPERM); 861 862 flags &= SF_SETTABLE; 863 flags |= (vap->va_flags & UF_SETTABLE); 864 inode->i_flags = flags; 865 } 866 node->nn_flags |= IN_CHANGE; 867 if (vap->va_flags & (IMMUTABLE | APPEND)) 868 return (0); 869 } 870 if (inode->i_flags & (IMMUTABLE | APPEND)) 871 return (EPERM); 872 873 if (vap->va_size != (u_quad_t)VNOVAL) { 874 DPRINTF(VNCALL, ("%s: vp:%p td:%p size:%jx\n", __func__, vp, td, 875 (uintmax_t)vap->va_size)); 876 877 switch (vp->v_type) { 878 case VDIR: 879 return (EISDIR); 880 case VLNK: 881 case VREG: 882 if (vp->v_mount->mnt_flag & MNT_RDONLY) 883 return (EROFS); 884 if ((inode->i_flags & SF_SNAPSHOT) != 0) 885 return (EPERM); 886 break; 887 default: 888 return (0); 889 } 890 891 if (vap->va_size > node->nn_nandfsdev->nd_maxfilesize) 892 return (EFBIG); 893 894 KASSERT((vp->v_type == VREG), ("Set size %d", vp->v_type)); 895 nandfs_truncate(vp, vap->va_size); 896 node->nn_flags |= IN_CHANGE; 897 898 return (0); 899 } 900 901 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 902 if (vp->v_mount->mnt_flag & MNT_RDONLY) 903 return (EROFS); 904 DPRINTF(VNCALL, ("%s: vp:%p td:%p uid/gid %x/%x\n", __func__, 905 vp, td, vap->va_uid, vap->va_gid)); 906 error = nandfs_chown(vp, vap->va_uid, vap->va_gid, cred, td); 907 if (error) 908 return (error); 909 } 910 911 if (vap->va_mode != (mode_t)VNOVAL) { 912 if (vp->v_mount->mnt_flag & MNT_RDONLY) 913 return (EROFS); 914 DPRINTF(VNCALL, ("%s: vp:%p td:%p mode %x\n", __func__, vp, td, 915 vap->va_mode)); 916 917 error = nandfs_chmod(vp, (int)vap->va_mode, cred, td); 918 if (error) 919 return (error); 920 } 921 if (vap->va_atime.tv_sec != VNOVAL || 922 vap->va_mtime.tv_sec != VNOVAL || 923 vap->va_birthtime.tv_sec != VNOVAL) { 924 DPRINTF(VNCALL, ("%s: vp:%p td:%p time a/m/b %jx/%jx/%jx\n", 925 __func__, vp, td, (uintmax_t)vap->va_atime.tv_sec, 926 (uintmax_t)vap->va_mtime.tv_sec, 927 (uintmax_t)vap->va_birthtime.tv_sec)); 928 929 if (vap->va_atime.tv_sec != VNOVAL) 930 node->nn_flags |= IN_ACCESS; 931 if (vap->va_mtime.tv_sec != VNOVAL) 932 node->nn_flags |= IN_CHANGE | IN_UPDATE; 933 if (vap->va_birthtime.tv_sec != VNOVAL) 934 node->nn_flags |= IN_MODIFIED; 935 nandfs_itimes(vp); 936 return (0); 937 } 938 939 return (0); 940} 941 942static int 943nandfs_open(struct vop_open_args *ap) 944{ 945 struct nandfs_node *node = VTON(ap->a_vp); 946 uint64_t filesize; 947 948 DPRINTF(VNCALL, ("nandfs_open called ap->a_mode %x\n", ap->a_mode)); 949 950 if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK) 951 return (EOPNOTSUPP); 952 953 if ((node->nn_inode.i_flags & APPEND) && 954 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) 955 return (EPERM); 956 957 filesize = node->nn_inode.i_size; 958 vnode_create_vobject(ap->a_vp, filesize, ap->a_td); 959 960 return (0); 961} 962 963static int 964nandfs_close(struct vop_close_args *ap) 965{ 966 struct vnode *vp = ap->a_vp; 967 struct nandfs_node *node = VTON(vp); 968 969 DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node)); 970 971 mtx_lock(&vp->v_interlock); 972 if (vp->v_usecount > 1) 973 nandfs_itimes_locked(vp); 974 mtx_unlock(&vp->v_interlock); 975 976 return (0); 977} 978 979static int 980nandfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode) 981{ 982 983 /* Check if we are allowed to write */ 984 switch (vap->va_type) { 985 case VDIR: 986 case VLNK: 987 case VREG: 988 /* 989 * Normal nodes: check if we're on a read-only mounted 990 * filingsystem and bomb out if we're trying to write. 991 */ 992 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) 993 return (EROFS); 994 break; 995 case VBLK: 996 case VCHR: 997 case VSOCK: 998 case VFIFO: 999 /* 1000 * Special nodes: even on read-only mounted filingsystems 1001 * these are allowed to be written to if permissions allow. 1002 */ 1003 break; 1004 default: 1005 /* No idea what this is */ 1006 return (EINVAL); 1007 } 1008 1009 /* Noone may write immutable files */ 1010 if ((mode & VWRITE) && (VTON(vp)->nn_inode.i_flags & IMMUTABLE)) 1011 return (EPERM); 1012 1013 return (0); 1014} 1015 1016static int 1017nandfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode, 1018 struct ucred *cred) 1019{ 1020 1021 return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, mode, 1022 cred, NULL)); 1023} 1024 1025static int 1026nandfs_advlock(struct vop_advlock_args *ap) 1027{ 1028 struct nandfs_node *nvp; 1029 quad_t size; 1030 1031 nvp = VTON(ap->a_vp); 1032 size = nvp->nn_inode.i_size; 1033 return (lf_advlock(ap, &(nvp->nn_lockf), size)); 1034} 1035 1036static int 1037nandfs_access(struct vop_access_args *ap) 1038{ 1039 struct vnode *vp = ap->a_vp; 1040 accmode_t accmode = ap->a_accmode; 1041 struct ucred *cred = ap->a_cred; 1042 struct vattr vap; 1043 int error; 1044 1045 DPRINTF(VNCALL, ("%s: vp:%p mode: %x\n", __func__, vp, accmode)); 1046 1047 error = VOP_GETATTR(vp, &vap, NULL); 1048 if (error) 1049 return (error); 1050 1051 error = nandfs_check_possible(vp, &vap, accmode); 1052 if (error) { 1053 return (error); 1054 } 1055 1056 error = nandfs_check_permitted(vp, &vap, accmode, cred); 1057 1058 return (error); 1059} 1060 1061static int 1062nandfs_print(struct vop_print_args *ap) 1063{ 1064 struct vnode *vp = ap->a_vp; 1065 struct nandfs_node *nvp = VTON(vp); 1066 1067 printf("\tvp=%p, nandfs_node=%p\n", vp, nvp); 1068 printf("nandfs inode %#jx\n", (uintmax_t)nvp->nn_ino); 1069 printf("flags = 0x%b\n", (u_int)nvp->nn_flags, PRINT_NODE_FLAGS); 1070 1071 return (0); 1072} 1073 1074static void 1075nandfs_read_filebuf(struct nandfs_node *node, struct buf *bp) 1076{ 1077 struct nandfs_device *nandfsdev = node->nn_nandfsdev; 1078 struct buf *nbp; 1079 nandfs_daddr_t vblk, pblk; 1080 nandfs_lbn_t from; 1081 uint32_t blocksize; 1082 int error = 0; 1083 int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE; 1084 1085 /* 1086 * Translate all the block sectors into a series of buffers to read 1087 * asynchronously from the nandfs device. Note that this lookup may 1088 * induce readin's too. 1089 */ 1090 1091 blocksize = nandfsdev->nd_blocksize; 1092 if (bp->b_bcount / blocksize != 1) 1093 panic("invalid b_count in bp %p\n", bp); 1094 1095 from = bp->b_blkno; 1096 1097 DPRINTF(READ, ("\tread in from inode %#jx blkno %#jx" 1098 " count %#lx\n", (uintmax_t)node->nn_ino, from, 1099 bp->b_bcount)); 1100 1101 /* Get virtual block numbers for the vnode's buffer span */ 1102 error = nandfs_bmap_lookup(node, from, &vblk); 1103 if (error) { 1104 bp->b_error = EINVAL; 1105 bp->b_ioflags |= BIO_ERROR; 1106 bufdone(bp); 1107 return; 1108 } 1109 1110 /* Translate virtual block numbers to physical block numbers */ 1111 error = nandfs_vtop(node, vblk, &pblk); 1112 if (error) { 1113 bp->b_error = EINVAL; 1114 bp->b_ioflags |= BIO_ERROR; 1115 bufdone(bp); 1116 return; 1117 } 1118 1119 /* Issue translated blocks */ 1120 bp->b_resid = bp->b_bcount; 1121 1122 /* Note virtual block 0 marks not mapped */ 1123 if (vblk == 0) { 1124 vfs_bio_clrbuf(bp); 1125 bufdone(bp); 1126 return; 1127 } 1128 1129 nbp = bp; 1130 nbp->b_blkno = pblk * blk2dev; 1131 bp->b_iooffset = dbtob(nbp->b_blkno); 1132 MPASS(bp->b_iooffset >= 0); 1133 BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, nbp); 1134 nandfs_vblk_set(bp, vblk); 1135 DPRINTF(READ, ("read_filebuf : ino %#jx blk %#jx -> " 1136 "%#jx -> %#jx [bp %p]\n", (uintmax_t)node->nn_ino, 1137 (uintmax_t)(from), (uintmax_t)vblk, 1138 (uintmax_t)pblk, nbp)); 1139} 1140 1141static void 1142nandfs_write_filebuf(struct nandfs_node *node, struct buf *bp) 1143{ 1144 struct nandfs_device *nandfsdev = node->nn_nandfsdev; 1145 1146 bp->b_iooffset = dbtob(bp->b_blkno); 1147 MPASS(bp->b_iooffset >= 0); 1148 BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, bp); 1149} 1150 1151static int 1152nandfs_strategy(struct vop_strategy_args *ap) 1153{ 1154 struct vnode *vp = ap->a_vp; 1155 struct buf *bp = ap->a_bp; 1156 struct nandfs_node *node = VTON(vp); 1157 1158 1159 /* check if we ought to be here */ 1160 KASSERT((vp->v_type != VBLK && vp->v_type != VCHR), 1161 ("nandfs_strategy on type %d", vp->v_type)); 1162 1163 /* Translate if needed and pass on */ 1164 if (bp->b_iocmd == BIO_READ) { 1165 nandfs_read_filebuf(node, bp); 1166 return (0); 1167 } 1168 1169 /* Send to segment collector */ 1170 nandfs_write_filebuf(node, bp); 1171 return (0); 1172} 1173 1174static int 1175nandfs_readdir(struct vop_readdir_args *ap) 1176{ 1177 struct uio *uio = ap->a_uio; 1178 struct vnode *vp = ap->a_vp; 1179 struct nandfs_node *node = VTON(vp); 1180 struct nandfs_dir_entry *ndirent; 1181 struct dirent dirent; 1182 struct buf *bp; 1183 uint64_t file_size, diroffset, transoffset, blkoff; 1184 uint64_t blocknr; 1185 uint32_t blocksize = node->nn_nandfsdev->nd_blocksize; 1186 uint8_t *pos, name_len; 1187 int error; 1188 1189 DPRINTF(READDIR, ("nandfs_readdir called\n")); 1190 1191 if (vp->v_type != VDIR) 1192 return (ENOTDIR); 1193 1194 file_size = node->nn_inode.i_size; 1195 DPRINTF(READDIR, ("nandfs_readdir filesize %jd resid %zd\n", 1196 (uintmax_t)file_size, uio->uio_resid )); 1197 1198 /* We are called just as long as we keep on pushing data in */ 1199 error = 0; 1200 if ((uio->uio_offset < file_size) && 1201 (uio->uio_resid >= sizeof(struct dirent))) { 1202 diroffset = uio->uio_offset; 1203 transoffset = diroffset; 1204 1205 blocknr = diroffset / blocksize; 1206 blkoff = diroffset % blocksize; 1207 error = nandfs_bread(node, blocknr, NOCRED, 0, &bp); 1208 if (error) { 1209 brelse(bp); 1210 return (EIO); 1211 } 1212 while (diroffset < file_size) { 1213 DPRINTF(READDIR, ("readdir : offset = %"PRIu64"\n", 1214 diroffset)); 1215 if (blkoff >= blocksize) { 1216 blkoff = 0; blocknr++; 1217 brelse(bp); 1218 error = nandfs_bread(node, blocknr, NOCRED, 0, 1219 &bp); 1220 if (error) { 1221 brelse(bp); 1222 return (EIO); 1223 } 1224 } 1225 1226 /* Read in one dirent */ 1227 pos = (uint8_t *)bp->b_data + blkoff; 1228 ndirent = (struct nandfs_dir_entry *)pos; 1229 1230 name_len = ndirent->name_len; 1231 memset(&dirent, 0, sizeof(struct dirent)); 1232 dirent.d_fileno = ndirent->inode; 1233 if (dirent.d_fileno) { 1234 dirent.d_type = ndirent->file_type; 1235 dirent.d_namlen = name_len; 1236 strncpy(dirent.d_name, ndirent->name, name_len); 1237 dirent.d_reclen = GENERIC_DIRSIZ(&dirent); 1238 DPRINTF(READDIR, ("copying `%*.*s`\n", name_len, 1239 name_len, dirent.d_name)); 1240 } 1241 1242 /* 1243 * If there isn't enough space in the uio to return a 1244 * whole dirent, break off read 1245 */ 1246 if (uio->uio_resid < GENERIC_DIRSIZ(&dirent)) 1247 break; 1248 1249 /* Transfer */ 1250 if (dirent.d_fileno) 1251 uiomove(&dirent, GENERIC_DIRSIZ(&dirent), uio); 1252 1253 /* Advance */ 1254 diroffset += ndirent->rec_len; 1255 blkoff += ndirent->rec_len; 1256 1257 /* Remember the last entry we transfered */ 1258 transoffset = diroffset; 1259 } 1260 brelse(bp); 1261 1262 /* Pass on last transfered offset */ 1263 uio->uio_offset = transoffset; 1264 } 1265 1266 if (ap->a_eofflag) 1267 *ap->a_eofflag = (uio->uio_offset >= file_size); 1268 1269 return (error); 1270} 1271 1272static int 1273nandfs_dirempty(struct vnode *dvp, uint64_t parentino, struct ucred *cred) 1274{ 1275 struct nandfs_node *dnode = VTON(dvp); 1276 struct nandfs_dir_entry *dirent; 1277 uint64_t file_size = dnode->nn_inode.i_size; 1278 uint64_t blockcount = dnode->nn_inode.i_blocks; 1279 uint64_t blocknr; 1280 uint32_t blocksize = dnode->nn_nandfsdev->nd_blocksize; 1281 uint32_t limit; 1282 uint32_t off; 1283 uint8_t *pos; 1284 struct buf *bp; 1285 int error; 1286 1287 DPRINTF(LOOKUP, ("%s: dvp %p parentino %#jx cred %p\n", __func__, dvp, 1288 (uintmax_t)parentino, cred)); 1289 1290 KASSERT((file_size != 0), ("nandfs_dirempty for NULL dir %p", dvp)); 1291 1292 blocknr = 0; 1293 while (blocknr < blockcount) { 1294 error = nandfs_bread(dnode, blocknr, NOCRED, 0, &bp); 1295 if (error) { 1296 brelse(bp); 1297 return (0); 1298 } 1299 1300 pos = (uint8_t *)bp->b_data; 1301 off = 0; 1302 1303 if (blocknr == (blockcount - 1)) 1304 limit = file_size % blocksize; 1305 else 1306 limit = blocksize; 1307 1308 while (off < limit) { 1309 dirent = (struct nandfs_dir_entry *)(pos + off); 1310 off += dirent->rec_len; 1311 1312 if (dirent->inode == 0) 1313 continue; 1314 1315 switch (dirent->name_len) { 1316 case 0: 1317 break; 1318 case 1: 1319 if (dirent->name[0] != '.') 1320 goto notempty; 1321 1322 KASSERT(dirent->inode == dnode->nn_ino, 1323 (".'s inode does not match dir")); 1324 break; 1325 case 2: 1326 if (dirent->name[0] != '.' && 1327 dirent->name[1] != '.') 1328 goto notempty; 1329 1330 KASSERT(dirent->inode == parentino, 1331 ("..'s inode does not match parent")); 1332 break; 1333 default: 1334 goto notempty; 1335 } 1336 } 1337 1338 brelse(bp); 1339 blocknr++; 1340 } 1341 1342 return (1); 1343notempty: 1344 brelse(bp); 1345 return (0); 1346} 1347 1348static int 1349nandfs_link(struct vop_link_args *ap) 1350{ 1351 struct vnode *tdvp = ap->a_tdvp; 1352 struct vnode *vp = ap->a_vp; 1353 struct componentname *cnp = ap->a_cnp; 1354 struct nandfs_node *node = VTON(vp); 1355 struct nandfs_inode *inode = &node->nn_inode; 1356 int error; 1357 1358 if (inode->i_links_count >= LINK_MAX) 1359 return (EMLINK); 1360 1361 if (inode->i_flags & (IMMUTABLE | APPEND)) 1362 return (EPERM); 1363 1364 /* Update link count */ 1365 inode->i_links_count++; 1366 1367 /* Add dir entry */ 1368 error = nandfs_add_dirent(tdvp, node->nn_ino, cnp->cn_nameptr, 1369 cnp->cn_namelen, IFTODT(inode->i_mode)); 1370 if (error) { 1371 inode->i_links_count--; 1372 } 1373 1374 node->nn_flags |= IN_CHANGE; 1375 nandfs_itimes(vp); 1376 DPRINTF(VNCALL, ("%s: tdvp %p vp %p cnp %p\n", 1377 __func__, tdvp, vp, cnp)); 1378 1379 return (0); 1380} 1381 1382static int 1383nandfs_create(struct vop_create_args *ap) 1384{ 1385 struct vnode *dvp = ap->a_dvp; 1386 struct vnode **vpp = ap->a_vpp; 1387 struct componentname *cnp = ap->a_cnp; 1388 uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 1389 struct nandfs_node *dir_node = VTON(dvp); 1390 struct nandfsmount *nmp = dir_node->nn_nmp; 1391 struct nandfs_node *node; 1392 int error; 1393 1394 DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp)); 1395 1396 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1397 return (ENOSPC); 1398 1399 /* Create new vnode/inode */ 1400 error = nandfs_node_create(nmp, &node, mode); 1401 if (error) 1402 return (error); 1403 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1404 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1405 1406 /* Add new dir entry */ 1407 error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1408 cnp->cn_namelen, IFTODT(mode)); 1409 if (error) { 1410 if (nandfs_node_destroy(node)) { 1411 nandfs_error("%s: error destroying node %p\n", 1412 __func__, node); 1413 } 1414 return (error); 1415 } 1416 *vpp = NTOV(node); 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 = NAME_MAX; 2245 break; 2246 case _PC_PATH_MAX: 2247 *ap->a_retval = PATH_MAX; 2248 break; 2249 case _PC_PIPE_BUF: 2250 *ap->a_retval = PIPE_BUF; 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_ACL_EXTENDED: 2259 *ap->a_retval = 0; 2260 break; 2261 case _PC_ALLOC_SIZE_MIN: 2262 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize; 2263 break; 2264 case _PC_FILESIZEBITS: 2265 *ap->a_retval = 64; 2266 break; 2267 case _PC_REC_INCR_XFER_SIZE: 2268 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize; 2269 break; 2270 case _PC_REC_MAX_XFER_SIZE: 2271 *ap->a_retval = -1; /* means ``unlimited'' */ 2272 break; 2273 case _PC_REC_MIN_XFER_SIZE: 2274 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize; 2275 break; 2276 default: 2277 error = EINVAL; 2278 break; 2279 } 2280 return (error); 2281} 2282 2283static int 2284nandfs_vnlock1(struct vop_lock1_args *ap) 2285{ 2286 struct vnode *vp = ap->a_vp; 2287 struct nandfs_node *node = VTON(vp); 2288 int error, vi_locked; 2289 2290 /* 2291 * XXX can vnode go away while we are sleeping? 2292 */ 2293 vi_locked = mtx_owned(&vp->v_interlock); 2294 if (vi_locked) 2295 VI_UNLOCK(vp); 2296 error = NANDFS_WRITELOCKFLAGS(node->nn_nandfsdev, 2297 ap->a_flags & LK_NOWAIT); 2298 if (vi_locked && !error) 2299 VI_LOCK(vp); 2300 if (error) 2301 return (error); 2302 2303 error = vop_stdlock(ap); 2304 if (error) { 2305 NANDFS_WRITEUNLOCK(node->nn_nandfsdev); 2306 return (error); 2307 } 2308 2309 return (0); 2310} 2311 2312static int 2313nandfs_vnunlock(struct vop_unlock_args *ap) 2314{ 2315 struct vnode *vp = ap->a_vp; 2316 struct nandfs_node *node = VTON(vp); 2317 int error; 2318 2319 error = vop_stdunlock(ap); 2320 if (error) 2321 return (error); 2322 2323 NANDFS_WRITEUNLOCK(node->nn_nandfsdev); 2324 2325 return (0); 2326} 2327 2328/* 2329 * Global vfs data structures 2330 */ 2331struct vop_vector nandfs_vnodeops = { 2332 .vop_default = &default_vnodeops, 2333 .vop_access = nandfs_access, 2334 .vop_advlock = nandfs_advlock, 2335 .vop_bmap = nandfs_bmap, 2336 .vop_close = nandfs_close, 2337 .vop_create = nandfs_create, 2338 .vop_fsync = nandfs_fsync, 2339 .vop_getattr = nandfs_getattr, 2340 .vop_inactive = nandfs_inactive, 2341 .vop_cachedlookup = nandfs_lookup, 2342 .vop_ioctl = nandfs_ioctl, 2343 .vop_link = nandfs_link, 2344 .vop_lookup = vfs_cache_lookup, 2345 .vop_mkdir = nandfs_mkdir, 2346 .vop_mknod = nandfs_mknod, 2347 .vop_open = nandfs_open, 2348 .vop_pathconf = nandfs_pathconf, 2349 .vop_print = nandfs_print, 2350 .vop_read = nandfs_read, 2351 .vop_readdir = nandfs_readdir, 2352 .vop_readlink = nandfs_readlink, 2353 .vop_reclaim = nandfs_reclaim, 2354 .vop_remove = nandfs_remove, 2355 .vop_rename = nandfs_rename, 2356 .vop_rmdir = nandfs_rmdir, 2357 .vop_whiteout = nandfs_whiteout, 2358 .vop_write = nandfs_write, 2359 .vop_setattr = nandfs_setattr, 2360 .vop_strategy = nandfs_strategy, 2361 .vop_symlink = nandfs_symlink, 2362 .vop_lock1 = nandfs_vnlock1, 2363 .vop_unlock = nandfs_vnunlock, 2364}; 2365 2366struct vop_vector nandfs_system_vnodeops = { 2367 .vop_default = &default_vnodeops, 2368 .vop_close = nandfs_close, 2369 .vop_inactive = nandfs_inactive, 2370 .vop_reclaim = nandfs_reclaim, 2371 .vop_strategy = nandfs_strategy, 2372 .vop_fsync = nandfs_fsync, 2373 .vop_bmap = nandfs_bmap, 2374 .vop_access = VOP_PANIC, 2375 .vop_advlock = VOP_PANIC, 2376 .vop_create = VOP_PANIC, 2377 .vop_getattr = VOP_PANIC, 2378 .vop_cachedlookup = VOP_PANIC, 2379 .vop_ioctl = VOP_PANIC, 2380 .vop_link = VOP_PANIC, 2381 .vop_lookup = VOP_PANIC, 2382 .vop_mkdir = VOP_PANIC, 2383 .vop_mknod = VOP_PANIC, 2384 .vop_open = VOP_PANIC, 2385 .vop_pathconf = VOP_PANIC, 2386 .vop_print = VOP_PANIC, 2387 .vop_read = VOP_PANIC, 2388 .vop_readdir = VOP_PANIC, 2389 .vop_readlink = VOP_PANIC, 2390 .vop_remove = VOP_PANIC, 2391 .vop_rename = VOP_PANIC, 2392 .vop_rmdir = VOP_PANIC, 2393 .vop_whiteout = VOP_PANIC, 2394 .vop_write = VOP_PANIC, 2395 .vop_setattr = VOP_PANIC, 2396 .vop_symlink = VOP_PANIC, 2397}; 2398 2399static int 2400nandfsfifo_close(struct vop_close_args *ap) 2401{ 2402 struct vnode *vp = ap->a_vp; 2403 struct nandfs_node *node = VTON(vp); 2404 2405 DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node)); 2406 2407 mtx_lock(&vp->v_interlock); 2408 if (vp->v_usecount > 1) 2409 nandfs_itimes_locked(vp); 2410 mtx_unlock(&vp->v_interlock); 2411 2412 return (fifo_specops.vop_close(ap)); 2413} 2414 2415struct vop_vector nandfs_fifoops = { 2416 .vop_default = &fifo_specops, 2417 .vop_fsync = VOP_PANIC, 2418 .vop_access = nandfs_access, 2419 .vop_close = nandfsfifo_close, 2420 .vop_getattr = nandfs_getattr, 2421 .vop_inactive = nandfs_inactive, 2422 .vop_print = nandfs_print, 2423 .vop_read = VOP_PANIC, 2424 .vop_reclaim = nandfs_reclaim, 2425 .vop_setattr = nandfs_setattr, 2426 .vop_write = VOP_PANIC, 2427 .vop_lock1 = nandfs_vnlock1, 2428 .vop_unlock = nandfs_vnunlock, 2429}; 2430 2431int 2432nandfs_vinit(struct vnode *vp, uint64_t ino) 2433{ 2434 struct nandfs_node *node; 2435 2436 ASSERT_VOP_LOCKED(vp, __func__); 2437 2438 node = VTON(vp); 2439 2440 /* Check if we're fetching the root */ 2441 if (ino == NANDFS_ROOT_INO) 2442 vp->v_vflag |= VV_ROOT; 2443 2444 if (ino != NANDFS_GC_INO) 2445 vp->v_type = IFTOVT(node->nn_inode.i_mode); 2446 else 2447 vp->v_type = VREG; 2448 2449 if (vp->v_type == VFIFO) 2450 vp->v_op = &nandfs_fifoops; 2451 2452 return (0); 2453} 2454