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