1 /* $NetBSD: chfs_vnops.c,v 1.29 2016/08/20 12:37:09 hannken Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 Department of Software Engineering, 5 * University of Szeged, Hungary 6 * Copyright (C) 2010 Tamas Toth <ttoth@inf.u-szeged.hu> 7 * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org> 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by the Department of Software Engineering, University of Szeged, Hungary 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/param.h> 36 #include <miscfs/specfs/specdev.h> 37 #include <miscfs/fifofs/fifo.h> 38 #include <miscfs/genfs/genfs.h> 39 #include <ufs/ufs/dir.h> 40 #include <ufs/ufs/ufs_extern.h> 41 #include <uvm/uvm.h> 42 #include <sys/namei.h> 43 #include <sys/stat.h> 44 #include <sys/fcntl.h> 45 #include <sys/buf.h> 46 #include <sys/fstrans.h> 47 #include <sys/vnode.h> 48 49 #include "chfs.h" 50 51 #define READ_S "chfs_read" 52 53 int 54 chfs_lookup(void *v) 55 { 56 struct vnode *dvp = ((struct vop_lookup_v2_args *) v)->a_dvp; 57 struct vnode **vpp = ((struct vop_lookup_v2_args *) v)->a_vpp; 58 struct componentname *cnp = ((struct vop_lookup_v2_args *) v)->a_cnp; 59 60 int error; 61 struct chfs_inode* ip; 62 struct ufsmount* ump; 63 struct chfs_mount* chmp; 64 struct chfs_vnode_cache* chvc; 65 struct chfs_dirent* fd; 66 67 dbg("lookup(): %s\n", cnp->cn_nameptr); 68 69 KASSERT(VOP_ISLOCKED(dvp)); 70 71 *vpp = NULL; 72 73 /* Check accessibility of requested node as a first step. */ 74 error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred); 75 if (error != 0) { 76 goto out; 77 } 78 79 /* If requesting the last path component on a read-only file system 80 * with a write operation, deny it. */ 81 if ((cnp->cn_flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) 82 && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { 83 error = EROFS; 84 goto out; 85 } 86 87 /* Avoid doing a linear scan of the directory if the requested 88 * directory/name couple is already in the cache. */ 89 if (cache_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen, 90 cnp->cn_nameiop, cnp->cn_flags, NULL, vpp)) { 91 return (*vpp == NULLVP ? ENOENT : 0); 92 } 93 94 ip = VTOI(dvp); 95 ump = VFSTOUFS(dvp->v_mount); 96 chmp = ump->um_chfs; 97 if (ip->ino == 0) { 98 ip->ino = ++chmp->chm_max_vno; 99 } 100 mutex_enter(&chmp->chm_lock_vnocache); 101 chvc = chfs_vnode_cache_get(chmp, ip->ino); 102 mutex_exit(&chmp->chm_lock_vnocache); 103 104 /* We cannot be requesting the parent directory of the root node. */ 105 KASSERT(IMPLIES(ip->ch_type == CHT_DIR && chvc->pvno == chvc->vno, 106 !(cnp->cn_flags & ISDOTDOT))); 107 108 if (cnp->cn_flags & ISDOTDOT) { 109 VOP_UNLOCK(dvp); 110 error = VFS_VGET(dvp->v_mount, ip->chvc->pvno, vpp); 111 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 112 } else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { 113 vref(dvp); 114 *vpp = dvp; 115 error = 0; 116 } else { 117 fd = chfs_dir_lookup(ip, cnp); 118 119 if (fd == NULL) { 120 dbg("fd null\n"); 121 /* The entry was not found in the directory. 122 * This is OK if we are creating or renaming an 123 * entry and are working on the last component of 124 * the path name. */ 125 if ((cnp->cn_flags & ISLASTCN) && (cnp->cn_nameiop == CREATE 126 || cnp->cn_nameiop == RENAME)) { 127 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred); 128 if (error) { 129 dbg("after the entry was not found in dir\n"); 130 goto out; 131 } 132 133 dbg("return EJUSTRETURN\n"); 134 error = EJUSTRETURN; 135 } else { 136 error = ENOENT; 137 } 138 } else { 139 /* If we are not at the last path component and 140 * found a non-directory or non-link entry (which 141 * may itself be pointing to a directory), raise 142 * an error. */ 143 if ((fd->type != CHT_DIR && fd->type != CHT_LNK) && !(cnp->cn_flags 144 & ISLASTCN)) { 145 error = ENOTDIR; 146 goto out; 147 } 148 149 dbg("vno@allocating new vnode: %llu\n", 150 (unsigned long long)fd->vno); 151 error = VFS_VGET(dvp->v_mount, fd->vno, vpp); 152 } 153 } 154 /* Store the result of this lookup in the cache. Avoid this if the 155 * request was for creation, as it does not improve timings on 156 * emprical tests. */ 157 if (cnp->cn_nameiop != CREATE && (cnp->cn_flags & ISDOTDOT) == 0) { 158 cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, 159 cnp->cn_flags); 160 } 161 162 out: 163 /* If there were no errors, *vpp cannot be NULL. */ 164 KASSERT(IFF(error == 0, *vpp != NULL)); 165 KASSERT(VOP_ISLOCKED(dvp)); 166 167 if (error) 168 return error; 169 if (*vpp != dvp) 170 VOP_UNLOCK(*vpp); 171 return 0; 172 } 173 174 /* --------------------------------------------------------------------- */ 175 176 int 177 chfs_create(void *v) 178 { 179 struct vop_create_v3_args /* { 180 struct vnode *a_dvp; 181 struct vnode **a_vpp; 182 struct componentname *a_cnp; 183 struct vattr *a_vap; 184 } */*ap = v; 185 int error, mode; 186 dbg("create()\n"); 187 188 mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 189 190 if ((mode & IFMT) == 0) { 191 if (ap->a_vap->va_type == VREG) 192 mode |= IFREG; 193 if (ap->a_vap->va_type == VSOCK) 194 mode |= IFSOCK; 195 } 196 197 error = chfs_makeinode(mode, ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap->va_type); 198 199 if (error) { 200 dbg("error: %d\n", error); 201 return error; 202 } 203 204 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 205 return 0; 206 } 207 /* --------------------------------------------------------------------- */ 208 209 int 210 chfs_mknod(void *v) 211 { 212 struct vnode *dvp = ((struct vop_mknod_v3_args *) v)->a_dvp; 213 struct vnode **vpp = ((struct vop_mknod_v3_args *) v)->a_vpp; 214 struct componentname *cnp = ((struct vop_mknod_v3_args *) v)->a_cnp; 215 struct vattr *vap = ((struct vop_mknod_v3_args *) v)->a_vap; 216 int mode, err = 0; 217 struct chfs_inode *ip; 218 struct vnode *vp; 219 220 struct ufsmount *ump; 221 struct chfs_mount *chmp; 222 223 struct chfs_full_dnode *fd; 224 struct buf *bp; 225 int len; 226 dbg("mknod()\n"); 227 228 ump = VFSTOUFS(dvp->v_mount); 229 chmp = ump->um_chfs; 230 231 /* Check type of node. */ 232 if (vap->va_type != VBLK && vap->va_type != VCHR && vap->va_type != VFIFO) 233 return EINVAL; 234 235 vp = *vpp; 236 237 mode = MAKEIMODE(vap->va_type, vap->va_mode); 238 239 if ((mode & IFMT) == 0) { 240 switch (vap->va_type) { 241 case VBLK: 242 mode |= IFBLK; 243 break; 244 case VCHR: 245 mode |= IFCHR; 246 break; 247 case VFIFO: 248 mode |= IFIFO; 249 break; 250 default: 251 break; 252 } 253 } 254 255 /* Create a new node. */ 256 err = chfs_makeinode(mode, dvp, &vp, cnp, vap->va_type); 257 258 ip = VTOI(vp); 259 if (vap->va_rdev != VNOVAL) 260 ip->rdev = vap->va_rdev; 261 262 if (vap->va_type == VFIFO) 263 vp->v_op = chfs_fifoop_p; 264 else { 265 vp->v_op = chfs_specop_p; 266 spec_node_init(vp, ip->rdev); 267 } 268 269 if (err) 270 return err; 271 272 /* Device is written out as a data node. */ 273 len = sizeof(dev_t); 274 chfs_set_vnode_size(vp, len); 275 bp = getiobuf(vp, true); 276 bp->b_bufsize = bp->b_resid = len; 277 bp->b_data = kmem_alloc(len, KM_SLEEP); 278 memcpy(bp->b_data, &ip->rdev, len); 279 bp->b_blkno = 0; 280 281 fd = chfs_alloc_full_dnode(); 282 283 mutex_enter(&chmp->chm_lock_mountfields); 284 285 err = chfs_write_flash_dnode(chmp, vp, bp, fd); 286 if (err) { 287 mutex_exit(&chmp->chm_lock_mountfields); 288 kmem_free(bp->b_data, len); 289 return err; 290 } 291 292 /* Add data node to the inode. */ 293 err = chfs_add_full_dnode_to_inode(chmp, ip, fd); 294 if (err) { 295 mutex_exit(&chmp->chm_lock_mountfields); 296 kmem_free(bp->b_data, len); 297 return err; 298 } 299 300 mutex_exit(&chmp->chm_lock_mountfields); 301 302 *vpp = vp; 303 kmem_free(bp->b_data, len); 304 putiobuf(bp); 305 306 return 0; 307 } 308 309 /* --------------------------------------------------------------------- */ 310 311 int 312 chfs_open(void *v) 313 { 314 struct vnode *vp = ((struct vop_open_args *) v)->a_vp; 315 int mode = ((struct vop_open_args *) v)->a_mode; 316 dbg("open()\n"); 317 318 int error; 319 struct chfs_inode *ip; 320 321 KASSERT(VOP_ISLOCKED(vp)); 322 323 ip = VTOI(vp); 324 325 KASSERT(vp->v_size == ip->size); 326 if (ip->chvc->nlink < 1) { 327 error = ENOENT; 328 goto out; 329 } 330 331 /* If the file is marked append-only, deny write requests. */ 332 if (ip->flags & APPEND && (mode & (FWRITE | O_APPEND)) == FWRITE) 333 error = EPERM; 334 else 335 error = 0; 336 337 out: 338 KASSERT(VOP_ISLOCKED(vp)); 339 return error; 340 } 341 342 /* --------------------------------------------------------------------- */ 343 344 int 345 chfs_close(void *v) 346 { 347 struct vnode *vp = ((struct vop_close_args *) v)->a_vp; 348 dbg("close()\n"); 349 350 struct chfs_inode *ip; 351 352 KASSERT(VOP_ISLOCKED(vp)); 353 354 ip = VTOI(vp); 355 356 if (ip->chvc->nlink > 0) { 357 chfs_update(vp, NULL, NULL, UPDATE_CLOSE); 358 } 359 360 return 0; 361 } 362 363 /* --------------------------------------------------------------------- */ 364 365 int 366 chfs_access(void *v) 367 { 368 struct vnode *vp = ((struct vop_access_args *) v)->a_vp; 369 int mode = ((struct vop_access_args *) v)->a_mode; 370 kauth_cred_t cred = ((struct vop_access_args *) v)->a_cred; 371 372 dbg("access()\n"); 373 struct chfs_inode *ip = VTOI(vp); 374 375 if (mode & VWRITE) { 376 switch (vp->v_type) { 377 case VLNK: 378 case VDIR: 379 case VREG: 380 if (vp->v_mount->mnt_flag & MNT_RDONLY) 381 return (EROFS); 382 break; 383 case VBLK: 384 case VCHR: 385 case VSOCK: 386 case VFIFO: 387 break; 388 default: 389 break; 390 } 391 } 392 393 if (mode & VWRITE && ip->flags & IMMUTABLE) 394 return (EPERM); 395 396 return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, vp->v_type, 397 ip->mode & ALLPERMS), vp, NULL, genfs_can_access(vp->v_type, 398 ip->mode & ALLPERMS, ip->uid, ip->gid, mode, cred)); 399 } 400 401 /* --------------------------------------------------------------------- */ 402 403 int 404 chfs_getattr(void *v) 405 { 406 struct vnode *vp = ((struct vop_getattr_args *) v)->a_vp; 407 struct vattr *vap = ((struct vop_getattr_args *) v)->a_vap; 408 409 struct chfs_inode *ip = VTOI(vp); 410 dbg("getattr()\n"); 411 412 KASSERT(vp->v_size == ip->size); 413 414 vattr_null(vap); 415 CHFS_ITIMES(ip, NULL, NULL, NULL); 416 417 vap->va_type = CHTTOVT(ip->ch_type); 418 vap->va_mode = ip->mode & ALLPERMS; 419 vap->va_nlink = ip->chvc->nlink; 420 vap->va_uid = ip->uid; 421 vap->va_gid = ip->gid; 422 vap->va_fsid = ip->dev; 423 vap->va_fileid = ip->ino; 424 vap->va_size = ip->size; 425 vap->va_blocksize = PAGE_SIZE; 426 vap->va_atime.tv_sec = ip->atime; 427 vap->va_atime.tv_nsec = 0; 428 vap->va_mtime.tv_sec = ip->mtime; 429 vap->va_mtime.tv_nsec = 0; 430 vap->va_ctime.tv_sec = ip->ctime; 431 vap->va_ctime.tv_nsec = 0; 432 vap->va_gen = ip->version; 433 vap->va_flags = ip->flags; 434 vap->va_rdev = ip->rdev; 435 vap->va_bytes = round_page(ip->size); 436 vap->va_filerev = VNOVAL; 437 vap->va_vaflags = 0; 438 vap->va_spare = VNOVAL; 439 440 return 0; 441 } 442 443 /* --------------------------------------------------------------------- */ 444 445 /* Note: modelled after tmpfs's same function */ 446 447 int 448 chfs_setattr(void *v) 449 { 450 struct vnode *vp = ((struct vop_setattr_args *) v)->a_vp; 451 struct vattr *vap = ((struct vop_setattr_args *) v)->a_vap; 452 kauth_cred_t cred = ((struct vop_setattr_args *) v)->a_cred; 453 454 struct chfs_inode *ip; 455 struct ufsmount *ump = VFSTOUFS(vp->v_mount); 456 struct chfs_mount *chmp = ump->um_chfs; 457 int error = 0; 458 459 dbg("setattr()\n"); 460 461 KASSERT(VOP_ISLOCKED(vp)); 462 ip = VTOI(vp); 463 464 /* Abort if any unsettable attribute is given. */ 465 if (vap->va_type != VNON || vap->va_nlink != VNOVAL || 466 vap->va_fsid != VNOVAL || vap->va_fileid != VNOVAL || 467 vap->va_blocksize != VNOVAL /*|| GOODTIME(&vap->va_ctime)*/ || 468 vap->va_gen != VNOVAL || vap->va_rdev != VNOVAL || 469 vap->va_bytes != VNOVAL) { 470 return EINVAL; 471 } 472 473 /* set flags */ 474 if (error == 0 && (vap->va_flags != VNOVAL)) { 475 error = chfs_chflags(vp, vap->va_flags, cred); 476 return error; 477 } 478 479 if (ip->flags & (IMMUTABLE | APPEND)) { 480 error = EPERM; 481 return error; 482 } 483 484 /* set size */ 485 if (error == 0 && (vap->va_size != VNOVAL)) { 486 error = chfs_chsize(vp, vap->va_size, cred); 487 if (error) 488 return error; 489 } 490 491 /* set owner */ 492 if (error == 0 && (vap->va_uid != VNOVAL || vap->va_gid != VNOVAL)) { 493 error = chfs_chown(vp, vap->va_uid, vap->va_gid, cred); 494 if (error) 495 return error; 496 } 497 498 /* set mode */ 499 if (error == 0 && (vap->va_mode != VNOVAL)) { 500 error = chfs_chmod(vp, vap->va_mode, cred); 501 if (error) 502 return error; 503 } 504 505 /* set time */ 506 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 507 error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, 508 NULL, genfs_can_chtimes(vp, vap->va_vaflags, ip->uid, cred)); 509 if (error) 510 return error; 511 if (vap->va_atime.tv_sec != VNOVAL) 512 ip->iflag |= IN_ACCESS; 513 if (vap->va_mtime.tv_sec != VNOVAL) 514 ip->iflag |= IN_CHANGE | IN_UPDATE; 515 error = chfs_update(vp, 516 &vap->va_atime, &vap->va_mtime, UPDATE_WAIT); 517 if (error) 518 return error; 519 } 520 521 /* Write it out. */ 522 mutex_enter(&chmp->chm_lock_mountfields); 523 error = chfs_write_flash_vnode(chmp, ip, ALLOC_NORMAL); 524 mutex_exit(&chmp->chm_lock_mountfields); 525 526 return error; 527 } 528 529 int 530 chfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred) 531 { 532 struct chfs_inode *ip = VTOI(vp); 533 int error; 534 dbg("chmod\n"); 535 536 error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, 537 NULL, genfs_can_chmod(vp->v_type, cred, ip->uid, ip->gid, mode)); 538 if (error) 539 return error; 540 ip->mode &= ~ALLPERMS; 541 ip->mode |= (mode & ALLPERMS); 542 ip->iflag |= IN_CHANGE; 543 544 error = chfs_update(vp, NULL, NULL, UPDATE_WAIT); 545 if (error) 546 return error; 547 548 return 0; 549 } 550 551 int 552 chfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred) 553 { 554 struct chfs_inode *ip = VTOI(vp); 555 int error; 556 dbg("chown\n"); 557 558 if (uid == (uid_t)VNOVAL) 559 uid = ip->uid; 560 if (gid == (gid_t)VNOVAL) 561 gid = ip->gid; 562 563 error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, 564 NULL, genfs_can_chown(cred, ip->uid, ip->gid, uid, gid)); 565 if (error) 566 return error; 567 568 ip->gid = gid; 569 ip->uid = uid; 570 ip->iflag |= IN_CHANGE; 571 572 error = chfs_update(vp, NULL, NULL, UPDATE_WAIT); 573 if (error) 574 return error; 575 576 return 0; 577 } 578 579 580 /* --------------------------------------------------------------------- */ 581 /* calculates ((off_t)blk * chmp->chm_chm_fs_bsize) */ 582 #define chfs_lblktosize(chmp, blk) \ 583 (((off_t)(blk)) << (chmp)->chm_fs_bshift) 584 585 /* calculates (loc % chmp->chm_chm_fs_bsize) */ 586 #define chfs_blkoff(chmp, loc) \ 587 ((loc) & (chmp)->chm_fs_qbmask) 588 589 /* calculates (loc / chmp->chm_chm_fs_bsize) */ 590 #define chfs_lblkno(chmp, loc) \ 591 ((loc) >> (chmp)->chm_fs_bshift) 592 593 /* calculates roundup(size, chmp->chm_chm_fs_fsize) */ 594 #define chfs_fragroundup(chmp, size) \ 595 (((size) + (chmp)->chm_fs_qfmask) & (chmp)->chm_fs_fmask) 596 597 #define chfs_blksize(chmp, ip, lbn) \ 598 (((lbn) >= UFS_NDADDR || (ip)->size >= chfs_lblktosize(chmp, (lbn) + 1)) \ 599 ? (chmp)->chm_fs_bsize \ 600 : (chfs_fragroundup(chmp, chfs_blkoff(chmp, (ip)->size)))) 601 602 /* calculates roundup(size, chmp->chm_chm_fs_bsize) */ 603 #define chfs_blkroundup(chmp, size) \ 604 (((size) + (chmp)->chm_fs_qbmask) & (chmp)->chm_fs_bmask) 605 606 /* from ffs read */ 607 int 608 chfs_read(void *v) 609 { 610 struct vop_read_args /* { 611 struct vnode *a_vp; 612 struct uio *a_uio; 613 int a_ioflag; 614 kauth_cred_t a_cred; 615 } */ *ap = v; 616 struct vnode *vp; 617 struct chfs_inode *ip; 618 struct uio *uio; 619 struct ufsmount *ump; 620 struct buf *bp; 621 struct chfs_mount *chmp; 622 daddr_t lbn, nextlbn; 623 off_t bytesinfile; 624 long size, xfersize, blkoffset; 625 int error, ioflag; 626 vsize_t bytelen; 627 bool usepc = false; 628 629 dbg("chfs_read\n"); 630 631 vp = ap->a_vp; 632 ip = VTOI(vp); 633 ump = ip->ump; 634 uio = ap->a_uio; 635 ioflag = ap->a_ioflag; 636 error = 0; 637 638 dbg("ip->size:%llu\n", (unsigned long long)ip->size); 639 640 #ifdef DIAGNOSTIC 641 if (uio->uio_rw != UIO_READ) 642 panic("%s: mode", READ_S); 643 644 if (vp->v_type == VLNK) { 645 if (ip->size < ump->um_maxsymlinklen) 646 panic("%s: short symlink", READ_S); 647 } else if (vp->v_type != VREG && vp->v_type != VDIR) 648 panic("%s: type %d", READ_S, vp->v_type); 649 #endif 650 chmp = ip->chmp; 651 if ((u_int64_t)uio->uio_offset > ump->um_maxfilesize) 652 return (EFBIG); 653 if (uio->uio_resid == 0) 654 return (0); 655 656 fstrans_start(vp->v_mount, FSTRANS_SHARED); 657 658 if (uio->uio_offset >= ip->size) 659 goto out; 660 661 usepc = vp->v_type == VREG; 662 bytelen = 0; 663 if (usepc) { 664 const int advice = IO_ADV_DECODE(ap->a_ioflag); 665 666 while (uio->uio_resid > 0) { 667 if (ioflag & IO_DIRECT) { 668 genfs_directio(vp, uio, ioflag); 669 } 670 bytelen = MIN(ip->size - uio->uio_offset, 671 uio->uio_resid); 672 if (bytelen == 0) 673 break; 674 error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice, 675 UBC_READ | UBC_PARTIALOK | 676 (UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0)); 677 if (error) 678 break; 679 680 } 681 goto out; 682 } 683 684 dbg("start reading\n"); 685 for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { 686 bytesinfile = ip->size - uio->uio_offset; 687 if (bytesinfile <= 0) 688 break; 689 lbn = chfs_lblkno(chmp, uio->uio_offset); 690 nextlbn = lbn + 1; 691 size = chfs_blksize(chmp, ip, lbn); 692 blkoffset = chfs_blkoff(chmp, uio->uio_offset); 693 xfersize = MIN(MIN(chmp->chm_fs_bsize - blkoffset, uio->uio_resid), 694 bytesinfile); 695 696 if (chfs_lblktosize(chmp, nextlbn) >= ip->size) { 697 error = bread(vp, lbn, size, 0, &bp); 698 dbg("after bread\n"); 699 } else { 700 int nextsize = chfs_blksize(chmp, ip, nextlbn); 701 dbg("size: %ld\n", size); 702 error = breadn(vp, lbn, 703 size, &nextlbn, &nextsize, 1, 0, &bp); 704 dbg("after breadN\n"); 705 } 706 if (error) 707 break; 708 709 /* 710 * We should only get non-zero b_resid when an I/O error 711 * has occurred, which should cause us to break above. 712 * However, if the short read did not cause an error, 713 * then we want to ensure that we do not uiomove bad 714 * or uninitialized data. 715 */ 716 size -= bp->b_resid; 717 if (size < xfersize) { 718 if (size == 0) 719 break; 720 xfersize = size; 721 } 722 dbg("uiomove\n"); 723 error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio); 724 if (error) 725 break; 726 brelse(bp, 0); 727 } 728 729 if (bp != NULL) 730 brelse(bp, 0); 731 732 out: 733 // FIXME HACK 734 ip->ino = ip->chvc->vno; 735 736 if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) { 737 ip->iflag |= IN_ACCESS; 738 if ((ap->a_ioflag & IO_SYNC) == IO_SYNC) { 739 if (error) { 740 fstrans_done(vp->v_mount); 741 return error; 742 } 743 error = chfs_update(vp, NULL, NULL, UPDATE_WAIT); 744 } 745 } 746 747 dbg("[END]\n"); 748 fstrans_done(vp->v_mount); 749 750 return (error); 751 } 752 753 754 /* --------------------------------------------------------------------- */ 755 756 /* from ffs write */ 757 int 758 chfs_write(void *v) 759 { 760 struct vop_write_args /* { 761 struct vnode *a_vp; 762 struct uio *a_uio; 763 int a_ioflag; 764 kauth_cred_t a_cred; 765 } */ *ap = v; 766 struct vnode *vp ; 767 struct uio *uio; 768 struct chfs_inode *ip; 769 struct chfs_mount *chmp; 770 struct lwp *l; 771 kauth_cred_t cred; 772 off_t osize, origoff, oldoff, preallocoff, endallocoff, nsize; 773 int blkoffset, error, flags, ioflag, resid; 774 int aflag; 775 int extended=0; 776 vsize_t bytelen; 777 bool async; 778 struct ufsmount *ump; 779 780 781 cred = ap->a_cred; 782 ioflag = ap->a_ioflag; 783 uio = ap->a_uio; 784 vp = ap->a_vp; 785 ip = VTOI(vp); 786 ump = ip->ump; 787 788 dbg("write\n"); 789 790 KASSERT(vp->v_size == ip->size); 791 792 switch (vp->v_type) { 793 case VREG: 794 if (ioflag & IO_APPEND) 795 uio->uio_offset = ip->size; 796 if ((ip->flags & APPEND) && uio->uio_offset != ip->size) 797 return (EPERM); 798 /* FALLTHROUGH */ 799 case VLNK: 800 break; 801 case VDIR: 802 if ((ioflag & IO_SYNC) == 0) 803 panic("chfs_write: nonsync dir write"); 804 break; 805 default: 806 panic("chfs_write: type"); 807 } 808 809 chmp = ip->chmp; 810 if (uio->uio_offset < 0 || 811 (u_int64_t)uio->uio_offset + 812 uio->uio_resid > ump->um_maxfilesize) { 813 dbg("uio->uio_offset = %lld | uio->uio_offset + " 814 "uio->uio_resid (%llu) > ump->um_maxfilesize (%lld)\n", 815 (long long)uio->uio_offset, 816 (uint64_t)uio->uio_offset + uio->uio_resid, 817 (long long)ump->um_maxfilesize); 818 return (EFBIG); 819 } 820 /* 821 * Maybe this should be above the vnode op call, but so long as 822 * file servers have no limits, I don't think it matters. 823 */ 824 l = curlwp; 825 if (vp->v_type == VREG && l && 826 uio->uio_offset + uio->uio_resid > 827 l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 828 mutex_enter(proc_lock); 829 psignal(l->l_proc, SIGXFSZ); 830 mutex_exit(proc_lock); 831 return (EFBIG); 832 } 833 if (uio->uio_resid == 0) 834 return (0); 835 836 fstrans_start(vp->v_mount, FSTRANS_SHARED); 837 838 flags = ioflag & IO_SYNC ? B_SYNC : 0; 839 async = vp->v_mount->mnt_flag & MNT_ASYNC; 840 origoff = uio->uio_offset; 841 resid = uio->uio_resid; 842 osize = ip->size; 843 error = 0; 844 845 preallocoff = round_page(chfs_blkroundup(chmp, 846 MAX(osize, uio->uio_offset))); 847 aflag = ioflag & IO_SYNC ? B_SYNC : 0; 848 nsize = MAX(osize, uio->uio_offset + uio->uio_resid); 849 endallocoff = nsize - chfs_blkoff(chmp, nsize); 850 851 /* 852 * if we're increasing the file size, deal with expanding 853 * the fragment if there is one. 854 */ 855 856 if (nsize > osize && chfs_lblkno(chmp, osize) < UFS_NDADDR && 857 chfs_lblkno(chmp, osize) != chfs_lblkno(chmp, nsize) && 858 chfs_blkroundup(chmp, osize) != osize) { 859 off_t eob; 860 861 eob = chfs_blkroundup(chmp, osize); 862 uvm_vnp_setwritesize(vp, eob); 863 error = ufs_balloc_range(vp, osize, eob - osize, cred, aflag); 864 if (error) 865 goto out; 866 if (flags & B_SYNC) { 867 mutex_enter(vp->v_interlock); 868 VOP_PUTPAGES(vp, 869 trunc_page(osize & chmp->chm_fs_bmask), 870 round_page(eob), 871 PGO_CLEANIT | PGO_SYNCIO | PGO_JOURNALLOCKED); 872 } 873 } 874 875 while (uio->uio_resid > 0) { 876 int ubc_flags = UBC_WRITE; 877 bool overwrite; /* if we're overwrite a whole block */ 878 off_t newoff; 879 880 if (ioflag & IO_DIRECT) { 881 genfs_directio(vp, uio, ioflag | IO_JOURNALLOCKED); 882 } 883 884 oldoff = uio->uio_offset; 885 blkoffset = chfs_blkoff(chmp, uio->uio_offset); 886 bytelen = MIN(chmp->chm_fs_bsize - blkoffset, uio->uio_resid); 887 if (bytelen == 0) { 888 break; 889 } 890 891 /* 892 * if we're filling in a hole, allocate the blocks now and 893 * initialize the pages first. if we're extending the file, 894 * we can safely allocate blocks without initializing pages 895 * since the new blocks will be inaccessible until the write 896 * is complete. 897 */ 898 overwrite = uio->uio_offset >= preallocoff && 899 uio->uio_offset < endallocoff; 900 if (!overwrite && (vp->v_vflag & VV_MAPPED) == 0 && 901 chfs_blkoff(chmp, uio->uio_offset) == 0 && 902 (uio->uio_offset & PAGE_MASK) == 0) { 903 vsize_t len; 904 905 len = trunc_page(bytelen); 906 len -= chfs_blkoff(chmp, len); 907 if (len > 0) { 908 overwrite = true; 909 bytelen = len; 910 } 911 } 912 913 newoff = oldoff + bytelen; 914 if (vp->v_size < newoff) { 915 uvm_vnp_setwritesize(vp, newoff); 916 } 917 918 if (!overwrite) { 919 error = ufs_balloc_range(vp, uio->uio_offset, bytelen, 920 cred, aflag); 921 if (error) 922 break; 923 } else { 924 genfs_node_wrlock(vp); 925 error = GOP_ALLOC(vp, uio->uio_offset, bytelen, 926 aflag, cred); 927 genfs_node_unlock(vp); 928 if (error) 929 break; 930 ubc_flags |= UBC_FAULTBUSY; 931 } 932 933 /* 934 * copy the data. 935 */ 936 937 ubc_flags |= UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0; 938 error = ubc_uiomove(&vp->v_uobj, uio, bytelen, 939 IO_ADV_DECODE(ioflag), ubc_flags); 940 941 /* 942 * update UVM's notion of the size now that we've 943 * copied the data into the vnode's pages. 944 * 945 * we should update the size even when uiomove failed. 946 */ 947 948 if (vp->v_size < newoff) { 949 uvm_vnp_setsize(vp, newoff); 950 extended = 1; 951 } 952 953 if (error) 954 break; 955 956 /* 957 * flush what we just wrote if necessary. 958 * XXXUBC simplistic async flushing. 959 */ 960 961 if (!async && oldoff >> 16 != uio->uio_offset >> 16) { 962 mutex_enter(vp->v_interlock); 963 error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16, 964 (uio->uio_offset >> 16) << 16, 965 PGO_CLEANIT | PGO_JOURNALLOCKED); 966 if (error) 967 break; 968 } 969 } 970 out: 971 if (error == 0 && ioflag & IO_SYNC) { 972 mutex_enter(vp->v_interlock); 973 error = VOP_PUTPAGES(vp, 974 trunc_page(origoff & chmp->chm_fs_bmask), 975 round_page(chfs_blkroundup(chmp, uio->uio_offset)), 976 PGO_CLEANIT | PGO_SYNCIO | PGO_JOURNALLOCKED); 977 } 978 ip->iflag |= IN_CHANGE | IN_UPDATE; 979 if (resid > uio->uio_resid && ap->a_cred) { 980 if (ip->mode & ISUID) { 981 if (kauth_authorize_vnode(ap->a_cred, 982 KAUTH_VNODE_RETAIN_SUID, vp, NULL, EPERM) != 0) 983 ip->mode &= ~ISUID; 984 } 985 986 if (ip->mode & ISGID) { 987 if (kauth_authorize_vnode(ap->a_cred, 988 KAUTH_VNODE_RETAIN_SGID, vp, NULL, EPERM) != 0) 989 ip->mode &= ~ISGID; 990 } 991 } 992 if (resid > uio->uio_resid) 993 VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0)); 994 if (error) { 995 (void) UFS_TRUNCATE(vp, osize, ioflag & IO_SYNC, ap->a_cred); 996 uio->uio_offset -= resid - uio->uio_resid; 997 uio->uio_resid = resid; 998 } else if (resid > uio->uio_resid && (ioflag & IO_SYNC) == IO_SYNC) 999 error = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT); 1000 1001 //FIXME HACK 1002 chfs_set_vnode_size(vp, vp->v_size); 1003 1004 1005 KASSERT(vp->v_size == ip->size); 1006 fstrans_done(vp->v_mount); 1007 1008 mutex_enter(&chmp->chm_lock_mountfields); 1009 error = chfs_write_flash_vnode(chmp, ip, ALLOC_NORMAL); 1010 mutex_exit(&chmp->chm_lock_mountfields); 1011 1012 return (error); 1013 } 1014 1015 1016 /* --------------------------------------------------------------------- */ 1017 1018 int 1019 chfs_fsync(void *v) 1020 { 1021 struct vop_fsync_args /* { 1022 struct vnode *a_vp; 1023 kauth_cred_t a_cred; 1024 int a_flags; 1025 off_t offlo; 1026 off_t offhi; 1027 } */ *ap = v; 1028 struct vnode *vp = ap->a_vp; 1029 1030 if (ap->a_flags & FSYNC_CACHE) { 1031 return ENODEV; 1032 } 1033 vflushbuf(vp, ap->a_flags); 1034 1035 return 0; 1036 } 1037 1038 /* --------------------------------------------------------------------- */ 1039 1040 int 1041 chfs_remove(void *v) 1042 { 1043 struct vnode *dvp = ((struct vop_remove_args *) v)->a_dvp; 1044 struct vnode *vp = ((struct vop_remove_args *) v)->a_vp; 1045 struct componentname *cnp = (((struct vop_remove_args *) v)->a_cnp); 1046 dbg("remove\n"); 1047 1048 KASSERT(VOP_ISLOCKED(dvp)); 1049 KASSERT(VOP_ISLOCKED(vp)); 1050 1051 struct chfs_inode *ip = VTOI(vp); 1052 struct chfs_inode *parent = VTOI(dvp); 1053 int error = 0; 1054 1055 if (vp->v_type == VDIR || (ip->flags & (IMMUTABLE | APPEND)) || 1056 (parent->flags & APPEND)) { 1057 error = EPERM; 1058 goto out; 1059 } 1060 1061 KASSERT(ip->chvc->vno != ip->chvc->pvno); 1062 1063 error = chfs_do_unlink(ip, 1064 parent, cnp->cn_nameptr, cnp->cn_namelen); 1065 1066 out: 1067 vput(dvp); 1068 vput(vp); 1069 1070 return error; 1071 } 1072 1073 /* --------------------------------------------------------------------- */ 1074 1075 int 1076 chfs_link(void *v) 1077 { 1078 struct vnode *dvp = ((struct vop_link_v2_args *) v)->a_dvp; 1079 struct vnode *vp = ((struct vop_link_v2_args *) v)->a_vp; 1080 struct componentname *cnp = ((struct vop_link_v2_args *) v)->a_cnp; 1081 1082 struct chfs_inode *ip, *parent; 1083 int error = 0; 1084 1085 if (vp->v_type == VDIR) { 1086 VOP_ABORTOP(dvp, cnp); 1087 error = EISDIR; 1088 goto out; 1089 } 1090 if (dvp->v_mount != vp->v_mount) { 1091 VOP_ABORTOP(dvp, cnp); 1092 error = EXDEV; 1093 goto out; 1094 } 1095 if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) { 1096 VOP_ABORTOP(dvp, cnp); 1097 goto out; 1098 } 1099 1100 parent = VTOI(dvp); 1101 ip = VTOI(vp); 1102 1103 error = chfs_do_link(ip, 1104 parent, cnp->cn_nameptr, cnp->cn_namelen, ip->ch_type); 1105 1106 if (dvp != vp) 1107 VOP_UNLOCK(vp); 1108 out: 1109 return error; 1110 } 1111 1112 /* --------------------------------------------------------------------- */ 1113 1114 int 1115 chfs_rename(void *v) 1116 { 1117 struct vnode *fdvp = ((struct vop_rename_args *) v)->a_fdvp; 1118 struct vnode *fvp = ((struct vop_rename_args *) v)->a_fvp; 1119 struct componentname *fcnp = ((struct vop_rename_args *) v)->a_fcnp; 1120 struct vnode *tdvp = ((struct vop_rename_args *) v)->a_tdvp; 1121 struct vnode *tvp = ((struct vop_rename_args *) v)->a_tvp; 1122 struct componentname *tcnp = ((struct vop_rename_args *) v)->a_tcnp; 1123 1124 struct chfs_inode *oldparent, *old; 1125 struct chfs_inode *newparent; 1126 struct chfs_dirent *fd; 1127 struct chfs_inode *ip; 1128 int error = 0; 1129 dbg("rename\n"); 1130 1131 KASSERT(VOP_ISLOCKED(tdvp)); 1132 KASSERT(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 1133 1134 oldparent = VTOI(fdvp); 1135 old = VTOI(fvp); 1136 newparent = VTOI(tdvp); 1137 if (tvp) { 1138 dbg("tvp not null\n"); 1139 ip = VTOI(tvp); 1140 if (tvp->v_type == VDIR) { 1141 TAILQ_FOREACH(fd, &ip->dents, fds) { 1142 if (fd->vno) { 1143 error = ENOTEMPTY; 1144 goto out_unlocked; 1145 } 1146 } 1147 } 1148 error = chfs_do_unlink(ip, 1149 newparent, tcnp->cn_nameptr, tcnp->cn_namelen); 1150 vput(tvp); 1151 } 1152 VFS_VGET(tdvp->v_mount, old->ino, &tvp); 1153 ip = VTOI(tvp); 1154 1155 /* link new */ 1156 error = chfs_do_link(ip, 1157 newparent, tcnp->cn_nameptr, tcnp->cn_namelen, ip->ch_type); 1158 /* remove old */ 1159 error = chfs_do_unlink(old, 1160 oldparent, fcnp->cn_nameptr, fcnp->cn_namelen); 1161 1162 out_unlocked: 1163 /* Release target nodes. */ 1164 if (tdvp == tvp) 1165 vrele(tdvp); 1166 else 1167 vput(tdvp); 1168 if (tvp != NULL) 1169 vput(tvp); 1170 1171 /* Release source nodes. */ 1172 vrele(fdvp); 1173 vrele(fvp); 1174 1175 return error; 1176 } 1177 1178 /* --------------------------------------------------------------------- */ 1179 1180 int 1181 chfs_mkdir(void *v) 1182 { 1183 struct vnode *dvp = ((struct vop_mkdir_v3_args *) v)->a_dvp; 1184 struct vnode **vpp = ((struct vop_mkdir_v3_args *)v)->a_vpp; 1185 struct componentname *cnp = ((struct vop_mkdir_v3_args *) v)->a_cnp; 1186 struct vattr *vap = ((struct vop_mkdir_v3_args *) v)->a_vap; 1187 dbg("mkdir()\n"); 1188 1189 int mode; 1190 1191 mode = vap->va_mode & ACCESSPERMS; 1192 if ((mode & IFMT) == 0) { 1193 mode |= IFDIR; 1194 } 1195 1196 KASSERT(vap->va_type == VDIR); 1197 1198 return chfs_makeinode(mode, dvp, vpp, cnp, VDIR); 1199 } 1200 1201 /* --------------------------------------------------------------------- */ 1202 1203 int 1204 chfs_rmdir(void *v) 1205 { 1206 struct vnode *dvp = ((struct vop_rmdir_args *) v)->a_dvp; 1207 struct vnode *vp = ((struct vop_rmdir_args *) v)->a_vp; 1208 struct componentname *cnp = ((struct vop_rmdir_args *) v)->a_cnp; 1209 dbg("rmdir()\n"); 1210 1211 KASSERT(VOP_ISLOCKED(dvp)); 1212 KASSERT(VOP_ISLOCKED(vp)); 1213 1214 struct chfs_inode *ip = VTOI(vp); 1215 struct chfs_inode *parent = VTOI(dvp); 1216 struct chfs_dirent *fd; 1217 int error = 0; 1218 1219 if (vp->v_type != VDIR) { 1220 error = ENOTDIR; 1221 goto out; 1222 } 1223 1224 KASSERT(ip->chvc->vno != ip->chvc->pvno); 1225 1226 TAILQ_FOREACH(fd, &ip->dents, fds) { 1227 if (fd->vno) { 1228 error = ENOTEMPTY; 1229 goto out; 1230 } 1231 } 1232 1233 error = chfs_do_unlink(ip, 1234 parent, cnp->cn_nameptr, cnp->cn_namelen); 1235 1236 out: 1237 vput(dvp); 1238 vput(vp); 1239 1240 return error; 1241 } 1242 1243 /* --------------------------------------------------------------------- */ 1244 1245 int 1246 chfs_symlink(void *v) 1247 { 1248 struct vnode *dvp = ((struct vop_symlink_v3_args *) v)->a_dvp; 1249 struct vnode **vpp = ((struct vop_symlink_v3_args *) v)->a_vpp; 1250 struct componentname *cnp = ((struct vop_symlink_v3_args *) v)->a_cnp; 1251 struct vattr *vap = ((struct vop_symlink_v3_args *) v)->a_vap; 1252 char *target = ((struct vop_symlink_v3_args *) v)->a_target; 1253 1254 struct ufsmount *ump; 1255 struct chfs_mount *chmp; 1256 struct vnode *vp; 1257 struct chfs_inode *ip; 1258 int len, err; 1259 struct chfs_full_dnode *fd; 1260 struct buf *bp; 1261 dbg("symlink()\n"); 1262 1263 ump = VFSTOUFS(dvp->v_mount); 1264 chmp = ump->um_chfs; 1265 1266 err = chfs_makeinode(IFLNK | vap->va_mode, dvp, vpp, cnp, VLNK); 1267 if (err) 1268 return (err); 1269 VN_KNOTE(dvp, NOTE_WRITE); 1270 vp = *vpp; 1271 len = strlen(target); 1272 ip = VTOI(vp); 1273 /* TODO max symlink len instead of "100" */ 1274 if (len < 100) { 1275 /* symlink path stored as a data node */ 1276 ip->target = kmem_alloc(len, KM_SLEEP); 1277 memcpy(ip->target, target, len); 1278 chfs_set_vnode_size(vp, len); 1279 ip->iflag |= IN_CHANGE | IN_UPDATE; 1280 1281 bp = getiobuf(vp, true); 1282 bp->b_bufsize = bp->b_resid = len; 1283 bp->b_data = kmem_alloc(len, KM_SLEEP); 1284 memcpy(bp->b_data, target, len); 1285 bp->b_blkno = 0; 1286 1287 fd = chfs_alloc_full_dnode(); 1288 1289 mutex_enter(&chmp->chm_lock_mountfields); 1290 1291 /* write out the data node */ 1292 err = chfs_write_flash_dnode(chmp, vp, bp, fd); 1293 if (err) { 1294 mutex_exit(&chmp->chm_lock_mountfields); 1295 goto out; 1296 } 1297 1298 /* add it to the inode */ 1299 err = chfs_add_full_dnode_to_inode(chmp, ip, fd); 1300 if (err) { 1301 mutex_exit(&chmp->chm_lock_mountfields); 1302 goto out; 1303 } 1304 1305 mutex_exit(&chmp->chm_lock_mountfields); 1306 1307 kmem_free(bp->b_data, len); 1308 putiobuf(bp); 1309 1310 uvm_vnp_setsize(vp, len); 1311 } else { 1312 err = ufs_bufio(UIO_WRITE, vp, target, len, (off_t)0, 1313 IO_NODELOCKED, cnp->cn_cred, (size_t *)0, NULL); 1314 } 1315 1316 out: 1317 if (err) 1318 vrele(vp); 1319 1320 return (err); 1321 } 1322 1323 /* --------------------------------------------------------------------- */ 1324 1325 int 1326 chfs_readdir(void *v) 1327 { 1328 struct vnode *vp = ((struct vop_readdir_args *) v)->a_vp; 1329 struct uio *uio = ((struct vop_readdir_args *) v)->a_uio; 1330 int *eofflag = ((struct vop_readdir_args *) v)->a_eofflag; 1331 1332 int error = 0; 1333 off_t skip, offset; 1334 struct chfs_inode *ip; 1335 struct chfs_dirent *fd; 1336 1337 struct ufsmount *ump; 1338 struct chfs_mount *chmp; 1339 struct chfs_vnode_cache *chvc; 1340 1341 KASSERT(VOP_ISLOCKED(vp)); 1342 1343 /* This operation only makes sense on directory nodes. */ 1344 if (vp->v_type != VDIR) { 1345 error = ENOTDIR; 1346 goto out; 1347 } 1348 1349 ip = VTOI(vp); 1350 1351 /* uiomove in chfs_filldir automatically increments the 1352 * uio_offset by an arbitrary size, so we discard any change 1353 * to uio_offset and set it to our own value on return 1354 */ 1355 offset = uio->uio_offset; 1356 1357 /* Add this entry. */ 1358 if (offset == CHFS_OFFSET_DOT) { 1359 error = chfs_filldir(uio, ip->ino, ".", 1, CHT_DIR); 1360 if (error == -1) { 1361 error = 0; 1362 goto outok; 1363 } else if (error != 0) 1364 goto outok; 1365 1366 offset = CHFS_OFFSET_DOTDOT; 1367 } 1368 1369 /* Add parent entry. */ 1370 if (offset == CHFS_OFFSET_DOTDOT) { 1371 ump = VFSTOUFS(vp->v_mount); 1372 chmp = ump->um_chfs; 1373 mutex_enter(&chmp->chm_lock_vnocache); 1374 chvc = chfs_vnode_cache_get(chmp, ip->ino); 1375 mutex_exit(&chmp->chm_lock_vnocache); 1376 1377 error = chfs_filldir(uio, chvc->pvno, "..", 2, CHT_DIR); 1378 if (error == -1) { 1379 error = 0; 1380 goto outok; 1381 } else if (error != 0) { 1382 goto outok; 1383 } 1384 1385 /* Has child or not? */ 1386 if (TAILQ_EMPTY(&ip->dents)) { 1387 offset = CHFS_OFFSET_EOF; 1388 } else { 1389 offset = CHFS_OFFSET_FIRST; 1390 } 1391 } 1392 1393 if (offset != CHFS_OFFSET_EOF) { 1394 /* Child entries. */ 1395 skip = offset - CHFS_OFFSET_FIRST; 1396 1397 TAILQ_FOREACH(fd, &ip->dents, fds) { 1398 /* seek to offset by skipping items */ 1399 /* XXX race conditions by changed dirent? */ 1400 if (skip > 0) { 1401 skip--; 1402 continue; 1403 } 1404 1405 if (fd->vno != 0) { 1406 error = chfs_filldir(uio, fd->vno, 1407 fd->name, fd->nsize, fd->type); 1408 if (error == -1) { 1409 error = 0; 1410 goto outok; 1411 } else if (error != 0) { 1412 dbg("err %d\n", error); 1413 goto outok; 1414 } 1415 } 1416 offset++; 1417 } 1418 } 1419 offset = CHFS_OFFSET_EOF; 1420 1421 outok: 1422 uio->uio_offset = offset; 1423 1424 if (eofflag != NULL) { 1425 *eofflag = (error == 0 && 1426 uio->uio_offset == CHFS_OFFSET_EOF); 1427 } 1428 1429 out: 1430 KASSERT(VOP_ISLOCKED(vp)); 1431 1432 return error; 1433 } 1434 1435 /* --------------------------------------------------------------------- */ 1436 1437 int 1438 chfs_readlink(void *v) 1439 { 1440 1441 struct vnode *vp = ((struct vop_readlink_args *) v)->a_vp; 1442 struct uio *uio = ((struct vop_readlink_args *) v)->a_uio; 1443 kauth_cred_t cred = ((struct vop_readlink_args *) v)->a_cred; 1444 1445 struct chfs_inode *ip = VTOI(vp); 1446 1447 dbg("readlink()\n"); 1448 1449 /* TODO max symlink len instead of "100" */ 1450 if (ip->size < 100) { 1451 uiomove(ip->target, ip->size, uio); 1452 return (0); 1453 } 1454 1455 return (UFS_BUFRD(vp, uio, 0, cred)); 1456 } 1457 1458 /* --------------------------------------------------------------------- */ 1459 1460 int 1461 chfs_inactive(void *v) 1462 { 1463 struct vnode *vp = ((struct vop_inactive_args *) v)->a_vp; 1464 struct chfs_inode *ip = VTOI(vp); 1465 struct chfs_vnode_cache *chvc; 1466 dbg("inactive | vno: %llu\n", (unsigned long long)ip->ino); 1467 1468 KASSERT(VOP_ISLOCKED(vp)); 1469 1470 /* Reclaim only if there is no link to the node. */ 1471 if (ip->ino) { 1472 chvc = ip->chvc; 1473 if (chvc->nlink) 1474 *((struct vop_inactive_args *) v)->a_recycle = 0; 1475 } else { 1476 *((struct vop_inactive_args *) v)->a_recycle = 1; 1477 } 1478 1479 VOP_UNLOCK(vp); 1480 1481 return 0; 1482 } 1483 1484 /* --------------------------------------------------------------------- */ 1485 1486 int 1487 chfs_reclaim(void *v) 1488 { 1489 struct vop_reclaim_args *ap = v; 1490 struct vnode *vp = ap->a_vp; 1491 struct chfs_inode *ip = VTOI(vp); 1492 struct chfs_mount *chmp = ip->chmp; 1493 struct chfs_dirent *fd; 1494 1495 mutex_enter(&chmp->chm_lock_mountfields); 1496 1497 mutex_enter(&chmp->chm_lock_vnocache); 1498 ip->chvc->state = VNO_STATE_CHECKEDABSENT; 1499 mutex_exit(&chmp->chm_lock_vnocache); 1500 1501 chfs_update(vp, NULL, NULL, UPDATE_CLOSE); 1502 1503 /* Clean fragments. */ 1504 chfs_kill_fragtree(chmp, &ip->fragtree); 1505 1506 /* Clean dirents. */ 1507 fd = TAILQ_FIRST(&ip->dents); 1508 while (fd) { 1509 TAILQ_REMOVE(&ip->dents, fd, fds); 1510 chfs_free_dirent(fd); 1511 fd = TAILQ_FIRST(&ip->dents); 1512 } 1513 1514 cache_purge(vp); 1515 if (ip->devvp) { 1516 vrele(ip->devvp); 1517 ip->devvp = 0; 1518 } 1519 1520 genfs_node_destroy(vp); 1521 pool_put(&chfs_inode_pool, vp->v_data); 1522 vp->v_data = NULL; 1523 1524 mutex_exit(&chmp->chm_lock_mountfields); 1525 1526 return (0); 1527 } 1528 1529 /* --------------------------------------------------------------------- */ 1530 1531 int 1532 chfs_advlock(void *v) 1533 { 1534 return 0; 1535 } 1536 1537 /* --------------------------------------------------------------------- */ 1538 int 1539 chfs_strategy(void *v) 1540 { 1541 struct vop_strategy_args /* { 1542 const struct vnodeop_desc *a_desc; 1543 struct vnode *a_vp; 1544 struct buf *a_bp; 1545 } */ *ap = v; 1546 struct chfs_full_dnode *fd; 1547 struct buf *bp = ap->a_bp; 1548 struct vnode *vp = ap->a_vp; 1549 struct chfs_inode *ip = VTOI(vp); 1550 struct chfs_mount *chmp = ip->chmp; 1551 int read = (bp->b_flags & B_READ) ? 1 : 0; 1552 int err = 0; 1553 1554 if (read) { 1555 err = chfs_read_data(chmp, vp, bp); 1556 } else { 1557 mutex_enter(&chmp->chm_lock_mountfields); 1558 1559 fd = chfs_alloc_full_dnode(); 1560 1561 err = chfs_write_flash_dnode(chmp, vp, bp, fd); 1562 if (err) { 1563 mutex_exit(&chmp->chm_lock_mountfields); 1564 goto out; 1565 } 1566 1567 ip = VTOI(vp); 1568 err = chfs_add_full_dnode_to_inode(chmp, ip, fd); 1569 1570 mutex_exit(&chmp->chm_lock_mountfields); 1571 } 1572 out: 1573 biodone(bp); 1574 return err; 1575 } 1576 1577 int 1578 chfs_bmap(void *v) 1579 { 1580 struct vop_bmap_args /* { 1581 struct vnode *a_vp; 1582 daddr_t a_bn; 1583 struct vnode **a_vpp; 1584 daddr_t *a_bnp; 1585 int *a_runp; 1586 int *a_runb; 1587 } */ *ap = v; 1588 if (ap->a_vpp != NULL) 1589 *ap->a_vpp = ap->a_vp; 1590 if (ap->a_bnp != NULL) 1591 *ap->a_bnp = ap->a_bn; 1592 if (ap->a_runp != NULL) 1593 *ap->a_runp = 0; 1594 return (0); 1595 } 1596 1597 /* 1598 * vnode operations vector used for files stored in a chfs file system. 1599 */ 1600 int 1601 (**chfs_vnodeop_p)(void *); 1602 const struct vnodeopv_entry_desc chfs_vnodeop_entries[] = 1603 { 1604 { &vop_default_desc, vn_default_error }, 1605 { &vop_lookup_desc, chfs_lookup }, 1606 { &vop_create_desc, chfs_create }, 1607 { &vop_mknod_desc, chfs_mknod }, 1608 { &vop_open_desc, chfs_open }, 1609 { &vop_close_desc, chfs_close }, 1610 { &vop_access_desc, chfs_access }, 1611 { &vop_getattr_desc, chfs_getattr }, 1612 { &vop_setattr_desc, chfs_setattr }, 1613 { &vop_read_desc, chfs_read }, 1614 { &vop_write_desc, chfs_write }, 1615 { &vop_fallocate_desc, genfs_eopnotsupp }, 1616 { &vop_fdiscard_desc, genfs_eopnotsupp }, 1617 { &vop_ioctl_desc, genfs_enoioctl }, 1618 { &vop_fcntl_desc, genfs_fcntl }, 1619 { &vop_poll_desc, genfs_poll }, 1620 { &vop_kqfilter_desc, genfs_kqfilter }, 1621 { &vop_revoke_desc, genfs_revoke }, 1622 { &vop_mmap_desc, genfs_mmap }, 1623 { &vop_fsync_desc, chfs_fsync }, 1624 { &vop_seek_desc, genfs_seek }, 1625 { &vop_remove_desc, chfs_remove }, 1626 { &vop_link_desc, chfs_link }, 1627 { &vop_rename_desc, chfs_rename }, 1628 { &vop_mkdir_desc, chfs_mkdir }, 1629 { &vop_rmdir_desc, chfs_rmdir }, 1630 { &vop_symlink_desc, chfs_symlink }, 1631 { &vop_readdir_desc, chfs_readdir }, 1632 { &vop_readlink_desc, chfs_readlink }, 1633 { &vop_abortop_desc, genfs_abortop }, 1634 { &vop_inactive_desc, chfs_inactive }, 1635 { &vop_reclaim_desc, chfs_reclaim }, 1636 { &vop_lock_desc, genfs_lock }, 1637 { &vop_unlock_desc, genfs_unlock }, 1638 { &vop_bmap_desc, chfs_bmap }, 1639 { &vop_strategy_desc, chfs_strategy }, 1640 { &vop_print_desc, ufs_print }, 1641 { &vop_pathconf_desc, ufs_pathconf }, 1642 { &vop_islocked_desc, genfs_islocked }, 1643 { &vop_advlock_desc, chfs_advlock }, 1644 { &vop_bwrite_desc, vn_bwrite }, 1645 { &vop_getpages_desc, genfs_getpages }, 1646 { &vop_putpages_desc, genfs_putpages }, 1647 { NULL, NULL } }; 1648 1649 const struct vnodeopv_desc chfs_vnodeop_opv_desc = 1650 { &chfs_vnodeop_p, chfs_vnodeop_entries }; 1651 1652 /* --------------------------------------------------------------------- */ 1653 1654 /* 1655 * vnode operations vector used for special devices stored in a chfs 1656 * file system. 1657 */ 1658 int 1659 (**chfs_specop_p)(void *); 1660 const struct vnodeopv_entry_desc chfs_specop_entries[] = 1661 { 1662 { &vop_default_desc, vn_default_error }, 1663 { &vop_lookup_desc, spec_lookup }, 1664 { &vop_create_desc, spec_create }, 1665 { &vop_mknod_desc, spec_mknod }, 1666 { &vop_open_desc, spec_open }, 1667 { &vop_close_desc, ufsspec_close }, 1668 { &vop_access_desc, chfs_access }, 1669 { &vop_getattr_desc, chfs_getattr }, 1670 { &vop_setattr_desc, chfs_setattr }, 1671 { &vop_read_desc, chfs_read }, 1672 { &vop_write_desc, chfs_write }, 1673 { &vop_fallocate_desc, spec_fallocate }, 1674 { &vop_fdiscard_desc, spec_fdiscard }, 1675 { &vop_ioctl_desc, spec_ioctl }, 1676 { &vop_fcntl_desc, genfs_fcntl }, 1677 { &vop_poll_desc, spec_poll }, 1678 { &vop_kqfilter_desc, spec_kqfilter }, 1679 { &vop_revoke_desc, spec_revoke }, 1680 { &vop_mmap_desc, spec_mmap }, 1681 { &vop_fsync_desc, spec_fsync }, 1682 { &vop_seek_desc, spec_seek }, 1683 { &vop_remove_desc, spec_remove }, 1684 { &vop_link_desc, spec_link }, 1685 { &vop_rename_desc, spec_rename }, 1686 { &vop_mkdir_desc, spec_mkdir }, 1687 { &vop_rmdir_desc, spec_rmdir }, 1688 { &vop_symlink_desc, spec_symlink }, 1689 { &vop_readdir_desc, spec_readdir }, 1690 { &vop_readlink_desc, spec_readlink }, 1691 { &vop_abortop_desc, spec_abortop }, 1692 { &vop_inactive_desc, chfs_inactive }, 1693 { &vop_reclaim_desc, chfs_reclaim }, 1694 { &vop_lock_desc, genfs_lock }, 1695 { &vop_unlock_desc, genfs_unlock }, 1696 { &vop_bmap_desc, spec_bmap }, 1697 { &vop_strategy_desc, spec_strategy }, 1698 { &vop_print_desc, ufs_print }, 1699 { &vop_pathconf_desc, spec_pathconf }, 1700 { &vop_islocked_desc, genfs_islocked }, 1701 { &vop_advlock_desc, spec_advlock }, 1702 { &vop_bwrite_desc, vn_bwrite }, 1703 { &vop_getpages_desc, spec_getpages }, 1704 { &vop_putpages_desc, spec_putpages }, 1705 { NULL, NULL } }; 1706 1707 const struct vnodeopv_desc chfs_specop_opv_desc = 1708 { &chfs_specop_p, chfs_specop_entries }; 1709 1710 /* --------------------------------------------------------------------- */ 1711 /* 1712 * vnode operations vector used for fifos stored in a chfs file system. 1713 */ 1714 int 1715 (**chfs_fifoop_p)(void *); 1716 const struct vnodeopv_entry_desc chfs_fifoop_entries[] = 1717 { 1718 { &vop_default_desc, vn_default_error }, 1719 { &vop_lookup_desc, vn_fifo_bypass }, 1720 { &vop_create_desc, vn_fifo_bypass }, 1721 { &vop_mknod_desc, vn_fifo_bypass }, 1722 { &vop_open_desc, vn_fifo_bypass }, 1723 { &vop_close_desc, ufsfifo_close }, 1724 { &vop_access_desc, chfs_access }, 1725 { &vop_getattr_desc, chfs_getattr }, 1726 { &vop_setattr_desc, chfs_setattr }, 1727 { &vop_read_desc, ufsfifo_read }, 1728 { &vop_write_desc, ufsfifo_write }, 1729 { &vop_fallocate_desc, vn_fifo_bypass }, 1730 { &vop_fdiscard_desc, vn_fifo_bypass }, 1731 { &vop_ioctl_desc, vn_fifo_bypass }, 1732 { &vop_fcntl_desc, genfs_fcntl }, 1733 { &vop_poll_desc, vn_fifo_bypass }, 1734 { &vop_kqfilter_desc, vn_fifo_bypass }, 1735 { &vop_revoke_desc, vn_fifo_bypass }, 1736 { &vop_mmap_desc, vn_fifo_bypass }, 1737 { &vop_fsync_desc, vn_fifo_bypass }, 1738 { &vop_seek_desc, vn_fifo_bypass }, 1739 { &vop_remove_desc, vn_fifo_bypass }, 1740 { &vop_link_desc, vn_fifo_bypass }, 1741 { &vop_rename_desc, vn_fifo_bypass }, 1742 { &vop_mkdir_desc, vn_fifo_bypass }, 1743 { &vop_rmdir_desc, vn_fifo_bypass }, 1744 { &vop_symlink_desc, vn_fifo_bypass }, 1745 { &vop_readdir_desc, vn_fifo_bypass }, 1746 { &vop_readlink_desc, vn_fifo_bypass }, 1747 { &vop_abortop_desc, vn_fifo_bypass }, 1748 { &vop_inactive_desc, chfs_inactive }, 1749 { &vop_reclaim_desc, chfs_reclaim }, 1750 { &vop_lock_desc, genfs_lock }, 1751 { &vop_unlock_desc, genfs_unlock }, 1752 { &vop_bmap_desc, vn_fifo_bypass }, 1753 { &vop_strategy_desc, vn_fifo_bypass }, 1754 { &vop_print_desc, ufs_print }, 1755 { &vop_pathconf_desc, vn_fifo_bypass }, 1756 { &vop_islocked_desc, genfs_islocked }, 1757 { &vop_advlock_desc, vn_fifo_bypass }, 1758 { &vop_bwrite_desc, genfs_nullop }, 1759 { &vop_getpages_desc, genfs_badop }, 1760 { &vop_putpages_desc, vn_fifo_bypass }, 1761 { NULL, NULL } }; 1762 1763 const struct vnodeopv_desc chfs_fifoop_opv_desc = 1764 { &chfs_fifoop_p, chfs_fifoop_entries }; 1765