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