1 /* $NetBSD: advfsops.c,v 1.60 2010/06/24 13:03:08 hannken Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Christian E. Hopps 5 * Copyright (c) 1996 Matthias Scheler 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Christian E. Hopps. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 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, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: advfsops.c,v 1.60 2010/06/24 13:03:08 hannken Exp $"); 36 37 #if defined(_KERNEL_OPT) 38 #include "opt_compat_netbsd.h" 39 #endif 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/sysctl.h> 44 #include <sys/vnode.h> 45 #include <sys/mount.h> 46 #include <sys/proc.h> 47 #include <sys/time.h> 48 #include <sys/malloc.h> 49 #include <sys/pool.h> 50 #include <sys/disklabel.h> 51 #include <miscfs/genfs/genfs.h> 52 #include <miscfs/specfs/specdev.h> /* XXX */ 53 #include <sys/fcntl.h> 54 #include <sys/namei.h> 55 #include <sys/ioctl.h> 56 #include <sys/queue.h> 57 #include <sys/buf.h> 58 #include <sys/conf.h> 59 #include <sys/kauth.h> 60 #include <sys/simplelock.h> 61 #include <sys/module.h> 62 #include <fs/adosfs/adosfs.h> 63 64 MODULE(MODULE_CLASS_VFS, adosfs, NULL); 65 66 VFS_PROTOS(adosfs); 67 68 static struct sysctllog *adosfs_sysctl_log; 69 70 int adosfs_mountfs(struct vnode *, struct mount *, struct lwp *); 71 int adosfs_loadbitmap(struct adosfsmount *); 72 73 struct simplelock adosfs_hashlock; 74 75 struct pool adosfs_node_pool; 76 77 MALLOC_JUSTDEFINE(M_ADOSFSMNT, "adosfs mount", "adosfs mount structures"); 78 MALLOC_JUSTDEFINE(M_ANODE, "adosfs anode","adosfs anode structures and tables"); 79 MALLOC_JUSTDEFINE(M_ADOSFSBITMAP, "adosfs bitmap", "adosfs bitmap"); 80 81 static const struct genfs_ops adosfs_genfsops = { 82 .gop_size = genfs_size, 83 }; 84 85 int (**adosfs_vnodeop_p)(void *); 86 87 int 88 adosfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) 89 { 90 struct lwp *l = curlwp; 91 struct vnode *devvp; 92 struct adosfs_args *args = data; 93 struct adosfsmount *amp; 94 int error; 95 mode_t accessmode; 96 97 if (*data_len < sizeof *args) 98 return EINVAL; 99 100 if (mp->mnt_flag & MNT_GETARGS) { 101 amp = VFSTOADOSFS(mp); 102 if (amp == NULL) 103 return EIO; 104 args->uid = amp->uid; 105 args->gid = amp->gid; 106 args->mask = amp->mask; 107 args->fspec = NULL; 108 *data_len = sizeof *args; 109 return 0; 110 } 111 112 if ((mp->mnt_flag & MNT_RDONLY) == 0) 113 return (EROFS); 114 115 if ((mp->mnt_flag & MNT_UPDATE) && args->fspec == NULL) 116 return EOPNOTSUPP; 117 118 /* 119 * Not an update, or updating the name: look up the name 120 * and verify that it refers to a sensible block device. 121 */ 122 error = namei_simple_user(args->fspec, 123 NSM_FOLLOW_NOEMULROOT, &devvp); 124 if (error != 0) 125 return (error); 126 127 if (devvp->v_type != VBLK) { 128 vrele(devvp); 129 return (ENOTBLK); 130 } 131 if (bdevsw_lookup(devvp->v_rdev) == NULL) { 132 vrele(devvp); 133 return (ENXIO); 134 } 135 /* 136 * If mount by non-root, then verify that user has necessary 137 * permissions on the device. 138 */ 139 accessmode = VREAD; 140 if ((mp->mnt_flag & MNT_RDONLY) == 0) 141 accessmode |= VWRITE; 142 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 143 error = genfs_can_mount(devvp, accessmode, l->l_cred); 144 VOP_UNLOCK(devvp); 145 if (error) { 146 vrele(devvp); 147 return (error); 148 } 149 /* MNT_UPDATE? */ 150 if ((error = adosfs_mountfs(devvp, mp, l)) != 0) { 151 vrele(devvp); 152 return (error); 153 } 154 amp = VFSTOADOSFS(mp); 155 amp->uid = args->uid; 156 amp->gid = args->gid; 157 amp->mask = args->mask; 158 return set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE, 159 mp->mnt_op->vfs_name, mp, l); 160 } 161 162 int 163 adosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l) 164 { 165 struct disklabel dl; 166 struct partition *parp; 167 struct adosfsmount *amp; 168 struct buf *bp; 169 struct vnode *rvp; 170 int error, part, i; 171 172 part = DISKPART(devvp->v_rdev); 173 amp = NULL; 174 175 if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)) != 0) 176 return (error); 177 178 /* 179 * open blkdev and read root block 180 */ 181 if ((error = VOP_OPEN(devvp, FREAD, NOCRED)) != 0) 182 return (error); 183 error = VOP_IOCTL(devvp, DIOCGDINFO, &dl, FREAD, NOCRED); 184 if (error) 185 goto fail; 186 187 parp = &dl.d_partitions[part]; 188 amp = malloc(sizeof(struct adosfsmount), M_ADOSFSMNT, M_WAITOK); 189 memset((char *)amp, 0, (u_long)sizeof(struct adosfsmount)); 190 amp->mp = mp; 191 if (dl.d_type == DTYPE_FLOPPY) { 192 amp->bsize = dl.d_secsize; 193 amp->secsperblk = 1; 194 } 195 else { 196 amp->bsize = parp->p_fsize * parp->p_frag; 197 amp->secsperblk = parp->p_frag; 198 } 199 200 /* invalid fs ? */ 201 if (amp->secsperblk == 0) { 202 error = EINVAL; 203 goto fail; 204 } 205 206 bp = NULL; 207 if ((error = bread(devvp, (daddr_t)BBOFF, 208 amp->bsize, NOCRED, 0, &bp)) != 0) { 209 brelse(bp, 0); 210 goto fail; 211 } 212 amp->dostype = adoswordn(bp, 0); 213 brelse(bp, 0); 214 215 /* basic sanity checks */ 216 if (amp->dostype < 0x444f5300 || amp->dostype > 0x444f5305) { 217 error = EINVAL; 218 goto fail; 219 } 220 221 amp->rootb = (parp->p_size / amp->secsperblk - 1 + parp->p_cpg) >> 1; 222 amp->numblks = parp->p_size / amp->secsperblk - parp->p_cpg; 223 224 amp->nwords = amp->bsize >> 2; 225 amp->dbsize = amp->bsize - (IS_FFS(amp) ? 0 : OFS_DATA_OFFSET); 226 amp->devvp = devvp; 227 228 mp->mnt_data = amp; 229 mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)devvp->v_rdev; 230 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_ADOSFS); 231 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 232 mp->mnt_stat.f_namemax = ADMAXNAMELEN; 233 mp->mnt_fs_bshift = ffs(amp->bsize) - 1; 234 mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */ 235 mp->mnt_flag |= MNT_LOCAL; 236 237 /* 238 * init anode table. 239 */ 240 for (i = 0; i < ANODEHASHSZ; i++) 241 LIST_INIT(&->anodetab[i]); 242 243 /* 244 * get the root anode, if not a valid fs this will fail. 245 */ 246 if ((error = VFS_ROOT(mp, &rvp)) != 0) 247 goto fail; 248 /* allocate and load bitmap, set free space */ 249 amp->bitmap = malloc(((amp->numblks + 31) / 32) * sizeof(*amp->bitmap), 250 M_ADOSFSBITMAP, M_WAITOK); 251 if (amp->bitmap) 252 adosfs_loadbitmap(amp); 253 if (mp->mnt_flag & MNT_RDONLY && amp->bitmap) { 254 /* 255 * Don't need the bitmap any more if it's read-only. 256 */ 257 free(amp->bitmap, M_ADOSFSBITMAP); 258 amp->bitmap = NULL; 259 } 260 vput(rvp); 261 262 return(0); 263 264 fail: 265 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 266 (void) VOP_CLOSE(devvp, FREAD, NOCRED); 267 VOP_UNLOCK(devvp); 268 if (amp && amp->bitmap) 269 free(amp->bitmap, M_ADOSFSBITMAP); 270 if (amp) 271 free(amp, M_ADOSFSMNT); 272 return (error); 273 } 274 275 int 276 adosfs_start(struct mount *mp, int flags) 277 { 278 279 return (0); 280 } 281 282 int 283 adosfs_unmount(struct mount *mp, int mntflags) 284 { 285 struct adosfsmount *amp; 286 int error, flags; 287 288 flags = 0; 289 if (mntflags & MNT_FORCE) 290 flags |= FORCECLOSE; 291 if ((error = vflush(mp, NULLVP, flags)) != 0) 292 return (error); 293 amp = VFSTOADOSFS(mp); 294 if (amp->devvp->v_type != VBAD) 295 amp->devvp->v_specmountpoint = NULL; 296 vn_lock(amp->devvp, LK_EXCLUSIVE | LK_RETRY); 297 error = VOP_CLOSE(amp->devvp, FREAD, NOCRED); 298 vput(amp->devvp); 299 if (amp->bitmap) 300 free(amp->bitmap, M_ADOSFSBITMAP); 301 free(amp, M_ADOSFSMNT); 302 mp->mnt_data = NULL; 303 mp->mnt_flag &= ~MNT_LOCAL; 304 return (error); 305 } 306 307 int 308 adosfs_root(struct mount *mp, struct vnode **vpp) 309 { 310 struct vnode *nvp; 311 int error; 312 313 if ((error = VFS_VGET(mp, (ino_t)VFSTOADOSFS(mp)->rootb, &nvp)) != 0) 314 return (error); 315 /* XXX verify it's a root block? */ 316 *vpp = nvp; 317 return (0); 318 } 319 320 int 321 adosfs_statvfs(struct mount *mp, struct statvfs *sbp) 322 { 323 struct adosfsmount *amp; 324 325 amp = VFSTOADOSFS(mp); 326 sbp->f_bsize = amp->bsize; 327 sbp->f_frsize = amp->bsize; 328 sbp->f_iosize = amp->dbsize; 329 sbp->f_blocks = amp->numblks; 330 sbp->f_bfree = amp->freeblks; 331 sbp->f_bavail = amp->freeblks; 332 sbp->f_bresvd = 0; 333 sbp->f_files = 0; /* who knows */ 334 sbp->f_ffree = 0; /* " " */ 335 sbp->f_favail = 0; /* " " */ 336 sbp->f_fresvd = 0; 337 copy_statvfs_info(sbp, mp); 338 return (0); 339 } 340 341 /* 342 * lookup an anode, check mount's hash table if not found, create 343 * return locked and referenced al la vget(vp, 1); 344 */ 345 int 346 adosfs_vget(struct mount *mp, ino_t an, struct vnode **vpp) 347 { 348 struct adosfsmount *amp; 349 struct vnode *vp; 350 struct anode *ap; 351 struct buf *bp; 352 char *nam, *tmp; 353 int namlen, error; 354 355 error = 0; 356 amp = VFSTOADOSFS(mp); 357 bp = NULL; 358 359 /* 360 * check hash table. we are done if found 361 */ 362 if ((*vpp = adosfs_ahashget(mp, an)) != NULL) 363 return (0); 364 365 error = getnewvnode(VT_ADOSFS, mp, adosfs_vnodeop_p, &vp); 366 if (error) 367 return (error); 368 369 /* 370 * setup, insert in hash, and lock before io. 371 */ 372 vp->v_data = ap = pool_get(&adosfs_node_pool, PR_WAITOK); 373 memset(ap, 0, sizeof(struct anode)); 374 ap->vp = vp; 375 ap->amp = amp; 376 ap->block = an; 377 ap->nwords = amp->nwords; 378 genfs_node_init(vp, &adosfs_genfsops); 379 adosfs_ainshash(amp, ap); 380 381 if ((error = bread(amp->devvp, an * amp->bsize / DEV_BSIZE, 382 amp->bsize, NOCRED, 0, &bp)) != 0) { 383 brelse(bp, 0); 384 vput(vp); 385 return (error); 386 } 387 388 /* 389 * get type and fill rest in based on that. 390 */ 391 switch (ap->type = adosfs_getblktype(amp, bp)) { 392 case AROOT: 393 vp->v_type = VDIR; 394 vp->v_vflag |= VV_ROOT; 395 ap->mtimev.days = adoswordn(bp, ap->nwords - 10); 396 ap->mtimev.mins = adoswordn(bp, ap->nwords - 9); 397 ap->mtimev.ticks = adoswordn(bp, ap->nwords - 8); 398 ap->created.days = adoswordn(bp, ap->nwords - 7); 399 ap->created.mins = adoswordn(bp, ap->nwords - 6); 400 ap->created.ticks = adoswordn(bp, ap->nwords - 5); 401 break; 402 case ALDIR: 403 case ADIR: 404 vp->v_type = VDIR; 405 break; 406 case ALFILE: 407 case AFILE: 408 vp->v_type = VREG; 409 ap->fsize = adoswordn(bp, ap->nwords - 47); 410 break; 411 case ASLINK: /* XXX soft link */ 412 vp->v_type = VLNK; 413 /* 414 * convert from BCPL string and 415 * from: "part:dir/file" to: "/part/dir/file" 416 */ 417 nam = (char *)bp->b_data + (6 * sizeof(long)); 418 namlen = strlen(nam); 419 tmp = nam; 420 while (*tmp && *tmp != ':') 421 tmp++; 422 if (*tmp == 0) { 423 ap->slinkto = malloc(namlen + 1, M_ANODE, M_WAITOK); 424 memcpy(ap->slinkto, nam, namlen); 425 } else if (*nam == ':') { 426 ap->slinkto = malloc(namlen + 1, M_ANODE, M_WAITOK); 427 memcpy(ap->slinkto, nam, namlen); 428 ap->slinkto[0] = '/'; 429 } else { 430 ap->slinkto = malloc(namlen + 2, M_ANODE, M_WAITOK); 431 ap->slinkto[0] = '/'; 432 memcpy(&ap->slinkto[1], nam, namlen); 433 ap->slinkto[tmp - nam + 1] = '/'; 434 namlen++; 435 } 436 ap->slinkto[namlen] = 0; 437 ap->fsize = namlen; 438 break; 439 default: 440 brelse(bp, 0); 441 vput(vp); 442 return (EINVAL); 443 } 444 445 /* 446 * Get appropriate data from this block; hard link needs 447 * to get other data from the "real" block. 448 */ 449 450 /* 451 * copy in name (from original block) 452 */ 453 nam = (char *)bp->b_data + (ap->nwords - 20) * sizeof(u_int32_t); 454 namlen = *(u_char *)nam++; 455 if (namlen > 30) { 456 #ifdef DIAGNOSTIC 457 printf("adosfs: aget: name length too long blk %llu\n", 458 (unsigned long long)an); 459 #endif 460 brelse(bp, 0); 461 vput(vp); 462 return (EINVAL); 463 } 464 memcpy(ap->name, nam, namlen); 465 ap->name[namlen] = 0; 466 467 /* 468 * if dir alloc hash table and copy it in 469 */ 470 if (vp->v_type == VDIR) { 471 int i; 472 473 ap->tab = malloc(ANODETABSZ(ap) * 2, M_ANODE, M_WAITOK); 474 ap->ntabent = ANODETABENT(ap); 475 ap->tabi = (int *)&ap->tab[ap->ntabent]; 476 memset(ap->tabi, 0, ANODETABSZ(ap)); 477 for (i = 0; i < ap->ntabent; i++) 478 ap->tab[i] = adoswordn(bp, i + 6); 479 } 480 481 /* 482 * misc. 483 */ 484 ap->pblock = adoswordn(bp, ap->nwords - 3); 485 ap->hashf = adoswordn(bp, ap->nwords - 4); 486 ap->linknext = adoswordn(bp, ap->nwords - 10); 487 ap->linkto = adoswordn(bp, ap->nwords - 11); 488 489 /* 490 * setup last indirect block cache. 491 */ 492 ap->lastlindblk = 0; 493 if (ap->type == AFILE) { 494 ap->lastindblk = ap->block; 495 if (adoswordn(bp, ap->nwords - 10)) 496 ap->linkto = ap->block; 497 } else if (ap->type == ALFILE) { 498 ap->lastindblk = ap->linkto; 499 brelse(bp, 0); 500 bp = NULL; 501 error = bread(amp->devvp, ap->linkto * amp->bsize / DEV_BSIZE, 502 amp->bsize, NOCRED, 0, &bp); 503 if (error) { 504 brelse(bp, 0); 505 vput(vp); 506 return (error); 507 } 508 ap->fsize = adoswordn(bp, ap->nwords - 47); 509 /* 510 * Should ap->block be set to the real file header block? 511 */ 512 ap->block = ap->linkto; 513 } 514 515 if (ap->type == AROOT) { 516 ap->adprot = 15; 517 ap->uid = amp->uid; 518 ap->gid = amp->gid; 519 } else { 520 ap->adprot = adoswordn(bp, ap->nwords - 48) ^ 15; 521 /* 522 * ADOS directories do not have a `x' protection bit as 523 * it is known in VFS; this functionality is fulfilled 524 * by the ADOS `r' bit. 525 * 526 * To retain the ADOS behaviour, fake execute permissions 527 * in that case. 528 */ 529 if ((ap->type == ADIR || ap->type == ALDIR) && 530 (ap->adprot & 0x00000008) == 0) 531 ap->adprot &= ~0x00000002; 532 533 /* 534 * Get uid/gid from extensions in file header 535 * (really need to know if this is a muFS partition) 536 */ 537 ap->uid = (adoswordn(bp, ap->nwords - 49) >> 16) & 0xffff; 538 ap->gid = adoswordn(bp, ap->nwords - 49) & 0xffff; 539 if (ap->uid || ap->gid) { 540 if (ap->uid == 0xffff) 541 ap->uid = 0; 542 if (ap->gid == 0xffff) 543 ap->gid = 0; 544 ap->adprot |= 0x40000000; /* Kludge */ 545 } 546 else { 547 /* 548 * uid & gid extension don't exist, 549 * so use the mount-point uid/gid 550 */ 551 ap->uid = amp->uid; 552 ap->gid = amp->gid; 553 } 554 } 555 ap->mtime.days = adoswordn(bp, ap->nwords - 23); 556 ap->mtime.mins = adoswordn(bp, ap->nwords - 22); 557 ap->mtime.ticks = adoswordn(bp, ap->nwords - 21); 558 559 *vpp = vp; 560 brelse(bp, 0); 561 uvm_vnp_setsize(vp, ap->fsize); 562 return (0); 563 } 564 565 /* 566 * Load the bitmap into memory, and count the number of available 567 * blocks. 568 * The bitmap will be released if the filesystem is read-only; it's 569 * only needed to find the free space. 570 */ 571 int 572 adosfs_loadbitmap(struct adosfsmount *amp) 573 { 574 struct buf *bp, *mapbp; 575 u_long bn; 576 int blkix, endix, mapix; 577 int bmsize; 578 int error; 579 580 bp = mapbp = NULL; 581 bn = amp->rootb; 582 if ((error = bread(amp->devvp, bn * amp->bsize / DEV_BSIZE, amp->bsize, 583 NOCRED, 0, &bp)) != 0) { 584 brelse(bp, 0); 585 return (error); 586 } 587 blkix = amp->nwords - 49; 588 endix = amp->nwords - 24; 589 mapix = 0; 590 bmsize = (amp->numblks + 31) / 32; 591 while (mapix < bmsize) { 592 int n; 593 u_long bits; 594 595 if (adoswordn(bp, blkix) == 0) 596 break; 597 if (mapbp != NULL) 598 brelse(mapbp, 0); 599 if ((error = bread(amp->devvp, 600 adoswordn(bp, blkix) * amp->bsize / DEV_BSIZE, amp->bsize, 601 NOCRED, 0, &mapbp)) != 0) 602 break; 603 if (adoscksum(mapbp, amp->nwords)) { 604 #ifdef DIAGNOSTIC 605 printf("adosfs: loadbitmap - cksum of blk %d failed\n", 606 adoswordn(bp, blkix)); 607 #endif 608 /* XXX Force read-only? Set free space 0? */ 609 break; 610 } 611 n = 1; 612 while (n < amp->nwords && mapix < bmsize) { 613 amp->bitmap[mapix++] = bits = adoswordn(mapbp, n); 614 ++n; 615 if (mapix == bmsize && amp->numblks & 31) 616 bits &= ~(0xffffffff << (amp->numblks & 31)); 617 while (bits) { 618 if (bits & 1) 619 ++amp->freeblks; 620 bits >>= 1; 621 } 622 } 623 ++blkix; 624 if (mapix < bmsize && blkix == endix) { 625 bn = adoswordn(bp, blkix); 626 brelse(bp, 0); 627 if ((error = bread(amp->devvp, bn * amp->bsize / DEV_BSIZE, 628 amp->bsize, NOCRED, 0, &bp)) != 0) 629 break; 630 /* 631 * Why is there no checksum on these blocks? 632 */ 633 blkix = 0; 634 endix = amp->nwords - 1; 635 } 636 } 637 if (bp) 638 brelse(bp, 0); 639 if (mapbp) 640 brelse(mapbp, 0); 641 return (error); 642 } 643 644 645 /* 646 * File handle to vnode 647 * 648 * Have to be really careful about stale file handles: 649 * - check that the inode number is in range 650 * - call iget() to get the locked inode 651 * - check for an unallocated inode (i_mode == 0) 652 * - check that the generation number matches 653 */ 654 655 struct ifid { 656 ushort ifid_len; 657 ushort ifid_pad; 658 int ifid_ino; 659 long ifid_start; 660 }; 661 662 int 663 adosfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) 664 { 665 struct ifid ifh; 666 #if 0 667 struct anode *ap; 668 #endif 669 struct vnode *nvp; 670 int error; 671 672 if (fhp->fid_len != sizeof(struct ifid)) 673 return EINVAL; 674 675 #ifdef ADOSFS_DIAGNOSTIC 676 printf("adfhtovp(%p, %p, %p)\n", mp, fhp, vpp); 677 #endif 678 679 memcpy(&ifh, fhp, sizeof(ifh)); 680 681 if ((error = VFS_VGET(mp, ifh.ifid_ino, &nvp)) != 0) { 682 *vpp = NULLVP; 683 return (error); 684 } 685 #if 0 686 ap = VTOA(nvp); 687 if (ap->inode.iso_mode == 0) { 688 vput(nvp); 689 *vpp = NULLVP; 690 return (ESTALE); 691 } 692 #endif 693 *vpp = nvp; 694 return(0); 695 } 696 697 int 698 adosfs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) 699 { 700 struct anode *ap = VTOA(vp); 701 struct ifid ifh; 702 703 if (*fh_size < sizeof(struct ifid)) { 704 *fh_size = sizeof(struct ifid); 705 return E2BIG; 706 } 707 *fh_size = sizeof(struct ifid); 708 709 memset(&ifh, 0, sizeof(ifh)); 710 ifh.ifid_len = sizeof(struct ifid); 711 ifh.ifid_ino = ap->block; 712 ifh.ifid_start = ap->block; 713 memcpy(fhp, &ifh, sizeof(ifh)); 714 715 #ifdef ADOSFS_DIAGNOSTIC 716 printf("advptofh(%p, %p)\n", vp, fhp); 717 #endif 718 return(0); 719 } 720 721 int 722 adosfs_sync(struct mount *mp, int waitfor, kauth_cred_t uc) 723 { 724 #ifdef ADOSFS_DIAGNOSTIC 725 printf("ad_sync(%p, %d)\n", mp, waitfor); 726 #endif 727 return(0); 728 } 729 730 void 731 adosfs_init(void) 732 { 733 734 malloc_type_attach(M_ADOSFSMNT); 735 malloc_type_attach(M_ANODE); 736 malloc_type_attach(M_ADOSFSBITMAP); 737 pool_init(&adosfs_node_pool, sizeof(struct anode), 0, 0, 0, "adosndpl", 738 &pool_allocator_nointr, IPL_NONE); 739 simple_lock_init(&adosfs_hashlock); 740 } 741 742 void 743 adosfs_done(void) 744 { 745 746 pool_destroy(&adosfs_node_pool); 747 malloc_type_detach(M_ADOSFSBITMAP); 748 malloc_type_detach(M_ANODE); 749 malloc_type_detach(M_ADOSFSMNT); 750 } 751 752 /* 753 * vfs generic function call table 754 */ 755 756 extern const struct vnodeopv_desc adosfs_vnodeop_opv_desc; 757 758 const struct vnodeopv_desc *adosfs_vnodeopv_descs[] = { 759 &adosfs_vnodeop_opv_desc, 760 NULL, 761 }; 762 763 struct vfsops adosfs_vfsops = { 764 MOUNT_ADOSFS, 765 sizeof (struct adosfs_args), 766 adosfs_mount, 767 adosfs_start, 768 adosfs_unmount, 769 adosfs_root, 770 (void *)eopnotsupp, /* vfs_quotactl */ 771 adosfs_statvfs, 772 adosfs_sync, 773 adosfs_vget, 774 adosfs_fhtovp, 775 adosfs_vptofh, 776 adosfs_init, 777 NULL, 778 adosfs_done, 779 NULL, /* vfs_mountroot */ 780 (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp, 781 vfs_stdextattrctl, 782 (void *)eopnotsupp, /* vfs_suspendctl */ 783 genfs_renamelock_enter, 784 genfs_renamelock_exit, 785 (void *)eopnotsupp, 786 adosfs_vnodeopv_descs, 787 0, 788 { NULL, NULL }, 789 }; 790 791 static int 792 adosfs_modcmd(modcmd_t cmd, void *arg) 793 { 794 int error; 795 796 switch (cmd) { 797 case MODULE_CMD_INIT: 798 error = vfs_attach(&adosfs_vfsops); 799 if (error != 0) 800 break; 801 sysctl_createv(&adosfs_sysctl_log, 0, NULL, NULL, 802 CTLFLAG_PERMANENT, 803 CTLTYPE_NODE, "vfs", NULL, 804 NULL, 0, NULL, 0, 805 CTL_VFS, CTL_EOL); 806 sysctl_createv(&adosfs_sysctl_log, 0, NULL, NULL, 807 CTLFLAG_PERMANENT, 808 CTLTYPE_NODE, "adosfs", 809 SYSCTL_DESCR("AmigaDOS file system"), 810 NULL, 0, NULL, 0, 811 CTL_VFS, 16, CTL_EOL); 812 /* 813 * XXX the "16" above could be dynamic, thereby eliminating 814 * one more instance of the "number to vfs" mapping problem, 815 * but "16" is the order as taken from sys/mount.h 816 */ 817 break; 818 case MODULE_CMD_FINI: 819 error = vfs_detach(&adosfs_vfsops); 820 if (error != 0) 821 break; 822 sysctl_teardown(&adosfs_sysctl_log); 823 break; 824 default: 825 error = ENOTTY; 826 break; 827 } 828 829 return (error); 830 } 831