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