1 /* 2 * Copyright (c) 2011-2015 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@dragonflybsd.org> 6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org> 7 * by Daniel Flores (GSOC 2013 - mentored by Matthew Dillon, compression) 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 3. Neither the name of The DragonFly Project nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific, prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 /* 37 * Kernel Filesystem interface 38 * 39 * NOTE! local ipdata pointers must be reloaded on any modifying operation 40 * to the inode as its underlying chain may have changed. 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/fcntl.h> 47 #include <sys/buf.h> 48 #include <sys/proc.h> 49 #include <sys/namei.h> 50 #include <sys/mount.h> 51 #include <sys/vnode.h> 52 #include <sys/mountctl.h> 53 #include <sys/dirent.h> 54 #include <sys/uio.h> 55 #include <sys/objcache.h> 56 #include <sys/event.h> 57 #include <sys/file.h> 58 #include <vfs/fifofs/fifo.h> 59 60 #include "hammer2.h" 61 62 static int hammer2_read_file(hammer2_inode_t *ip, struct uio *uio, 63 int seqcount); 64 static int hammer2_write_file(hammer2_inode_t *ip, struct uio *uio, 65 int ioflag, int seqcount); 66 static void hammer2_extend_file(hammer2_inode_t *ip, hammer2_key_t nsize); 67 static void hammer2_truncate_file(hammer2_inode_t *ip, hammer2_key_t nsize); 68 69 struct objcache *cache_xops; 70 71 static __inline 72 void 73 hammer2_knote(struct vnode *vp, int flags) 74 { 75 if (flags) 76 KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags); 77 } 78 79 /* 80 * Last reference to a vnode is going away but it is still cached. 81 */ 82 static 83 int 84 hammer2_vop_inactive(struct vop_inactive_args *ap) 85 { 86 hammer2_inode_t *ip; 87 struct vnode *vp; 88 89 LOCKSTART; 90 vp = ap->a_vp; 91 ip = VTOI(vp); 92 93 /* 94 * Degenerate case 95 */ 96 if (ip == NULL) { 97 vrecycle(vp); 98 LOCKSTOP; 99 return (0); 100 } 101 102 /* 103 * Check for deleted inodes and recycle immediately on the last 104 * release. Be sure to destroy any left-over buffer cache buffers 105 * so we do not waste time trying to flush them. 106 * 107 * Note that deleting the file block chains under the inode chain 108 * would just be a waste of energy, so don't do it. 109 * 110 * WARNING: nvtruncbuf() can only be safely called without the inode 111 * lock held due to the way our write thread works. 112 */ 113 if (ip->flags & HAMMER2_INODE_ISUNLINKED) { 114 hammer2_key_t lbase; 115 int nblksize; 116 117 /* 118 * Detect updates to the embedded data which may be 119 * synchronized by the strategy code. Simply mark the 120 * inode modified so it gets picked up by our normal flush. 121 */ 122 nblksize = hammer2_calc_logical(ip, 0, &lbase, NULL); 123 nvtruncbuf(vp, 0, nblksize, 0, 0); 124 vrecycle(vp); 125 } 126 LOCKSTOP; 127 return (0); 128 } 129 130 /* 131 * Reclaim a vnode so that it can be reused; after the inode is 132 * disassociated, the filesystem must manage it alone. 133 */ 134 static 135 int 136 hammer2_vop_reclaim(struct vop_reclaim_args *ap) 137 { 138 hammer2_inode_t *ip; 139 hammer2_pfs_t *pmp; 140 struct vnode *vp; 141 142 LOCKSTART; 143 vp = ap->a_vp; 144 ip = VTOI(vp); 145 if (ip == NULL) { 146 LOCKSTOP; 147 return(0); 148 } 149 pmp = ip->pmp; 150 151 /* 152 * The final close of a deleted file or directory marks it for 153 * destruction. The DELETED flag allows the flusher to shortcut 154 * any modified blocks still unflushed (that is, just ignore them). 155 * 156 * HAMMER2 usually does not try to optimize the freemap by returning 157 * deleted blocks to it as it does not usually know how many snapshots 158 * might be referencing portions of the file/dir. 159 */ 160 vp->v_data = NULL; 161 ip->vp = NULL; 162 163 /* 164 * NOTE! We do not attempt to flush chains here, flushing is 165 * really fragile and could also deadlock. 166 */ 167 vclrisdirty(vp); 168 169 /* 170 * An unlinked inode may have been relinked to the ihidden directory. 171 * This occurs if the inode was unlinked while open. Reclamation of 172 * these inodes requires processing we cannot safely do here so add 173 * the inode to the sideq in that situation. 174 * 175 * A modified inode may require chain synchronization which will no 176 * longer be driven by a sync or fsync without the vnode, also use 177 * the sideq for that. 178 * 179 * A reclaim can occur at any time so we cannot safely start a 180 * transaction to handle reclamation of unlinked files. Instead, 181 * the ip is left with a reference and placed on a linked list and 182 * handled later on. 183 */ 184 185 if ((ip->flags & (HAMMER2_INODE_ISUNLINKED | 186 HAMMER2_INODE_MODIFIED | 187 HAMMER2_INODE_RESIZED)) && 188 (ip->flags & HAMMER2_INODE_ISDELETED) == 0) { 189 hammer2_inode_sideq_t *ipul; 190 191 ipul = kmalloc(sizeof(*ipul), pmp->minode, M_WAITOK | M_ZERO); 192 ipul->ip = ip; 193 194 hammer2_spin_ex(&pmp->list_spin); 195 if ((ip->flags & HAMMER2_INODE_ONSIDEQ) == 0) { 196 /* ref -> sideq */ 197 atomic_set_int(&ip->flags, HAMMER2_INODE_ONSIDEQ); 198 TAILQ_INSERT_TAIL(&pmp->sideq, ipul, entry); 199 hammer2_spin_unex(&pmp->list_spin); 200 } else { 201 hammer2_spin_unex(&pmp->list_spin); 202 kfree(ipul, pmp->minode); 203 hammer2_inode_drop(ip); /* vp ref */ 204 } 205 /* retain ref from vp for ipul */ 206 } else { 207 hammer2_inode_drop(ip); /* vp ref */ 208 } 209 210 /* 211 * XXX handle background sync when ip dirty, kernel will no longer 212 * notify us regarding this inode because there is no longer a 213 * vnode attached to it. 214 */ 215 216 LOCKSTOP; 217 return (0); 218 } 219 220 static 221 int 222 hammer2_vop_fsync(struct vop_fsync_args *ap) 223 { 224 hammer2_inode_t *ip; 225 struct vnode *vp; 226 227 LOCKSTART; 228 vp = ap->a_vp; 229 ip = VTOI(vp); 230 231 #if 0 232 /* XXX can't do this yet */ 233 hammer2_trans_init(ip->pmp, HAMMER2_TRANS_ISFLUSH); 234 vfsync(vp, ap->a_waitfor, 1, NULL, NULL); 235 #endif 236 hammer2_trans_init(ip->pmp, 0); 237 vfsync(vp, ap->a_waitfor, 1, NULL, NULL); 238 239 /* 240 * Calling chain_flush here creates a lot of duplicative 241 * COW operations due to non-optimal vnode ordering. 242 * 243 * Only do it for an actual fsync() syscall. The other forms 244 * which call this function will eventually call chain_flush 245 * on the volume root as a catch-all, which is far more optimal. 246 */ 247 hammer2_inode_lock(ip, 0); 248 if (ip->flags & HAMMER2_INODE_MODIFIED) 249 hammer2_inode_chain_sync(ip); 250 hammer2_inode_unlock(ip); 251 hammer2_trans_done(ip->pmp); 252 253 LOCKSTOP; 254 return (0); 255 } 256 257 static 258 int 259 hammer2_vop_access(struct vop_access_args *ap) 260 { 261 hammer2_inode_t *ip = VTOI(ap->a_vp); 262 uid_t uid; 263 gid_t gid; 264 int error; 265 266 LOCKSTART; 267 hammer2_inode_lock(ip, HAMMER2_RESOLVE_SHARED); 268 uid = hammer2_to_unix_xid(&ip->meta.uid); 269 gid = hammer2_to_unix_xid(&ip->meta.gid); 270 error = vop_helper_access(ap, uid, gid, ip->meta.mode, ip->meta.uflags); 271 hammer2_inode_unlock(ip); 272 273 LOCKSTOP; 274 return (error); 275 } 276 277 static 278 int 279 hammer2_vop_getattr(struct vop_getattr_args *ap) 280 { 281 hammer2_pfs_t *pmp; 282 hammer2_inode_t *ip; 283 struct vnode *vp; 284 struct vattr *vap; 285 hammer2_chain_t *chain; 286 int i; 287 288 LOCKSTART; 289 vp = ap->a_vp; 290 vap = ap->a_vap; 291 292 ip = VTOI(vp); 293 pmp = ip->pmp; 294 295 hammer2_inode_lock(ip, HAMMER2_RESOLVE_SHARED); 296 297 vap->va_fsid = pmp->mp->mnt_stat.f_fsid.val[0]; 298 vap->va_fileid = ip->meta.inum; 299 vap->va_mode = ip->meta.mode; 300 vap->va_nlink = ip->meta.nlinks; 301 vap->va_uid = hammer2_to_unix_xid(&ip->meta.uid); 302 vap->va_gid = hammer2_to_unix_xid(&ip->meta.gid); 303 vap->va_rmajor = 0; 304 vap->va_rminor = 0; 305 vap->va_size = ip->meta.size; /* protected by shared lock */ 306 vap->va_blocksize = HAMMER2_PBUFSIZE; 307 vap->va_flags = ip->meta.uflags; 308 hammer2_time_to_timespec(ip->meta.ctime, &vap->va_ctime); 309 hammer2_time_to_timespec(ip->meta.mtime, &vap->va_mtime); 310 hammer2_time_to_timespec(ip->meta.mtime, &vap->va_atime); 311 vap->va_gen = 1; 312 vap->va_bytes = 0; 313 if (ip->meta.type == HAMMER2_OBJTYPE_DIRECTORY) { 314 /* 315 * Can't really calculate directory use sans the files under 316 * it, just assume one block for now. 317 */ 318 vap->va_bytes += HAMMER2_INODE_BYTES; 319 } else { 320 for (i = 0; i < ip->cluster.nchains; ++i) { 321 if ((chain = ip->cluster.array[i].chain) != NULL) { 322 if (vap->va_bytes < chain->bref.data_count) 323 vap->va_bytes = chain->bref.data_count; 324 } 325 } 326 } 327 vap->va_type = hammer2_get_vtype(ip->meta.type); 328 vap->va_filerev = 0; 329 vap->va_uid_uuid = ip->meta.uid; 330 vap->va_gid_uuid = ip->meta.gid; 331 vap->va_vaflags = VA_UID_UUID_VALID | VA_GID_UUID_VALID | 332 VA_FSID_UUID_VALID; 333 334 hammer2_inode_unlock(ip); 335 336 LOCKSTOP; 337 return (0); 338 } 339 340 static 341 int 342 hammer2_vop_setattr(struct vop_setattr_args *ap) 343 { 344 hammer2_inode_t *ip; 345 struct vnode *vp; 346 struct vattr *vap; 347 int error; 348 int kflags = 0; 349 uint64_t ctime; 350 351 LOCKSTART; 352 vp = ap->a_vp; 353 vap = ap->a_vap; 354 hammer2_update_time(&ctime); 355 356 ip = VTOI(vp); 357 358 if (ip->pmp->ronly) { 359 LOCKSTOP; 360 return(EROFS); 361 } 362 363 hammer2_pfs_memory_wait(ip->pmp); 364 hammer2_trans_init(ip->pmp, 0); 365 hammer2_inode_lock(ip, 0); 366 error = 0; 367 368 if (vap->va_flags != VNOVAL) { 369 u_int32_t flags; 370 371 flags = ip->meta.uflags; 372 error = vop_helper_setattr_flags(&flags, vap->va_flags, 373 hammer2_to_unix_xid(&ip->meta.uid), 374 ap->a_cred); 375 if (error == 0) { 376 if (ip->meta.uflags != flags) { 377 hammer2_inode_modify(ip); 378 ip->meta.uflags = flags; 379 ip->meta.ctime = ctime; 380 kflags |= NOTE_ATTRIB; 381 } 382 if (ip->meta.uflags & (IMMUTABLE | APPEND)) { 383 error = 0; 384 goto done; 385 } 386 } 387 goto done; 388 } 389 if (ip->meta.uflags & (IMMUTABLE | APPEND)) { 390 error = EPERM; 391 goto done; 392 } 393 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 394 mode_t cur_mode = ip->meta.mode; 395 uid_t cur_uid = hammer2_to_unix_xid(&ip->meta.uid); 396 gid_t cur_gid = hammer2_to_unix_xid(&ip->meta.gid); 397 uuid_t uuid_uid; 398 uuid_t uuid_gid; 399 400 error = vop_helper_chown(ap->a_vp, vap->va_uid, vap->va_gid, 401 ap->a_cred, 402 &cur_uid, &cur_gid, &cur_mode); 403 if (error == 0) { 404 hammer2_guid_to_uuid(&uuid_uid, cur_uid); 405 hammer2_guid_to_uuid(&uuid_gid, cur_gid); 406 if (bcmp(&uuid_uid, &ip->meta.uid, sizeof(uuid_uid)) || 407 bcmp(&uuid_gid, &ip->meta.gid, sizeof(uuid_gid)) || 408 ip->meta.mode != cur_mode 409 ) { 410 hammer2_inode_modify(ip); 411 ip->meta.uid = uuid_uid; 412 ip->meta.gid = uuid_gid; 413 ip->meta.mode = cur_mode; 414 ip->meta.ctime = ctime; 415 } 416 kflags |= NOTE_ATTRIB; 417 } 418 } 419 420 /* 421 * Resize the file 422 */ 423 if (vap->va_size != VNOVAL && ip->meta.size != vap->va_size) { 424 switch(vp->v_type) { 425 case VREG: 426 if (vap->va_size == ip->meta.size) 427 break; 428 if (vap->va_size < ip->meta.size) { 429 hammer2_truncate_file(ip, vap->va_size); 430 } else { 431 hammer2_extend_file(ip, vap->va_size); 432 } 433 hammer2_inode_modify(ip); 434 ip->meta.mtime = ctime; 435 break; 436 default: 437 error = EINVAL; 438 goto done; 439 } 440 } 441 #if 0 442 /* atime not supported */ 443 if (vap->va_atime.tv_sec != VNOVAL) { 444 hammer2_inode_modify(ip); 445 ip->meta.atime = hammer2_timespec_to_time(&vap->va_atime); 446 kflags |= NOTE_ATTRIB; 447 } 448 #endif 449 if (vap->va_mode != (mode_t)VNOVAL) { 450 mode_t cur_mode = ip->meta.mode; 451 uid_t cur_uid = hammer2_to_unix_xid(&ip->meta.uid); 452 gid_t cur_gid = hammer2_to_unix_xid(&ip->meta.gid); 453 454 error = vop_helper_chmod(ap->a_vp, vap->va_mode, ap->a_cred, 455 cur_uid, cur_gid, &cur_mode); 456 if (error == 0 && ip->meta.mode != cur_mode) { 457 hammer2_inode_modify(ip); 458 ip->meta.mode = cur_mode; 459 ip->meta.ctime = ctime; 460 kflags |= NOTE_ATTRIB; 461 } 462 } 463 464 if (vap->va_mtime.tv_sec != VNOVAL) { 465 hammer2_inode_modify(ip); 466 ip->meta.mtime = hammer2_timespec_to_time(&vap->va_mtime); 467 kflags |= NOTE_ATTRIB; 468 } 469 470 done: 471 /* 472 * If a truncation occurred we must call inode_fsync() now in order 473 * to trim the related data chains, otherwise a later expansion can 474 * cause havoc. 475 * 476 * If an extend occured that changed the DIRECTDATA state, we must 477 * call inode_fsync now in order to prepare the inode's indirect 478 * block table. 479 */ 480 if (ip->flags & HAMMER2_INODE_RESIZED) 481 hammer2_inode_chain_sync(ip); 482 483 /* 484 * Cleanup. 485 */ 486 hammer2_inode_unlock(ip); 487 hammer2_trans_done(ip->pmp); 488 hammer2_knote(ip->vp, kflags); 489 490 LOCKSTOP; 491 return (error); 492 } 493 494 static 495 int 496 hammer2_vop_readdir(struct vop_readdir_args *ap) 497 { 498 hammer2_xop_readdir_t *xop; 499 hammer2_blockref_t bref; 500 hammer2_inode_t *ip; 501 hammer2_tid_t inum; 502 hammer2_key_t lkey; 503 struct uio *uio; 504 off_t *cookies; 505 off_t saveoff; 506 int cookie_index; 507 int ncookies; 508 int error; 509 int eofflag; 510 int dtype; 511 int r; 512 513 LOCKSTART; 514 ip = VTOI(ap->a_vp); 515 uio = ap->a_uio; 516 saveoff = uio->uio_offset; 517 eofflag = 0; 518 error = 0; 519 520 /* 521 * Setup cookies directory entry cookies if requested 522 */ 523 if (ap->a_ncookies) { 524 ncookies = uio->uio_resid / 16 + 1; 525 if (ncookies > 1024) 526 ncookies = 1024; 527 cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK); 528 } else { 529 ncookies = -1; 530 cookies = NULL; 531 } 532 cookie_index = 0; 533 534 hammer2_inode_lock(ip, HAMMER2_RESOLVE_SHARED); 535 536 /* 537 * Handle artificial entries. To ensure that only positive 64 bit 538 * quantities are returned to userland we always strip off bit 63. 539 * The hash code is designed such that codes 0x0000-0x7FFF are not 540 * used, allowing us to use these codes for articial entries. 541 * 542 * Entry 0 is used for '.' and entry 1 is used for '..'. Do not 543 * allow '..' to cross the mount point into (e.g.) the super-root. 544 */ 545 if (saveoff == 0) { 546 inum = ip->meta.inum & HAMMER2_DIRHASH_USERMSK; 547 r = vop_write_dirent(&error, uio, inum, DT_DIR, 1, "."); 548 if (r) 549 goto done; 550 if (cookies) 551 cookies[cookie_index] = saveoff; 552 ++saveoff; 553 ++cookie_index; 554 if (cookie_index == ncookies) 555 goto done; 556 } 557 558 if (saveoff == 1) { 559 /* 560 * Be careful with lockorder when accessing ".." 561 * 562 * (ip is the current dir. xip is the parent dir). 563 */ 564 inum = ip->meta.inum & HAMMER2_DIRHASH_USERMSK; 565 if (ip->pip && ip != ip->pmp->iroot) 566 inum = ip->pip->meta.inum & HAMMER2_DIRHASH_USERMSK; 567 r = vop_write_dirent(&error, uio, inum, DT_DIR, 2, ".."); 568 if (r) 569 goto done; 570 if (cookies) 571 cookies[cookie_index] = saveoff; 572 ++saveoff; 573 ++cookie_index; 574 if (cookie_index == ncookies) 575 goto done; 576 } 577 578 lkey = saveoff | HAMMER2_DIRHASH_VISIBLE; 579 if (hammer2_debug & 0x0020) 580 kprintf("readdir: lkey %016jx\n", lkey); 581 if (error) 582 goto done; 583 584 /* 585 * Use XOP for cluster scan. 586 * 587 * parent is the inode cluster, already locked for us. Don't 588 * double lock shared locks as this will screw up upgrades. 589 */ 590 xop = hammer2_xop_alloc(ip, 0); 591 xop->lkey = lkey; 592 hammer2_xop_start(&xop->head, hammer2_xop_readdir); 593 594 for (;;) { 595 const hammer2_inode_data_t *ripdata; 596 597 error = hammer2_xop_collect(&xop->head, 0); 598 if (error) 599 break; 600 if (cookie_index == ncookies) 601 break; 602 if (hammer2_debug & 0x0020) 603 kprintf("cluster chain %p %p\n", 604 xop->head.cluster.focus, 605 (xop->head.cluster.focus ? 606 xop->head.cluster.focus->data : (void *)-1)); 607 ripdata = &hammer2_cluster_rdata(&xop->head.cluster)->ipdata; 608 hammer2_cluster_bref(&xop->head.cluster, &bref); 609 if (bref.type == HAMMER2_BREF_TYPE_INODE) { 610 dtype = hammer2_get_dtype(ripdata); 611 saveoff = bref.key & HAMMER2_DIRHASH_USERMSK; 612 r = vop_write_dirent(&error, uio, 613 ripdata->meta.inum & 614 HAMMER2_DIRHASH_USERMSK, 615 dtype, 616 ripdata->meta.name_len, 617 ripdata->filename); 618 if (r) 619 break; 620 if (cookies) 621 cookies[cookie_index] = saveoff; 622 ++cookie_index; 623 } else { 624 /* XXX chain error */ 625 kprintf("bad chain type readdir %d\n", bref.type); 626 } 627 } 628 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP); 629 if (error == ENOENT) { 630 error = 0; 631 eofflag = 1; 632 saveoff = (hammer2_key_t)-1; 633 } else { 634 saveoff = bref.key & HAMMER2_DIRHASH_USERMSK; 635 } 636 done: 637 hammer2_inode_unlock(ip); 638 if (ap->a_eofflag) 639 *ap->a_eofflag = eofflag; 640 if (hammer2_debug & 0x0020) 641 kprintf("readdir: done at %016jx\n", saveoff); 642 uio->uio_offset = saveoff & ~HAMMER2_DIRHASH_VISIBLE; 643 if (error && cookie_index == 0) { 644 if (cookies) { 645 kfree(cookies, M_TEMP); 646 *ap->a_ncookies = 0; 647 *ap->a_cookies = NULL; 648 } 649 } else { 650 if (cookies) { 651 *ap->a_ncookies = cookie_index; 652 *ap->a_cookies = cookies; 653 } 654 } 655 LOCKSTOP; 656 return (error); 657 } 658 659 /* 660 * hammer2_vop_readlink { vp, uio, cred } 661 */ 662 static 663 int 664 hammer2_vop_readlink(struct vop_readlink_args *ap) 665 { 666 struct vnode *vp; 667 hammer2_inode_t *ip; 668 int error; 669 670 vp = ap->a_vp; 671 if (vp->v_type != VLNK) 672 return (EINVAL); 673 ip = VTOI(vp); 674 675 error = hammer2_read_file(ip, ap->a_uio, 0); 676 return (error); 677 } 678 679 static 680 int 681 hammer2_vop_read(struct vop_read_args *ap) 682 { 683 struct vnode *vp; 684 hammer2_inode_t *ip; 685 struct uio *uio; 686 int error; 687 int seqcount; 688 int bigread; 689 690 /* 691 * Read operations supported on this vnode? 692 */ 693 vp = ap->a_vp; 694 if (vp->v_type != VREG) 695 return (EINVAL); 696 697 /* 698 * Misc 699 */ 700 ip = VTOI(vp); 701 uio = ap->a_uio; 702 error = 0; 703 704 seqcount = ap->a_ioflag >> 16; 705 bigread = (uio->uio_resid > 100 * 1024 * 1024); 706 707 error = hammer2_read_file(ip, uio, seqcount); 708 return (error); 709 } 710 711 static 712 int 713 hammer2_vop_write(struct vop_write_args *ap) 714 { 715 hammer2_inode_t *ip; 716 thread_t td; 717 struct vnode *vp; 718 struct uio *uio; 719 int error; 720 int seqcount; 721 722 /* 723 * Read operations supported on this vnode? 724 */ 725 vp = ap->a_vp; 726 if (vp->v_type != VREG) 727 return (EINVAL); 728 729 /* 730 * Misc 731 */ 732 ip = VTOI(vp); 733 uio = ap->a_uio; 734 error = 0; 735 if (ip->pmp->ronly) { 736 return (EROFS); 737 } 738 739 seqcount = ap->a_ioflag >> 16; 740 741 /* 742 * Check resource limit 743 */ 744 if (uio->uio_resid > 0 && (td = uio->uio_td) != NULL && td->td_proc && 745 uio->uio_offset + uio->uio_resid > 746 td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 747 lwpsignal(td->td_proc, td->td_lwp, SIGXFSZ); 748 return (EFBIG); 749 } 750 751 /* 752 * The transaction interlocks against flushes initiations 753 * (note: but will run concurrently with the actual flush). 754 */ 755 hammer2_trans_init(ip->pmp, 0); 756 error = hammer2_write_file(ip, uio, ap->a_ioflag, seqcount); 757 hammer2_trans_done(ip->pmp); 758 759 return (error); 760 } 761 762 /* 763 * Perform read operations on a file or symlink given an UNLOCKED 764 * inode and uio. 765 * 766 * The passed ip is not locked. 767 */ 768 static 769 int 770 hammer2_read_file(hammer2_inode_t *ip, struct uio *uio, int seqcount) 771 { 772 hammer2_off_t size; 773 struct buf *bp; 774 int error; 775 776 error = 0; 777 778 /* 779 * UIO read loop. 780 * 781 * WARNING! Assumes that the kernel interlocks size changes at the 782 * vnode level. 783 */ 784 hammer2_mtx_sh(&ip->lock); 785 size = ip->meta.size; 786 hammer2_mtx_unlock(&ip->lock); 787 788 while (uio->uio_resid > 0 && uio->uio_offset < size) { 789 hammer2_key_t lbase; 790 hammer2_key_t leof; 791 int lblksize; 792 int loff; 793 int n; 794 795 lblksize = hammer2_calc_logical(ip, uio->uio_offset, 796 &lbase, &leof); 797 798 error = cluster_read(ip->vp, leof, lbase, lblksize, 799 uio->uio_resid, seqcount * BKVASIZE, 800 &bp); 801 802 if (error) 803 break; 804 loff = (int)(uio->uio_offset - lbase); 805 n = lblksize - loff; 806 if (n > uio->uio_resid) 807 n = uio->uio_resid; 808 if (n > size - uio->uio_offset) 809 n = (int)(size - uio->uio_offset); 810 bp->b_flags |= B_AGE; 811 uiomove((char *)bp->b_data + loff, n, uio); 812 bqrelse(bp); 813 } 814 return (error); 815 } 816 817 /* 818 * Write to the file represented by the inode via the logical buffer cache. 819 * The inode may represent a regular file or a symlink. 820 * 821 * The inode must not be locked. 822 */ 823 static 824 int 825 hammer2_write_file(hammer2_inode_t *ip, struct uio *uio, 826 int ioflag, int seqcount) 827 { 828 hammer2_key_t old_eof; 829 hammer2_key_t new_eof; 830 struct buf *bp; 831 int kflags; 832 int error; 833 int modified; 834 835 /* 836 * Setup if append 837 * 838 * WARNING! Assumes that the kernel interlocks size changes at the 839 * vnode level. 840 */ 841 hammer2_mtx_ex(&ip->lock); 842 if (ioflag & IO_APPEND) 843 uio->uio_offset = ip->meta.size; 844 old_eof = ip->meta.size; 845 846 /* 847 * Extend the file if necessary. If the write fails at some point 848 * we will truncate it back down to cover as much as we were able 849 * to write. 850 * 851 * Doing this now makes it easier to calculate buffer sizes in 852 * the loop. 853 */ 854 kflags = 0; 855 error = 0; 856 modified = 0; 857 858 if (uio->uio_offset + uio->uio_resid > old_eof) { 859 new_eof = uio->uio_offset + uio->uio_resid; 860 modified = 1; 861 hammer2_extend_file(ip, new_eof); 862 kflags |= NOTE_EXTEND; 863 } else { 864 new_eof = old_eof; 865 } 866 hammer2_mtx_unlock(&ip->lock); 867 868 /* 869 * UIO write loop 870 */ 871 while (uio->uio_resid > 0) { 872 hammer2_key_t lbase; 873 int trivial; 874 int endofblk; 875 int lblksize; 876 int loff; 877 int n; 878 879 /* 880 * Don't allow the buffer build to blow out the buffer 881 * cache. 882 */ 883 if ((ioflag & IO_RECURSE) == 0) 884 bwillwrite(HAMMER2_PBUFSIZE); 885 886 /* 887 * This nominally tells us how much we can cluster and 888 * what the logical buffer size needs to be. Currently 889 * we don't try to cluster the write and just handle one 890 * block at a time. 891 */ 892 lblksize = hammer2_calc_logical(ip, uio->uio_offset, 893 &lbase, NULL); 894 loff = (int)(uio->uio_offset - lbase); 895 896 KKASSERT(lblksize <= 65536); 897 898 /* 899 * Calculate bytes to copy this transfer and whether the 900 * copy completely covers the buffer or not. 901 */ 902 trivial = 0; 903 n = lblksize - loff; 904 if (n > uio->uio_resid) { 905 n = uio->uio_resid; 906 if (loff == lbase && uio->uio_offset + n == new_eof) 907 trivial = 1; 908 endofblk = 0; 909 } else { 910 if (loff == 0) 911 trivial = 1; 912 endofblk = 1; 913 } 914 915 /* 916 * Get the buffer 917 */ 918 if (uio->uio_segflg == UIO_NOCOPY) { 919 /* 920 * Issuing a write with the same data backing the 921 * buffer. Instantiate the buffer to collect the 922 * backing vm pages, then read-in any missing bits. 923 * 924 * This case is used by vop_stdputpages(). 925 */ 926 bp = getblk(ip->vp, lbase, lblksize, GETBLK_BHEAVY, 0); 927 if ((bp->b_flags & B_CACHE) == 0) { 928 bqrelse(bp); 929 error = bread(ip->vp, lbase, lblksize, &bp); 930 } 931 } else if (trivial) { 932 /* 933 * Even though we are entirely overwriting the buffer 934 * we may still have to zero it out to avoid a 935 * mmap/write visibility issue. 936 */ 937 bp = getblk(ip->vp, lbase, lblksize, GETBLK_BHEAVY, 0); 938 if ((bp->b_flags & B_CACHE) == 0) 939 vfs_bio_clrbuf(bp); 940 } else { 941 /* 942 * Partial overwrite, read in any missing bits then 943 * replace the portion being written. 944 * 945 * (The strategy code will detect zero-fill physical 946 * blocks for this case). 947 */ 948 error = bread(ip->vp, lbase, lblksize, &bp); 949 if (error == 0) 950 bheavy(bp); 951 } 952 953 if (error) { 954 brelse(bp); 955 break; 956 } 957 958 /* 959 * Ok, copy the data in 960 */ 961 error = uiomove(bp->b_data + loff, n, uio); 962 kflags |= NOTE_WRITE; 963 modified = 1; 964 if (error) { 965 brelse(bp); 966 break; 967 } 968 969 /* 970 * WARNING: Pageout daemon will issue UIO_NOCOPY writes 971 * with IO_SYNC or IO_ASYNC set. These writes 972 * must be handled as the pageout daemon expects. 973 */ 974 if (ioflag & IO_SYNC) { 975 bwrite(bp); 976 } else if ((ioflag & IO_DIRECT) && endofblk) { 977 bawrite(bp); 978 } else if (ioflag & IO_ASYNC) { 979 bawrite(bp); 980 } else { 981 bdwrite(bp); 982 } 983 } 984 985 /* 986 * Cleanup. If we extended the file EOF but failed to write through 987 * the entire write is a failure and we have to back-up. 988 */ 989 if (error && new_eof != old_eof) { 990 hammer2_mtx_ex(&ip->lock); 991 hammer2_truncate_file(ip, old_eof); 992 if (ip->flags & HAMMER2_INODE_MODIFIED) 993 hammer2_inode_chain_sync(ip); 994 hammer2_mtx_unlock(&ip->lock); 995 } else if (modified) { 996 hammer2_mtx_ex(&ip->lock); 997 hammer2_inode_modify(ip); 998 hammer2_update_time(&ip->meta.mtime); 999 if (ip->flags & HAMMER2_INODE_MODIFIED) 1000 hammer2_inode_chain_sync(ip); 1001 hammer2_mtx_unlock(&ip->lock); 1002 hammer2_knote(ip->vp, kflags); 1003 } 1004 hammer2_trans_assert_strategy(ip->pmp); 1005 1006 return error; 1007 } 1008 1009 /* 1010 * Truncate the size of a file. The inode must not be locked. 1011 * 1012 * We must unconditionally set HAMMER2_INODE_RESIZED to properly 1013 * ensure that any on-media data beyond the new file EOF has been destroyed. 1014 * 1015 * WARNING: nvtruncbuf() can only be safely called without the inode lock 1016 * held due to the way our write thread works. If the truncation 1017 * occurs in the middle of a buffer, nvtruncbuf() is responsible 1018 * for dirtying that buffer and zeroing out trailing bytes. 1019 * 1020 * WARNING! Assumes that the kernel interlocks size changes at the 1021 * vnode level. 1022 * 1023 * WARNING! Caller assumes responsibility for removing dead blocks 1024 * if INODE_RESIZED is set. 1025 */ 1026 static 1027 void 1028 hammer2_truncate_file(hammer2_inode_t *ip, hammer2_key_t nsize) 1029 { 1030 hammer2_key_t lbase; 1031 int nblksize; 1032 1033 LOCKSTART; 1034 hammer2_mtx_unlock(&ip->lock); 1035 if (ip->vp) { 1036 nblksize = hammer2_calc_logical(ip, nsize, &lbase, NULL); 1037 nvtruncbuf(ip->vp, nsize, 1038 nblksize, (int)nsize & (nblksize - 1), 1039 0); 1040 } 1041 hammer2_mtx_ex(&ip->lock); 1042 KKASSERT((ip->flags & HAMMER2_INODE_RESIZED) == 0); 1043 ip->osize = ip->meta.size; 1044 ip->meta.size = nsize; 1045 atomic_set_int(&ip->flags, HAMMER2_INODE_RESIZED); 1046 hammer2_inode_modify(ip); 1047 LOCKSTOP; 1048 } 1049 1050 /* 1051 * Extend the size of a file. The inode must not be locked. 1052 * 1053 * Even though the file size is changing, we do not have to set the 1054 * INODE_RESIZED bit unless the file size crosses the EMBEDDED_BYTES 1055 * boundary. When this occurs a hammer2_inode_chain_sync() is required 1056 * to prepare the inode cluster's indirect block table, otherwise 1057 * async execution of the strategy code will implode on us. 1058 * 1059 * WARNING! Assumes that the kernel interlocks size changes at the 1060 * vnode level. 1061 * 1062 * WARNING! Caller assumes responsibility for transitioning out 1063 * of the inode DIRECTDATA mode if INODE_RESIZED is set. 1064 */ 1065 static 1066 void 1067 hammer2_extend_file(hammer2_inode_t *ip, hammer2_key_t nsize) 1068 { 1069 hammer2_key_t lbase; 1070 hammer2_key_t osize; 1071 int oblksize; 1072 int nblksize; 1073 1074 LOCKSTART; 1075 1076 KKASSERT((ip->flags & HAMMER2_INODE_RESIZED) == 0); 1077 hammer2_inode_modify(ip); 1078 osize = ip->meta.size; 1079 ip->osize = osize; 1080 ip->meta.size = nsize; 1081 1082 if (osize <= HAMMER2_EMBEDDED_BYTES && nsize > HAMMER2_EMBEDDED_BYTES) { 1083 atomic_set_int(&ip->flags, HAMMER2_INODE_RESIZED); 1084 hammer2_inode_chain_sync(ip); 1085 } 1086 1087 hammer2_mtx_unlock(&ip->lock); 1088 if (ip->vp) { 1089 oblksize = hammer2_calc_logical(ip, osize, &lbase, NULL); 1090 nblksize = hammer2_calc_logical(ip, nsize, &lbase, NULL); 1091 nvextendbuf(ip->vp, 1092 osize, nsize, 1093 oblksize, nblksize, 1094 -1, -1, 0); 1095 } 1096 hammer2_mtx_ex(&ip->lock); 1097 1098 LOCKSTOP; 1099 } 1100 1101 static 1102 int 1103 hammer2_vop_nresolve(struct vop_nresolve_args *ap) 1104 { 1105 hammer2_xop_nresolve_t *xop; 1106 hammer2_inode_t *ip; 1107 hammer2_inode_t *dip; 1108 struct namecache *ncp; 1109 struct vnode *vp; 1110 int error; 1111 1112 LOCKSTART; 1113 dip = VTOI(ap->a_dvp); 1114 xop = hammer2_xop_alloc(dip, 0); 1115 1116 ncp = ap->a_nch->ncp; 1117 hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen); 1118 1119 /* 1120 * Note: In DragonFly the kernel handles '.' and '..'. 1121 */ 1122 hammer2_inode_lock(dip, HAMMER2_RESOLVE_SHARED); 1123 hammer2_xop_start(&xop->head, hammer2_xop_nresolve); 1124 1125 error = hammer2_xop_collect(&xop->head, 0); 1126 if (error) { 1127 ip = NULL; 1128 } else { 1129 ip = hammer2_inode_get(dip->pmp, dip, &xop->head.cluster, -1); 1130 } 1131 hammer2_inode_unlock(dip); 1132 1133 /* 1134 * Acquire the related vnode 1135 * 1136 * NOTE: For error processing, only ENOENT resolves the namecache 1137 * entry to NULL, otherwise we just return the error and 1138 * leave the namecache unresolved. 1139 * 1140 * NOTE: multiple hammer2_inode structures can be aliased to the 1141 * same chain element, for example for hardlinks. This 1142 * use case does not 'reattach' inode associations that 1143 * might already exist, but always allocates a new one. 1144 * 1145 * WARNING: inode structure is locked exclusively via inode_get 1146 * but chain was locked shared. inode_unlock() 1147 * will handle it properly. 1148 */ 1149 if (ip) { 1150 vp = hammer2_igetv(ip, &error); 1151 if (error == 0) { 1152 vn_unlock(vp); 1153 cache_setvp(ap->a_nch, vp); 1154 } else if (error == ENOENT) { 1155 cache_setvp(ap->a_nch, NULL); 1156 } 1157 hammer2_inode_unlock(ip); 1158 1159 /* 1160 * The vp should not be released until after we've disposed 1161 * of our locks, because it might cause vop_inactive() to 1162 * be called. 1163 */ 1164 if (vp) 1165 vrele(vp); 1166 } else { 1167 error = ENOENT; 1168 cache_setvp(ap->a_nch, NULL); 1169 } 1170 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP); 1171 KASSERT(error || ap->a_nch->ncp->nc_vp != NULL, 1172 ("resolve error %d/%p ap %p\n", 1173 error, ap->a_nch->ncp->nc_vp, ap)); 1174 LOCKSTOP; 1175 1176 return error; 1177 } 1178 1179 static 1180 int 1181 hammer2_vop_nlookupdotdot(struct vop_nlookupdotdot_args *ap) 1182 { 1183 hammer2_inode_t *dip; 1184 hammer2_inode_t *ip; 1185 int error; 1186 1187 LOCKSTART; 1188 dip = VTOI(ap->a_dvp); 1189 1190 if ((ip = dip->pip) == NULL) { 1191 *ap->a_vpp = NULL; 1192 LOCKSTOP; 1193 return ENOENT; 1194 } 1195 hammer2_inode_lock(ip, 0); 1196 *ap->a_vpp = hammer2_igetv(ip, &error); 1197 hammer2_inode_unlock(ip); 1198 1199 LOCKSTOP; 1200 return error; 1201 } 1202 1203 static 1204 int 1205 hammer2_vop_nmkdir(struct vop_nmkdir_args *ap) 1206 { 1207 hammer2_inode_t *dip; 1208 hammer2_inode_t *nip; 1209 struct namecache *ncp; 1210 const uint8_t *name; 1211 size_t name_len; 1212 int error; 1213 1214 LOCKSTART; 1215 dip = VTOI(ap->a_dvp); 1216 if (dip->pmp->ronly) { 1217 LOCKSTOP; 1218 return (EROFS); 1219 } 1220 1221 ncp = ap->a_nch->ncp; 1222 name = ncp->nc_name; 1223 name_len = ncp->nc_nlen; 1224 1225 hammer2_pfs_memory_wait(dip->pmp); 1226 hammer2_trans_init(dip->pmp, 0); 1227 nip = hammer2_inode_create(dip, ap->a_vap, ap->a_cred, 1228 name, name_len, 0, 1229 hammer2_trans_newinum(dip->pmp), 0, 0, 1230 0, &error); 1231 if (error) { 1232 KKASSERT(nip == NULL); 1233 *ap->a_vpp = NULL; 1234 } else { 1235 *ap->a_vpp = hammer2_igetv(nip, &error); 1236 hammer2_inode_unlock(nip); 1237 } 1238 hammer2_trans_done(dip->pmp); 1239 1240 if (error == 0) { 1241 cache_setunresolved(ap->a_nch); 1242 cache_setvp(ap->a_nch, *ap->a_vpp); 1243 } 1244 LOCKSTOP; 1245 return error; 1246 } 1247 1248 static 1249 int 1250 hammer2_vop_open(struct vop_open_args *ap) 1251 { 1252 return vop_stdopen(ap); 1253 } 1254 1255 /* 1256 * hammer2_vop_advlock { vp, id, op, fl, flags } 1257 */ 1258 static 1259 int 1260 hammer2_vop_advlock(struct vop_advlock_args *ap) 1261 { 1262 hammer2_inode_t *ip = VTOI(ap->a_vp); 1263 hammer2_off_t size; 1264 1265 size = ip->meta.size; 1266 return (lf_advlock(ap, &ip->advlock, size)); 1267 } 1268 1269 static 1270 int 1271 hammer2_vop_close(struct vop_close_args *ap) 1272 { 1273 return vop_stdclose(ap); 1274 } 1275 1276 /* 1277 * hammer2_vop_nlink { nch, dvp, vp, cred } 1278 * 1279 * Create a hardlink from (vp) to {dvp, nch}. 1280 */ 1281 static 1282 int 1283 hammer2_vop_nlink(struct vop_nlink_args *ap) 1284 { 1285 hammer2_xop_nlink_t *xop1; 1286 hammer2_inode_t *fdip; /* target directory to create link in */ 1287 hammer2_inode_t *tdip; /* target directory to create link in */ 1288 hammer2_inode_t *cdip; /* common parent directory */ 1289 hammer2_inode_t *ip; /* inode we are hardlinking to */ 1290 struct namecache *ncp; 1291 const uint8_t *name; 1292 size_t name_len; 1293 int nlink_locked; 1294 int error; 1295 1296 LOCKSTART; 1297 tdip = VTOI(ap->a_dvp); 1298 if (tdip->pmp->ronly) { 1299 LOCKSTOP; 1300 return (EROFS); 1301 } 1302 1303 ncp = ap->a_nch->ncp; 1304 name = ncp->nc_name; 1305 name_len = ncp->nc_nlen; 1306 1307 /* 1308 * ip represents the file being hardlinked. The file could be a 1309 * normal file or a hardlink target if it has already been hardlinked. 1310 * If ip is a hardlinked target then ip->pip represents the location 1311 * of the hardlinked target, NOT the location of the hardlink pointer. 1312 * 1313 * Bump nlinks and potentially also create or move the hardlink 1314 * target in the parent directory common to (ip) and (tdip). The 1315 * consolidation code can modify ip->cluster and ip->pip. The 1316 * returned cluster is locked. 1317 */ 1318 ip = VTOI(ap->a_vp); 1319 hammer2_pfs_memory_wait(ip->pmp); 1320 hammer2_trans_init(ip->pmp, 0); 1321 1322 /* 1323 * The common parent directory must be locked first to avoid deadlocks. 1324 * Also note that fdip and/or tdip might match cdip. 1325 * 1326 * WARNING! The kernel's namecache locks are insufficient for 1327 * protecting us from hardlink shifts, since unrelated 1328 * rename() or link() calls on parent directories might 1329 * cause a shift. A PFS-wide lock is required for this 1330 * situation. 1331 */ 1332 if (ip->meta.type == HAMMER2_OBJTYPE_DIRECTORY || 1333 (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE) == 0) { 1334 lockmgr(&ip->pmp->lock_nlink, LK_EXCLUSIVE); 1335 nlink_locked = 1; 1336 } else { 1337 nlink_locked = 0; 1338 } 1339 fdip = ip->pip; 1340 error = 0; 1341 1342 /* 1343 * Can return NULL and error == EXDEV if the common parent 1344 * crosses a directory with the xlink flag set. 1345 */ 1346 cdip = hammer2_inode_common_parent(fdip, tdip, &error, 1); 1347 if (cdip) 1348 hammer2_inode_lock(cdip, 0); 1349 hammer2_inode_lock(fdip, 0); 1350 hammer2_inode_lock(tdip, 0); 1351 hammer2_inode_lock(ip, 0); 1352 1353 /* 1354 * Dispatch xop_nlink unconditionally since we have to update nlinks. 1355 * 1356 * Otherwise we'd be able to avoid the XOP if the ip does not have 1357 * to be converted or moved. 1358 * If ip is not a hardlink target we must convert it to a hardlink. 1359 * If fdip != cdip we must shift the inode to cdip. 1360 * 1361 * XXX this and other nlink update usage should be passed top-down 1362 * and not updated with a delta bottom-up. 1363 */ 1364 #if 0 1365 if (fdip != cdip || (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) 1366 #endif 1367 if (error == 0) { 1368 xop1 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING); 1369 hammer2_xop_setip2(&xop1->head, ip); 1370 hammer2_xop_setip3(&xop1->head, cdip); 1371 xop1->nlinks_delta = 1; 1372 1373 hammer2_xop_start(&xop1->head, hammer2_xop_nlink); 1374 error = hammer2_xop_collect(&xop1->head, 0); 1375 hammer2_xop_retire(&xop1->head, HAMMER2_XOPMASK_VOP); 1376 if (error == ENOENT) 1377 error = 0; 1378 } 1379 1380 /* 1381 * Must synchronize original inode whos chains are now a hardlink 1382 * target. We must match what the backend XOP did to the 1383 * chains. 1384 */ 1385 if (error == 0 && (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) { 1386 hammer2_inode_modify(ip); 1387 ip->meta.name_key = ip->meta.inum; 1388 ip->meta.name_len = 18; /* "0x%016jx" */ 1389 } 1390 1391 /* 1392 * Create the hardlink target and bump nlinks. 1393 */ 1394 if (error == 0) { 1395 hammer2_inode_create(tdip, NULL, NULL, 1396 name, name_len, 0, 1397 ip->meta.inum, 1398 HAMMER2_OBJTYPE_HARDLINK, ip->meta.type, 1399 0, &error); 1400 hammer2_inode_modify(ip); 1401 ++ip->meta.nlinks; 1402 } 1403 if (error == 0) { 1404 cache_setunresolved(ap->a_nch); 1405 cache_setvp(ap->a_nch, ap->a_vp); 1406 } 1407 hammer2_inode_unlock(ip); 1408 hammer2_inode_unlock(tdip); 1409 hammer2_inode_unlock(fdip); 1410 if (cdip) { 1411 hammer2_inode_unlock(cdip); 1412 hammer2_inode_drop(cdip); 1413 } 1414 1415 if (nlink_locked) 1416 lockmgr(&ip->pmp->lock_nlink, LK_RELEASE); 1417 hammer2_trans_done(ip->pmp); 1418 1419 LOCKSTOP; 1420 return error; 1421 } 1422 1423 /* 1424 * hammer2_vop_ncreate { nch, dvp, vpp, cred, vap } 1425 * 1426 * The operating system has already ensured that the directory entry 1427 * does not exist and done all appropriate namespace locking. 1428 */ 1429 static 1430 int 1431 hammer2_vop_ncreate(struct vop_ncreate_args *ap) 1432 { 1433 hammer2_inode_t *dip; 1434 hammer2_inode_t *nip; 1435 struct namecache *ncp; 1436 const uint8_t *name; 1437 size_t name_len; 1438 int error; 1439 1440 LOCKSTART; 1441 dip = VTOI(ap->a_dvp); 1442 if (dip->pmp->ronly) { 1443 LOCKSTOP; 1444 return (EROFS); 1445 } 1446 1447 ncp = ap->a_nch->ncp; 1448 name = ncp->nc_name; 1449 name_len = ncp->nc_nlen; 1450 hammer2_pfs_memory_wait(dip->pmp); 1451 hammer2_trans_init(dip->pmp, 0); 1452 1453 nip = hammer2_inode_create(dip, ap->a_vap, ap->a_cred, 1454 name, name_len, 0, 1455 hammer2_trans_newinum(dip->pmp), 0, 0, 1456 0, &error); 1457 if (error) { 1458 KKASSERT(nip == NULL); 1459 *ap->a_vpp = NULL; 1460 } else { 1461 *ap->a_vpp = hammer2_igetv(nip, &error); 1462 hammer2_inode_unlock(nip); 1463 } 1464 hammer2_trans_done(dip->pmp); 1465 1466 if (error == 0) { 1467 cache_setunresolved(ap->a_nch); 1468 cache_setvp(ap->a_nch, *ap->a_vpp); 1469 } 1470 LOCKSTOP; 1471 return error; 1472 } 1473 1474 /* 1475 * Make a device node (typically a fifo) 1476 */ 1477 static 1478 int 1479 hammer2_vop_nmknod(struct vop_nmknod_args *ap) 1480 { 1481 hammer2_inode_t *dip; 1482 hammer2_inode_t *nip; 1483 struct namecache *ncp; 1484 const uint8_t *name; 1485 size_t name_len; 1486 int error; 1487 1488 LOCKSTART; 1489 dip = VTOI(ap->a_dvp); 1490 if (dip->pmp->ronly) { 1491 LOCKSTOP; 1492 return (EROFS); 1493 } 1494 1495 ncp = ap->a_nch->ncp; 1496 name = ncp->nc_name; 1497 name_len = ncp->nc_nlen; 1498 hammer2_pfs_memory_wait(dip->pmp); 1499 hammer2_trans_init(dip->pmp, 0); 1500 1501 nip = hammer2_inode_create(dip, ap->a_vap, ap->a_cred, 1502 name, name_len, 0, 1503 hammer2_trans_newinum(dip->pmp), 0, 0, 1504 0, &error); 1505 if (error) { 1506 KKASSERT(nip == NULL); 1507 *ap->a_vpp = NULL; 1508 } else { 1509 *ap->a_vpp = hammer2_igetv(nip, &error); 1510 hammer2_inode_unlock(nip); 1511 } 1512 hammer2_trans_done(dip->pmp); 1513 1514 if (error == 0) { 1515 cache_setunresolved(ap->a_nch); 1516 cache_setvp(ap->a_nch, *ap->a_vpp); 1517 } 1518 LOCKSTOP; 1519 return error; 1520 } 1521 1522 /* 1523 * hammer2_vop_nsymlink { nch, dvp, vpp, cred, vap, target } 1524 */ 1525 static 1526 int 1527 hammer2_vop_nsymlink(struct vop_nsymlink_args *ap) 1528 { 1529 hammer2_inode_t *dip; 1530 hammer2_inode_t *nip; 1531 struct namecache *ncp; 1532 const uint8_t *name; 1533 size_t name_len; 1534 int error; 1535 1536 dip = VTOI(ap->a_dvp); 1537 if (dip->pmp->ronly) 1538 return (EROFS); 1539 1540 ncp = ap->a_nch->ncp; 1541 name = ncp->nc_name; 1542 name_len = ncp->nc_nlen; 1543 hammer2_pfs_memory_wait(dip->pmp); 1544 hammer2_trans_init(dip->pmp, 0); 1545 1546 ap->a_vap->va_type = VLNK; /* enforce type */ 1547 1548 nip = hammer2_inode_create(dip, ap->a_vap, ap->a_cred, 1549 name, name_len, 0, 1550 hammer2_trans_newinum(dip->pmp), 0, 0, 1551 0, &error); 1552 if (error) { 1553 KKASSERT(nip == NULL); 1554 *ap->a_vpp = NULL; 1555 hammer2_trans_done(dip->pmp); 1556 return error; 1557 } 1558 *ap->a_vpp = hammer2_igetv(nip, &error); 1559 1560 /* 1561 * Build the softlink (~like file data) and finalize the namecache. 1562 */ 1563 if (error == 0) { 1564 size_t bytes; 1565 struct uio auio; 1566 struct iovec aiov; 1567 1568 bytes = strlen(ap->a_target); 1569 1570 hammer2_inode_unlock(nip); 1571 bzero(&auio, sizeof(auio)); 1572 bzero(&aiov, sizeof(aiov)); 1573 auio.uio_iov = &aiov; 1574 auio.uio_segflg = UIO_SYSSPACE; 1575 auio.uio_rw = UIO_WRITE; 1576 auio.uio_resid = bytes; 1577 auio.uio_iovcnt = 1; 1578 auio.uio_td = curthread; 1579 aiov.iov_base = ap->a_target; 1580 aiov.iov_len = bytes; 1581 error = hammer2_write_file(nip, &auio, IO_APPEND, 0); 1582 /* XXX handle error */ 1583 error = 0; 1584 } else { 1585 hammer2_inode_unlock(nip); 1586 } 1587 hammer2_trans_done(dip->pmp); 1588 1589 /* 1590 * Finalize namecache 1591 */ 1592 if (error == 0) { 1593 cache_setunresolved(ap->a_nch); 1594 cache_setvp(ap->a_nch, *ap->a_vpp); 1595 /* hammer2_knote(ap->a_dvp, NOTE_WRITE); */ 1596 } 1597 return error; 1598 } 1599 1600 /* 1601 * hammer2_vop_nremove { nch, dvp, cred } 1602 */ 1603 static 1604 int 1605 hammer2_vop_nremove(struct vop_nremove_args *ap) 1606 { 1607 hammer2_xop_unlink_t *xop; 1608 hammer2_inode_t *dip; 1609 hammer2_inode_t *ip; 1610 struct namecache *ncp; 1611 int error; 1612 int isopen; 1613 1614 LOCKSTART; 1615 dip = VTOI(ap->a_dvp); 1616 if (dip->pmp->ronly) { 1617 LOCKSTOP; 1618 return(EROFS); 1619 } 1620 1621 ncp = ap->a_nch->ncp; 1622 1623 hammer2_pfs_memory_wait(dip->pmp); 1624 hammer2_trans_init(dip->pmp, 0); 1625 hammer2_inode_lock(dip, 0); 1626 1627 /* 1628 * The unlink XOP unlinks the path from the directory and 1629 * locates and returns the cluster associated with the real inode. 1630 * We have to handle nlinks here on the frontend. 1631 */ 1632 xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING); 1633 hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen); 1634 isopen = cache_isopen(ap->a_nch); 1635 xop->isdir = 0; 1636 xop->dopermanent = isopen ? 0 : HAMMER2_DELETE_PERMANENT; 1637 hammer2_xop_start(&xop->head, hammer2_xop_unlink); 1638 1639 /* 1640 * Collect the real inode and adjust nlinks, destroy the real 1641 * inode if nlinks transitions to 0 and it was the real inode 1642 * (else it has already been removed). 1643 */ 1644 error = hammer2_xop_collect(&xop->head, 0); 1645 hammer2_inode_unlock(dip); 1646 1647 if (error == 0) { 1648 ip = hammer2_inode_get(dip->pmp, dip, &xop->head.cluster, -1); 1649 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP); 1650 if (ip) { 1651 hammer2_inode_unlink_finisher(ip, isopen); 1652 hammer2_inode_unlock(ip); 1653 } 1654 } else { 1655 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP); 1656 } 1657 1658 hammer2_inode_run_sideq(dip->pmp); 1659 hammer2_trans_done(dip->pmp); 1660 if (error == 0) 1661 cache_unlink(ap->a_nch); 1662 LOCKSTOP; 1663 return (error); 1664 } 1665 1666 /* 1667 * hammer2_vop_nrmdir { nch, dvp, cred } 1668 */ 1669 static 1670 int 1671 hammer2_vop_nrmdir(struct vop_nrmdir_args *ap) 1672 { 1673 hammer2_xop_unlink_t *xop; 1674 hammer2_inode_t *dip; 1675 hammer2_inode_t *ip; 1676 struct namecache *ncp; 1677 int isopen; 1678 int error; 1679 1680 LOCKSTART; 1681 dip = VTOI(ap->a_dvp); 1682 if (dip->pmp->ronly) { 1683 LOCKSTOP; 1684 return(EROFS); 1685 } 1686 1687 hammer2_pfs_memory_wait(dip->pmp); 1688 hammer2_trans_init(dip->pmp, 0); 1689 hammer2_inode_lock(dip, 0); 1690 1691 xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING); 1692 1693 ncp = ap->a_nch->ncp; 1694 hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen); 1695 isopen = cache_isopen(ap->a_nch); 1696 xop->isdir = 1; 1697 xop->dopermanent = isopen ? 0 : HAMMER2_DELETE_PERMANENT; 1698 hammer2_xop_start(&xop->head, hammer2_xop_unlink); 1699 1700 /* 1701 * Collect the real inode and adjust nlinks, destroy the real 1702 * inode if nlinks transitions to 0 and it was the real inode 1703 * (else it has already been removed). 1704 */ 1705 error = hammer2_xop_collect(&xop->head, 0); 1706 hammer2_inode_unlock(dip); 1707 1708 if (error == 0) { 1709 ip = hammer2_inode_get(dip->pmp, dip, &xop->head.cluster, -1); 1710 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP); 1711 if (ip) { 1712 hammer2_inode_unlink_finisher(ip, isopen); 1713 hammer2_inode_unlock(ip); 1714 } 1715 } else { 1716 hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP); 1717 } 1718 hammer2_inode_run_sideq(dip->pmp); 1719 hammer2_trans_done(dip->pmp); 1720 if (error == 0) 1721 cache_unlink(ap->a_nch); 1722 LOCKSTOP; 1723 return (error); 1724 } 1725 1726 /* 1727 * hammer2_vop_nrename { fnch, tnch, fdvp, tdvp, cred } 1728 */ 1729 static 1730 int 1731 hammer2_vop_nrename(struct vop_nrename_args *ap) 1732 { 1733 struct namecache *fncp; 1734 struct namecache *tncp; 1735 hammer2_inode_t *cdip; 1736 hammer2_inode_t *fdip; 1737 hammer2_inode_t *tdip; 1738 hammer2_inode_t *ip; 1739 const uint8_t *fname; 1740 size_t fname_len; 1741 const uint8_t *tname; 1742 size_t tname_len; 1743 int error; 1744 int tnch_error; 1745 int nlink_locked; 1746 hammer2_key_t tlhc; 1747 1748 if (ap->a_fdvp->v_mount != ap->a_tdvp->v_mount) 1749 return(EXDEV); 1750 if (ap->a_fdvp->v_mount != ap->a_fnch->ncp->nc_vp->v_mount) 1751 return(EXDEV); 1752 1753 fdip = VTOI(ap->a_fdvp); /* source directory */ 1754 tdip = VTOI(ap->a_tdvp); /* target directory */ 1755 1756 if (fdip->pmp->ronly) 1757 return(EROFS); 1758 1759 LOCKSTART; 1760 fncp = ap->a_fnch->ncp; /* entry name in source */ 1761 fname = fncp->nc_name; 1762 fname_len = fncp->nc_nlen; 1763 1764 tncp = ap->a_tnch->ncp; /* entry name in target */ 1765 tname = tncp->nc_name; 1766 tname_len = tncp->nc_nlen; 1767 1768 hammer2_pfs_memory_wait(tdip->pmp); 1769 hammer2_trans_init(tdip->pmp, 0); 1770 1771 /* 1772 * ip is the inode being renamed. If this is a hardlink then 1773 * ip represents the actual file and not the hardlink marker. 1774 */ 1775 ip = VTOI(fncp->nc_vp); 1776 1777 /* 1778 * The common parent directory must be locked first to avoid deadlocks. 1779 * Also note that fdip and/or tdip might match cdip. 1780 * 1781 * WARNING! The kernel's namecache locks are insufficient for 1782 * protecting us from hardlink shifts, since unrelated 1783 * rename() or link() calls on parent directories might 1784 * cause a shift. A PFS-wide lock is required for this 1785 * situation. 1786 */ 1787 if (ip->meta.type == HAMMER2_OBJTYPE_DIRECTORY || 1788 (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE) == 0) { 1789 lockmgr(&ip->pmp->lock_nlink, LK_EXCLUSIVE); 1790 nlink_locked = 1; 1791 } else { 1792 nlink_locked = 0; 1793 } 1794 1795 /* 1796 * Can return NULL and error == EXDEV if the common parent 1797 * crosses a directory with the xlink flag set. 1798 */ 1799 error = 0; 1800 cdip = hammer2_inode_common_parent(ip->pip, tdip, &error, 0); 1801 if (cdip == NULL) { 1802 tnch_error = error; 1803 goto done3; 1804 } 1805 hammer2_inode_lock(cdip, 0); 1806 hammer2_inode_lock(fdip, 0); 1807 hammer2_inode_lock(tdip, 0); 1808 hammer2_inode_ref(ip); /* extra ref */ 1809 1810 /* 1811 * If ip is a hardlink target and fdip != cdip we must shift the 1812 * inode to cdip. 1813 */ 1814 hammer2_inode_lock(ip, 0); 1815 1816 if (fdip != cdip && 1817 (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE) == 0) { 1818 hammer2_xop_nlink_t *xop1; 1819 1820 xop1 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING); 1821 hammer2_xop_setip2(&xop1->head, ip); 1822 hammer2_xop_setip3(&xop1->head, cdip); 1823 xop1->nlinks_delta = 0; 1824 1825 hammer2_xop_start(&xop1->head, hammer2_xop_nlink); 1826 error = hammer2_xop_collect(&xop1->head, 0); 1827 hammer2_xop_retire(&xop1->head, HAMMER2_XOPMASK_VOP); 1828 } 1829 /* hammer2_inode_unlock(ip); */ 1830 1831 /* 1832 * Delete the target namespace. 1833 */ 1834 { 1835 hammer2_xop_unlink_t *xop2; 1836 hammer2_inode_t *tip; 1837 int isopen; 1838 1839 /* 1840 * The unlink XOP unlinks the path from the directory and 1841 * locates and returns the cluster associated with the real 1842 * inode. We have to handle nlinks here on the frontend. 1843 */ 1844 xop2 = hammer2_xop_alloc(tdip, HAMMER2_XOP_MODIFYING); 1845 hammer2_xop_setname(&xop2->head, tname, tname_len); 1846 isopen = cache_isopen(ap->a_tnch); 1847 xop2->isdir = -1; 1848 xop2->dopermanent = isopen ? 0 : HAMMER2_DELETE_PERMANENT; 1849 hammer2_xop_start(&xop2->head, hammer2_xop_unlink); 1850 1851 /* 1852 * Collect the real inode and adjust nlinks, destroy the real 1853 * inode if nlinks transitions to 0 and it was the real inode 1854 * (else it has already been removed). 1855 */ 1856 tnch_error = hammer2_xop_collect(&xop2->head, 0); 1857 /* hammer2_inode_unlock(tdip); */ 1858 1859 if (tnch_error == 0) { 1860 tip = hammer2_inode_get(tdip->pmp, NULL, 1861 &xop2->head.cluster, -1); 1862 hammer2_xop_retire(&xop2->head, HAMMER2_XOPMASK_VOP); 1863 if (tip) { 1864 hammer2_inode_unlink_finisher(tip, isopen); 1865 hammer2_inode_unlock(tip); 1866 } 1867 } else { 1868 hammer2_xop_retire(&xop2->head, HAMMER2_XOPMASK_VOP); 1869 } 1870 /* hammer2_inode_lock(tdip, 0); */ 1871 1872 if (tnch_error && tnch_error != ENOENT) { 1873 error = tnch_error; 1874 goto done2; 1875 } 1876 } 1877 1878 /* 1879 * Resolve the collision space for (tdip, tname, tname_len) 1880 * 1881 * tdip must be held exclusively locked to prevent races. 1882 */ 1883 { 1884 hammer2_xop_scanlhc_t *sxop; 1885 hammer2_tid_t lhcbase; 1886 1887 tlhc = hammer2_dirhash(tname, tname_len); 1888 lhcbase = tlhc; 1889 sxop = hammer2_xop_alloc(tdip, HAMMER2_XOP_MODIFYING); 1890 sxop->lhc = tlhc; 1891 hammer2_xop_start(&sxop->head, hammer2_xop_scanlhc); 1892 while ((error = hammer2_xop_collect(&sxop->head, 0)) == 0) { 1893 if (tlhc != sxop->head.cluster.focus->bref.key) 1894 break; 1895 ++tlhc; 1896 } 1897 hammer2_xop_retire(&sxop->head, HAMMER2_XOPMASK_VOP); 1898 1899 if (error) { 1900 if (error != ENOENT) 1901 goto done2; 1902 ++tlhc; 1903 error = 0; 1904 } 1905 if ((lhcbase ^ tlhc) & ~HAMMER2_DIRHASH_LOMASK) { 1906 error = ENOSPC; 1907 goto done2; 1908 } 1909 } 1910 1911 /* 1912 * Everything is setup, do the rename. 1913 * 1914 * We have to synchronize ip->meta to the underlying operation. 1915 * 1916 * NOTE: To avoid deadlocks we cannot lock (ip) while we are 1917 * unlinking elements from their directories. Locking 1918 * the nlinks field does not lock the whole inode. 1919 */ 1920 /* hammer2_inode_lock(ip, 0); */ 1921 if (error == 0) { 1922 hammer2_xop_nrename_t *xop4; 1923 1924 xop4 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING); 1925 xop4->lhc = tlhc; 1926 xop4->ip_key = ip->meta.name_key; 1927 hammer2_xop_setip2(&xop4->head, ip); 1928 hammer2_xop_setip3(&xop4->head, tdip); 1929 hammer2_xop_setname(&xop4->head, fname, fname_len); 1930 hammer2_xop_setname2(&xop4->head, tname, tname_len); 1931 hammer2_xop_start(&xop4->head, hammer2_xop_nrename); 1932 1933 error = hammer2_xop_collect(&xop4->head, 0); 1934 hammer2_xop_retire(&xop4->head, HAMMER2_XOPMASK_VOP); 1935 1936 if (error == ENOENT) 1937 error = 0; 1938 if (error == 0 && 1939 (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) { 1940 hammer2_inode_modify(ip); 1941 ip->meta.name_len = tname_len; 1942 ip->meta.name_key = tlhc; 1943 1944 } 1945 } 1946 1947 /* 1948 * Fixup ip->pip if we were renaming the actual file and not a 1949 * hardlink pointer. 1950 */ 1951 if (error == 0 && (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) { 1952 hammer2_inode_t *opip; 1953 1954 if (ip->pip != tdip) { 1955 hammer2_inode_ref(tdip); 1956 opip = ip->pip; 1957 ip->pip = tdip; 1958 if (opip) 1959 hammer2_inode_drop(opip); 1960 } 1961 } 1962 done2: 1963 hammer2_inode_unlock(ip); 1964 hammer2_inode_unlock(tdip); 1965 hammer2_inode_unlock(fdip); 1966 hammer2_inode_unlock(cdip); 1967 hammer2_inode_drop(ip); 1968 hammer2_inode_drop(cdip); 1969 done3: 1970 hammer2_inode_run_sideq(fdip->pmp); 1971 1972 if (nlink_locked) 1973 lockmgr(&ip->pmp->lock_nlink, LK_RELEASE); 1974 hammer2_trans_done(tdip->pmp); 1975 1976 /* 1977 * Issue the namecache update after unlocking all the internal 1978 * hammer structures, otherwise we might deadlock. 1979 */ 1980 if (tnch_error == 0) { 1981 cache_unlink(ap->a_tnch); 1982 cache_setunresolved(ap->a_tnch); 1983 } 1984 if (error == 0) 1985 cache_rename(ap->a_fnch, ap->a_tnch); 1986 1987 LOCKSTOP; 1988 return (error); 1989 } 1990 1991 /* 1992 * hammer2_vop_ioctl { vp, command, data, fflag, cred } 1993 */ 1994 static 1995 int 1996 hammer2_vop_ioctl(struct vop_ioctl_args *ap) 1997 { 1998 hammer2_inode_t *ip; 1999 int error; 2000 2001 LOCKSTART; 2002 ip = VTOI(ap->a_vp); 2003 2004 error = hammer2_ioctl(ip, ap->a_command, (void *)ap->a_data, 2005 ap->a_fflag, ap->a_cred); 2006 LOCKSTOP; 2007 return (error); 2008 } 2009 2010 static 2011 int 2012 hammer2_vop_mountctl(struct vop_mountctl_args *ap) 2013 { 2014 struct mount *mp; 2015 hammer2_pfs_t *pmp; 2016 int rc; 2017 2018 LOCKSTART; 2019 switch (ap->a_op) { 2020 case (MOUNTCTL_SET_EXPORT): 2021 mp = ap->a_head.a_ops->head.vv_mount; 2022 pmp = MPTOPMP(mp); 2023 2024 if (ap->a_ctllen != sizeof(struct export_args)) 2025 rc = (EINVAL); 2026 else 2027 rc = vfs_export(mp, &pmp->export, 2028 (const struct export_args *)ap->a_ctl); 2029 break; 2030 default: 2031 rc = vop_stdmountctl(ap); 2032 break; 2033 } 2034 LOCKSTOP; 2035 return (rc); 2036 } 2037 2038 /* 2039 * KQFILTER 2040 */ 2041 static void filt_hammer2detach(struct knote *kn); 2042 static int filt_hammer2read(struct knote *kn, long hint); 2043 static int filt_hammer2write(struct knote *kn, long hint); 2044 static int filt_hammer2vnode(struct knote *kn, long hint); 2045 2046 static struct filterops hammer2read_filtops = 2047 { FILTEROP_ISFD | FILTEROP_MPSAFE, 2048 NULL, filt_hammer2detach, filt_hammer2read }; 2049 static struct filterops hammer2write_filtops = 2050 { FILTEROP_ISFD | FILTEROP_MPSAFE, 2051 NULL, filt_hammer2detach, filt_hammer2write }; 2052 static struct filterops hammer2vnode_filtops = 2053 { FILTEROP_ISFD | FILTEROP_MPSAFE, 2054 NULL, filt_hammer2detach, filt_hammer2vnode }; 2055 2056 static 2057 int 2058 hammer2_vop_kqfilter(struct vop_kqfilter_args *ap) 2059 { 2060 struct vnode *vp = ap->a_vp; 2061 struct knote *kn = ap->a_kn; 2062 2063 switch (kn->kn_filter) { 2064 case EVFILT_READ: 2065 kn->kn_fop = &hammer2read_filtops; 2066 break; 2067 case EVFILT_WRITE: 2068 kn->kn_fop = &hammer2write_filtops; 2069 break; 2070 case EVFILT_VNODE: 2071 kn->kn_fop = &hammer2vnode_filtops; 2072 break; 2073 default: 2074 return (EOPNOTSUPP); 2075 } 2076 2077 kn->kn_hook = (caddr_t)vp; 2078 2079 knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn); 2080 2081 return(0); 2082 } 2083 2084 static void 2085 filt_hammer2detach(struct knote *kn) 2086 { 2087 struct vnode *vp = (void *)kn->kn_hook; 2088 2089 knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn); 2090 } 2091 2092 static int 2093 filt_hammer2read(struct knote *kn, long hint) 2094 { 2095 struct vnode *vp = (void *)kn->kn_hook; 2096 hammer2_inode_t *ip = VTOI(vp); 2097 off_t off; 2098 2099 if (hint == NOTE_REVOKE) { 2100 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); 2101 return(1); 2102 } 2103 off = ip->meta.size - kn->kn_fp->f_offset; 2104 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX; 2105 if (kn->kn_sfflags & NOTE_OLDAPI) 2106 return(1); 2107 return (kn->kn_data != 0); 2108 } 2109 2110 2111 static int 2112 filt_hammer2write(struct knote *kn, long hint) 2113 { 2114 if (hint == NOTE_REVOKE) 2115 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); 2116 kn->kn_data = 0; 2117 return (1); 2118 } 2119 2120 static int 2121 filt_hammer2vnode(struct knote *kn, long hint) 2122 { 2123 if (kn->kn_sfflags & hint) 2124 kn->kn_fflags |= hint; 2125 if (hint == NOTE_REVOKE) { 2126 kn->kn_flags |= (EV_EOF | EV_NODATA); 2127 return (1); 2128 } 2129 return (kn->kn_fflags != 0); 2130 } 2131 2132 /* 2133 * FIFO VOPS 2134 */ 2135 static 2136 int 2137 hammer2_vop_markatime(struct vop_markatime_args *ap) 2138 { 2139 hammer2_inode_t *ip; 2140 struct vnode *vp; 2141 2142 vp = ap->a_vp; 2143 ip = VTOI(vp); 2144 2145 if (ip->pmp->ronly) 2146 return(EROFS); 2147 return(0); 2148 } 2149 2150 static 2151 int 2152 hammer2_vop_fifokqfilter(struct vop_kqfilter_args *ap) 2153 { 2154 int error; 2155 2156 error = VOCALL(&fifo_vnode_vops, &ap->a_head); 2157 if (error) 2158 error = hammer2_vop_kqfilter(ap); 2159 return(error); 2160 } 2161 2162 /* 2163 * VOPS vector 2164 */ 2165 struct vop_ops hammer2_vnode_vops = { 2166 .vop_default = vop_defaultop, 2167 .vop_fsync = hammer2_vop_fsync, 2168 .vop_getpages = vop_stdgetpages, 2169 .vop_putpages = vop_stdputpages, 2170 .vop_access = hammer2_vop_access, 2171 .vop_advlock = hammer2_vop_advlock, 2172 .vop_close = hammer2_vop_close, 2173 .vop_nlink = hammer2_vop_nlink, 2174 .vop_ncreate = hammer2_vop_ncreate, 2175 .vop_nsymlink = hammer2_vop_nsymlink, 2176 .vop_nremove = hammer2_vop_nremove, 2177 .vop_nrmdir = hammer2_vop_nrmdir, 2178 .vop_nrename = hammer2_vop_nrename, 2179 .vop_getattr = hammer2_vop_getattr, 2180 .vop_setattr = hammer2_vop_setattr, 2181 .vop_readdir = hammer2_vop_readdir, 2182 .vop_readlink = hammer2_vop_readlink, 2183 .vop_getpages = vop_stdgetpages, 2184 .vop_putpages = vop_stdputpages, 2185 .vop_read = hammer2_vop_read, 2186 .vop_write = hammer2_vop_write, 2187 .vop_open = hammer2_vop_open, 2188 .vop_inactive = hammer2_vop_inactive, 2189 .vop_reclaim = hammer2_vop_reclaim, 2190 .vop_nresolve = hammer2_vop_nresolve, 2191 .vop_nlookupdotdot = hammer2_vop_nlookupdotdot, 2192 .vop_nmkdir = hammer2_vop_nmkdir, 2193 .vop_nmknod = hammer2_vop_nmknod, 2194 .vop_ioctl = hammer2_vop_ioctl, 2195 .vop_mountctl = hammer2_vop_mountctl, 2196 .vop_bmap = hammer2_vop_bmap, 2197 .vop_strategy = hammer2_vop_strategy, 2198 .vop_kqfilter = hammer2_vop_kqfilter 2199 }; 2200 2201 struct vop_ops hammer2_spec_vops = { 2202 .vop_default = vop_defaultop, 2203 .vop_fsync = hammer2_vop_fsync, 2204 .vop_read = vop_stdnoread, 2205 .vop_write = vop_stdnowrite, 2206 .vop_access = hammer2_vop_access, 2207 .vop_close = hammer2_vop_close, 2208 .vop_markatime = hammer2_vop_markatime, 2209 .vop_getattr = hammer2_vop_getattr, 2210 .vop_inactive = hammer2_vop_inactive, 2211 .vop_reclaim = hammer2_vop_reclaim, 2212 .vop_setattr = hammer2_vop_setattr 2213 }; 2214 2215 struct vop_ops hammer2_fifo_vops = { 2216 .vop_default = fifo_vnoperate, 2217 .vop_fsync = hammer2_vop_fsync, 2218 #if 0 2219 .vop_read = hammer2_vop_fiforead, 2220 .vop_write = hammer2_vop_fifowrite, 2221 #endif 2222 .vop_access = hammer2_vop_access, 2223 #if 0 2224 .vop_close = hammer2_vop_fifoclose, 2225 #endif 2226 .vop_markatime = hammer2_vop_markatime, 2227 .vop_getattr = hammer2_vop_getattr, 2228 .vop_inactive = hammer2_vop_inactive, 2229 .vop_reclaim = hammer2_vop_reclaim, 2230 .vop_setattr = hammer2_vop_setattr, 2231 .vop_kqfilter = hammer2_vop_fifokqfilter 2232 }; 2233 2234