1 /* 2 * Copyright (c) 2013 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Antonio Huete Jimenez <tuxillo@quantumachine.net> 6 * by Matthew Dillon <dillon@dragonflybsd.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 3. Neither the name of The DragonFly Project nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific, prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 */ 36 37 #include <stdio.h> 38 #include <errno.h> 39 #include <strings.h> 40 #include <unistd.h> 41 42 #include <sys/vfsops.h> 43 #include <sys/vnode.h> 44 #include <sys/stat.h> 45 #include <sys/namecache.h> 46 #include <sys/queue.h> 47 #include <sys/systm.h> 48 #include <sys/dirent.h> 49 #include <sys/mount.h> 50 #include <sys/signalvar.h> 51 #include <sys/resource.h> 52 #include <sys/buf2.h> 53 #include <sys/kern_syscall.h> 54 #include <sys/ktr.h> 55 56 #include "dirfs.h" 57 58 /* 59 * Kernel tracing facilities 60 */ 61 KTR_INFO_MASTER_EXTERN(dirfs); 62 63 KTR_INFO(KTR_DIRFS, dirfs, unsupported, 0, 64 "DIRFS(func=%s)", 65 const char *func); 66 67 KTR_INFO(KTR_DIRFS, dirfs, nresolve, 0, 68 "DIRFS(dnp=%p ncp_name=%s parent=%p pfd=%d error=%d)", 69 dirfs_node_t dnp, char *name, dirfs_node_t pdnp, int pfd, int error); 70 71 KTR_INFO(KTR_DIRFS, dirfs, ncreate, 1, 72 "DIRFS(dnp=%p ncp_name=%s parent=%p pfd=%d error=%d)", 73 dirfs_node_t dnp, char *name, dirfs_node_t pdnp, int pfd, int error); 74 75 KTR_INFO(KTR_DIRFS, dirfs, open, 2, 76 "DIRFS(dnp=%p dn_name=%s nfd=%d)", 77 dirfs_node_t dnp, char *name, int fd); 78 79 KTR_INFO(KTR_DIRFS, dirfs, close, 3, 80 "DIRFS(dnp=%p fd=%d opencount=%d writecount=%d vfsync error=%d)", 81 dirfs_node_t dnp, int fd, int oc, int wc, int error); 82 83 KTR_INFO(KTR_DIRFS, dirfs, readdir, 4, 84 "DIRFS(dnp=%p fd=%d startoff=%jd uio_offset=%jd)", 85 dirfs_node_t dnp, int fd, off_t startoff, off_t uoff); 86 87 KTR_INFO(KTR_DIRFS, dirfs, access, 5, 88 "DIRFS(dnp=%p error=%d)", 89 dirfs_node_t dnp, int error); 90 91 KTR_INFO(KTR_DIRFS, dirfs, getattr, 6, 92 "DIRFS(dnp=%p error=%d)", 93 dirfs_node_t dnp, int error); 94 95 KTR_INFO(KTR_DIRFS, dirfs, setattr, 7, 96 "DIRFS(dnp=%p action=%s error=%d)", 97 dirfs_node_t dnp, const char *action, int error); 98 99 KTR_INFO(KTR_DIRFS, dirfs, fsync, 8, 100 "DIRFS(dnp=%p error=%d)", 101 dirfs_node_t dnp, int error); 102 103 KTR_INFO(KTR_DIRFS, dirfs, read, 9, 104 "DIRFS(dnp=%p size=%jd error=%d)", 105 dirfs_node_t dnp, size_t size, int error); 106 107 KTR_INFO(KTR_DIRFS, dirfs, write, 10, 108 "DIRFS(dnp=%p size=%jd boff=%jd uio_resid=%jd error=%d)", 109 dirfs_node_t dnp, off_t boff, size_t resid, size_t size, int error); 110 111 KTR_INFO(KTR_DIRFS, dirfs, strategy, 11, 112 "DIRFS(dnp=%p dnp_size=%jd iosize=%jd b_cmd=%d b_error=%d " 113 "b_resid=%d bio_off=%jd error=%d)", 114 dirfs_node_t dnp, size_t size, size_t iosize, int cmd, int berror, 115 int bresid, off_t biooff, int error); 116 117 KTR_INFO(KTR_DIRFS, dirfs, nremove, 12, 118 "DIRFS(dnp=%p pdnp=%p error=%d)", 119 dirfs_node_t dnp, dirfs_node_t pdnp, int error); 120 121 KTR_INFO(KTR_DIRFS, dirfs, nmkdir, 13, 122 "DIRFS(pdnp=%p dnp=%p nc_name=%p error=%d)", 123 dirfs_node_t dnp, dirfs_node_t pdnp, char *n, int error); 124 125 KTR_INFO(KTR_DIRFS, dirfs, nrmdir, 13, 126 "DIRFS(pdnp=%p dnp=%p error=%d)", 127 dirfs_node_t dnp, dirfs_node_t pdnp, int error); 128 129 KTR_INFO(KTR_DIRFS, dirfs, nsymlink, 14, 130 "DIRFS(dnp=%p target=%s symlink=%s error=%d)", 131 dirfs_node_t dnp, char *tgt, char *lnk, int error); 132 133 /* Needed prototypes */ 134 int dirfs_access(struct vop_access_args *); 135 int dirfs_getattr(struct vop_getattr_args *); 136 int dirfs_setattr(struct vop_setattr_args *); 137 int dirfs_reclaim(struct vop_reclaim_args *); 138 139 static __inline 140 void 141 dirfs_knote(struct vnode *vp, int flags) 142 { 143 if (flags) 144 KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags); 145 } 146 147 static int 148 dirfs_nresolve(struct vop_nresolve_args *ap) 149 { 150 dirfs_node_t pdnp, dnp, d1, d2; 151 dirfs_mount_t dmp; 152 struct namecache *ncp; 153 struct nchandle *nch; 154 struct vnode *dvp; 155 struct vnode *vp; 156 struct mount *mp; 157 int error; 158 159 dbg(3, "called\n"); 160 161 error = 0; 162 nch = ap->a_nch; 163 ncp = nch->ncp; 164 mp = nch->mount; 165 dvp = ap->a_dvp; 166 vp = NULL; 167 dnp = d1 = d2 = NULL; 168 pdnp = VP_TO_NODE(dvp); 169 dmp = VFS_TO_DIRFS(mp); 170 171 dirfs_node_lock(pdnp); 172 TAILQ_FOREACH_MUTABLE(d1, &dmp->dm_fdlist, dn_fdentry, d2) { 173 if (d1->dn_parent == pdnp && 174 (strcmp(d1->dn_name, ncp->nc_name) == 0)) { 175 dnp = d1; 176 dirfs_node_ref(dnp); 177 passive_fd_list_hits++; 178 break; 179 } 180 } 181 dirfs_node_unlock(pdnp); 182 183 if (dnp) { 184 dirfs_alloc_vp(mp, &vp, LK_CANRECURSE, dnp); 185 dirfs_node_drop(dmp, dnp); 186 } else { 187 passive_fd_list_miss++; 188 error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, &vp, NULL, 0); 189 } 190 191 if (vp) { 192 if (error && error == ENOENT) { 193 cache_setvp(nch, NULL); 194 } else { 195 vn_unlock(vp); 196 cache_setvp(nch, vp); 197 vrele(vp); 198 } 199 } 200 201 KTR_LOG(dirfs_nresolve, dnp, ncp->nc_name, pdnp, pdnp->dn_fd, error); 202 203 return error; 204 } 205 206 static int 207 dirfs_nlookupdotdot(struct vop_nlookupdotdot_args *ap) 208 { 209 dbg(3, "called\n"); 210 211 KTR_LOG(dirfs_unsupported, __func__); 212 213 return EOPNOTSUPP; 214 } 215 216 static int 217 dirfs_ncreate(struct vop_ncreate_args *ap) 218 { 219 dirfs_node_t pdnp; 220 dirfs_node_t dnp; 221 dirfs_mount_t dmp; 222 struct namecache *ncp; 223 struct vnode *dvp; 224 struct vnode **vpp; 225 struct vattr *vap; 226 int perms = 0; 227 int error; 228 229 dbg(3, "called\n"); 230 231 error = 0; 232 dnp = NULL; 233 dvp = ap->a_dvp; 234 pdnp = VP_TO_NODE(dvp); 235 dmp = VFS_TO_DIRFS(dvp->v_mount); 236 vap = ap->a_vap; 237 ncp = ap->a_nch->ncp; 238 vpp = ap->a_vpp; 239 240 dirfs_node_getperms(pdnp, &perms); 241 if ((perms & DIRFS_NODE_WR) == 0) 242 error = EPERM; 243 244 error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, vpp, vap, 245 (O_CREAT | O_RDWR)); 246 247 if (error == 0) { 248 cache_setunresolved(ap->a_nch); 249 cache_setvp(ap->a_nch, *vpp); 250 dirfs_knote(dvp, NOTE_WRITE); 251 } 252 253 KTR_LOG(dirfs_ncreate, dnp, ncp->nc_name, pdnp, pdnp->dn_fd, error); 254 255 return error; 256 } 257 258 static int 259 dirfs_nmknod(struct vop_nmknod_args *v) 260 { 261 dbg(3, "called\n"); 262 263 return EOPNOTSUPP; 264 } 265 266 static int 267 dirfs_open(struct vop_open_args *ap) 268 { 269 dirfs_node_t dnp; 270 dirfs_mount_t dmp; 271 struct vnode *vp; 272 int error; 273 274 dbg(3, "called\n"); 275 276 vp = ap->a_vp; 277 dnp = VP_TO_NODE(vp); 278 dmp = VFS_TO_DIRFS(vp->v_mount); 279 error = 0; 280 281 /* 282 * Root inode has been allocated and opened in VFS_ROOT() so 283 * no reason to attempt to open it again. 284 */ 285 if (dmp->dm_root != dnp && dnp->dn_fd == DIRFS_NOFD) { 286 error = dirfs_open_helper(dmp, dnp, DIRFS_NOFD, NULL); 287 if (error) 288 return error; 289 } 290 291 KTR_LOG(dirfs_open, dnp, dnp->dn_name, dnp->dn_fd); 292 293 return vop_stdopen(ap); 294 } 295 296 static int 297 dirfs_close(struct vop_close_args *ap) 298 { 299 struct vnode *vp; 300 dirfs_node_t dnp; 301 int error; 302 303 dbg(3, "called\n"); 304 305 error = 0; 306 vp = ap->a_vp; 307 dnp = VP_TO_NODE(vp); 308 309 if (vp->v_type == VREG) { 310 error = vfsync(vp, 0, 1, NULL, NULL); 311 if (error) 312 dbg(9, "vfsync error=%d\n", error); 313 } 314 vop_stdclose(ap); 315 316 KTR_LOG(dirfs_close, dnp, dnp->dn_fd, vp->v_opencount, 317 vp->v_writecount, error); 318 319 return 0; 320 } 321 322 int 323 dirfs_access(struct vop_access_args *ap) 324 { 325 struct vnode *vp = ap->a_vp; 326 int error; 327 dirfs_node_t dnp; 328 329 dbg(3, "called\n"); 330 331 dnp = VP_TO_NODE(vp); 332 333 switch (vp->v_type) { 334 case VDIR: 335 /* FALLTHROUGH */ 336 case VLNK: 337 /* FALLTHROUGH */ 338 case VREG: 339 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 340 error = EROFS; 341 goto out; 342 } 343 break; 344 case VBLK: 345 /* FALLTHROUGH */ 346 case VCHR: 347 /* FALLTHROUGH */ 348 case VSOCK: 349 /* FALLTHROUGH */ 350 case VFIFO: 351 break; 352 353 default: 354 error = EINVAL; 355 goto out; 356 } 357 358 error = vop_helper_access(ap, dnp->dn_uid, 359 dnp->dn_gid, dnp->dn_mode, 0); 360 361 out: 362 KTR_LOG(dirfs_access, dnp, error); 363 364 return error; 365 } 366 367 int 368 dirfs_getattr(struct vop_getattr_args *ap) 369 { 370 dirfs_mount_t dmp; 371 dirfs_node_t dnp; 372 dirfs_node_t pathnp; 373 struct vnode *vp; 374 struct vattr *vap; 375 char *tmp; 376 char *pathfree; 377 int error; 378 379 dbg(3, "called\n"); 380 381 vp = ap->a_vp; 382 vap = ap->a_vap; 383 dnp = VP_TO_NODE(vp); 384 dmp = VFS_TO_DIRFS(vp->v_mount); 385 386 KKASSERT(dnp); /* This must not happen */ 387 388 if (!dirfs_node_isroot(dnp)) { 389 pathnp = dirfs_findfd(dmp, dnp, &tmp, &pathfree); 390 391 KKASSERT(pathnp->dn_fd != DIRFS_NOFD); 392 393 error = dirfs_node_stat(pathnp->dn_fd, tmp, dnp); 394 dirfs_dropfd(dmp, pathnp, pathfree); 395 } else { 396 error = dirfs_node_stat(DIRFS_NOFD, dmp->dm_path, dnp); 397 } 398 399 if (error == 0) { 400 dirfs_node_lock(dnp); 401 vap->va_nlink = dnp->dn_links; 402 vap->va_type = dnp->dn_type; 403 vap->va_mode = dnp->dn_mode; 404 vap->va_uid = dnp->dn_uid; 405 vap->va_gid = dnp->dn_gid; 406 vap->va_fileid = dnp->dn_ino; 407 vap->va_size = dnp->dn_size; 408 vap->va_blocksize = dnp->dn_blocksize; 409 vap->va_atime.tv_sec = dnp->dn_atime; 410 vap->va_atime.tv_nsec = dnp->dn_atimensec; 411 vap->va_mtime.tv_sec = dnp->dn_mtime; 412 vap->va_mtime.tv_nsec = dnp->dn_mtimensec; 413 vap->va_ctime.tv_sec = dnp->dn_ctime; 414 vap->va_ctime.tv_nsec = dnp->dn_ctimensec; 415 vap->va_bytes = dnp->dn_size; 416 vap->va_gen = dnp->dn_gen; 417 vap->va_flags = dnp->dn_flags; 418 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 419 dirfs_node_unlock(dnp); 420 } 421 422 KTR_LOG(dirfs_getattr, dnp, error); 423 424 return 0; 425 } 426 427 int 428 dirfs_setattr(struct vop_setattr_args *ap) 429 { 430 dirfs_mount_t dmp; 431 dirfs_node_t dnp; 432 struct vnode *vp; 433 struct vattr *vap; 434 struct ucred *cred; 435 int error; 436 int kflags = 0; 437 #ifdef KTR 438 const char *msg[6] = { 439 "invalid", 440 "chflags", 441 "chsize", 442 "chown", 443 "chmod", 444 "chtimes" 445 }; 446 #endif 447 int msgno; 448 449 dbg(3, "called\n"); 450 451 error = msgno = 0; 452 vp = ap->a_vp; 453 vap = ap->a_vap; 454 cred = ap->a_cred; 455 dnp = VP_TO_NODE(vp); 456 dmp = VFS_TO_DIRFS(vp->v_mount); 457 458 /* 459 * Check for unsettable attributes. 460 */ 461 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 462 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 463 (vap->va_blocksize != VNOVAL) || (vap->va_rmajor != VNOVAL) || 464 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 465 msgno = 0; 466 error = EINVAL; 467 goto out; 468 } 469 470 /* 471 * Change file flags 472 */ 473 if (error == 0 && (vap->va_flags != VNOVAL)) { 474 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 475 error = EROFS; 476 } else { 477 error = dirfs_node_chflags(dnp, vap->va_flags, cred); 478 kflags |= NOTE_ATTRIB; 479 } 480 msgno = 1; 481 goto out; 482 } 483 484 /* 485 * Extend or truncate a file 486 */ 487 if (error == 0 && (vap->va_size != VNOVAL)) { 488 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 489 error = EROFS; 490 } else { 491 if (vap->va_size > dnp->dn_size) 492 kflags |= NOTE_WRITE | NOTE_EXTEND; 493 else 494 kflags |= NOTE_WRITE; 495 error = dirfs_node_chsize(dnp, vap->va_size); 496 } 497 dbg(9, "dnp size=%jd vap size=%jd\n", dnp->dn_size, vap->va_size); 498 msgno = 2; 499 goto out; 500 } 501 502 /* 503 * Change file owner or group 504 */ 505 if (error == 0 && (vap->va_uid != (uid_t)VNOVAL || 506 vap->va_gid != (gid_t)VNOVAL)) { 507 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 508 error = EROFS; 509 } else { 510 mode_t cur_mode = dnp->dn_mode; 511 uid_t cur_uid = dnp->dn_uid; 512 gid_t cur_gid = dnp->dn_gid; 513 514 error = vop_helper_chown(ap->a_vp, vap->va_uid, 515 vap->va_gid, ap->a_cred, 516 &cur_uid, &cur_gid, &cur_mode); 517 if (error == 0 && 518 (cur_mode != dnp->dn_mode || 519 cur_uid != dnp->dn_uid || 520 cur_gid != dnp->dn_gid)) { 521 error = dirfs_node_chown(dmp, dnp, cur_uid, 522 cur_gid, cur_mode); 523 kflags |= NOTE_ATTRIB; 524 } 525 } 526 msgno = 3; 527 goto out; 528 } 529 530 /* 531 * Change file mode 532 */ 533 if (error == 0 && (vap->va_mode != (mode_t)VNOVAL)) { 534 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 535 error = EROFS; 536 } else { 537 mode_t cur_mode = dnp->dn_mode; 538 uid_t cur_uid = dnp->dn_uid; 539 gid_t cur_gid = dnp->dn_gid; 540 541 error = vop_helper_chmod(ap->a_vp, vap->va_mode, 542 ap->a_cred, 543 cur_uid, cur_gid, &cur_mode); 544 if (error == 0 && cur_mode != dnp->dn_mode) { 545 error = dirfs_node_chmod(dmp, dnp, cur_mode); 546 kflags |= NOTE_ATTRIB; 547 } 548 } 549 msgno = 4; 550 goto out; 551 } 552 553 /* 554 * Change file times 555 */ 556 if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL && 557 vap->va_atime.tv_nsec != VNOVAL) || 558 (vap->va_mtime.tv_sec != VNOVAL && 559 vap->va_mtime.tv_nsec != VNOVAL) )) { 560 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 561 error = EROFS; 562 } else { 563 error = dirfs_node_chtimes(dnp); 564 kflags |= NOTE_ATTRIB; 565 } 566 msgno = 5; 567 goto out; 568 569 } 570 out: 571 KTR_LOG(dirfs_setattr, dnp, msg[msgno], error); 572 573 dirfs_knote(vp, kflags); 574 575 return error; 576 } 577 578 static int 579 dirfs_fsync(struct vop_fsync_args *ap) 580 { 581 dirfs_node_t dnp = VP_TO_NODE(ap->a_vp); 582 int error = 0; 583 584 dbg(3, "called\n"); 585 586 vfsync(ap->a_vp, ap->a_waitfor, 1, NULL, NULL); 587 588 if (dnp->dn_fd != DIRFS_NOFD) { 589 if (fsync(dnp->dn_fd) == -1) 590 error = fsync(dnp->dn_fd); 591 } 592 593 KTR_LOG(dirfs_fsync, dnp, error); 594 595 return 0; 596 } 597 598 static int 599 dirfs_read(struct vop_read_args *ap) 600 { 601 struct buf *bp; 602 struct vnode *vp = ap->a_vp; 603 struct uio *uio = ap->a_uio; 604 dirfs_node_t dnp; 605 off_t base_offset; 606 size_t offset; 607 size_t len; 608 int error; 609 610 dbg(3, "called\n"); 611 612 error = 0; 613 if (uio->uio_resid == 0) { 614 dbg(9, "zero len uio->uio_resid\n"); 615 return error; 616 } 617 618 dnp = VP_TO_NODE(vp); 619 620 if (uio->uio_offset < 0) 621 return (EINVAL); 622 if (vp->v_type != VREG) 623 return (EINVAL); 624 625 while (uio->uio_resid > 0 && uio->uio_offset < dnp->dn_size) { 626 /* 627 * Use buffer cache I/O (via dirfs_strategy) 628 */ 629 offset = (size_t)uio->uio_offset & BMASK; 630 base_offset = (off_t)uio->uio_offset - offset; 631 bp = getcacheblk(vp, base_offset, BSIZE, 0); 632 if (bp == NULL) { 633 lwkt_gettoken(&vp->v_mount->mnt_token); 634 error = bread(vp, base_offset, BSIZE, &bp); 635 if (error) { 636 brelse(bp); 637 lwkt_reltoken(&vp->v_mount->mnt_token); 638 dbg(9, "dirfs_read bread error %d\n", error); 639 break; 640 } 641 lwkt_reltoken(&vp->v_mount->mnt_token); 642 } 643 644 /* 645 * Figure out how many bytes we can actually copy this loop. 646 */ 647 len = BSIZE - offset; 648 if (len > uio->uio_resid) 649 len = uio->uio_resid; 650 if (len > dnp->dn_size - uio->uio_offset) 651 len = (size_t)(dnp->dn_size - uio->uio_offset); 652 653 error = uiomovebp(bp, (char *)bp->b_data + offset, len, uio); 654 bqrelse(bp); 655 if (error) { 656 dbg(9, "dirfs_read uiomove error %d\n", error); 657 break; 658 } 659 } 660 661 KTR_LOG(dirfs_read, dnp, dnp->dn_size, error); 662 663 return(error); 664 } 665 666 static int 667 dirfs_write (struct vop_write_args *ap) 668 { 669 dirfs_node_t dnp; 670 dirfs_mount_t dmp; 671 struct buf *bp; 672 struct vnode *vp = ap->a_vp; 673 struct uio *uio = ap->a_uio; 674 struct thread *td = uio->uio_td; 675 int error; 676 int kflags = 0; 677 off_t osize; 678 off_t nsize; 679 off_t base_offset; 680 size_t offset; 681 size_t len; 682 struct rlimit limit; 683 684 dbg(3, "called\n"); 685 686 error = 0; 687 if (uio->uio_resid == 0) { 688 dbg(9, "zero-length uio->uio_resid\n"); 689 return error; 690 } 691 692 dnp = VP_TO_NODE(vp); 693 dmp = VFS_TO_DIRFS(vp->v_mount); 694 695 if (vp->v_type != VREG) 696 return (EINVAL); 697 698 if (vp->v_type == VREG && td != NULL) { 699 error = kern_getrlimit(RLIMIT_FSIZE, &limit); 700 if (error != 0) { 701 dbg(9, "rlimit failure\n"); 702 return error; 703 } 704 if (uio->uio_offset + uio->uio_resid > limit.rlim_cur) { 705 dbg(9, "file too big\n"); 706 ksignal(td->td_proc, SIGXFSZ); 707 return (EFBIG); 708 } 709 } 710 711 if (ap->a_ioflag & IO_APPEND) 712 uio->uio_offset = dnp->dn_size; 713 714 /* 715 * buffer cache operations may be deferred, make sure 716 * the file is correctly sized right now. 717 */ 718 osize = dnp->dn_size; 719 nsize = uio->uio_offset + uio->uio_resid; 720 if (nsize > osize && uio->uio_resid) { 721 KKASSERT(dnp->dn_fd >= 0); 722 dnp->dn_size = nsize; 723 ftruncate(dnp->dn_fd, nsize); 724 nvextendbuf(vp, osize, nsize, 725 BSIZE, BSIZE, -1, -1, 0); 726 kflags |= NOTE_EXTEND; 727 } /* else nsize = osize; NOT USED */ 728 729 while (uio->uio_resid > 0) { 730 /* 731 * Use buffer cache I/O (via dirfs_strategy) 732 */ 733 offset = (size_t)uio->uio_offset & BMASK; 734 base_offset = (off_t)uio->uio_offset - offset; 735 len = BSIZE - offset; 736 737 if (len > uio->uio_resid) 738 len = uio->uio_resid; 739 740 error = bread(vp, base_offset, BSIZE, &bp); 741 error = uiomovebp(bp, (char *)bp->b_data + offset, len, uio); 742 if (error) { 743 brelse(bp); 744 dbg(9, "WRITE uiomove failed\n"); 745 break; 746 } 747 kflags |= NOTE_WRITE; 748 749 dbg(9, "WRITE dn_size=%jd uio_offset=%jd uio_resid=%jd base_offset=%jd\n", 750 dnp->dn_size, uio->uio_offset, uio->uio_resid, base_offset); 751 752 if (ap->a_ioflag & IO_SYNC) 753 bwrite(bp); 754 else 755 bdwrite(bp); 756 } 757 758 KTR_LOG(dirfs_write, dnp, base_offset, uio->uio_resid, 759 dnp->dn_size, error); 760 761 if (kflags) 762 dirfs_knote(vp, kflags); 763 return error; 764 } 765 766 static int 767 dirfs_advlock (struct vop_advlock_args *ap) 768 { 769 struct vnode *vp = ap->a_vp; 770 dirfs_node_t dnp = VP_TO_NODE(vp); 771 772 dbg(3, "called\n"); 773 774 return (lf_advlock(ap, &dnp->dn_advlock, dnp->dn_size)); 775 } 776 777 static int 778 dirfs_strategy(struct vop_strategy_args *ap) 779 { 780 dirfs_node_t dnp; 781 dirfs_mount_t dmp; 782 struct bio *bio = ap->a_bio; 783 struct buf *bp = bio->bio_buf; 784 struct vnode *vp = ap->a_vp; 785 int error; 786 size_t iosize; 787 char *tmp; 788 char *pathfree; 789 790 dbg(3, "called\n"); 791 792 dnp = VP_TO_NODE(vp); 793 dmp = VFS_TO_DIRFS(vp->v_mount); 794 795 error = 0; 796 797 if (vp->v_type != VREG) { 798 dbg(9, "not VREG\n"); 799 bp->b_resid = bp->b_bcount; 800 bp->b_flags |= B_ERROR | B_INVAL; 801 bp->b_error = EINVAL; 802 biodone(bio); 803 return(0); 804 } 805 806 if (dnp->dn_fd == DIRFS_NOFD) { 807 print_backtrace(-1); 808 panic("Meh, no fd to write to. dnp=%p\n", dnp); 809 } 810 811 if (bio->bio_offset + bp->b_bcount > dnp->dn_size) 812 iosize = dnp->dn_size - bio->bio_offset; 813 else 814 iosize = bp->b_bcount; 815 KKASSERT((ssize_t)iosize >= 0); 816 817 switch (bp->b_cmd) { 818 case BUF_CMD_WRITE: 819 error = pwrite(dnp->dn_fd, bp->b_data, iosize, bio->bio_offset); 820 break; 821 case BUF_CMD_READ: 822 error = pread(dnp->dn_fd, bp->b_data, iosize, bio->bio_offset); 823 break; 824 default: 825 bp->b_error = error = EINVAL; 826 bp->b_flags |= B_ERROR; 827 break; 828 } 829 830 if (error >= 0 && error < bp->b_bcount) 831 bzero(bp->b_data + error, bp->b_bcount - error); 832 833 if (error < 0 && errno != EINTR) { 834 dbg(9, "error=%d dnp=%p dnp->dn_fd=%d " 835 "bio->bio_offset=%ld bcount=%d resid=%d iosize=%zd\n", 836 errno, dnp, dnp->dn_fd, bio->bio_offset, bp->b_bcount, 837 bp->b_resid, iosize); 838 bp->b_error = errno; 839 bp->b_resid = bp->b_bcount; 840 bp->b_flags |= B_ERROR; 841 } else { 842 tmp = dirfs_node_absolute_path(dmp, dnp, &pathfree); 843 dirfs_node_stat(DIRFS_NOFD, tmp, dnp); 844 dirfs_dropfd(dmp, NULL, pathfree); 845 } 846 847 KTR_LOG(dirfs_strategy, dnp, dnp->dn_size, iosize, bp->b_cmd, 848 bp->b_error, bp->b_resid, bio->bio_offset, error); 849 850 biodone(bio); 851 852 return 0; 853 } 854 855 static int 856 dirfs_bmap(struct vop_bmap_args *ap) 857 { 858 dbg(3, "called\n"); 859 860 if (ap->a_doffsetp != NULL) 861 *ap->a_doffsetp = ap->a_loffset; 862 if (ap->a_runp != NULL) 863 *ap->a_runp = 0; 864 if (ap->a_runb != NULL) 865 *ap->a_runb = 0; 866 867 return 0; 868 } 869 870 static int 871 dirfs_nremove(struct vop_nremove_args *ap) 872 { 873 dirfs_node_t dnp, pdnp; 874 dirfs_node_t pathnp; 875 dirfs_mount_t dmp; 876 struct vnode *dvp; 877 struct nchandle *nch; 878 struct namecache *ncp; 879 struct mount *mp; 880 struct vnode *vp; 881 int error; 882 char *tmp; 883 char *pathfree; 884 885 dbg(3, "called\n"); 886 887 error = 0; 888 tmp = NULL; 889 vp = NULL; 890 dvp = ap->a_dvp; 891 nch = ap->a_nch; 892 ncp = nch->ncp; 893 894 mp = dvp->v_mount; 895 dmp = VFS_TO_DIRFS(mp); 896 897 lwkt_gettoken(&mp->mnt_token); 898 cache_vget(nch, ap->a_cred, LK_SHARED, &vp); 899 vn_unlock(vp); 900 901 pdnp = VP_TO_NODE(dvp); 902 dnp = VP_TO_NODE(vp); 903 904 if (vp->v_type == VDIR) { 905 error = EISDIR; 906 } else { 907 pathnp = dirfs_findfd(dmp, dnp, &tmp, &pathfree); 908 dirfs_node_lock(pdnp); 909 error = unlinkat(pathnp->dn_fd, tmp, 0); 910 if (error == 0) { 911 cache_unlink(nch); 912 dirfs_knote(vp, NOTE_DELETE); 913 dirfs_node_setpassive(dmp, dnp, 0); 914 if (dnp->dn_parent) { 915 dirfs_node_drop(dmp, dnp->dn_parent); 916 dnp->dn_parent = NULL; 917 } 918 } else { 919 error = errno; 920 } 921 dirfs_node_unlock(pdnp); 922 dirfs_dropfd(dmp, pathnp, pathfree); 923 } 924 dirfs_knote(dvp, NOTE_WRITE); 925 vrele(vp); 926 lwkt_reltoken(&mp->mnt_token); 927 928 KTR_LOG(dirfs_nremove, dnp, pdnp, error); 929 930 return error; 931 } 932 933 static int 934 dirfs_nlink(struct vop_nlink_args *ap) 935 { 936 dbg(3, "called\n"); 937 938 KTR_LOG(dirfs_unsupported, __func__); 939 940 return EOPNOTSUPP; 941 } 942 943 static int 944 dirfs_nrename(struct vop_nrename_args *ap) 945 { 946 dirfs_node_t dnp, fdnp, tdnp; 947 dirfs_mount_t dmp; 948 struct namecache *fncp, *tncp; 949 struct vnode *fdvp, *tdvp, *vp; 950 struct mount *mp; 951 char *fpath, *fpathfree; 952 char *tpath, *tpathfree; 953 int error; 954 955 dbg(3, "called\n"); 956 957 error = 0; 958 fdvp = ap->a_fdvp; 959 tdvp = ap->a_tdvp; 960 fncp = ap->a_fnch->ncp; 961 tncp = ap->a_tnch->ncp; 962 mp = fdvp->v_mount; 963 dmp = VFS_TO_DIRFS(mp); 964 fdnp = VP_TO_NODE(fdvp); 965 tdnp = VP_TO_NODE(tdvp); 966 967 dbg(9, "fdnp=%p tdnp=%p from=%s to=%s\n", fdnp, tdnp, fncp->nc_name, 968 tncp->nc_name); 969 970 if (fdvp->v_mount != tdvp->v_mount) 971 return(EXDEV); 972 if (fdvp->v_mount != fncp->nc_vp->v_mount) 973 return(EXDEV); 974 if (fdvp->v_mount->mnt_flag & MNT_RDONLY) 975 return (EROFS); 976 977 tpath = dirfs_node_absolute_path_plus(dmp, tdnp, 978 tncp->nc_name, &tpathfree); 979 fpath = dirfs_node_absolute_path_plus(dmp, fdnp, 980 fncp->nc_name, &fpathfree); 981 error = rename(fpath, tpath); 982 if (error < 0) 983 error = errno; 984 if (error == 0) { 985 vp = fncp->nc_vp; /* file being renamed */ 986 dnp = VP_TO_NODE(vp); 987 dirfs_node_setname(dnp, tncp->nc_name, tncp->nc_nlen); 988 dirfs_knote(fdvp, NOTE_RENAME); 989 /* 990 * We have to mark the target file that was replaced by 991 * the rename as having been unlinked. 992 */ 993 vp = tncp->nc_vp; 994 if (vp) { 995 dbg(9, "RENAME2\n"); 996 dnp = VP_TO_NODE(vp); 997 cache_unlink(ap->a_tnch); 998 dirfs_knote(vp, NOTE_DELETE); 999 dirfs_node_setpassive(dmp, dnp, 0); 1000 if (dnp->dn_parent) { 1001 dirfs_node_drop(dmp, dnp->dn_parent); 1002 dnp->dn_parent = NULL; 1003 } 1004 1005 /* 1006 * nlinks on directories can be a bit weird. Zero 1007 * it out. 1008 */ 1009 dnp->dn_links = 0; 1010 cache_inval_vp(vp, CINV_DESTROY); 1011 } 1012 cache_rename(ap->a_fnch, ap->a_tnch); 1013 dirfs_knote(fdvp, NOTE_WRITE); 1014 dirfs_knote(tdvp, NOTE_WRITE); 1015 1016 } 1017 dirfs_dropfd(dmp, NULL, fpathfree); 1018 dirfs_dropfd(dmp, NULL, tpathfree); 1019 1020 return error; 1021 } 1022 1023 static int 1024 dirfs_nmkdir(struct vop_nmkdir_args *ap) 1025 { 1026 dirfs_mount_t dmp; 1027 dirfs_node_t dnp, pdnp, dnp1; 1028 struct namecache *ncp; 1029 struct vattr *vap; 1030 struct vnode *dvp; 1031 struct vnode **vpp; 1032 char *tmp, *pathfree; 1033 char *path; 1034 int pfd, error; 1035 int extrapath; 1036 1037 dbg(3, "called\n"); 1038 1039 extrapath = error = 0; 1040 dvp = ap->a_dvp; 1041 vpp = ap->a_vpp; 1042 dmp = VFS_TO_DIRFS(dvp->v_mount); 1043 pdnp = VP_TO_NODE(dvp); 1044 ncp = ap->a_nch->ncp; 1045 vap = ap->a_vap; 1046 pathfree = tmp = path = NULL; 1047 dnp = NULL; 1048 1049 dirfs_node_lock(pdnp); 1050 if (pdnp->dn_fd != DIRFS_NOFD) { 1051 pfd = pdnp->dn_fd; 1052 path = ncp->nc_name; 1053 } else { 1054 dnp1 = dirfs_findfd(dmp, pdnp, &tmp, &pathfree); 1055 pfd = dnp1->dn_fd; 1056 /* XXX check there is room to copy the path */ 1057 path = kmalloc(MAXPATHLEN, M_DIRFS_MISC, M_ZERO | M_WAITOK); 1058 ksnprintf(path, MAXPATHLEN, "%s/%s", tmp, ncp->nc_name); 1059 extrapath = 1; 1060 dirfs_dropfd(dmp, dnp1, pathfree); 1061 } 1062 1063 error = mkdirat(pfd, path, vap->va_mode); 1064 if (error) { 1065 error = errno; 1066 } else { /* Directory has been made */ 1067 error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, vpp, 1068 vap, O_DIRECTORY); 1069 if (error) 1070 error = errno; 1071 cache_setunresolved(ap->a_nch); 1072 cache_setvp(ap->a_nch, *vpp); 1073 dirfs_knote(dvp, NOTE_WRITE | NOTE_LINK); 1074 } 1075 dirfs_node_unlock(pdnp); 1076 1077 if (extrapath) 1078 kfree(path, M_DIRFS_MISC); 1079 1080 KTR_LOG(dirfs_nmkdir, pdnp, dnp, ncp->nc_name, error); 1081 1082 return error; 1083 } 1084 1085 static int 1086 dirfs_nrmdir(struct vop_nrmdir_args *ap) 1087 { 1088 dirfs_node_t dnp, pdnp; 1089 dirfs_mount_t dmp; 1090 struct vnode *dvp; 1091 struct nchandle *nch; 1092 struct namecache *ncp; 1093 struct mount *mp; 1094 struct vnode *vp; 1095 int error; 1096 char *tmp; 1097 char *pathfree; 1098 1099 dbg(3, "called\n"); 1100 1101 error = 0; 1102 tmp = NULL; 1103 vp = NULL; 1104 dvp = ap->a_dvp; 1105 nch = ap->a_nch; 1106 ncp = nch->ncp; 1107 1108 mp = dvp->v_mount; 1109 dmp = VFS_TO_DIRFS(mp); 1110 1111 lwkt_gettoken(&mp->mnt_token); 1112 cache_vget(nch, ap->a_cred, LK_SHARED, &vp); 1113 vn_unlock(vp); 1114 1115 pdnp = VP_TO_NODE(dvp); 1116 dnp = VP_TO_NODE(vp); 1117 1118 if (vp->v_type != VDIR) { 1119 error = ENOTDIR; 1120 } else { 1121 tmp = dirfs_node_absolute_path(dmp, dnp, &pathfree); 1122 dirfs_node_lock(pdnp); 1123 error = rmdir(tmp); 1124 if (error == 0) { 1125 cache_unlink(nch); 1126 dirfs_knote(dvp, NOTE_WRITE | NOTE_LINK); 1127 dirfs_node_setpassive(dmp, dnp, 0); 1128 if (dnp->dn_parent) { 1129 dirfs_node_drop(dmp, dnp->dn_parent); 1130 dnp->dn_parent = NULL; 1131 } 1132 1133 /* 1134 * nlinks on directories can be a bit weird. Zero 1135 * it out. 1136 */ 1137 dnp->dn_links = 0; 1138 cache_inval_vp(vp, CINV_DESTROY); 1139 } else { 1140 error = errno; 1141 } 1142 dirfs_node_unlock(pdnp); 1143 dirfs_dropfd(dmp, NULL, pathfree); 1144 } 1145 vrele(vp); 1146 lwkt_reltoken(&mp->mnt_token); 1147 1148 KTR_LOG(dirfs_nrmdir, dnp, pdnp, error); 1149 1150 return error; 1151 } 1152 1153 static int 1154 dirfs_nsymlink(struct vop_nsymlink_args *ap) 1155 { 1156 dirfs_mount_t dmp; 1157 dirfs_node_t dnp, pdnp; 1158 struct mount *mp; 1159 struct namecache *ncp; 1160 struct vattr *vap; 1161 struct vnode *dvp; 1162 struct vnode **vpp; 1163 char *tmp, *pathfree; 1164 char *path; 1165 int error; 1166 1167 dbg(3, "called\n"); 1168 1169 error = 0; 1170 dvp = ap->a_dvp; 1171 vpp = ap->a_vpp; 1172 mp = dvp->v_mount; 1173 dmp = VFS_TO_DIRFS(dvp->v_mount); 1174 pdnp = VP_TO_NODE(dvp); 1175 ncp = ap->a_nch->ncp; 1176 vap = ap->a_vap; 1177 pathfree = tmp = path = NULL; 1178 dnp = NULL; 1179 1180 lwkt_gettoken(&mp->mnt_token); 1181 vap->va_type = VLNK; 1182 1183 /* Find out the whole path of our new symbolic link */ 1184 tmp = dirfs_node_absolute_path(dmp, pdnp, &pathfree); 1185 /* XXX check there is room to copy the path */ 1186 path = kmalloc(MAXPATHLEN, M_DIRFS_MISC, M_ZERO | M_WAITOK); 1187 ksnprintf(path, MAXPATHLEN, "%s/%s", tmp, ncp->nc_name); 1188 dirfs_dropfd(dmp, NULL, pathfree); 1189 1190 error = symlink(ap->a_target, path); 1191 if (error) { 1192 error = errno; 1193 } else { /* Symlink has been made */ 1194 error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, vpp, 1195 NULL, 0); 1196 if (error) 1197 error = errno; 1198 cache_setunresolved(ap->a_nch); 1199 cache_setvp(ap->a_nch, *vpp); 1200 dirfs_knote(*vpp, NOTE_WRITE); 1201 } 1202 dbg(5, "path=%s a_target=%s\n", path, ap->a_target); 1203 1204 KTR_LOG(dirfs_nsymlink, dnp, ap->a_target, path, error); 1205 kfree(path, M_DIRFS_MISC); 1206 lwkt_reltoken(&mp->mnt_token); 1207 1208 return error; 1209 1210 } 1211 1212 static int 1213 dirfs_readdir(struct vop_readdir_args *ap) 1214 { 1215 1216 struct dirent *dp, *dpn; 1217 off_t __unused **cookies = ap->a_cookies; 1218 int *ncookies = ap->a_ncookies; 1219 int bytes; 1220 char *buf; 1221 long base; 1222 struct vnode *vp = ap->a_vp; 1223 struct uio *uio; 1224 dirfs_node_t dnp; 1225 off_t startoff; 1226 off_t cnt; 1227 int error, r; 1228 size_t bufsiz; 1229 off_t curoff; 1230 1231 dbg(3, "called\n"); 1232 1233 if (ncookies) 1234 debug(1, "ncookies=%d\n", *ncookies); 1235 1236 dnp = VP_TO_NODE(vp); 1237 uio = ap->a_uio; 1238 startoff = uio->uio_offset; 1239 cnt = 0; 1240 error = 0; 1241 base = 0; 1242 bytes = 0; 1243 1244 if (vp->v_type != VDIR) 1245 return ENOTDIR; 1246 if (uio->uio_resid < 0) 1247 return EINVAL; 1248 if ((bufsiz = uio->uio_resid) > 4096) 1249 bufsiz = 4096; 1250 buf = kmalloc(bufsiz, M_DIRFS_MISC, M_WAITOK | M_ZERO); 1251 1252 /* 1253 * Generally speaking we have to be able to process ALL the 1254 * entries returned by getdirentries() in order for the seek 1255 * position to be correct. For now try to size the buffer 1256 * to make this happen. A smaller buffer always works. For 1257 * now just use an appropriate size. 1258 */ 1259 dirfs_node_lock(dnp); 1260 lseek(dnp->dn_fd, startoff, SEEK_SET); 1261 bytes = getdirentries(dnp->dn_fd, buf, bufsiz, &base); 1262 dbg(9, "seek %016jx %016jx %016jx\n", 1263 (intmax_t)startoff, (intmax_t)base, 1264 (intmax_t)lseek(dnp->dn_fd, 0, SEEK_CUR)); 1265 if (bytes < 0) { 1266 if (errno == EINVAL) 1267 panic("EINVAL on readdir\n"); 1268 error = errno; 1269 curoff = startoff; 1270 goto out; 1271 } else if (bytes == 0) { 1272 *ap->a_eofflag = 1; 1273 curoff = startoff; 1274 goto out; 1275 } 1276 1277 for (dp = (struct dirent *)buf; bytes > 0 && uio->uio_resid > 0; 1278 bytes -= _DIRENT_DIRSIZ(dp), dp = dpn) { 1279 r = vop_write_dirent(&error, uio, dp->d_ino, dp->d_type, 1280 dp->d_namlen, dp->d_name); 1281 if (error || r) 1282 break; 1283 dpn = _DIRENT_NEXT(dp); 1284 dp = dpn; 1285 cnt++; 1286 } 1287 curoff = lseek(dnp->dn_fd, 0, SEEK_CUR); 1288 1289 out: 1290 kfree(buf, M_DIRFS_MISC); 1291 uio->uio_offset = curoff; 1292 dirfs_node_unlock(dnp); 1293 1294 KTR_LOG(dirfs_readdir, dnp, dnp->dn_fd, startoff, uio->uio_offset); 1295 1296 return error; 1297 } 1298 1299 static int 1300 dirfs_readlink(struct vop_readlink_args *ap) 1301 { 1302 dirfs_node_t dnp, pathnp; 1303 dirfs_mount_t dmp; 1304 struct vnode *vp; 1305 struct mount *mp; 1306 struct uio *uio; 1307 char *tmp, *pathfree, *buf; 1308 ssize_t nlen; 1309 int error; 1310 1311 dbg(3, "called\n"); 1312 1313 vp = ap->a_vp; 1314 1315 KKASSERT(vp->v_type == VLNK); 1316 1317 error = 0; 1318 tmp = pathfree = NULL; 1319 uio = ap->a_uio; 1320 mp = vp->v_mount; 1321 dmp = VFS_TO_DIRFS(mp); 1322 dnp = VP_TO_NODE(vp); 1323 1324 lwkt_gettoken(&mp->mnt_token); 1325 1326 pathnp = dirfs_findfd(dmp, dnp, &tmp, &pathfree); 1327 1328 buf = kmalloc(uio->uio_resid, M_DIRFS_MISC, M_WAITOK | M_ZERO); 1329 nlen = readlinkat(pathnp->dn_fd, dnp->dn_name, buf, uio->uio_resid); 1330 if (nlen == -1 ) { 1331 error = errno; 1332 } else { 1333 error = uiomove(buf, nlen + 1, uio); 1334 buf[nlen] = '\0'; 1335 if (error) 1336 error = errno; 1337 } 1338 dirfs_dropfd(dmp, pathnp, pathfree); 1339 kfree(buf, M_DIRFS_MISC); 1340 1341 lwkt_reltoken(&mp->mnt_token); 1342 1343 return error; 1344 } 1345 1346 /* 1347 * Main tasks to be performed. 1348 * 1) When inode is NULL recycle the vnode 1349 * 2) When the inode has 0 links: 1350 * - Check if in the TAILQ, if so remove. 1351 * - Destroy the inode. 1352 * - Recycle the vnode. 1353 * 3) If none of the above, add the node to the TAILQ 1354 * when it has a valid fd and there is room on the 1355 * queue. 1356 * 1357 */ 1358 static int 1359 dirfs_inactive(struct vop_inactive_args *ap) 1360 { 1361 struct vnode *vp; 1362 dirfs_mount_t dmp; 1363 dirfs_node_t dnp; 1364 1365 dbg(3, "called\n"); 1366 1367 vp = ap->a_vp; 1368 dmp = VFS_TO_DIRFS(vp->v_mount); 1369 dnp = VP_TO_NODE(vp); 1370 1371 /* Degenerate case */ 1372 if (dnp == NULL) { 1373 dbg(5, "dnp was NULL\n"); 1374 vrecycle(vp); 1375 return 0; 1376 } 1377 1378 /* 1379 * Deal with the case the inode has 0 links which means it was unlinked. 1380 */ 1381 if (dnp->dn_links == 0) { 1382 vrecycle(vp); 1383 dbg(5, "recycled a vnode of an unlinked dnp\n"); 1384 1385 goto out; 1386 } 1387 1388 /* 1389 * Try to retain the fd in our fd cache. 1390 */ 1391 dirfs_node_setpassive(dmp, dnp, 1); 1392 out: 1393 1394 return 0; 1395 1396 } 1397 1398 int 1399 dirfs_reclaim(struct vop_reclaim_args *ap) 1400 { 1401 struct vnode *vp; 1402 dirfs_node_t dnp; 1403 dirfs_mount_t dmp; 1404 1405 dbg(3, "called\n"); 1406 1407 vp = ap->a_vp; 1408 dnp = VP_TO_NODE(vp); 1409 dmp = VFS_TO_DIRFS(vp->v_mount); 1410 1411 dirfs_free_vp(dmp, dnp); 1412 /* dnp is now invalid, may have been destroyed */ 1413 1414 return 0; 1415 } 1416 1417 static int 1418 dirfs_mountctl(struct vop_mountctl_args *ap) 1419 { 1420 dbg(3, "called\n"); 1421 1422 KTR_LOG(dirfs_unsupported, __func__); 1423 1424 return EOPNOTSUPP; 1425 } 1426 1427 static int 1428 dirfs_print(struct vop_print_args *v) 1429 { 1430 dbg(3, "called\n"); 1431 1432 KTR_LOG(dirfs_unsupported, __func__); 1433 1434 return EOPNOTSUPP; 1435 } 1436 1437 static int __unused 1438 dirfs_pathconf(struct vop_pathconf_args *v) 1439 { 1440 dbg(3, "called\n"); 1441 1442 return EOPNOTSUPP; 1443 } 1444 1445 /************************************************************************ 1446 * KQFILTER OPS * 1447 ************************************************************************/ 1448 1449 static void filt_dirfsdetach(struct knote *kn); 1450 static int filt_dirfsread(struct knote *kn, long hint); 1451 static int filt_dirfswrite(struct knote *kn, long hint); 1452 static int filt_dirfsvnode(struct knote *kn, long hint); 1453 1454 static struct filterops dirfsread_filtops = 1455 { FILTEROP_ISFD | FILTEROP_MPSAFE, 1456 NULL, filt_dirfsdetach, filt_dirfsread }; 1457 static struct filterops dirfswrite_filtops = 1458 { FILTEROP_ISFD | FILTEROP_MPSAFE, 1459 NULL, filt_dirfsdetach, filt_dirfswrite }; 1460 static struct filterops dirfsvnode_filtops = 1461 { FILTEROP_ISFD | FILTEROP_MPSAFE, 1462 NULL, filt_dirfsdetach, filt_dirfsvnode }; 1463 1464 static int 1465 dirfs_kqfilter (struct vop_kqfilter_args *ap) 1466 { 1467 struct vnode *vp = ap->a_vp; 1468 struct knote *kn = ap->a_kn; 1469 1470 switch (kn->kn_filter) { 1471 case EVFILT_READ: 1472 kn->kn_fop = &dirfsread_filtops; 1473 break; 1474 case EVFILT_WRITE: 1475 kn->kn_fop = &dirfswrite_filtops; 1476 break; 1477 case EVFILT_VNODE: 1478 kn->kn_fop = &dirfsvnode_filtops; 1479 break; 1480 default: 1481 return (EOPNOTSUPP); 1482 } 1483 1484 kn->kn_hook = (caddr_t)vp; 1485 1486 knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn); 1487 1488 return(0); 1489 } 1490 1491 static void 1492 filt_dirfsdetach(struct knote *kn) 1493 { 1494 struct vnode *vp = (void *)kn->kn_hook; 1495 1496 knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn); 1497 } 1498 1499 static int 1500 filt_dirfsread(struct knote *kn, long hint) 1501 { 1502 struct vnode *vp = (void *)kn->kn_hook; 1503 dirfs_node_t dnp = VP_TO_NODE(vp); 1504 off_t off; 1505 1506 if (hint == NOTE_REVOKE) { 1507 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); 1508 return(1); 1509 } 1510 1511 /* 1512 * Interlock against MP races when performing this function. 1513 */ 1514 dirfs_node_lock(dnp); 1515 off = dnp->dn_size - kn->kn_fp->f_offset; 1516 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX; 1517 if (kn->kn_sfflags & NOTE_OLDAPI) { 1518 dirfs_node_unlock(dnp); 1519 return(1); 1520 } 1521 if (kn->kn_data == 0) { 1522 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX; 1523 } 1524 dirfs_node_unlock(dnp); 1525 return (kn->kn_data != 0); 1526 } 1527 1528 static int 1529 filt_dirfswrite(struct knote *kn, long hint) 1530 { 1531 if (hint == NOTE_REVOKE) 1532 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); 1533 kn->kn_data = 0; 1534 return (1); 1535 } 1536 1537 static int 1538 filt_dirfsvnode(struct knote *kn, long hint) 1539 { 1540 if (kn->kn_sfflags & hint) 1541 kn->kn_fflags |= hint; 1542 if (hint == NOTE_REVOKE) { 1543 kn->kn_flags |= (EV_EOF | EV_NODATA); 1544 return (1); 1545 } 1546 return (kn->kn_fflags != 0); 1547 } 1548 1549 1550 /* --------------------------------------------------------------------- */ 1551 1552 struct vop_ops dirfs_vnode_vops = { 1553 .vop_default = vop_defaultop, 1554 .vop_nwhiteout = vop_compat_nwhiteout, 1555 .vop_ncreate = dirfs_ncreate, 1556 .vop_nresolve = dirfs_nresolve, 1557 .vop_markatime = vop_stdmarkatime, 1558 .vop_nlookupdotdot = dirfs_nlookupdotdot, 1559 .vop_nmknod = dirfs_nmknod, 1560 .vop_open = dirfs_open, 1561 .vop_close = dirfs_close, 1562 .vop_access = dirfs_access, 1563 .vop_getattr = dirfs_getattr, 1564 .vop_setattr = dirfs_setattr, 1565 .vop_read = dirfs_read, 1566 .vop_write = dirfs_write, 1567 .vop_fsync = dirfs_fsync, 1568 .vop_mountctl = dirfs_mountctl, 1569 .vop_nremove = dirfs_nremove, 1570 .vop_nlink = dirfs_nlink, 1571 .vop_nrename = dirfs_nrename, 1572 .vop_nmkdir = dirfs_nmkdir, 1573 .vop_nrmdir = dirfs_nrmdir, 1574 .vop_nsymlink = dirfs_nsymlink, 1575 .vop_readdir = dirfs_readdir, 1576 .vop_readlink = dirfs_readlink, 1577 .vop_inactive = dirfs_inactive, 1578 .vop_reclaim = dirfs_reclaim, 1579 .vop_print = dirfs_print, 1580 .vop_pathconf = vop_stdpathconf, 1581 .vop_bmap = dirfs_bmap, 1582 .vop_strategy = dirfs_strategy, 1583 .vop_advlock = dirfs_advlock, 1584 .vop_kqfilter = dirfs_kqfilter, 1585 .vop_getpages = vop_stdgetpages, 1586 .vop_putpages = vop_stdputpages 1587 }; 1588