nandfs_vnops.c revision 269421
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: head/sys/fs/nandfs/nandfs_vnops.c 269421 2014-08-02 05:05:10Z imp $"); 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, 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) && nameiop != CREATE) 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(struct 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 DPRINTF(READDIR, ("copying `%*.*s`\n", name_len, 1236 name_len, dirent.d_name)); 1237 } 1238 1239 /* 1240 * If there isn't enough space in the uio to return a 1241 * whole dirent, break off read 1242 */ 1243 if (uio->uio_resid < GENERIC_DIRSIZ(&dirent)) 1244 break; 1245 1246 /* Transfer */ 1247 if (dirent.d_fileno) 1248 uiomove(&dirent, GENERIC_DIRSIZ(&dirent), uio); 1249 1250 /* Advance */ 1251 diroffset += ndirent->rec_len; 1252 blkoff += ndirent->rec_len; 1253 1254 /* Remember the last entry we transfered */ 1255 transoffset = diroffset; 1256 } 1257 brelse(bp); 1258 1259 /* Pass on last transfered offset */ 1260 uio->uio_offset = transoffset; 1261 } 1262 1263 if (ap->a_eofflag) 1264 *ap->a_eofflag = (uio->uio_offset >= file_size); 1265 1266 return (error); 1267} 1268 1269static int 1270nandfs_dirempty(struct vnode *dvp, uint64_t parentino, struct ucred *cred) 1271{ 1272 struct nandfs_node *dnode = VTON(dvp); 1273 struct nandfs_dir_entry *dirent; 1274 uint64_t file_size = dnode->nn_inode.i_size; 1275 uint64_t blockcount = dnode->nn_inode.i_blocks; 1276 uint64_t blocknr; 1277 uint32_t blocksize = dnode->nn_nandfsdev->nd_blocksize; 1278 uint32_t limit; 1279 uint32_t off; 1280 uint8_t *pos; 1281 struct buf *bp; 1282 int error; 1283 1284 DPRINTF(LOOKUP, ("%s: dvp %p parentino %#jx cred %p\n", __func__, dvp, 1285 (uintmax_t)parentino, cred)); 1286 1287 KASSERT((file_size != 0), ("nandfs_dirempty for NULL dir %p", dvp)); 1288 1289 blocknr = 0; 1290 while (blocknr < blockcount) { 1291 error = nandfs_bread(dnode, blocknr, NOCRED, 0, &bp); 1292 if (error) { 1293 brelse(bp); 1294 return (0); 1295 } 1296 1297 pos = (uint8_t *)bp->b_data; 1298 off = 0; 1299 1300 if (blocknr == (blockcount - 1)) 1301 limit = file_size % blocksize; 1302 else 1303 limit = blocksize; 1304 1305 while (off < limit) { 1306 dirent = (struct nandfs_dir_entry *)(pos + off); 1307 off += dirent->rec_len; 1308 1309 if (dirent->inode == 0) 1310 continue; 1311 1312 switch (dirent->name_len) { 1313 case 0: 1314 break; 1315 case 1: 1316 if (dirent->name[0] != '.') 1317 goto notempty; 1318 1319 KASSERT(dirent->inode == dnode->nn_ino, 1320 (".'s inode does not match dir")); 1321 break; 1322 case 2: 1323 if (dirent->name[0] != '.' && 1324 dirent->name[1] != '.') 1325 goto notempty; 1326 1327 KASSERT(dirent->inode == parentino, 1328 ("..'s inode does not match parent")); 1329 break; 1330 default: 1331 goto notempty; 1332 } 1333 } 1334 1335 brelse(bp); 1336 blocknr++; 1337 } 1338 1339 return (1); 1340notempty: 1341 brelse(bp); 1342 return (0); 1343} 1344 1345static int 1346nandfs_link(struct vop_link_args *ap) 1347{ 1348 struct vnode *tdvp = ap->a_tdvp; 1349 struct vnode *vp = ap->a_vp; 1350 struct componentname *cnp = ap->a_cnp; 1351 struct nandfs_node *node = VTON(vp); 1352 struct nandfs_inode *inode = &node->nn_inode; 1353 int error; 1354 1355 if (inode->i_links_count >= LINK_MAX) 1356 return (EMLINK); 1357 1358 if (inode->i_flags & (IMMUTABLE | APPEND)) 1359 return (EPERM); 1360 1361 /* Update link count */ 1362 inode->i_links_count++; 1363 1364 /* Add dir entry */ 1365 error = nandfs_add_dirent(tdvp, node->nn_ino, cnp->cn_nameptr, 1366 cnp->cn_namelen, IFTODT(inode->i_mode)); 1367 if (error) { 1368 inode->i_links_count--; 1369 } 1370 1371 node->nn_flags |= IN_CHANGE; 1372 nandfs_itimes(vp); 1373 DPRINTF(VNCALL, ("%s: tdvp %p vp %p cnp %p\n", 1374 __func__, tdvp, vp, cnp)); 1375 1376 return (0); 1377} 1378 1379static int 1380nandfs_create(struct vop_create_args *ap) 1381{ 1382 struct vnode *dvp = ap->a_dvp; 1383 struct vnode **vpp = ap->a_vpp; 1384 struct componentname *cnp = ap->a_cnp; 1385 uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 1386 struct nandfs_node *dir_node = VTON(dvp); 1387 struct nandfsmount *nmp = dir_node->nn_nmp; 1388 struct nandfs_node *node; 1389 int error; 1390 1391 DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp)); 1392 1393 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1394 return (ENOSPC); 1395 1396 /* Create new vnode/inode */ 1397 error = nandfs_node_create(nmp, &node, mode); 1398 if (error) 1399 return (error); 1400 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1401 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1402 1403 /* Add new dir entry */ 1404 error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1405 cnp->cn_namelen, IFTODT(mode)); 1406 if (error) { 1407 if (nandfs_node_destroy(node)) { 1408 nandfs_error("%s: error destroying node %p\n", 1409 __func__, node); 1410 } 1411 return (error); 1412 } 1413 *vpp = NTOV(node); 1414 1415 DPRINTF(VNCALL, ("created file vp %p nandnode %p ino %jx\n", *vpp, node, 1416 (uintmax_t)node->nn_ino)); 1417 return (0); 1418} 1419 1420static int 1421nandfs_remove(struct vop_remove_args *ap) 1422{ 1423 struct vnode *vp = ap->a_vp; 1424 struct vnode *dvp = ap->a_dvp; 1425 struct nandfs_node *node = VTON(vp); 1426 struct nandfs_node *dnode = VTON(dvp); 1427 struct componentname *cnp = ap->a_cnp; 1428 1429 DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx link %d\n", 1430 __func__, dvp, vp, node, (uintmax_t)node->nn_ino, 1431 node->nn_inode.i_links_count)); 1432 1433 if (vp->v_type == VDIR) 1434 return (EISDIR); 1435 1436 /* Files marked as immutable or append-only cannot be deleted. */ 1437 if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) || 1438 (dnode->nn_inode.i_flags & APPEND)) 1439 return (EPERM); 1440 1441 nandfs_remove_dirent(dvp, node, cnp); 1442 node->nn_inode.i_links_count--; 1443 node->nn_flags |= IN_CHANGE; 1444 1445 return (0); 1446} 1447 1448/* 1449 * Check if source directory is in the path of the target directory. 1450 * Target is supplied locked, source is unlocked. 1451 * The target is always vput before returning. 1452 */ 1453static int 1454nandfs_checkpath(struct nandfs_node *src, struct nandfs_node *dest, 1455 struct ucred *cred) 1456{ 1457 struct vnode *vp; 1458 int error, rootino; 1459 struct nandfs_dir_entry dirent; 1460 1461 vp = NTOV(dest); 1462 if (src->nn_ino == dest->nn_ino) { 1463 error = EEXIST; 1464 goto out; 1465 } 1466 rootino = NANDFS_ROOT_INO; 1467 error = 0; 1468 if (dest->nn_ino == rootino) 1469 goto out; 1470 1471 for (;;) { 1472 if (vp->v_type != VDIR) { 1473 error = ENOTDIR; 1474 break; 1475 } 1476 1477 error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirent, 1478 NANDFS_DIR_REC_LEN(2), (off_t)0, UIO_SYSSPACE, 1479 IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, 1480 NULL, NULL); 1481 if (error != 0) 1482 break; 1483 if (dirent.name_len != 2 || 1484 dirent.name[0] != '.' || 1485 dirent.name[1] != '.') { 1486 error = ENOTDIR; 1487 break; 1488 } 1489 if (dirent.inode == src->nn_ino) { 1490 error = EINVAL; 1491 break; 1492 } 1493 if (dirent.inode == rootino) 1494 break; 1495 vput(vp); 1496 if ((error = VFS_VGET(vp->v_mount, dirent.inode, 1497 LK_EXCLUSIVE, &vp)) != 0) { 1498 vp = NULL; 1499 break; 1500 } 1501 } 1502 1503out: 1504 if (error == ENOTDIR) 1505 printf("checkpath: .. not a directory\n"); 1506 if (vp != NULL) 1507 vput(vp); 1508 return (error); 1509} 1510 1511static int 1512nandfs_rename(struct vop_rename_args *ap) 1513{ 1514 struct vnode *tvp = ap->a_tvp; 1515 struct vnode *tdvp = ap->a_tdvp; 1516 struct vnode *fvp = ap->a_fvp; 1517 struct vnode *fdvp = ap->a_fdvp; 1518 struct componentname *tcnp = ap->a_tcnp; 1519 struct componentname *fcnp = ap->a_fcnp; 1520 int doingdirectory = 0, oldparent = 0, newparent = 0; 1521 int error = 0; 1522 1523 struct nandfs_node *fdnode, *fnode, *fnode1; 1524 struct nandfs_node *tdnode = VTON(tdvp); 1525 struct nandfs_node *tnode; 1526 1527 uint32_t tdflags, fflags, fdflags; 1528 uint16_t mode; 1529 1530 DPRINTF(VNCALL, ("%s: fdvp:%p fvp:%p tdvp:%p tdp:%p\n", __func__, fdvp, 1531 fvp, tdvp, tvp)); 1532 1533 /* 1534 * Check for cross-device rename. 1535 */ 1536 if ((fvp->v_mount != tdvp->v_mount) || 1537 (tvp && (fvp->v_mount != tvp->v_mount))) { 1538 error = EXDEV; 1539abortit: 1540 if (tdvp == tvp) 1541 vrele(tdvp); 1542 else 1543 vput(tdvp); 1544 if (tvp) 1545 vput(tvp); 1546 vrele(fdvp); 1547 vrele(fvp); 1548 return (error); 1549 } 1550 1551 tdflags = tdnode->nn_inode.i_flags; 1552 if (tvp && 1553 ((VTON(tvp)->nn_inode.i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 1554 (tdflags & APPEND))) { 1555 error = EPERM; 1556 goto abortit; 1557 } 1558 1559 /* 1560 * Renaming a file to itself has no effect. The upper layers should 1561 * not call us in that case. Temporarily just warn if they do. 1562 */ 1563 if (fvp == tvp) { 1564 printf("nandfs_rename: fvp == tvp (can't happen)\n"); 1565 error = 0; 1566 goto abortit; 1567 } 1568 1569 if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) 1570 goto abortit; 1571 1572 fdnode = VTON(fdvp); 1573 fnode = VTON(fvp); 1574 1575 if (fnode->nn_inode.i_links_count >= LINK_MAX) { 1576 VOP_UNLOCK(fvp, 0); 1577 error = EMLINK; 1578 goto abortit; 1579 } 1580 1581 fflags = fnode->nn_inode.i_flags; 1582 fdflags = fdnode->nn_inode.i_flags; 1583 1584 if ((fflags & (NOUNLINK | IMMUTABLE | APPEND)) || 1585 (fdflags & APPEND)) { 1586 VOP_UNLOCK(fvp, 0); 1587 error = EPERM; 1588 goto abortit; 1589 } 1590 1591 mode = fnode->nn_inode.i_mode; 1592 if ((mode & S_IFMT) == S_IFDIR) { 1593 /* 1594 * Avoid ".", "..", and aliases of "." for obvious reasons. 1595 */ 1596 1597 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1598 (fdvp == fvp) || 1599 ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) || 1600 (fnode->nn_flags & IN_RENAME)) { 1601 VOP_UNLOCK(fvp, 0); 1602 error = EINVAL; 1603 goto abortit; 1604 } 1605 fnode->nn_flags |= IN_RENAME; 1606 doingdirectory = 1; 1607 DPRINTF(VNCALL, ("%s: doingdirectory dvp %p\n", __func__, 1608 tdvp)); 1609 oldparent = fdnode->nn_ino; 1610 } 1611 1612 vrele(fdvp); 1613 1614 tnode = NULL; 1615 if (tvp) 1616 tnode = VTON(tvp); 1617 1618 /* 1619 * Bump link count on fvp while we are moving stuff around. If we 1620 * crash before completing the work, the link count may be wrong 1621 * but correctable. 1622 */ 1623 fnode->nn_inode.i_links_count++; 1624 1625 /* Check for in path moving XXX */ 1626 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread); 1627 VOP_UNLOCK(fvp, 0); 1628 if (oldparent != tdnode->nn_ino) 1629 newparent = tdnode->nn_ino; 1630 if (doingdirectory && newparent) { 1631 if (error) /* write access check above */ 1632 goto bad; 1633 if (tnode != NULL) 1634 vput(tvp); 1635 1636 error = nandfs_checkpath(fnode, tdnode, tcnp->cn_cred); 1637 if (error) 1638 goto out; 1639 1640 VREF(tdvp); 1641 error = relookup(tdvp, &tvp, tcnp); 1642 if (error) 1643 goto out; 1644 vrele(tdvp); 1645 tdnode = VTON(tdvp); 1646 tnode = NULL; 1647 if (tvp) 1648 tnode = VTON(tvp); 1649 } 1650 1651 /* 1652 * If the target doesn't exist, link the target to the source and 1653 * unlink the source. Otherwise, rewrite the target directory to 1654 * reference the source and remove the original entry. 1655 */ 1656 1657 if (tvp == NULL) { 1658 /* 1659 * Account for ".." in new directory. 1660 */ 1661 if (doingdirectory && fdvp != tdvp) 1662 tdnode->nn_inode.i_links_count++; 1663 1664 DPRINTF(VNCALL, ("%s: new entry in dvp:%p\n", __func__, tdvp)); 1665 /* 1666 * Add name in new directory. 1667 */ 1668 error = nandfs_add_dirent(tdvp, fnode->nn_ino, tcnp->cn_nameptr, 1669 tcnp->cn_namelen, IFTODT(fnode->nn_inode.i_mode)); 1670 if (error) { 1671 if (doingdirectory && fdvp != tdvp) 1672 tdnode->nn_inode.i_links_count--; 1673 goto bad; 1674 } 1675 1676 vput(tdvp); 1677 } else { 1678 /* 1679 * If the parent directory is "sticky", then the user must 1680 * own the parent directory, or the destination of the rename, 1681 * otherwise the destination may not be changed (except by 1682 * root). This implements append-only directories. 1683 */ 1684 if ((tdnode->nn_inode.i_mode & S_ISTXT) && 1685 tcnp->cn_cred->cr_uid != 0 && 1686 tcnp->cn_cred->cr_uid != tdnode->nn_inode.i_uid && 1687 tnode->nn_inode.i_uid != tcnp->cn_cred->cr_uid) { 1688 error = EPERM; 1689 goto bad; 1690 } 1691 /* 1692 * Target must be empty if a directory and have no links 1693 * to it. Also, ensure source and target are compatible 1694 * (both directories, or both not directories). 1695 */ 1696 mode = tnode->nn_inode.i_mode; 1697 if ((mode & S_IFMT) == S_IFDIR) { 1698 if (!nandfs_dirempty(tvp, tdnode->nn_ino, 1699 tcnp->cn_cred)) { 1700 error = ENOTEMPTY; 1701 goto bad; 1702 } 1703 if (!doingdirectory) { 1704 error = ENOTDIR; 1705 goto bad; 1706 } 1707 /* 1708 * Update name cache since directory is going away. 1709 */ 1710 cache_purge(tdvp); 1711 } else if (doingdirectory) { 1712 error = EISDIR; 1713 goto bad; 1714 } 1715 1716 DPRINTF(VNCALL, ("%s: update entry dvp:%p\n", __func__, tdvp)); 1717 /* 1718 * Change name tcnp in tdvp to point at fvp. 1719 */ 1720 error = nandfs_update_dirent(tdvp, fnode, tnode); 1721 if (error) 1722 goto bad; 1723 1724 if (doingdirectory && !newparent) 1725 tdnode->nn_inode.i_links_count--; 1726 1727 vput(tdvp); 1728 1729 tnode->nn_inode.i_links_count--; 1730 vput(tvp); 1731 tnode = NULL; 1732 } 1733 1734 /* 1735 * Unlink the source. 1736 */ 1737 fcnp->cn_flags &= ~MODMASK; 1738 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 1739 VREF(fdvp); 1740 error = relookup(fdvp, &fvp, fcnp); 1741 if (error == 0) 1742 vrele(fdvp); 1743 if (fvp != NULL) { 1744 fnode1 = VTON(fvp); 1745 fdnode = VTON(fdvp); 1746 } else { 1747 /* 1748 * From name has disappeared. 1749 */ 1750 if (doingdirectory) 1751 panic("nandfs_rename: lost dir entry"); 1752 vrele(ap->a_fvp); 1753 return (0); 1754 } 1755 1756 DPRINTF(VNCALL, ("%s: unlink source fnode:%p\n", __func__, fnode)); 1757 1758 /* 1759 * Ensure that the directory entry still exists and has not 1760 * changed while the new name has been entered. If the source is 1761 * a file then the entry may have been unlinked or renamed. In 1762 * either case there is no further work to be done. If the source 1763 * is a directory then it cannot have been rmdir'ed; its link 1764 * count of three would cause a rmdir to fail with ENOTEMPTY. 1765 * The IN_RENAME flag ensures that it cannot be moved by another 1766 * rename. 1767 */ 1768 if (fnode != fnode1) { 1769 if (doingdirectory) 1770 panic("nandfs: lost dir entry"); 1771 } else { 1772 /* 1773 * If the source is a directory with a 1774 * new parent, the link count of the old 1775 * parent directory must be decremented 1776 * and ".." set to point to the new parent. 1777 */ 1778 if (doingdirectory && newparent) { 1779 DPRINTF(VNCALL, ("%s: new parent %#jx -> %#jx\n", 1780 __func__, (uintmax_t) oldparent, 1781 (uintmax_t) newparent)); 1782 error = nandfs_update_parent_dir(fvp, newparent); 1783 if (!error) { 1784 fdnode->nn_inode.i_links_count--; 1785 fdnode->nn_flags |= IN_CHANGE; 1786 } 1787 } 1788 error = nandfs_remove_dirent(fdvp, fnode, fcnp); 1789 if (!error) { 1790 fnode->nn_inode.i_links_count--; 1791 fnode->nn_flags |= IN_CHANGE; 1792 } 1793 fnode->nn_flags &= ~IN_RENAME; 1794 } 1795 if (fdnode) 1796 vput(fdvp); 1797 if (fnode) 1798 vput(fvp); 1799 vrele(ap->a_fvp); 1800 return (error); 1801 1802bad: 1803 DPRINTF(VNCALL, ("%s: error:%d\n", __func__, error)); 1804 if (tnode) 1805 vput(NTOV(tnode)); 1806 vput(NTOV(tdnode)); 1807out: 1808 if (doingdirectory) 1809 fnode->nn_flags &= ~IN_RENAME; 1810 if (vn_lock(fvp, LK_EXCLUSIVE) == 0) { 1811 fnode->nn_inode.i_links_count--; 1812 fnode->nn_flags |= IN_CHANGE; 1813 fnode->nn_flags &= ~IN_RENAME; 1814 vput(fvp); 1815 } else 1816 vrele(fvp); 1817 return (error); 1818} 1819 1820static int 1821nandfs_mkdir(struct vop_mkdir_args *ap) 1822{ 1823 struct vnode *dvp = ap->a_dvp; 1824 struct vnode **vpp = ap->a_vpp; 1825 struct componentname *cnp = ap->a_cnp; 1826 struct nandfs_node *dir_node = VTON(dvp); 1827 struct nandfs_inode *dir_inode = &dir_node->nn_inode; 1828 struct nandfs_node *node; 1829 struct nandfsmount *nmp = dir_node->nn_nmp; 1830 uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 1831 int error; 1832 1833 DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp)); 1834 1835 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1836 return (ENOSPC); 1837 1838 if (dir_inode->i_links_count >= LINK_MAX) 1839 return (EMLINK); 1840 1841 error = nandfs_node_create(nmp, &node, mode); 1842 if (error) 1843 return (error); 1844 1845 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1846 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1847 1848 *vpp = NTOV(node); 1849 1850 error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1851 cnp->cn_namelen, IFTODT(mode)); 1852 if (error) { 1853 vput(*vpp); 1854 return (error); 1855 } 1856 1857 dir_node->nn_inode.i_links_count++; 1858 dir_node->nn_flags |= IN_CHANGE; 1859 1860 error = nandfs_init_dir(NTOV(node), node->nn_ino, dir_node->nn_ino); 1861 if (error) { 1862 vput(NTOV(node)); 1863 return (error); 1864 } 1865 1866 DPRINTF(VNCALL, ("created dir vp %p nandnode %p ino %jx\n", *vpp, node, 1867 (uintmax_t)node->nn_ino)); 1868 return (0); 1869} 1870 1871static int 1872nandfs_mknod(struct vop_mknod_args *ap) 1873{ 1874 struct vnode *dvp = ap->a_dvp; 1875 struct vnode **vpp = ap->a_vpp; 1876 struct vattr *vap = ap->a_vap; 1877 uint16_t mode = MAKEIMODE(vap->va_type, vap->va_mode); 1878 struct componentname *cnp = ap->a_cnp; 1879 struct nandfs_node *dir_node = VTON(dvp); 1880 struct nandfsmount *nmp = dir_node->nn_nmp; 1881 struct nandfs_node *node; 1882 int error; 1883 1884 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1885 return (ENOSPC); 1886 1887 error = nandfs_node_create(nmp, &node, mode); 1888 if (error) 1889 return (error); 1890 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1891 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1892 if (vap->va_rdev != VNOVAL) 1893 node->nn_inode.i_special = vap->va_rdev; 1894 1895 *vpp = NTOV(node); 1896 1897 if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1898 cnp->cn_namelen, IFTODT(mode))) { 1899 vput(*vpp); 1900 return (ENOTDIR); 1901 } 1902 1903 node->nn_flags |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 1904 1905 return (0); 1906} 1907 1908static int 1909nandfs_symlink(struct vop_symlink_args *ap) 1910{ 1911 struct vnode **vpp = ap->a_vpp; 1912 struct vnode *dvp = ap->a_dvp; 1913 uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 1914 struct componentname *cnp = ap->a_cnp; 1915 struct nandfs_node *dir_node = VTON(dvp); 1916 struct nandfsmount *nmp = dir_node->nn_nmp; 1917 struct nandfs_node *node; 1918 int len, error; 1919 1920 if (nandfs_fs_full(dir_node->nn_nandfsdev)) 1921 return (ENOSPC); 1922 1923 error = nandfs_node_create(nmp, &node, S_IFLNK | mode); 1924 if (error) 1925 return (error); 1926 node->nn_inode.i_gid = dir_node->nn_inode.i_gid; 1927 node->nn_inode.i_uid = cnp->cn_cred->cr_uid; 1928 1929 *vpp = NTOV(node); 1930 1931 if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr, 1932 cnp->cn_namelen, IFTODT(mode))) { 1933 vput(*vpp); 1934 return (ENOTDIR); 1935 } 1936 1937 1938 len = strlen(ap->a_target); 1939 error = vn_rdwr(UIO_WRITE, *vpp, ap->a_target, len, (off_t)0, 1940 UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, 1941 cnp->cn_cred, NOCRED, NULL, NULL); 1942 if (error) 1943 vput(*vpp); 1944 1945 return (error); 1946} 1947 1948static int 1949nandfs_readlink(struct vop_readlink_args *ap) 1950{ 1951 struct vnode *vp = ap->a_vp; 1952 1953 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); 1954} 1955 1956static int 1957nandfs_rmdir(struct vop_rmdir_args *ap) 1958{ 1959 struct vnode *vp = ap->a_vp; 1960 struct vnode *dvp = ap->a_dvp; 1961 struct componentname *cnp = ap->a_cnp; 1962 struct nandfs_node *node, *dnode; 1963 uint32_t dflag, flag; 1964 int error = 0; 1965 1966 node = VTON(vp); 1967 dnode = VTON(dvp); 1968 1969 /* Files marked as immutable or append-only cannot be deleted. */ 1970 if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) || 1971 (dnode->nn_inode.i_flags & APPEND)) 1972 return (EPERM); 1973 1974 DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx\n", __func__, 1975 dvp, vp, node, (uintmax_t)node->nn_ino)); 1976 1977 if (node->nn_inode.i_links_count < 2) 1978 return (EINVAL); 1979 1980 if (!nandfs_dirempty(vp, dnode->nn_ino, cnp->cn_cred)) 1981 return (ENOTEMPTY); 1982 1983 /* Files marked as immutable or append-only cannot be deleted. */ 1984 dflag = dnode->nn_inode.i_flags; 1985 flag = node->nn_inode.i_flags; 1986 if ((dflag & APPEND) || 1987 (flag & (NOUNLINK | IMMUTABLE | APPEND))) { 1988 return (EPERM); 1989 } 1990 1991 if (vp->v_mountedhere != 0) 1992 return (EINVAL); 1993 1994 nandfs_remove_dirent(dvp, node, cnp); 1995 dnode->nn_inode.i_links_count -= 1; 1996 dnode->nn_flags |= IN_CHANGE; 1997 1998 cache_purge(dvp); 1999 2000 error = nandfs_truncate(vp, (uint64_t)0); 2001 if (error) 2002 return (error); 2003 2004 node->nn_inode.i_links_count -= 2; 2005 node->nn_flags |= IN_CHANGE; 2006 2007 cache_purge(vp); 2008 2009 return (error); 2010} 2011 2012static int 2013nandfs_fsync(struct vop_fsync_args *ap) 2014{ 2015 struct vnode *vp = ap->a_vp; 2016 struct nandfs_node *node = VTON(vp); 2017 int locked; 2018 2019 DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp, 2020 node, (uintmax_t)node->nn_ino)); 2021 2022 /* 2023 * Start syncing vnode only if inode was modified or 2024 * there are some dirty buffers 2025 */ 2026 if (VTON(vp)->nn_flags & IN_MODIFIED || 2027 vp->v_bufobj.bo_dirty.bv_cnt) { 2028 locked = VOP_ISLOCKED(vp); 2029 VOP_UNLOCK(vp, 0); 2030 nandfs_wakeup_wait_sync(node->nn_nandfsdev, SYNCER_FSYNC); 2031 VOP_LOCK(vp, locked | LK_RETRY); 2032 } 2033 2034 return (0); 2035} 2036 2037static int 2038nandfs_bmap(struct vop_bmap_args *ap) 2039{ 2040 struct vnode *vp = ap->a_vp; 2041 struct nandfs_node *nnode = VTON(vp); 2042 struct nandfs_device *nandfsdev = nnode->nn_nandfsdev; 2043 nandfs_daddr_t l2vmap, v2pmap; 2044 int error; 2045 int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE; 2046 2047 DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp, 2048 nnode, (uintmax_t)nnode->nn_ino)); 2049 2050 if (ap->a_bop != NULL) 2051 *ap->a_bop = &nandfsdev->nd_devvp->v_bufobj; 2052 if (ap->a_bnp == NULL) 2053 return (0); 2054 if (ap->a_runp != NULL) 2055 *ap->a_runp = 0; 2056 if (ap->a_runb != NULL) 2057 *ap->a_runb = 0; 2058 2059 /* 2060 * Translate all the block sectors into a series of buffers to read 2061 * asynchronously from the nandfs device. Note that this lookup may 2062 * induce readin's too. 2063 */ 2064 2065 /* Get virtual block numbers for the vnode's buffer span */ 2066 error = nandfs_bmap_lookup(nnode, ap->a_bn, &l2vmap); 2067 if (error) 2068 return (-1); 2069 2070 /* Translate virtual block numbers to physical block numbers */ 2071 error = nandfs_vtop(nnode, l2vmap, &v2pmap); 2072 if (error) 2073 return (-1); 2074 2075 /* Note virtual block 0 marks not mapped */ 2076 if (l2vmap == 0) 2077 *ap->a_bnp = -1; 2078 else 2079 *ap->a_bnp = v2pmap * blk2dev; /* in DEV_BSIZE */ 2080 2081 DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx lblk %jx -> blk %jx\n", 2082 __func__, vp, nnode, (uintmax_t)nnode->nn_ino, (uintmax_t)ap->a_bn, 2083 (uintmax_t)*ap->a_bnp )); 2084 2085 return (0); 2086} 2087 2088static void 2089nandfs_force_syncer(struct nandfsmount *nmp) 2090{ 2091 2092 nmp->nm_flags |= NANDFS_FORCE_SYNCER; 2093 nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_FFORCE); 2094} 2095 2096static int 2097nandfs_ioctl(struct vop_ioctl_args *ap) 2098{ 2099 struct vnode *vp = ap->a_vp; 2100 u_long command = ap->a_command; 2101 caddr_t data = ap->a_data; 2102 struct nandfs_node *node = VTON(vp); 2103 struct nandfs_device *nandfsdev = node->nn_nandfsdev; 2104 struct nandfsmount *nmp = node->nn_nmp; 2105 uint64_t *tab, *cno; 2106 struct nandfs_seg_stat *nss; 2107 struct nandfs_cpmode *ncpm; 2108 struct nandfs_argv *nargv; 2109 struct nandfs_cpstat *ncp; 2110 int error; 2111 2112 DPRINTF(VNCALL, ("%s: %x\n", __func__, (uint32_t)command)); 2113 2114 error = priv_check(ap->a_td, PRIV_VFS_MOUNT); 2115 if (error) 2116 return (error); 2117 2118 if (nmp->nm_ronly) { 2119 switch (command) { 2120 case NANDFS_IOCTL_GET_FSINFO: 2121 case NANDFS_IOCTL_GET_SUSTAT: 2122 case NANDFS_IOCTL_GET_CPINFO: 2123 case NANDFS_IOCTL_GET_CPSTAT: 2124 case NANDFS_IOCTL_GET_SUINFO: 2125 case NANDFS_IOCTL_GET_VINFO: 2126 case NANDFS_IOCTL_GET_BDESCS: 2127 break; 2128 default: 2129 return (EROFS); 2130 } 2131 } 2132 2133 switch (command) { 2134 case NANDFS_IOCTL_GET_FSINFO: 2135 error = nandfs_get_fsinfo(nmp, (struct nandfs_fsinfo *)data); 2136 break; 2137 case NANDFS_IOCTL_GET_SUSTAT: 2138 nss = (struct nandfs_seg_stat *)data; 2139 error = nandfs_get_seg_stat(nandfsdev, nss); 2140 break; 2141 case NANDFS_IOCTL_CHANGE_CPMODE: 2142 ncpm = (struct nandfs_cpmode *)data; 2143 error = nandfs_chng_cpmode(nandfsdev->nd_cp_node, ncpm); 2144 nandfs_force_syncer(nmp); 2145 break; 2146 case NANDFS_IOCTL_GET_CPINFO: 2147 nargv = (struct nandfs_argv *)data; 2148 error = nandfs_get_cpinfo_ioctl(nandfsdev->nd_cp_node, nargv); 2149 break; 2150 case NANDFS_IOCTL_DELETE_CP: 2151 tab = (uint64_t *)data; 2152 error = nandfs_delete_cp(nandfsdev->nd_cp_node, tab[0], tab[1]); 2153 nandfs_force_syncer(nmp); 2154 break; 2155 case NANDFS_IOCTL_GET_CPSTAT: 2156 ncp = (struct nandfs_cpstat *)data; 2157 error = nandfs_get_cpstat(nandfsdev->nd_cp_node, ncp); 2158 break; 2159 case NANDFS_IOCTL_GET_SUINFO: 2160 nargv = (struct nandfs_argv *)data; 2161 error = nandfs_get_segment_info_ioctl(nandfsdev, nargv); 2162 break; 2163 case NANDFS_IOCTL_GET_VINFO: 2164 nargv = (struct nandfs_argv *)data; 2165 error = nandfs_get_dat_vinfo_ioctl(nandfsdev, nargv); 2166 break; 2167 case NANDFS_IOCTL_GET_BDESCS: 2168 nargv = (struct nandfs_argv *)data; 2169 error = nandfs_get_dat_bdescs_ioctl(nandfsdev, nargv); 2170 break; 2171 case NANDFS_IOCTL_SYNC: 2172 cno = (uint64_t *)data; 2173 nandfs_force_syncer(nmp); 2174 *cno = nandfsdev->nd_last_cno; 2175 error = 0; 2176 break; 2177 case NANDFS_IOCTL_MAKE_SNAP: 2178 cno = (uint64_t *)data; 2179 error = nandfs_make_snap(nandfsdev, cno); 2180 nandfs_force_syncer(nmp); 2181 break; 2182 case NANDFS_IOCTL_DELETE_SNAP: 2183 cno = (uint64_t *)data; 2184 error = nandfs_delete_snap(nandfsdev, *cno); 2185 nandfs_force_syncer(nmp); 2186 break; 2187 default: 2188 error = ENOTTY; 2189 break; 2190 } 2191 2192 return (error); 2193} 2194 2195/* 2196 * Whiteout vnode call 2197 */ 2198static int 2199nandfs_whiteout(struct vop_whiteout_args *ap) 2200{ 2201 struct vnode *dvp = ap->a_dvp; 2202 struct componentname *cnp = ap->a_cnp; 2203 int error = 0; 2204 2205 switch (ap->a_flags) { 2206 case LOOKUP: 2207 return (0); 2208 case CREATE: 2209 /* Create a new directory whiteout */ 2210#ifdef INVARIANTS 2211 if ((cnp->cn_flags & SAVENAME) == 0) 2212 panic("ufs_whiteout: missing name"); 2213#endif 2214 error = nandfs_add_dirent(dvp, NANDFS_WHT_INO, cnp->cn_nameptr, 2215 cnp->cn_namelen, DT_WHT); 2216 break; 2217 2218 case DELETE: 2219 /* Remove an existing directory whiteout */ 2220 cnp->cn_flags &= ~DOWHITEOUT; 2221 error = nandfs_remove_dirent(dvp, NULL, cnp); 2222 break; 2223 default: 2224 panic("nandf_whiteout: unknown op: %d", ap->a_flags); 2225 } 2226 2227 return (error); 2228} 2229 2230static int 2231nandfs_pathconf(struct vop_pathconf_args *ap) 2232{ 2233 int error; 2234 2235 error = 0; 2236 switch (ap->a_name) { 2237 case _PC_LINK_MAX: 2238 *ap->a_retval = LINK_MAX; 2239 break; 2240 case _PC_NAME_MAX: 2241 *ap->a_retval = NAME_MAX; 2242 break; 2243 case _PC_PATH_MAX: 2244 *ap->a_retval = PATH_MAX; 2245 break; 2246 case _PC_PIPE_BUF: 2247 *ap->a_retval = PIPE_BUF; 2248 break; 2249 case _PC_CHOWN_RESTRICTED: 2250 *ap->a_retval = 1; 2251 break; 2252 case _PC_NO_TRUNC: 2253 *ap->a_retval = 1; 2254 break; 2255 case _PC_ACL_EXTENDED: 2256 *ap->a_retval = 0; 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 = EINVAL; 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_print = nandfs_print, 2420 .vop_read = VOP_PANIC, 2421 .vop_reclaim = nandfs_reclaim, 2422 .vop_setattr = nandfs_setattr, 2423 .vop_write = VOP_PANIC, 2424 .vop_lock1 = nandfs_vnlock1, 2425 .vop_unlock = nandfs_vnunlock, 2426}; 2427 2428int 2429nandfs_vinit(struct vnode *vp, uint64_t ino) 2430{ 2431 struct nandfs_node *node; 2432 2433 ASSERT_VOP_LOCKED(vp, __func__); 2434 2435 node = VTON(vp); 2436 2437 /* Check if we're fetching the root */ 2438 if (ino == NANDFS_ROOT_INO) 2439 vp->v_vflag |= VV_ROOT; 2440 2441 if (ino != NANDFS_GC_INO) 2442 vp->v_type = IFTOVT(node->nn_inode.i_mode); 2443 else 2444 vp->v_type = VREG; 2445 2446 if (vp->v_type == VFIFO) 2447 vp->v_op = &nandfs_fifoops; 2448 2449 return (0); 2450} 2451