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