1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Vnode operations for the High Sierra filesystem 30 */ 31 32 #include <sys/types.h> 33 #include <sys/t_lock.h> 34 #include <sys/param.h> 35 #include <sys/time.h> 36 #include <sys/systm.h> 37 #include <sys/sysmacros.h> 38 #include <sys/resource.h> 39 #include <sys/signal.h> 40 #include <sys/cred.h> 41 #include <sys/user.h> 42 #include <sys/buf.h> 43 #include <sys/vfs.h> 44 #include <sys/vfs_opreg.h> 45 #include <sys/stat.h> 46 #include <sys/vnode.h> 47 #include <sys/mode.h> 48 #include <sys/proc.h> 49 #include <sys/disp.h> 50 #include <sys/file.h> 51 #include <sys/fcntl.h> 52 #include <sys/flock.h> 53 #include <sys/kmem.h> 54 #include <sys/uio.h> 55 #include <sys/conf.h> 56 #include <sys/errno.h> 57 #include <sys/mman.h> 58 #include <sys/pathname.h> 59 #include <sys/debug.h> 60 #include <sys/vmsystm.h> 61 #include <sys/cmn_err.h> 62 #include <sys/fbuf.h> 63 #include <sys/dirent.h> 64 #include <sys/errno.h> 65 66 #include <vm/hat.h> 67 #include <vm/page.h> 68 #include <vm/pvn.h> 69 #include <vm/as.h> 70 #include <vm/seg.h> 71 #include <vm/seg_map.h> 72 #include <vm/seg_kmem.h> 73 #include <vm/seg_vn.h> 74 #include <vm/rm.h> 75 #include <vm/page.h> 76 #include <sys/swap.h> 77 78 #include <sys/fs/hsfs_spec.h> 79 #include <sys/fs/hsfs_node.h> 80 #include <sys/fs/hsfs_impl.h> 81 #include <sys/fs/hsfs_susp.h> 82 #include <sys/fs/hsfs_rrip.h> 83 84 #include <fs/fs_subr.h> 85 86 /* ARGSUSED */ 87 static int 88 hsfs_fsync(vnode_t *cp, int syncflag, cred_t *cred) 89 { 90 return (0); 91 } 92 93 94 /*ARGSUSED*/ 95 static int 96 hsfs_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *cred, 97 struct caller_context *ct) 98 { 99 caddr_t base; 100 offset_t diff; 101 int error; 102 struct hsnode *hp; 103 uint_t filesize; 104 105 hp = VTOH(vp); 106 /* 107 * if vp is of type VDIR, make sure dirent 108 * is filled up with all info (because of ptbl) 109 */ 110 if (vp->v_type == VDIR) { 111 if (hp->hs_dirent.ext_size == 0) 112 hs_filldirent(vp, &hp->hs_dirent); 113 } 114 filesize = hp->hs_dirent.ext_size; 115 116 /* Sanity checks. */ 117 if (uiop->uio_resid == 0 || /* No data wanted. */ 118 uiop->uio_loffset > HS_MAXFILEOFF || /* Offset too big. */ 119 uiop->uio_loffset >= filesize) /* Past EOF. */ 120 return (0); 121 122 do { 123 /* 124 * We want to ask for only the "right" amount of data. 125 * In this case that means:- 126 * 127 * We can't get data from beyond our EOF. If asked, 128 * we will give a short read. 129 * 130 * segmap_getmapflt returns buffers of MAXBSIZE bytes. 131 * These buffers are always MAXBSIZE aligned. 132 * If our starting offset is not MAXBSIZE aligned, 133 * we can only ask for less than MAXBSIZE bytes. 134 * 135 * If our requested offset and length are such that 136 * they belong in different MAXBSIZE aligned slots 137 * then we'll be making more than one call on 138 * segmap_getmapflt. 139 * 140 * This diagram shows the variables we use and their 141 * relationships. 142 * 143 * |<-----MAXBSIZE----->| 144 * +--------------------------...+ 145 * |.....mapon->|<--n-->|....*...|EOF 146 * +--------------------------...+ 147 * uio_loffset->| 148 * uio_resid....|<---------->| 149 * diff.........|<-------------->| 150 * 151 * So, in this case our offset is not aligned 152 * and our request takes us outside of the 153 * MAXBSIZE window. We will break this up into 154 * two segmap_getmapflt calls. 155 */ 156 size_t nbytes; 157 offset_t mapon; 158 size_t n; 159 uint_t flags; 160 161 mapon = uiop->uio_loffset & MAXBOFFSET; 162 diff = filesize - uiop->uio_loffset; 163 nbytes = (size_t)MIN(MAXBSIZE - mapon, uiop->uio_resid); 164 n = MIN(diff, nbytes); 165 if (n <= 0) { 166 /* EOF or request satisfied. */ 167 return (0); 168 } 169 170 base = segmap_getmapflt(segkmap, vp, 171 (u_offset_t)uiop->uio_loffset, n, 1, S_READ); 172 173 error = uiomove(base + mapon, n, UIO_READ, uiop); 174 175 if (error == 0) { 176 /* 177 * if read a whole block, or read to eof, 178 * won't need this buffer again soon. 179 */ 180 if (n + mapon == MAXBSIZE || 181 uiop->uio_loffset == filesize) 182 flags = SM_DONTNEED; 183 else 184 flags = 0; 185 error = segmap_release(segkmap, base, flags); 186 } else 187 (void) segmap_release(segkmap, base, 0); 188 } while (error == 0 && uiop->uio_resid > 0); 189 190 return (error); 191 } 192 193 /*ARGSUSED2*/ 194 static int 195 hsfs_getattr( 196 struct vnode *vp, 197 struct vattr *vap, 198 int flags, 199 struct cred *cred) 200 { 201 struct hsnode *hp; 202 struct vfs *vfsp; 203 struct hsfs *fsp; 204 205 hp = VTOH(vp); 206 fsp = VFS_TO_HSFS(vp->v_vfsp); 207 vfsp = vp->v_vfsp; 208 209 if ((hp->hs_dirent.ext_size == 0) && (vp->v_type == VDIR)) { 210 hs_filldirent(vp, &hp->hs_dirent); 211 } 212 vap->va_type = IFTOVT(hp->hs_dirent.mode); 213 vap->va_mode = hp->hs_dirent.mode; 214 vap->va_uid = hp->hs_dirent.uid; 215 vap->va_gid = hp->hs_dirent.gid; 216 217 vap->va_fsid = vfsp->vfs_dev; 218 vap->va_nodeid = (ino64_t)hp->hs_nodeid; 219 vap->va_nlink = hp->hs_dirent.nlink; 220 vap->va_size = (offset_t)hp->hs_dirent.ext_size; 221 222 vap->va_atime.tv_sec = hp->hs_dirent.adate.tv_sec; 223 vap->va_atime.tv_nsec = hp->hs_dirent.adate.tv_usec*1000; 224 vap->va_mtime.tv_sec = hp->hs_dirent.mdate.tv_sec; 225 vap->va_mtime.tv_nsec = hp->hs_dirent.mdate.tv_usec*1000; 226 vap->va_ctime.tv_sec = hp->hs_dirent.cdate.tv_sec; 227 vap->va_ctime.tv_nsec = hp->hs_dirent.cdate.tv_usec*1000; 228 if (vp->v_type == VCHR || vp->v_type == VBLK) 229 vap->va_rdev = hp->hs_dirent.r_dev; 230 else 231 vap->va_rdev = 0; 232 vap->va_blksize = vfsp->vfs_bsize; 233 /* no. of blocks = no. of data blocks + no. of xar blocks */ 234 vap->va_nblocks = (fsblkcnt64_t)howmany(vap->va_size + (u_longlong_t) 235 (hp->hs_dirent.xar_len << fsp->hsfs_vol.lbn_shift), DEV_BSIZE); 236 vap->va_seq = hp->hs_seq; 237 return (0); 238 } 239 240 /*ARGSUSED*/ 241 static int 242 hsfs_readlink(struct vnode *vp, struct uio *uiop, struct cred *cred) 243 { 244 struct hsnode *hp; 245 246 if (vp->v_type != VLNK) 247 return (EINVAL); 248 249 hp = VTOH(vp); 250 251 if (hp->hs_dirent.sym_link == (char *)NULL) 252 return (ENOENT); 253 254 return (uiomove(hp->hs_dirent.sym_link, 255 (size_t)MIN(hp->hs_dirent.ext_size, 256 uiop->uio_resid), UIO_READ, uiop)); 257 } 258 259 /*ARGSUSED*/ 260 static void 261 hsfs_inactive(struct vnode *vp, struct cred *cred) 262 { 263 struct hsnode *hp; 264 struct hsfs *fsp; 265 266 int nopage; 267 268 hp = VTOH(vp); 269 fsp = VFS_TO_HSFS(vp->v_vfsp); 270 /* 271 * Note: acquiring and holding v_lock for quite a while 272 * here serializes on the vnode; this is unfortunate, but 273 * likely not to overly impact performance, as the underlying 274 * device (CDROM drive) is quite slow. 275 */ 276 rw_enter(&fsp->hsfs_hash_lock, RW_WRITER); 277 mutex_enter(&hp->hs_contents_lock); 278 mutex_enter(&vp->v_lock); 279 280 if (vp->v_count < 1) { 281 panic("hsfs_inactive: v_count < 1"); 282 /*NOTREACHED*/ 283 } 284 285 if (vp->v_count > 1 || (hp->hs_flags & HREF) == 0) { 286 vp->v_count--; /* release hold from vn_rele */ 287 mutex_exit(&vp->v_lock); 288 mutex_exit(&hp->hs_contents_lock); 289 rw_exit(&fsp->hsfs_hash_lock); 290 return; 291 } 292 vp->v_count--; /* release hold from vn_rele */ 293 if (vp->v_count == 0) { 294 /* 295 * Free the hsnode. 296 * If there are no pages associated with the 297 * hsnode, give it back to the kmem_cache, 298 * else put at the end of this file system's 299 * internal free list. 300 */ 301 nopage = !vn_has_cached_data(vp); 302 hp->hs_flags = 0; 303 /* 304 * exit these locks now, since hs_freenode may 305 * kmem_free the hsnode and embedded vnode 306 */ 307 mutex_exit(&vp->v_lock); 308 mutex_exit(&hp->hs_contents_lock); 309 hs_freenode(vp, fsp, nopage); 310 } else { 311 mutex_exit(&vp->v_lock); 312 mutex_exit(&hp->hs_contents_lock); 313 } 314 rw_exit(&fsp->hsfs_hash_lock); 315 } 316 317 318 /*ARGSUSED*/ 319 static int 320 hsfs_lookup( 321 struct vnode *dvp, 322 char *nm, 323 struct vnode **vpp, 324 struct pathname *pnp, 325 int flags, 326 struct vnode *rdir, 327 struct cred *cred) 328 { 329 int error; 330 int namelen = (int)strlen(nm); 331 332 if (*nm == '\0') { 333 VN_HOLD(dvp); 334 *vpp = dvp; 335 return (0); 336 } 337 338 /* 339 * If we're looking for ourself, life is simple. 340 */ 341 if (namelen == 1 && *nm == '.') { 342 if (error = hs_access(dvp, (mode_t)VEXEC, cred)) 343 return (error); 344 VN_HOLD(dvp); 345 *vpp = dvp; 346 return (0); 347 } 348 349 return (hs_dirlook(dvp, nm, namelen, vpp, cred)); 350 } 351 352 353 /*ARGSUSED*/ 354 static int 355 hsfs_readdir( 356 struct vnode *vp, 357 struct uio *uiop, 358 struct cred *cred, 359 int *eofp) 360 { 361 struct hsnode *dhp; 362 struct hsfs *fsp; 363 struct hs_direntry hd; 364 struct dirent64 *nd; 365 int error; 366 uint_t offset; /* real offset in directory */ 367 uint_t dirsiz; /* real size of directory */ 368 uchar_t *blkp; 369 int hdlen; /* length of hs directory entry */ 370 long ndlen; /* length of dirent entry */ 371 int bytes_wanted; 372 size_t bufsize; /* size of dirent buffer */ 373 char *outbuf; /* ptr to dirent buffer */ 374 char *dname; 375 int dnamelen; 376 size_t dname_size; 377 struct fbuf *fbp; 378 uint_t last_offset; /* last index into current dir block */ 379 ulong_t dir_lbn; /* lbn of directory */ 380 ino64_t dirino; /* temporary storage before storing in dirent */ 381 off_t diroff; 382 383 dhp = VTOH(vp); 384 fsp = VFS_TO_HSFS(vp->v_vfsp); 385 if (dhp->hs_dirent.ext_size == 0) 386 hs_filldirent(vp, &dhp->hs_dirent); 387 dirsiz = dhp->hs_dirent.ext_size; 388 dir_lbn = dhp->hs_dirent.ext_lbn; 389 if (uiop->uio_loffset >= dirsiz) { /* at or beyond EOF */ 390 if (eofp) 391 *eofp = 1; 392 return (0); 393 } 394 ASSERT(uiop->uio_loffset <= HS_MAXFILEOFF); 395 offset = uiop->uio_loffset; 396 397 dname_size = fsp->hsfs_namemax + 1; /* 1 for the ending NUL */ 398 dname = kmem_alloc(dname_size, KM_SLEEP); 399 bufsize = uiop->uio_resid + sizeof (struct dirent64); 400 401 outbuf = kmem_alloc(bufsize, KM_SLEEP); 402 nd = (struct dirent64 *)outbuf; 403 404 while (offset < dirsiz) { 405 bytes_wanted = MIN(MAXBSIZE, dirsiz - (offset & MAXBMASK)); 406 407 error = fbread(vp, (offset_t)(offset & MAXBMASK), 408 (unsigned int)bytes_wanted, S_READ, &fbp); 409 if (error) 410 goto done; 411 412 blkp = (uchar_t *)fbp->fb_addr; 413 last_offset = (offset & MAXBMASK) + fbp->fb_count; 414 415 #define rel_offset(offset) ((offset) & MAXBOFFSET) /* index into blkp */ 416 417 while (offset < last_offset) { 418 /* 419 * Very similar validation code is found in 420 * process_dirblock(), hsfs_node.c. 421 * For an explanation, see there. 422 * It may make sense for the future to 423 * "consolidate" the code in hs_parsedir(), 424 * process_dirblock() and hsfs_readdir() into 425 * a single utility function. 426 */ 427 hdlen = (int)((uchar_t) 428 HDE_DIR_LEN(&blkp[rel_offset(offset)])); 429 if (hdlen < HDE_ROOT_DIR_REC_SIZE || 430 offset + hdlen > last_offset) { 431 /* 432 * advance to next sector boundary 433 */ 434 offset = roundup(offset + 1, HS_SECTOR_SIZE); 435 if (hdlen) 436 hs_log_bogus_disk_warning(fsp, 437 HSFS_ERR_TRAILING_JUNK, 0); 438 439 continue; 440 } 441 442 bzero(&hd, sizeof (hd)); 443 444 /* 445 * Just ignore invalid directory entries. 446 * XXX - maybe hs_parsedir() will detect EXISTENCE bit 447 */ 448 if (!hs_parsedir(fsp, &blkp[rel_offset(offset)], 449 &hd, dname, &dnamelen, 450 last_offset - rel_offset(offset))) { 451 /* 452 * Determine if there is enough room 453 */ 454 ndlen = (long)DIRENT64_RECLEN((dnamelen)); 455 456 if ((ndlen + ((char *)nd - outbuf)) > 457 uiop->uio_resid) { 458 fbrelse(fbp, S_READ); 459 goto done; /* output buffer full */ 460 } 461 462 diroff = offset + hdlen; 463 /* 464 * Generate nodeid. 465 * If a directory, nodeid points to the 466 * canonical dirent describing the directory: 467 * the dirent of the "." entry for the 468 * directory, which is pointed to by all 469 * dirents for that directory. 470 * Otherwise, nodeid points to dirent of file. 471 */ 472 if (hd.type == VDIR) { 473 dirino = (ino64_t) 474 MAKE_NODEID(hd.ext_lbn, 0, 475 vp->v_vfsp); 476 } else { 477 struct hs_volume *hvp; 478 offset_t lbn, off; 479 480 /* 481 * Normalize lbn and off 482 */ 483 hvp = &fsp->hsfs_vol; 484 lbn = dir_lbn + 485 (offset >> hvp->lbn_shift); 486 off = offset & hvp->lbn_maxoffset; 487 dirino = (ino64_t)MAKE_NODEID(lbn, 488 off, vp->v_vfsp); 489 } 490 491 492 /* strncpy(9f) will zero uninitialized bytes */ 493 494 ASSERT(strlen(dname) + 1 <= 495 DIRENT64_NAMELEN(ndlen)); 496 (void) strncpy(nd->d_name, dname, 497 DIRENT64_NAMELEN(ndlen)); 498 nd->d_reclen = (ushort_t)ndlen; 499 nd->d_off = (offset_t)diroff; 500 nd->d_ino = dirino; 501 nd = (struct dirent64 *)((char *)nd + ndlen); 502 503 /* 504 * free up space allocated for symlink 505 */ 506 if (hd.sym_link != (char *)NULL) { 507 kmem_free(hd.sym_link, 508 (size_t)(hd.ext_size+1)); 509 hd.sym_link = (char *)NULL; 510 } 511 } 512 offset += hdlen; 513 } 514 fbrelse(fbp, S_READ); 515 } 516 517 /* 518 * Got here for one of the following reasons: 519 * 1) outbuf is full (error == 0) 520 * 2) end of directory reached (error == 0) 521 * 3) error reading directory sector (error != 0) 522 * 4) directory entry crosses sector boundary (error == 0) 523 * 524 * If any directory entries have been copied, don't report 525 * case 4. Instead, return the valid directory entries. 526 * 527 * If no entries have been copied, report the error. 528 * If case 4, this will be indistiguishable from EOF. 529 */ 530 done: 531 ndlen = ((char *)nd - outbuf); 532 if (ndlen != 0) { 533 error = uiomove(outbuf, (size_t)ndlen, UIO_READ, uiop); 534 uiop->uio_loffset = offset; 535 } 536 kmem_free(dname, dname_size); 537 kmem_free(outbuf, bufsize); 538 if (eofp && error == 0) 539 *eofp = (uiop->uio_loffset >= dirsiz); 540 return (error); 541 } 542 543 static int 544 hsfs_fid(struct vnode *vp, struct fid *fidp) 545 { 546 struct hsnode *hp; 547 struct hsfid *fid; 548 549 if (fidp->fid_len < (sizeof (*fid) - sizeof (fid->hf_len))) { 550 fidp->fid_len = sizeof (*fid) - sizeof (fid->hf_len); 551 return (ENOSPC); 552 } 553 554 fid = (struct hsfid *)fidp; 555 fid->hf_len = sizeof (*fid) - sizeof (fid->hf_len); 556 hp = VTOH(vp); 557 mutex_enter(&hp->hs_contents_lock); 558 fid->hf_dir_lbn = hp->hs_dir_lbn; 559 fid->hf_dir_off = (ushort_t)hp->hs_dir_off; 560 mutex_exit(&hp->hs_contents_lock); 561 return (0); 562 } 563 564 /*ARGSUSED*/ 565 static int 566 hsfs_open(struct vnode **vpp, int flag, struct cred *cred) 567 { 568 return (0); 569 } 570 571 /*ARGSUSED*/ 572 static int 573 hsfs_close( 574 struct vnode *vp, 575 int flag, 576 int count, 577 offset_t offset, 578 struct cred *cred) 579 { 580 (void) cleanlocks(vp, ttoproc(curthread)->p_pid, 0); 581 cleanshares(vp, ttoproc(curthread)->p_pid); 582 return (0); 583 } 584 585 /*ARGSUSED2*/ 586 static int 587 hsfs_access(struct vnode *vp, int mode, int flags, cred_t *cred) 588 { 589 return (hs_access(vp, (mode_t)mode, cred)); 590 } 591 592 /* 593 * the seek time of a CD-ROM is very slow, and data transfer 594 * rate is even worse (max. 150K per sec). The design 595 * decision is to reduce access to cd-rom as much as possible, 596 * and to transfer a sizable block (read-ahead) of data at a time. 597 * UFS style of read ahead one block at a time is not appropriate, 598 * and is not supported 599 */ 600 601 /* 602 * KLUSTSIZE should be a multiple of PAGESIZE and <= MAXPHYS. 603 */ 604 #define KLUSTSIZE (56 * 1024) 605 /* we don't support read ahead */ 606 int hsfs_lostpage; /* no. of times we lost original page */ 607 608 /* 609 * Used to prevent biodone() from releasing buf resources that 610 * we didn't allocate in quite the usual way. 611 */ 612 /*ARGSUSED*/ 613 int 614 hsfs_iodone(struct buf *bp) 615 { 616 sema_v(&bp->b_io); 617 return (0); 618 } 619 620 /* 621 * Each file may have a different interleaving on disk. This makes 622 * things somewhat interesting. The gist is that there are some 623 * number of contiguous data sectors, followed by some other number 624 * of contiguous skip sectors. The sum of those two sets of sectors 625 * defines the interleave size. Unfortunately, it means that we generally 626 * can't simply read N sectors starting at a given offset to satisfy 627 * any given request. 628 * 629 * What we do is get the relevant memory pages via pvn_read_kluster(), 630 * then stride through the interleaves, setting up a buf for each 631 * sector that needs to be brought in. Instead of kmem_alloc'ing 632 * space for the sectors, though, we just point at the appropriate 633 * spot in the relevant page for each of them. This saves us a bunch 634 * of copying. 635 */ 636 /*ARGSUSED*/ 637 static int 638 hsfs_getapage( 639 struct vnode *vp, 640 u_offset_t off, 641 size_t len, 642 uint_t *protp, 643 struct page *pl[], 644 size_t plsz, 645 struct seg *seg, 646 caddr_t addr, 647 enum seg_rw rw, 648 struct cred *cred) 649 { 650 struct hsnode *hp; 651 struct hsfs *fsp; 652 int err; 653 struct buf *bufs; 654 caddr_t *vas; 655 caddr_t va; 656 struct page *pp, *searchp, *lastp; 657 page_t *pagefound; 658 offset_t bof; 659 struct vnode *devvp; 660 ulong_t byte_offset; 661 size_t io_len_tmp; 662 uint_t io_off, io_len; 663 uint_t xlen; 664 uint_t filsiz; 665 uint_t secsize; 666 uint_t bufcnt; 667 uint_t bufsused; 668 uint_t count; 669 uint_t io_end; 670 uint_t which_chunk_lbn; 671 uint_t offset_lbn; 672 uint_t offset_extra; 673 offset_t offset_bytes; 674 uint_t remaining_bytes; 675 uint_t extension; 676 int remainder; /* must be signed */ 677 int chunk_lbn_count; 678 int chunk_data_bytes; 679 int xarsiz; 680 diskaddr_t driver_block; 681 u_offset_t io_off_tmp; 682 683 /* 684 * We don't support asynchronous operation at the moment, so 685 * just pretend we did it. If the pages are ever actually 686 * needed, they'll get brought in then. 687 */ 688 if (pl == NULL) 689 return (0); 690 691 hp = VTOH(vp); 692 fsp = VFS_TO_HSFS(vp->v_vfsp); 693 devvp = fsp->hsfs_devvp; 694 secsize = fsp->hsfs_vol.lbn_size; /* bytes per logical block */ 695 696 /* file data size */ 697 filsiz = hp->hs_dirent.ext_size; 698 699 /* disk addr for start of file */ 700 bof = LBN_TO_BYTE((offset_t)hp->hs_dirent.ext_lbn, vp->v_vfsp); 701 702 /* xarsiz byte must be skipped for data */ 703 xarsiz = hp->hs_dirent.xar_len << fsp->hsfs_vol.lbn_shift; 704 705 /* how many logical blocks in an interleave (data+skip) */ 706 chunk_lbn_count = hp->hs_dirent.intlf_sz + hp->hs_dirent.intlf_sk; 707 708 if (chunk_lbn_count == 0) { 709 chunk_lbn_count = 1; 710 } 711 712 /* 713 * Convert interleaving size into bytes. The zero case 714 * (no interleaving) optimization is handled as a side- 715 * effect of the read-ahead logic. 716 */ 717 if (hp->hs_dirent.intlf_sz == 0) { 718 chunk_data_bytes = LBN_TO_BYTE(1, vp->v_vfsp); 719 } else { 720 chunk_data_bytes = LBN_TO_BYTE(hp->hs_dirent.intlf_sz, 721 vp->v_vfsp); 722 } 723 724 reread: 725 err = 0; 726 pagefound = 0; 727 728 /* 729 * Do some read-ahead. This mostly saves us a bit of 730 * system cpu time more than anything else when doing 731 * sequential reads. At some point, could do the 732 * read-ahead asynchronously which might gain us something 733 * on wall time, but it seems unlikely.... 734 * 735 * We do the easy case here, which is to read through 736 * the end of the chunk, minus whatever's at the end that 737 * won't exactly fill a page. 738 */ 739 which_chunk_lbn = (off + len) / chunk_data_bytes; 740 extension = ((which_chunk_lbn + 1) * chunk_data_bytes) - off; 741 extension -= (extension % PAGESIZE); 742 if (extension != 0 && extension < filsiz - off) { 743 len = extension; 744 } else { 745 len = PAGESIZE; 746 } 747 /* 748 * Some cd writers don't write sectors that aren't used. Also, 749 * there's no point in reading sectors we'll never look at. So, 750 * if we're asked to go beyond the end of a file, truncate to the 751 * length of that file. 752 * 753 * Additionally, this behaviour is required by section 6.4.5 of 754 * ISO 9660:1988(E). 755 */ 756 if (len > (filsiz - off)) { 757 len = filsiz - off; 758 } 759 760 /* A little paranoia. */ 761 ASSERT(len > 0); 762 763 /* 764 * After all that, make sure we're asking for things in units 765 * that bdev_strategy() will understand (see bug 4202551). 766 */ 767 len = roundup(len, DEV_BSIZE); 768 769 pp = NULL; 770 again: 771 /* search for page in buffer */ 772 if ((pagefound = page_exists(vp, off)) == 0) { 773 /* 774 * Need to really do disk IO to get the page. 775 */ 776 pp = pvn_read_kluster(vp, off, seg, addr, &io_off_tmp, 777 &io_len_tmp, off, len, 0); 778 779 if (pp == NULL) 780 goto again; 781 782 io_off = (uint_t)io_off_tmp; 783 io_len = (uint_t)io_len_tmp; 784 785 /* check for truncation */ 786 /* 787 * xxx Clean up and return EIO instead? 788 * xxx Ought to go to u_offset_t for everything, but we 789 * xxx call lots of things that want uint_t arguments. 790 */ 791 ASSERT(io_off == io_off_tmp); 792 793 /* 794 * get enough buffers for worst-case scenario 795 * (i.e., no coalescing possible). 796 */ 797 bufcnt = (len + secsize - 1) / secsize; 798 bufs = kmem_zalloc(bufcnt * sizeof (struct buf), KM_SLEEP); 799 vas = kmem_alloc(bufcnt * sizeof (caddr_t), KM_SLEEP); 800 for (count = 0; count < bufcnt; count++) { 801 bufs[count].b_edev = devvp->v_rdev; 802 bufs[count].b_dev = cmpdev(devvp->v_rdev); 803 bufs[count].b_flags = B_NOCACHE|B_BUSY|B_READ; 804 bufs[count].b_iodone = hsfs_iodone; 805 bufs[count].b_vp = vp; 806 bufs[count].b_file = vp; 807 sema_init(&bufs[count].b_io, 0, NULL, 808 SEMA_DEFAULT, NULL); 809 sema_init(&bufs[count].b_sem, 0, NULL, 810 SEMA_DEFAULT, NULL); 811 } 812 813 /* 814 * If our filesize is not an integer multiple of PAGESIZE, 815 * we zero that part of the last page that's between EOF and 816 * the PAGESIZE boundary. 817 */ 818 xlen = io_len & PAGEOFFSET; 819 if (xlen != 0) 820 pagezero(pp->p_prev, xlen, PAGESIZE - xlen); 821 822 va = NULL; 823 lastp = NULL; 824 searchp = pp; 825 io_end = io_off + io_len; 826 for (count = 0, byte_offset = io_off; 827 byte_offset < io_end; 828 count++) { 829 ASSERT(count < bufcnt); 830 831 /* Compute disk address for interleaving. */ 832 833 /* considered without skips */ 834 which_chunk_lbn = byte_offset / chunk_data_bytes; 835 836 /* factor in skips */ 837 offset_lbn = which_chunk_lbn * chunk_lbn_count; 838 839 /* convert to physical byte offset for lbn */ 840 offset_bytes = LBN_TO_BYTE(offset_lbn, vp->v_vfsp); 841 842 /* don't forget offset into lbn */ 843 offset_extra = byte_offset % chunk_data_bytes; 844 845 /* get virtual block number for driver */ 846 driver_block = lbtodb(bof + xarsiz 847 + offset_bytes + offset_extra); 848 849 if (lastp != searchp) { 850 /* this branch taken first time through loop */ 851 va = vas[count] 852 = ppmapin(searchp, PROT_WRITE, 853 (caddr_t)-1); 854 /* ppmapin() guarantees not to return NULL */ 855 } else { 856 vas[count] = NULL; 857 } 858 859 bufs[count].b_un.b_addr = va + byte_offset % PAGESIZE; 860 bufs[count].b_offset = 861 (offset_t)(byte_offset - io_off + off); 862 863 /* 864 * We specifically use the b_lblkno member here 865 * as even in the 32 bit world driver_block can 866 * get very large in line with the ISO9660 spec. 867 */ 868 869 bufs[count].b_lblkno = driver_block; 870 871 remaining_bytes = ((which_chunk_lbn + 1) 872 * chunk_data_bytes) 873 - byte_offset; 874 875 /* 876 * remaining_bytes can't be zero, as we derived 877 * which_chunk_lbn directly from byte_offset. 878 */ 879 if ((remaining_bytes + byte_offset) < (off + len)) { 880 /* coalesce-read the rest of the chunk */ 881 bufs[count].b_bcount = remaining_bytes; 882 } else { 883 /* get the final bits */ 884 bufs[count].b_bcount = off + len - byte_offset; 885 } 886 887 /* 888 * It would be nice to do multiple pages' 889 * worth at once here when the opportunity 890 * arises, as that has been shown to improve 891 * our wall time. However, to do that 892 * requires that we use the pageio subsystem, 893 * which doesn't mix well with what we're 894 * already using here. We can't use pageio 895 * all the time, because that subsystem 896 * assumes that a page is stored in N 897 * contiguous blocks on the device. 898 * Interleaving violates that assumption. 899 */ 900 901 remainder = PAGESIZE - (byte_offset % PAGESIZE); 902 if (bufs[count].b_bcount > remainder) { 903 bufs[count].b_bcount = remainder; 904 } 905 906 bufs[count].b_bufsize = bufs[count].b_bcount; 907 if (((offset_t)byte_offset + bufs[count].b_bcount) > 908 HS_MAXFILEOFF) { 909 break; 910 } 911 byte_offset += bufs[count].b_bcount; 912 913 (void) bdev_strategy(&bufs[count]); 914 915 lwp_stat_update(LWP_STAT_INBLK, 1); 916 lastp = searchp; 917 if ((remainder - bufs[count].b_bcount) < 1) { 918 searchp = searchp->p_next; 919 } 920 } 921 922 bufsused = count; 923 /* Now wait for everything to come in */ 924 for (count = 0; count < bufsused; count++) { 925 if (err == 0) { 926 err = biowait(&bufs[count]); 927 } else 928 (void) biowait(&bufs[count]); 929 } 930 931 /* Don't leak resources */ 932 for (count = 0; count < bufcnt; count++) { 933 sema_destroy(&bufs[count].b_io); 934 sema_destroy(&bufs[count].b_sem); 935 if (count < bufsused && vas[count] != NULL) { 936 ppmapout(vas[count]); 937 } 938 } 939 940 kmem_free(vas, bufcnt * sizeof (caddr_t)); 941 kmem_free(bufs, bufcnt * sizeof (struct buf)); 942 } 943 944 if (err) { 945 pvn_read_done(pp, B_ERROR); 946 return (err); 947 } 948 949 /* 950 * Lock the requested page, and the one after it if possible. 951 * Don't bother if our caller hasn't given us a place to stash 952 * the page pointers, since otherwise we'd lock pages that would 953 * never get unlocked. 954 */ 955 if (pagefound) { 956 int index; 957 ulong_t soff; 958 959 /* 960 * Make sure it's in memory before we say it's here. 961 */ 962 if ((pp = page_lookup(vp, off, SE_SHARED)) == NULL) { 963 hsfs_lostpage++; 964 goto reread; 965 } 966 967 pl[0] = pp; 968 index = 1; 969 970 /* 971 * Try to lock the next page, if it exists, without 972 * blocking. 973 */ 974 plsz -= PAGESIZE; 975 /* LINTED (plsz is unsigned) */ 976 for (soff = off + PAGESIZE; plsz > 0; 977 soff += PAGESIZE, plsz -= PAGESIZE) { 978 pp = page_lookup_nowait(vp, (u_offset_t)soff, 979 SE_SHARED); 980 if (pp == NULL) 981 break; 982 pl[index++] = pp; 983 } 984 pl[index] = NULL; 985 return (0); 986 } 987 988 if (pp != NULL) { 989 pvn_plist_init(pp, pl, plsz, off, io_len, rw); 990 } 991 992 return (err); 993 } 994 995 static int 996 hsfs_getpage( 997 struct vnode *vp, 998 offset_t off, 999 size_t len, 1000 uint_t *protp, 1001 struct page *pl[], 1002 size_t plsz, 1003 struct seg *seg, 1004 caddr_t addr, 1005 enum seg_rw rw, 1006 struct cred *cred) 1007 { 1008 int err; 1009 uint_t filsiz; 1010 struct hsnode *hp = VTOH(vp); 1011 1012 /* does not support write */ 1013 if (rw == S_WRITE) { 1014 panic("write attempt on READ ONLY HSFS"); 1015 /*NOTREACHED*/ 1016 } 1017 1018 if (vp->v_flag & VNOMAP) { 1019 return (ENOSYS); 1020 } 1021 1022 ASSERT(off <= HS_MAXFILEOFF); 1023 1024 /* 1025 * Determine file data size for EOF check. 1026 */ 1027 filsiz = hp->hs_dirent.ext_size; 1028 if ((off + len) > (offset_t)(filsiz + PAGEOFFSET) && seg != segkmap) 1029 return (EFAULT); /* beyond EOF */ 1030 1031 if (protp != NULL) 1032 *protp = PROT_ALL; 1033 1034 if (len <= PAGESIZE) 1035 err = hsfs_getapage(vp, (u_offset_t)off, len, protp, pl, plsz, 1036 seg, addr, rw, cred); 1037 else 1038 err = pvn_getpages(hsfs_getapage, vp, off, len, protp, 1039 pl, plsz, seg, addr, rw, cred); 1040 1041 return (err); 1042 } 1043 1044 1045 1046 /* 1047 * This function should never be called. We need to have it to pass 1048 * it as an argument to other functions. 1049 */ 1050 /*ARGSUSED*/ 1051 int 1052 hsfs_putapage( 1053 vnode_t *vp, 1054 page_t *pp, 1055 u_offset_t *offp, 1056 size_t *lenp, 1057 int flags, 1058 cred_t *cr) 1059 { 1060 /* should never happen - just destroy it */ 1061 cmn_err(CE_NOTE, "hsfs_putapage: dirty HSFS page"); 1062 pvn_write_done(pp, B_ERROR | B_WRITE | B_INVAL | B_FORCE | flags); 1063 return (0); 1064 } 1065 1066 1067 /* 1068 * The only flags we support are B_INVAL, B_FREE and B_DONTNEED. 1069 * B_INVAL is set by: 1070 * 1071 * 1) the MC_SYNC command of memcntl(2) to support the MS_INVALIDATE flag. 1072 * 2) the MC_ADVISE command of memcntl(2) with the MADV_DONTNEED advice 1073 * which translates to an MC_SYNC with the MS_INVALIDATE flag. 1074 * 1075 * The B_FREE (as well as the B_DONTNEED) flag is set when the 1076 * MADV_SEQUENTIAL advice has been used. VOP_PUTPAGE is invoked 1077 * from SEGVN to release pages behind a pagefault. 1078 */ 1079 /*ARGSUSED*/ 1080 static int 1081 hsfs_putpage( 1082 struct vnode *vp, 1083 offset_t off, 1084 size_t len, 1085 int flags, 1086 struct cred *cr) 1087 { 1088 int error = 0; 1089 1090 if (vp->v_count == 0) { 1091 panic("hsfs_putpage: bad v_count"); 1092 /*NOTREACHED*/ 1093 } 1094 1095 if (vp->v_flag & VNOMAP) 1096 return (ENOSYS); 1097 1098 ASSERT(off <= HS_MAXFILEOFF); 1099 1100 if (!vn_has_cached_data(vp)) /* no pages mapped */ 1101 return (0); 1102 1103 if (len == 0) /* from 'off' to EOF */ 1104 error = pvn_vplist_dirty(vp, off, 1105 hsfs_putapage, flags, cr); 1106 else { 1107 offset_t end_off = off + len; 1108 offset_t file_size = VTOH(vp)->hs_dirent.ext_size; 1109 offset_t io_off; 1110 1111 file_size = (file_size + PAGESIZE - 1) & PAGEMASK; 1112 if (end_off > file_size) 1113 end_off = file_size; 1114 1115 for (io_off = off; io_off < end_off; io_off += PAGESIZE) { 1116 page_t *pp; 1117 1118 /* 1119 * We insist on getting the page only if we are 1120 * about to invalidate, free or write it and 1121 * the B_ASYNC flag is not set. 1122 */ 1123 if ((flags & B_INVAL) || ((flags & B_ASYNC) == 0)) { 1124 pp = page_lookup(vp, io_off, 1125 (flags & (B_INVAL | B_FREE)) ? 1126 SE_EXCL : SE_SHARED); 1127 } else { 1128 pp = page_lookup_nowait(vp, io_off, 1129 (flags & B_FREE) ? SE_EXCL : SE_SHARED); 1130 } 1131 1132 if (pp == NULL) 1133 continue; 1134 /* 1135 * Normally pvn_getdirty() should return 0, which 1136 * impies that it has done the job for us. 1137 * The shouldn't-happen scenario is when it returns 1. 1138 * This means that the page has been modified and 1139 * needs to be put back. 1140 * Since we can't write on a CD, we fake a failed 1141 * I/O and force pvn_write_done() to destroy the page. 1142 */ 1143 if (pvn_getdirty(pp, flags) == 1) { 1144 cmn_err(CE_NOTE, 1145 "hsfs_putpage: dirty HSFS page"); 1146 pvn_write_done(pp, flags | 1147 B_ERROR | B_WRITE | B_INVAL | B_FORCE); 1148 } 1149 } 1150 } 1151 return (error); 1152 } 1153 1154 1155 /*ARGSUSED*/ 1156 static int 1157 hsfs_map( 1158 struct vnode *vp, 1159 offset_t off, 1160 struct as *as, 1161 caddr_t *addrp, 1162 size_t len, 1163 uchar_t prot, 1164 uchar_t maxprot, 1165 uint_t flags, 1166 struct cred *cred) 1167 { 1168 struct segvn_crargs vn_a; 1169 int error; 1170 1171 /* VFS_RECORD(vp->v_vfsp, VS_MAP, VS_CALL); */ 1172 1173 if (vp->v_flag & VNOMAP) 1174 return (ENOSYS); 1175 1176 if (off > HS_MAXFILEOFF || off < 0 || 1177 (off + len) < 0 || (off + len) > HS_MAXFILEOFF) 1178 return (ENXIO); 1179 1180 if (vp->v_type != VREG) { 1181 return (ENODEV); 1182 } 1183 1184 /* 1185 * If file is being locked, disallow mapping. 1186 */ 1187 if (vn_has_mandatory_locks(vp, VTOH(vp)->hs_dirent.mode)) 1188 return (EAGAIN); 1189 1190 as_rangelock(as); 1191 1192 if ((flags & MAP_FIXED) == 0) { 1193 map_addr(addrp, len, off, 1, flags); 1194 if (*addrp == NULL) { 1195 as_rangeunlock(as); 1196 return (ENOMEM); 1197 } 1198 } else { 1199 /* 1200 * User specified address - blow away any previous mappings 1201 */ 1202 (void) as_unmap(as, *addrp, len); 1203 } 1204 1205 vn_a.vp = vp; 1206 vn_a.offset = off; 1207 vn_a.type = flags & MAP_TYPE; 1208 vn_a.prot = prot; 1209 vn_a.maxprot = maxprot; 1210 vn_a.flags = flags & ~MAP_TYPE; 1211 vn_a.cred = cred; 1212 vn_a.amp = NULL; 1213 vn_a.szc = 0; 1214 vn_a.lgrp_mem_policy_flags = 0; 1215 1216 error = as_map(as, *addrp, len, segvn_create, &vn_a); 1217 as_rangeunlock(as); 1218 return (error); 1219 } 1220 1221 /* ARGSUSED */ 1222 static int 1223 hsfs_addmap( 1224 struct vnode *vp, 1225 offset_t off, 1226 struct as *as, 1227 caddr_t addr, 1228 size_t len, 1229 uchar_t prot, 1230 uchar_t maxprot, 1231 uint_t flags, 1232 struct cred *cr) 1233 { 1234 struct hsnode *hp; 1235 1236 if (vp->v_flag & VNOMAP) 1237 return (ENOSYS); 1238 1239 hp = VTOH(vp); 1240 mutex_enter(&hp->hs_contents_lock); 1241 hp->hs_mapcnt += btopr(len); 1242 mutex_exit(&hp->hs_contents_lock); 1243 return (0); 1244 } 1245 1246 /*ARGSUSED*/ 1247 static int 1248 hsfs_delmap( 1249 struct vnode *vp, 1250 offset_t off, 1251 struct as *as, 1252 caddr_t addr, 1253 size_t len, 1254 uint_t prot, 1255 uint_t maxprot, 1256 uint_t flags, 1257 struct cred *cr) 1258 { 1259 struct hsnode *hp; 1260 1261 if (vp->v_flag & VNOMAP) 1262 return (ENOSYS); 1263 1264 hp = VTOH(vp); 1265 mutex_enter(&hp->hs_contents_lock); 1266 hp->hs_mapcnt -= btopr(len); /* Count released mappings */ 1267 ASSERT(hp->hs_mapcnt >= 0); 1268 mutex_exit(&hp->hs_contents_lock); 1269 return (0); 1270 } 1271 1272 /* ARGSUSED */ 1273 static int 1274 hsfs_seek(struct vnode *vp, offset_t ooff, offset_t *noffp) 1275 { 1276 return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0); 1277 } 1278 1279 /* ARGSUSED */ 1280 static int 1281 hsfs_frlock( 1282 struct vnode *vp, 1283 int cmd, 1284 struct flock64 *bfp, 1285 int flag, 1286 offset_t offset, 1287 struct flk_callback *flk_cbp, 1288 cred_t *cr) 1289 { 1290 struct hsnode *hp = VTOH(vp); 1291 1292 /* 1293 * If the file is being mapped, disallow fs_frlock. 1294 * We are not holding the hs_contents_lock while checking 1295 * hs_mapcnt because the current locking strategy drops all 1296 * locks before calling fs_frlock. 1297 * So, hs_mapcnt could change before we enter fs_frlock making 1298 * it meaningless to have held hs_contents_lock in the first place. 1299 */ 1300 if (hp->hs_mapcnt > 0 && MANDLOCK(vp, hp->hs_dirent.mode)) 1301 return (EAGAIN); 1302 1303 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr)); 1304 } 1305 1306 /* ARGSUSED */ 1307 static int 1308 hsfs_pathconf(struct vnode *vp, int cmd, ulong_t *valp, struct cred *cr) 1309 { 1310 struct hsfs *fsp; 1311 1312 int error = 0; 1313 1314 switch (cmd) { 1315 1316 case _PC_NAME_MAX: 1317 fsp = VFS_TO_HSFS(vp->v_vfsp); 1318 *valp = fsp->hsfs_namemax; 1319 break; 1320 1321 case _PC_FILESIZEBITS: 1322 *valp = 33; /* Without multi extent support: 4 GB - 2k */ 1323 break; 1324 1325 default: 1326 error = fs_pathconf(vp, cmd, valp, cr); 1327 } 1328 1329 return (error); 1330 } 1331 1332 1333 1334 const fs_operation_def_t hsfs_vnodeops_template[] = { 1335 VOPNAME_OPEN, { .vop_open = hsfs_open }, 1336 VOPNAME_CLOSE, { .vop_close = hsfs_close }, 1337 VOPNAME_READ, { .vop_read = hsfs_read }, 1338 VOPNAME_GETATTR, { .vop_getattr = hsfs_getattr }, 1339 VOPNAME_ACCESS, { .vop_access = hsfs_access }, 1340 VOPNAME_LOOKUP, { .vop_lookup = hsfs_lookup }, 1341 VOPNAME_READDIR, { .vop_readdir = hsfs_readdir }, 1342 VOPNAME_READLINK, { .vop_readlink = hsfs_readlink }, 1343 VOPNAME_FSYNC, { .vop_fsync = hsfs_fsync }, 1344 VOPNAME_INACTIVE, { .vop_inactive = hsfs_inactive }, 1345 VOPNAME_FID, { .vop_fid = hsfs_fid }, 1346 VOPNAME_SEEK, { .vop_seek = hsfs_seek }, 1347 VOPNAME_FRLOCK, { .vop_frlock = hsfs_frlock }, 1348 VOPNAME_GETPAGE, { .vop_getpage = hsfs_getpage }, 1349 VOPNAME_PUTPAGE, { .vop_putpage = hsfs_putpage }, 1350 VOPNAME_MAP, { .vop_map = hsfs_map }, 1351 VOPNAME_ADDMAP, { .vop_addmap = hsfs_addmap }, 1352 VOPNAME_DELMAP, { .vop_delmap = hsfs_delmap }, 1353 VOPNAME_PATHCONF, { .vop_pathconf = hsfs_pathconf }, 1354 NULL, NULL 1355 }; 1356 1357 struct vnodeops *hsfs_vnodeops; 1358