efs_vnops.c revision 1.7
1/* $NetBSD: efs_vnops.c,v 1.7 2007/09/08 16:21:27 rumble Exp $ */ 2 3/* 4 * Copyright (c) 2006 Stephen M. Rumble <rumble@ephemeral.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/cdefs.h> 20__KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,v 1.7 2007/09/08 16:21:27 rumble Exp $"); 21 22#include <sys/param.h> 23#include <sys/systm.h> 24#include <sys/proc.h> 25#include <sys/kernel.h> 26#include <sys/vnode.h> 27#include <sys/mount.h> 28#include <sys/malloc.h> 29#include <sys/namei.h> 30#include <sys/dirent.h> 31#include <sys/lockf.h> 32#include <sys/unistd.h> 33 34#include <miscfs/genfs/genfs.h> 35#include <miscfs/genfs/genfs_node.h> 36 37#include <fs/efs/efs.h> 38#include <fs/efs/efs_sb.h> 39#include <fs/efs/efs_dir.h> 40#include <fs/efs/efs_genfs.h> 41#include <fs/efs/efs_mount.h> 42#include <fs/efs/efs_extent.h> 43#include <fs/efs/efs_dinode.h> 44#include <fs/efs/efs_inode.h> 45#include <fs/efs/efs_subr.h> 46#include <fs/efs/efs_ihash.h> 47 48MALLOC_DECLARE(M_EFSTMP); 49 50/* 51 * Lookup a pathname component in the given directory. 52 * 53 * Returns 0 on success. 54 */ 55static int 56efs_lookup(void *v) 57{ 58 struct vop_lookup_args /* { 59 struct vnode *a_dvp; 60 struct vnode **a_vpp; 61 struct componentname *a_cnp; 62 } */ *ap = v; 63 struct componentname *cnp = ap->a_cnp; 64 struct vnode *vp; 65 ino_t ino; 66 int err, nameiop = cnp->cn_nameiop; 67 68 /* ensure that the directory can be accessed first */ 69 err = VOP_ACCESS(ap->a_dvp, VEXEC, cnp->cn_cred, cnp->cn_lwp); 70 if (err) 71 return (err); 72 73 err = cache_lookup(ap->a_dvp, ap->a_vpp, cnp); 74 if (err != -1) 75 return (err); 76 77 /* 78 * Handle the three lookup types: '.', '..', and everything else. 79 */ 80 if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { 81 vref(ap->a_dvp); 82 *ap->a_vpp = ap->a_dvp; 83 } else if (cnp->cn_flags & ISDOTDOT) { 84 err = efs_inode_lookup(VFSTOEFS(ap->a_dvp->v_mount), 85 EFS_VTOI(ap->a_dvp), ap->a_cnp, &ino); 86 if (err) 87 return (err); 88 89 VOP_UNLOCK(ap->a_dvp, 0); /* preserve lock order */ 90 91 err = VFS_VGET(ap->a_dvp->v_mount, ino, &vp); 92 if (err) { 93 vn_lock(ap->a_dvp, LK_EXCLUSIVE | LK_RETRY); 94 return (err); 95 } 96 vn_lock(ap->a_dvp, LK_EXCLUSIVE | LK_RETRY); 97 *ap->a_vpp = vp; 98 } else { 99 err = efs_inode_lookup(VFSTOEFS(ap->a_dvp->v_mount), 100 EFS_VTOI(ap->a_dvp), ap->a_cnp, &ino); 101 if (err) { 102 if (err == ENOENT && (cnp->cn_flags & MAKEENTRY) && 103 nameiop != CREATE) 104 cache_enter(ap->a_dvp, NULL, cnp); 105 if (err == ENOENT && (nameiop == CREATE || 106 nameiop == RENAME)) { 107 err = VOP_ACCESS(ap->a_dvp, VWRITE, 108 cnp->cn_cred, cnp->cn_lwp); 109 if (err) 110 return (err); 111 cnp->cn_flags |= SAVENAME; 112 return (EJUSTRETURN); 113 } 114 return (err); 115 } 116 err = VFS_VGET(ap->a_dvp->v_mount, ino, &vp); 117 if (err) 118 return (err); 119 *ap->a_vpp = vp; 120 } 121 122 if (cnp->cn_flags & MAKEENTRY) 123 cache_enter(ap->a_dvp, *ap->a_vpp, cnp); 124 125 return (0); 126} 127 128/* 129 * Determine the accessiblity of a file based on the permissions allowed by the 130 * specified credentials. 131 * 132 * Returns 0 on success. 133 */ 134static int 135efs_access(void *v) 136{ 137 struct vop_access_args /* { 138 const struct vnodeop_desc *a_desc; 139 struct vnode *a_vp; 140 int a_mode; 141 struct ucred *a_cred; 142 struct lwp *a_l; 143 } */ *ap = v; 144 struct vnode *vp = ap->a_vp; 145 struct efs_inode *eip = EFS_VTOI(vp); 146 147 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) 148 return (EROFS); 149 150 return (vaccess(vp->v_type, eip->ei_mode, eip->ei_uid, eip->ei_gid, 151 ap->a_mode, ap->a_cred)); 152} 153 154/* 155 * Get specific vnode attributes on a file. See vattr(9). 156 * 157 * Returns 0 on success. 158 */ 159static int 160efs_getattr(void *v) 161{ 162 struct vop_getattr_args /* { 163 const struct vnodeop_desc *a_desc; 164 struct vnode *a_vp; 165 struct vattr *a_vap; 166 struct ucred *a_cred; 167 struct lwp *a_l; 168 } */ *ap = v; 169 170 struct vattr *vap = ap->a_vap; 171 struct efs_inode *eip = EFS_VTOI(ap->a_vp); 172 173 vattr_null(ap->a_vap); 174 vap->va_type = ap->a_vp->v_type; 175 vap->va_mode = eip->ei_mode; 176 vap->va_nlink = eip->ei_nlink; 177 vap->va_uid = eip->ei_uid; 178 vap->va_gid = eip->ei_gid; 179 vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid; 180 vap->va_fileid = eip->ei_number; 181 vap->va_size = eip->ei_size; 182 183 if (ap->a_vp->v_type == VBLK) 184 vap->va_blocksize = BLKDEV_IOSIZE; 185 else if (ap->a_vp->v_type == VCHR) 186 vap->va_blocksize = MAXBSIZE; 187 else 188 vap->va_blocksize = EFS_BB_SIZE; 189 190 vap->va_atime.tv_sec = eip->ei_atime; 191 vap->va_mtime.tv_sec = eip->ei_mtime; 192 vap->va_ctime.tv_sec = eip->ei_ctime; 193/* vap->va_birthtime = */ 194 vap->va_gen = eip->ei_gen; 195 vap->va_flags = ap->a_vp->v_flag; 196 197 if (ap->a_vp->v_type == VBLK || ap->a_vp->v_type == VCHR) { 198 uint32_t dmaj, dmin; 199 200 if (be16toh(eip->ei_di.di_odev) != EFS_DINODE_ODEV_INVALID) { 201 dmaj = EFS_DINODE_ODEV_MAJ(be16toh(eip->ei_di.di_odev)); 202 dmin = EFS_DINODE_ODEV_MIN(be16toh(eip->ei_di.di_odev)); 203 } else { 204 dmaj = EFS_DINODE_NDEV_MAJ(be32toh(eip->ei_di.di_ndev)); 205 dmin = EFS_DINODE_NDEV_MIN(be32toh(eip->ei_di.di_ndev)); 206 } 207 208 vap->va_rdev = makedev(dmaj, dmin); 209 } 210 211 vap->va_bytes = eip->ei_size; 212/* vap->va_filerev = */ 213/* vap->va_vaflags = */ 214 215 return (0); 216} 217 218/* 219 * Read a file. 220 * 221 * Returns 0 on success. 222 */ 223static int 224efs_read(void *v) 225{ 226 struct vop_read_args /* { 227 const struct vnodeop_desc *a_desc; 228 struct vnode *a_vp; 229 struct uio *a_uio; 230 int a_ioflag; 231 struct ucred *a_cred; 232 } */ *ap = v; 233 struct efs_extent ex; 234 struct efs_extent_iterator exi; 235 void *win; 236 struct uio *uio = ap->a_uio; 237 struct efs_inode *eip = EFS_VTOI(ap->a_vp); 238 off_t start; 239 vsize_t len; 240 int err, ret, flags; 241 const int advice = IO_ADV_DECODE(ap->a_ioflag); 242 243 if (ap->a_vp->v_type == VDIR) 244 return (EISDIR); 245 246 if (ap->a_vp->v_type != VREG) 247 return (EINVAL); 248 249 efs_extent_iterator_init(&exi, eip, uio->uio_offset); 250 ret = efs_extent_iterator_next(&exi, &ex); 251 while (ret == 0) { 252 if (uio->uio_offset < 0 || uio->uio_offset >= eip->ei_size || 253 uio->uio_resid == 0) 254 break; 255 256 start = ex.ex_offset * EFS_BB_SIZE; 257 len = ex.ex_length * EFS_BB_SIZE; 258 259 if (!(uio->uio_offset >= start && 260 uio->uio_offset < (start + len))) { 261 ret = efs_extent_iterator_next(&exi, &ex); 262 continue; 263 } 264 265 start = uio->uio_offset - start; 266 267 len = MIN(len - start, uio->uio_resid); 268 len = MIN(len, eip->ei_size - uio->uio_offset); 269 270 win = ubc_alloc(&ap->a_vp->v_uobj, uio->uio_offset, 271 &len, advice, UBC_READ); 272 273 flags = UBC_WANT_UNMAP(ap->a_vp) ? UBC_UNMAP : 0; 274 275 err = uiomove(win, len, uio); 276 ubc_release(win, flags); 277 if (err) { 278 EFS_DPRINTF(("efs_read: uiomove error %d\n", 279 err)); 280 return (err); 281 } 282 } 283 284 return ((ret == -1) ? 0 : ret); 285} 286 287static int 288efs_readdir(void *v) 289{ 290 struct vop_readdir_args /* { 291 const struct vnodeop_desc *a_desc; 292 struct vnode *a_vp; 293 struct uio *a_uio; 294 struct ucred *a_cred; 295 int *a_eofflag; 296 off_t **a_cookies; 297 int *a_ncookies; 298 } */ *ap = v; 299 struct efs_dinode edi; 300 struct efs_extent ex; 301 struct efs_extent_iterator exi; 302 struct buf *bp; 303 struct dirent *dp; 304 struct efs_dirent *de; 305 struct efs_dirblk *db; 306 struct uio *uio = ap->a_uio; 307 struct efs_inode *ei = EFS_VTOI(ap->a_vp); 308 off_t *cookies = NULL; 309 off_t offset; 310 int i, j, err, ret, s, slot, ncookies, maxcookies = 0; 311 312 if (ap->a_vp->v_type != VDIR) 313 return (ENOTDIR); 314 315 if (ap->a_eofflag != NULL) 316 *ap->a_eofflag = false; 317 318 if (ap->a_ncookies != NULL) { 319 ncookies = 0; 320 maxcookies = 321 uio->uio_resid / _DIRENT_MINSIZE((struct dirent *)0); 322 cookies = malloc(maxcookies * sizeof(off_t), M_TEMP, M_WAITOK); 323 } 324 325 offset = 0; 326 efs_extent_iterator_init(&exi, ei, 0); 327 while ((ret = efs_extent_iterator_next(&exi, &ex)) == 0) { 328 for (i = 0; i < ex.ex_length; i++) { 329 err = efs_bread(VFSTOEFS(ap->a_vp->v_mount), 330 ex.ex_bn + i, NULL, &bp); 331 if (err) { 332 brelse(bp); 333 goto exit_err; 334 } 335 336 db = (struct efs_dirblk *)bp->b_data; 337 338 if (be16toh(db->db_magic) != EFS_DIRBLK_MAGIC) { 339 printf("efs_readdir: bad dirblk\n"); 340 brelse(bp); 341 continue; 342 } 343 344 for (j = 0; j < db->db_slots; j++) { 345 slot = EFS_DIRENT_OFF_EXPND(db->db_space[j]); 346 if (slot == EFS_DIRBLK_SLOT_FREE) 347 continue; 348 349 if (!EFS_DIRENT_OFF_VALID(slot)) { 350 printf("efs_readdir: bad dirent\n"); 351 continue; 352 } 353 354 de = EFS_DIRBLK_TO_DIRENT(db, slot); 355 s = _DIRENT_RECLEN(dp, de->de_namelen); 356 357 if (offset < uio->uio_offset) { 358 offset += s; 359 continue; 360 } 361 362 /* XXX - latter shouldn't happen, right? */ 363 if (s > uio->uio_resid || 364 offset > uio->uio_offset) { 365 brelse(bp); 366 goto exit_ok; 367 } 368 369 dp = malloc(s, M_EFSTMP, M_ZERO | M_WAITOK); 370 dp->d_fileno = be32toh(de->de_inumber); 371 dp->d_reclen = s; 372 dp->d_namlen = de->de_namelen; 373 memcpy(dp->d_name, de->de_name, 374 de->de_namelen); 375 dp->d_name[de->de_namelen] = '\0'; 376 377 /* look up inode to get type */ 378 err = efs_read_inode( 379 VFSTOEFS(ap->a_vp->v_mount), 380 dp->d_fileno, NULL, &edi); 381 if (err) { 382 brelse(bp); 383 free(dp, M_EFSTMP); 384 goto exit_err; 385 } 386 387 switch (be16toh(edi.di_mode) & EFS_IFMT) { 388 case EFS_IFIFO: 389 dp->d_type = DT_FIFO; 390 break; 391 case EFS_IFCHR: 392 dp->d_type = DT_CHR; 393 break; 394 case EFS_IFDIR: 395 dp->d_type = DT_DIR; 396 break; 397 case EFS_IFBLK: 398 dp->d_type = DT_BLK; 399 break; 400 case EFS_IFREG: 401 dp->d_type = DT_REG; 402 break; 403 case EFS_IFLNK: 404 dp->d_type = DT_LNK; 405 break; 406 case EFS_IFSOCK: 407 dp->d_type = DT_SOCK; 408 break; 409 default: 410 dp->d_type = DT_UNKNOWN; 411 break; 412 } 413 414 err = uiomove(dp, s, uio); 415 free(dp, M_EFSTMP); 416 if (err) { 417 brelse(bp); 418 goto exit_err; 419 } 420 421 offset += s; 422 423 if (cookies != NULL && maxcookies != 0) { 424 cookies[ncookies++] = offset; 425 if (ncookies == maxcookies) { 426 brelse(bp); 427 goto exit_ok; 428 } 429 } 430 } 431 432 brelse(bp); 433 } 434 } 435 436 if (ret != -1) { 437 err = ret; 438 goto exit_err; 439 } 440 441 if (ap->a_eofflag != NULL) 442 *ap->a_eofflag = true; 443 444 exit_ok: 445 if (cookies != NULL) { 446 *ap->a_cookies = cookies; 447 *ap->a_ncookies = ncookies; 448 } 449 450 uio->uio_offset = offset; 451 452 return (0); 453 454 exit_err: 455 if (cookies != NULL) 456 free(cookies, M_TEMP); 457 458 return (err); 459} 460 461static int 462efs_readlink(void *v) 463{ 464 struct vop_readlink_args /* { 465 const struct vnodeop_desc *a_desc; 466 struct vnode *a_vp; 467 struct uio *a_uio; 468 struct ucred *a_cred; 469 } */ *ap = v; 470 struct uio *uio = ap->a_uio; 471 struct efs_inode *eip = EFS_VTOI(ap->a_vp); 472 char *buf; 473 size_t len; 474 int err, i; 475 476 if ((eip->ei_mode & EFS_IFMT) != EFS_IFLNK) 477 return (EINVAL); 478 479 if (uio->uio_resid < 1) 480 return (EINVAL); 481 482 buf = malloc(eip->ei_size + 1, M_EFSTMP, M_ZERO | M_WAITOK); 483 484 /* symlinks are either inlined in the inode, or in extents */ 485 if (eip->ei_numextents == 0) { 486 if (eip->ei_size > sizeof(eip->ei_di.di_symlink)) { 487 EFS_DPRINTF(("efs_readlink: too big for inline\n")); 488 free(buf, M_EFSTMP); 489 return (EBADF); 490 } 491 492 memcpy(buf, eip->ei_di.di_symlink, eip->ei_size); 493 len = MIN(uio->uio_resid, eip->ei_size + 1); 494 } else { 495 struct efs_extent_iterator exi; 496 struct efs_extent ex; 497 struct buf *bp; 498 int resid, off, ret; 499 500 off = 0; 501 resid = eip->ei_size; 502 503 efs_extent_iterator_init(&exi, eip, 0); 504 while ((ret = efs_extent_iterator_next(&exi, &ex)) == 0) { 505 for (i = 0; i < ex.ex_length; i++) { 506 err = efs_bread(VFSTOEFS(ap->a_vp->v_mount), 507 ex.ex_bn + i, NULL, &bp); 508 if (err) { 509 brelse(bp); 510 free(buf, M_EFSTMP); 511 return (err); 512 } 513 514 len = MIN(resid, bp->b_bcount); 515 memcpy(buf + off, bp->b_data, len); 516 brelse(bp); 517 518 off += len; 519 resid -= len; 520 521 if (resid == 0) 522 break; 523 } 524 525 if (resid == 0) 526 break; 527 } 528 529 if (ret != 0 && ret != -1) { 530 free(buf, M_EFSTMP); 531 return (ret); 532 } 533 534 len = off + 1; 535 } 536 537 KASSERT(len >= 1 && len <= (eip->ei_size + 1)); 538 buf[len - 1] = '\0'; 539 err = uiomove(buf, len, uio); 540 free(buf, M_EFSTMP); 541 542 return (err); 543} 544 545/* 546 * Release an inactive vnode. The vnode _must_ be unlocked on return. 547 * It is either nolonger being used by the kernel, or an unmount is being 548 * forced. 549 * 550 * Returns 0 on success. 551 */ 552static int 553efs_inactive(void *v) 554{ 555 struct vop_inactive_args /* { 556 const struct vnodeop_desc *a_desc; 557 struct vnode *a_vp; 558 struct lwp *a_l; 559 } */ *ap = v; 560 struct efs_inode *eip = EFS_VTOI(ap->a_vp); 561 562 VOP_UNLOCK(ap->a_vp, 0); 563 564 if (eip->ei_mode == 0) 565 vrecycle(ap->a_vp, NULL, ap->a_l); 566 567 return (0); 568} 569 570static int 571efs_reclaim(void *v) 572{ 573 struct vop_reclaim_args /* { 574 const struct vnodeop_desc *a_desc; 575 struct vnode *a_vp; 576 struct lwp *a_l; 577 } */ *ap = v; 578 struct vnode *vp = ap->a_vp; 579 580 efs_ihashrem(EFS_VTOI(vp)); 581 cache_purge(vp); 582 genfs_node_destroy(vp); 583 pool_put(&efs_inode_pool, vp->v_data); 584 vp->v_data = NULL; 585 586 return (0); 587} 588 589static int 590efs_bmap(void *v) 591{ 592 struct vop_bmap_args /* { 593 const struct vnodeop_desc *a_desc; 594 struct vnode *a_vp; 595 daddr_t a_bn; 596 struct vnode **a_vpp; 597 daddr_t *a_bnp; 598 int *a_runp; 599 } */ *ap = v; 600 struct efs_extent ex; 601 struct efs_extent_iterator exi; 602 struct vnode *vp = ap->a_vp; 603 struct efs_inode *eip = EFS_VTOI(vp); 604 bool found; 605 int ret; 606 607 if (ap->a_vpp != NULL) 608 *ap->a_vpp = VFSTOEFS(vp->v_mount)->em_devvp; 609 610 found = false; 611 efs_extent_iterator_init(&exi, eip, ap->a_bn * EFS_BB_SIZE); 612 while ((ret = efs_extent_iterator_next(&exi, &ex)) == 0) { 613 if (ap->a_bn >= ex.ex_offset && 614 ap->a_bn < (ex.ex_offset + ex.ex_length)) { 615 found = true; 616 break; 617 } 618 } 619 620 KASSERT(!found || (found && ret == 0)); 621 622 if (!found) { 623 EFS_DPRINTF(("efs_bmap: ap->a_bn not in extents\n")); 624 return ((ret == -1) ? EIO : ret); 625 } 626 627 if (ex.ex_magic != EFS_EXTENT_MAGIC) { 628 EFS_DPRINTF(("efs_bmap: exn.ex_magic != EFS_EXTENT_MAGIC\n")); 629 return (EIO); 630 } 631 632 if (ap->a_bn < ex.ex_offset) { 633 EFS_DPRINTF(("efs_bmap: ap->a_bn < exn.ex_offset\n")); 634 return (EIO); 635 } 636 637 KASSERT(ap->a_bn >= ex.ex_offset); 638 KASSERT(ex.ex_length > ap->a_bn - ex.ex_offset); 639 640 *ap->a_bnp = ex.ex_bn + (ap->a_bn - ex.ex_offset); 641 if (ap->a_runp != NULL) 642 *ap->a_runp = ex.ex_length - (ap->a_bn - ex.ex_offset) - 1; 643 644 return (0); 645} 646 647static int 648efs_strategy(void *v) 649{ 650 struct vop_strategy_args /* { 651 const struct vnodeop_desc *a_desc; 652 struct vnode *a_vp; 653 struct buf *a_bp; 654 } */ *ap = v; 655 struct vnode *vp = ap->a_vp; 656 struct buf *bp = ap->a_bp; 657 int error; 658 659 if (vp == NULL) { 660 bp->b_error = EIO; 661 biodone(bp); 662 return (EIO); 663 } 664 665 if (bp->b_blkno == bp->b_lblkno) { 666 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL); 667 if (error) { 668 bp->b_error = error; 669 biodone(bp); 670 return (error); 671 } 672 if ((long)bp->b_blkno == -1) 673 clrbuf(bp); 674 } 675 676 if ((long)bp->b_blkno == -1) { 677 biodone(bp); 678 return (0); 679 } 680 681 return (VOP_STRATEGY(VFSTOEFS(vp->v_mount)->em_devvp, bp)); 682} 683 684static int 685efs_print(void *v) 686{ 687 struct vop_print_args /* { 688 const struct vnodeop_desc *a_desc; 689 struct vnode *a_vp; 690 } */ *ap = v; 691 struct efs_inode *eip = EFS_VTOI(ap->a_vp); 692 693 printf( "efs_inode (ino %lu):\n" 694 " ei_mode: %07o\n" 695 " ei_nlink: %d\n" 696 " ei_uid: %d\n" 697 " ei_gid: %d\n" 698 " ei_size: %d\n" 699 " ei_atime: %d\n" 700 " ei_mtime: %d\n" 701 " ei_ctime: %d\n" 702 " ei_gen: %d\n" 703 " ei_numextents: %d\n" 704 " ei_version: %d\n", 705 (unsigned long)eip->ei_number, 706 (unsigned int)eip->ei_mode, 707 eip->ei_nlink, 708 eip->ei_uid, 709 eip->ei_gid, 710 eip->ei_size, 711 (int32_t)eip->ei_atime, 712 (int32_t)eip->ei_mtime, 713 (int32_t)eip->ei_ctime, 714 eip->ei_gen, 715 eip->ei_numextents, 716 eip->ei_version); 717 718 return (0); 719} 720 721static int 722efs_pathconf(void *v) 723{ 724 struct vop_pathconf_args /* { 725 const struct vnodeop_desc *a_desc; 726 struct vnode *a_vp; 727 int a_name; 728 register_t *a_retval; 729 } */ *ap = v; 730 731 /* IRIX 4 values */ 732 switch (ap->a_name) { 733 case _PC_LINK_MAX: 734 *ap->a_retval = 30000; 735 break; 736 case _PC_NAME_MAX: 737 *ap->a_retval = 255; 738 break; 739 case _PC_PATH_MAX: 740 *ap->a_retval = 1024; 741 break; 742 case _PC_NO_TRUNC: 743 *ap->a_retval = 1; 744 break; 745 case _PC_CHOWN_RESTRICTED: 746 *ap->a_retval = 1; 747 break; 748 case _PC_SYNC_IO: 749 *ap->a_retval = 1; 750 break; 751 case _PC_FILESIZEBITS: 752 *ap->a_retval = 32; 753 break; 754 default: 755 return (EINVAL); 756 } 757 758 return (0); 759} 760 761static int 762efs_advlock(void *v) 763{ 764 struct vop_advlock_args /* { 765 const struct vnodeop_desc *a_desc; 766 struct vnode *a_vp; 767 void *a_id; 768 int a_op; 769 struct flock *a_fl; 770 int a_flags; 771 } */ *ap = v; 772 struct efs_inode *eip = EFS_VTOI(ap->a_vp); 773 774 return (lf_advlock(ap, &eip->ei_lockf, eip->ei_size)); 775} 776 777/* Global vfs data structures for efs */ 778int (**efs_vnodeop_p)(void *); 779const struct vnodeopv_entry_desc efs_vnodeop_entries[] = { 780 { &vop_default_desc, vn_default_error}, /* error handler */ 781 { &vop_lookup_desc, efs_lookup }, /* lookup */ 782 { &vop_create_desc, genfs_eopnotsupp}, /* create */ 783 { &vop_mknod_desc, genfs_eopnotsupp}, /* mknod */ 784 { &vop_open_desc, genfs_nullop }, /* open */ 785 { &vop_close_desc, genfs_nullop }, /* close */ 786 { &vop_access_desc, efs_access }, /* access */ 787 { &vop_getattr_desc, efs_getattr }, /* getattr */ 788 { &vop_setattr_desc, genfs_eopnotsupp}, /* setattr */ 789 { &vop_read_desc, efs_read }, /* read */ 790 { &vop_write_desc, genfs_eopnotsupp}, /* write */ 791 { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */ 792 { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 793 { &vop_poll_desc, genfs_poll }, /* poll */ 794 { &vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */ 795 { &vop_revoke_desc, genfs_revoke }, /* revoke */ 796 { &vop_mmap_desc, genfs_mmap }, /* mmap */ 797 { &vop_fsync_desc, genfs_eopnotsupp}, /* fsync */ 798 { &vop_seek_desc, genfs_seek }, /* seek */ 799 { &vop_remove_desc, genfs_eopnotsupp}, /* remove */ 800 { &vop_link_desc, genfs_eopnotsupp}, /* link */ 801 { &vop_rename_desc, genfs_eopnotsupp}, /* rename */ 802 { &vop_mkdir_desc, genfs_eopnotsupp}, /* mkdir */ 803 { &vop_rmdir_desc, genfs_eopnotsupp}, /* rmdir */ 804 { &vop_symlink_desc, genfs_eopnotsupp}, /* symlink */ 805 { &vop_readdir_desc, efs_readdir }, /* readdir */ 806 { &vop_readlink_desc, efs_readlink }, /* readlink */ 807 { &vop_abortop_desc, genfs_abortop }, /* abortop */ 808 { &vop_inactive_desc, efs_inactive }, /* inactive */ 809 { &vop_reclaim_desc, efs_reclaim }, /* reclaim */ 810 { &vop_lock_desc, genfs_lock, }, /* lock */ 811 { &vop_unlock_desc, genfs_unlock, }, /* unlock */ 812 { &vop_islocked_desc, genfs_islocked, }, /* islocked */ 813 { &vop_bmap_desc, efs_bmap }, /* bmap */ 814 { &vop_print_desc, efs_print }, /* print */ 815 { &vop_pathconf_desc, efs_pathconf }, /* pathconf */ 816 { &vop_advlock_desc, efs_advlock }, /* advlock */ 817 /* blkatoff */ 818 /* valloc */ 819 /* balloc */ 820 /* vfree */ 821 /* truncate */ 822 { &vop_lease_desc, genfs_lease_check }, /* lease */ 823 /* whiteout */ 824 { &vop_getpages_desc, genfs_getpages }, /* getpages */ 825 { &vop_putpages_desc, genfs_putpages }, /* putpages */ 826 { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 827 { &vop_strategy_desc, efs_strategy }, /* strategy */ 828 { NULL, NULL } 829}; 830const struct vnodeopv_desc efs_vnodeop_opv_desc = { 831 &efs_vnodeop_p, 832 efs_vnodeop_entries 833}; 834