1 /* $NetBSD: filecore_vfsops.c,v 1.16 2004/09/13 19:25:48 jdolecek Exp $ */ 2 3 /*- 4 * Copyright (c) 1994 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * filecore_vfsops.c 1.1 1998/6/26 32 */ 33 34 /*- 35 * Copyright (c) 1998 Andrew McMurry 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Berkeley and its contributors. 49 * 4. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * filecore_vfsops.c 1.1 1998/6/26 66 */ 67 68 #include <sys/cdefs.h> 69 __KERNEL_RCSID(0, "$NetBSD: filecore_vfsops.c,v 1.16 2004/09/13 19:25:48 jdolecek Exp $"); 70 71 #if defined(_KERNEL_OPT) 72 #include "opt_compat_netbsd.h" 73 #endif 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/namei.h> 78 #include <sys/proc.h> 79 #include <sys/vnode.h> 80 #include <miscfs/specfs/specdev.h> 81 #include <sys/mount.h> 82 #include <sys/buf.h> 83 #include <sys/file.h> 84 #include <sys/device.h> 85 #include <sys/errno.h> 86 #include <sys/malloc.h> 87 #include <sys/pool.h> 88 #include <sys/conf.h> 89 #include <sys/sysctl.h> 90 91 #include <fs/filecorefs/filecore.h> 92 #include <fs/filecorefs/filecore_extern.h> 93 #include <fs/filecorefs/filecore_node.h> 94 #include <fs/filecorefs/filecore_mount.h> 95 96 MALLOC_DEFINE(M_FILECOREMNT, "filecore mount", "Filecore FS mount structures"); 97 98 extern const struct vnodeopv_desc filecore_vnodeop_opv_desc; 99 100 const struct vnodeopv_desc * const filecore_vnodeopv_descs[] = { 101 &filecore_vnodeop_opv_desc, 102 NULL, 103 }; 104 105 struct vfsops filecore_vfsops = { 106 MOUNT_FILECORE, 107 filecore_mount, 108 filecore_start, 109 filecore_unmount, 110 filecore_root, 111 filecore_quotactl, 112 filecore_statvfs, 113 filecore_sync, 114 filecore_vget, 115 filecore_fhtovp, 116 filecore_vptofh, 117 filecore_init, 118 filecore_reinit, 119 filecore_done, 120 NULL, 121 NULL, /* filecore_mountroot */ 122 filecore_checkexp, 123 (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp, 124 filecore_vnodeopv_descs, 125 }; 126 127 struct genfs_ops filecore_genfsops = { 128 genfs_size, 129 }; 130 131 /* 132 * Called by vfs_mountroot when iso is going to be mounted as root. 133 * 134 * Name is updated by mount(8) after booting. 135 */ 136 137 static int filecore_mountfs __P((struct vnode *devvp, struct mount *mp, 138 struct proc *p, struct filecore_args *argp)); 139 140 #if 0 141 int 142 filecore_mountroot() 143 { 144 struct mount *mp; 145 extern struct vnode *rootvp; 146 struct proc *p = curproc; /* XXX */ 147 int error; 148 struct filecore_args args; 149 150 if (root_device->dv_class != DV_DISK) 151 return (ENODEV); 152 153 /* 154 * Get vnodes for swapdev and rootdev. 155 */ 156 if (bdevvp(rootdev, &rootvp)) 157 panic("filecore_mountroot: can't setup rootvp"); 158 159 if ((error = vfs_rootmountalloc(MOUNT_FILECORE, "root_device", &mp)) != 0) 160 return (error); 161 162 args.flags = FILECOREMNT_ROOT; 163 if ((error = filecore_mountfs(rootvp, mp, p, &args)) != 0) { 164 mp->mnt_op->vfs_refcount--; 165 vfs_unbusy(mp); 166 free(mp, M_MOUNT); 167 return (error); 168 } 169 simple_lock(&mountlist_slock); 170 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 171 simple_unlock(&mountlist_slock); 172 (void)filecore_statvfs(mp, &mp->mnt_stat, p); 173 vfs_unbusy(mp); 174 return (0); 175 } 176 #endif 177 178 /* 179 * VFS Operations. 180 * 181 * mount system call 182 */ 183 int 184 filecore_mount(mp, path, data, ndp, p) 185 struct mount *mp; 186 const char *path; 187 void *data; 188 struct nameidata *ndp; 189 struct proc *p; 190 { 191 struct vnode *devvp; 192 struct filecore_args args; 193 int error; 194 struct filecore_mnt *fcmp = NULL; 195 196 if (mp->mnt_flag & MNT_GETARGS) { 197 fcmp = VFSTOFILECORE(mp); 198 if (fcmp == NULL) 199 return EIO; 200 args.flags = fcmp->fc_mntflags; 201 args.uid = fcmp->fc_uid; 202 args.gid = fcmp->fc_gid; 203 args.fspec = NULL; 204 vfs_showexport(mp, &args.export, &fcmp->fc_export); 205 return copyout(&args, data, sizeof(args)); 206 } 207 error = copyin(data, &args, sizeof (struct filecore_args)); 208 if (error) 209 return (error); 210 211 if ((mp->mnt_flag & MNT_RDONLY) == 0) 212 return (EROFS); 213 214 /* 215 * If updating, check whether changing from read-only to 216 * read/write; if there is no device name, that's all we do. 217 */ 218 if (mp->mnt_flag & MNT_UPDATE) { 219 fcmp = VFSTOFILECORE(mp); 220 if (args.fspec == 0) 221 return (vfs_export(mp, &fcmp->fc_export, &args.export)); 222 } 223 /* 224 * Not an update, or updating the name: look up the name 225 * and verify that it refers to a sensible block device. 226 */ 227 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 228 if ((error = namei(ndp)) != 0) 229 return (error); 230 devvp = ndp->ni_vp; 231 232 if (devvp->v_type != VBLK) { 233 vrele(devvp); 234 return ENOTBLK; 235 } 236 if (bdevsw_lookup(devvp->v_rdev) == NULL) { 237 vrele(devvp); 238 return ENXIO; 239 } 240 /* 241 * If mount by non-root, then verify that user has necessary 242 * permissions on the device. 243 */ 244 if (p->p_ucred->cr_uid != 0) { 245 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 246 error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p); 247 VOP_UNLOCK(devvp, 0); 248 if (error) { 249 vrele(devvp); 250 return (error); 251 } 252 } 253 if ((mp->mnt_flag & MNT_UPDATE) == 0) 254 error = filecore_mountfs(devvp, mp, p, &args); 255 else { 256 if (devvp != fcmp->fc_devvp) 257 error = EINVAL; /* needs translation */ 258 else 259 vrele(devvp); 260 } 261 if (error) { 262 vrele(devvp); 263 return error; 264 } 265 fcmp = VFSTOFILECORE(mp); 266 return set_statvfs_info(path, UIO_USERSPACE, args.fspec, UIO_USERSPACE, 267 mp, p); 268 } 269 270 /* 271 * Common code for mount and mountroot 272 */ 273 static int 274 filecore_mountfs(devvp, mp, p, argp) 275 struct vnode *devvp; 276 struct mount *mp; 277 struct proc *p; 278 struct filecore_args *argp; 279 { 280 struct filecore_mnt *fcmp = (struct filecore_mnt *)0; 281 struct buf *bp = NULL; 282 dev_t dev = devvp->v_rdev; 283 int error = EINVAL; 284 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 285 extern struct vnode *rootvp; 286 struct filecore_disc_record *fcdr; 287 unsigned map; 288 unsigned log2secsize; 289 290 if (!ronly) 291 return EROFS; 292 293 /* 294 * Disallow multiple mounts of the same device. 295 * Disallow mounting of a device that is currently in use 296 * (except for root, which might share swap device for miniroot). 297 * Flush out any old buffers remaining from a previous use. 298 */ 299 if ((error = vfs_mountedon(devvp)) != 0) 300 return error; 301 if (vcount(devvp) > 1 && devvp != rootvp) 302 return EBUSY; 303 if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) 304 return (error); 305 306 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 307 if (error) 308 return error; 309 310 /* Read the filecore boot block to check FS validity and to find the map */ 311 error = bread(devvp, FILECORE_BOOTBLOCK_BLKN, 312 FILECORE_BOOTBLOCK_SIZE, NOCRED, &bp); 313 #ifdef FILECORE_DEBUG_BR 314 printf("bread(%p, %x, %d, CRED, %p)=%d\n", devvp, 315 FILECORE_BOOTBLOCK_BLKN, FILECORE_BOOTBLOCK_SIZE, 316 bp, error); 317 #endif 318 if (error != 0) 319 goto out; 320 if (filecore_bbchecksum(bp->b_data) != 0) { 321 error = EINVAL; 322 goto out; 323 } 324 fcdr = (struct filecore_disc_record *)(bp->b_data+FILECORE_BB_DISCREC); 325 map = ((((8 << fcdr->log2secsize) - fcdr->zone_spare) 326 * (fcdr->nzones / 2) - 8 * FILECORE_DISCREC_SIZE) 327 << fcdr->log2bpmb) >> fcdr->log2secsize; 328 log2secsize = fcdr->log2secsize; 329 bp->b_flags |= B_AGE; 330 #ifdef FILECORE_DEBUG_BR 331 printf("brelse(%p) vf1\n", bp); 332 #endif 333 brelse(bp); 334 bp = NULL; 335 336 /* Read the bootblock in the map */ 337 error = bread(devvp, map, 1 << log2secsize, NOCRED, &bp); 338 #ifdef FILECORE_DEBUG_BR 339 printf("bread(%p, %x, %d, CRED, %p)=%d\n", devvp, 340 map, 1 << log2secsize, bp, error); 341 #endif 342 if (error != 0) 343 goto out; 344 fcdr = (struct filecore_disc_record *)(bp->b_data + 4); 345 fcmp = malloc(sizeof *fcmp, M_FILECOREMNT, M_WAITOK); 346 memset(fcmp, 0, sizeof *fcmp); 347 if (fcdr->log2bpmb > fcdr->log2secsize) 348 fcmp->log2bsize = fcdr->log2bpmb; 349 else fcmp->log2bsize = fcdr->log2secsize; 350 fcmp->blksize = 1 << fcmp->log2bsize; 351 memcpy(&fcmp->drec, fcdr, sizeof(*fcdr)); 352 fcmp->map = map; 353 fcmp->idspz = ((8 << fcdr->log2secsize) - fcdr->zone_spare) 354 / (fcdr->idlen + 1); 355 fcmp->mask = (1 << fcdr->idlen) - 1; 356 if (fcdr->big_flag & 1) { 357 fcmp->nblks = ((((u_int64_t)fcdr->disc_size_2) << 32) 358 + fcdr->disc_size) / fcmp->blksize; 359 } else { 360 fcmp->nblks=fcdr->disc_size / fcmp->blksize; 361 } 362 363 bp->b_flags |= B_AGE; 364 #ifdef FILECORE_DEBUG_BR 365 printf("brelse(%p) vf2\n", bp); 366 #endif 367 brelse(bp); 368 bp = NULL; 369 370 mp->mnt_data = fcmp; 371 mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev; 372 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FILECORE); 373 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 374 mp->mnt_stat.f_namemax = 10; 375 mp->mnt_flag |= MNT_LOCAL; 376 mp->mnt_dev_bshift = fcdr->log2secsize; 377 mp->mnt_fs_bshift = fcmp->log2bsize; 378 379 fcmp->fc_mountp = mp; 380 fcmp->fc_dev = dev; 381 fcmp->fc_devvp = devvp; 382 fcmp->fc_mntflags = argp->flags; 383 if (argp->flags & FILECOREMNT_USEUID) { 384 fcmp->fc_uid = p->p_cred->p_ruid; 385 fcmp->fc_gid = p->p_cred->p_rgid; 386 } else { 387 fcmp->fc_uid = argp->uid; 388 fcmp->fc_gid = argp->gid; 389 } 390 391 return 0; 392 out: 393 if (bp) { 394 #ifdef FILECORE_DEBUG_BR 395 printf("brelse(%p) vf3\n", bp); 396 #endif 397 brelse(bp); 398 } 399 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 400 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 401 VOP_UNLOCK(devvp, 0); 402 if (fcmp) { 403 free(fcmp, M_FILECOREMNT); 404 mp->mnt_data = NULL; 405 } 406 return error; 407 } 408 409 /* 410 * Make a filesystem operational. 411 * Nothing to do at the moment. 412 */ 413 /* ARGSUSED */ 414 int 415 filecore_start(mp, flags, p) 416 struct mount *mp; 417 int flags; 418 struct proc *p; 419 { 420 return 0; 421 } 422 423 /* 424 * unmount system call 425 */ 426 int 427 filecore_unmount(mp, mntflags, p) 428 struct mount *mp; 429 int mntflags; 430 struct proc *p; 431 { 432 struct filecore_mnt *fcmp; 433 int error, flags = 0; 434 435 if (mntflags & MNT_FORCE) 436 flags |= FORCECLOSE; 437 #if 0 438 mntflushbuf(mp, 0); 439 if (mntinvalbuf(mp)) 440 return EBUSY; 441 #endif 442 if ((error = vflush(mp, NULLVP, flags)) != 0) 443 return (error); 444 445 fcmp = VFSTOFILECORE(mp); 446 447 if (fcmp->fc_devvp->v_type != VBAD) 448 fcmp->fc_devvp->v_specmountpoint = NULL; 449 vn_lock(fcmp->fc_devvp, LK_EXCLUSIVE | LK_RETRY); 450 error = VOP_CLOSE(fcmp->fc_devvp, FREAD, NOCRED, p); 451 vput(fcmp->fc_devvp); 452 free(fcmp, M_FILECOREMNT); 453 mp->mnt_data = NULL; 454 mp->mnt_flag &= ~MNT_LOCAL; 455 return (error); 456 } 457 458 /* 459 * Return root of a filesystem 460 */ 461 int 462 filecore_root(mp, vpp) 463 struct mount *mp; 464 struct vnode **vpp; 465 { 466 struct vnode *nvp; 467 int error; 468 469 if ((error = VFS_VGET(mp, FILECORE_ROOTINO, &nvp)) != 0) 470 return (error); 471 *vpp = nvp; 472 return (0); 473 } 474 475 /* 476 * Do operations associated with quotas, not supported 477 */ 478 /* ARGSUSED */ 479 int 480 filecore_quotactl(mp, cmd, uid, arg, p) 481 struct mount *mp; 482 int cmd; 483 uid_t uid; 484 void *arg; 485 struct proc *p; 486 { 487 488 return (EOPNOTSUPP); 489 } 490 491 /* 492 * Get file system statistics. 493 */ 494 int 495 filecore_statvfs(mp, sbp, p) 496 struct mount *mp; 497 struct statvfs *sbp; 498 struct proc *p; 499 { 500 struct filecore_mnt *fcmp = VFSTOFILECORE(mp); 501 502 sbp->f_bsize = fcmp->blksize; 503 sbp->f_frsize = sbp->f_bsize; /* XXX */ 504 sbp->f_iosize = sbp->f_bsize; /* XXX */ 505 sbp->f_blocks = fcmp->nblks; 506 sbp->f_bfree = 0; /* total free blocks */ 507 sbp->f_bavail = 0; /* blocks free for non superuser */ 508 sbp->f_bresvd = 0; /* reserved blocks */ 509 sbp->f_files = 0; /* total files */ 510 sbp->f_ffree = 0; /* free file nodes for non superuser */ 511 sbp->f_favail = 0; /* free file nodes */ 512 sbp->f_fresvd = 0; /* reserved file nodes */ 513 copy_statvfs_info(sbp, mp); 514 return 0; 515 } 516 517 /* ARGSUSED */ 518 int 519 filecore_sync(mp, waitfor, cred, p) 520 struct mount *mp; 521 int waitfor; 522 struct ucred *cred; 523 struct proc *p; 524 { 525 return (0); 526 } 527 528 /* 529 * File handle to vnode 530 * 531 * Have to be really careful about stale file handles: 532 * - check that the inode number is in range 533 * - call iget() to get the locked inode 534 * - check for an unallocated inode (i_mode == 0) 535 * - check that the generation number matches 536 */ 537 538 struct ifid { 539 ushort ifid_len; 540 ushort ifid_pad; 541 u_int32_t ifid_ino; 542 }; 543 544 /* ARGSUSED */ 545 int 546 filecore_fhtovp(mp, fhp, vpp) 547 struct mount *mp; 548 struct fid *fhp; 549 struct vnode **vpp; 550 { 551 struct ifid *ifhp = (struct ifid *)fhp; 552 struct vnode *nvp; 553 struct filecore_node *ip; 554 int error; 555 556 if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) { 557 *vpp = NULLVP; 558 return (error); 559 } 560 ip = VTOI(nvp); 561 if (filecore_staleinode(ip)) { 562 vput(nvp); 563 *vpp = NULLVP; 564 return (ESTALE); 565 } 566 *vpp = nvp; 567 return (0); 568 } 569 570 /* ARGSUSED */ 571 int 572 filecore_checkexp(mp, nam, exflagsp, credanonp) 573 struct mount *mp; 574 struct mbuf *nam; 575 int *exflagsp; 576 struct ucred **credanonp; 577 { 578 struct filecore_mnt *fcmp = VFSTOFILECORE(mp); 579 struct netcred *np; 580 581 /* 582 * Get the export permission structure for this <mp, client> tuple. 583 */ 584 np = vfs_export_lookup(mp, &fcmp->fc_export, nam); 585 if (np == NULL) 586 return (EACCES); 587 588 *exflagsp = np->netc_exflags; 589 *credanonp = &np->netc_anon; 590 return (0); 591 } 592 593 /* This looks complicated. Look at other vgets as well as the iso9660 one. 594 * 595 * The filecore inode number is made up of 1 byte directory entry index and 596 * 3 bytes of the internal disc address of the directory. On a read-only 597 * filesystem this is unique. For a read-write version we may not be able to 598 * do vget, see msdosfs. 599 */ 600 601 int 602 filecore_vget(mp, ino, vpp) 603 struct mount *mp; 604 ino_t ino; 605 struct vnode **vpp; 606 { 607 struct filecore_mnt *fcmp; 608 struct filecore_node *ip; 609 struct buf *bp; 610 struct vnode *vp; 611 dev_t dev; 612 int error; 613 614 fcmp = VFSTOFILECORE(mp); 615 dev = fcmp->fc_dev; 616 if ((*vpp = filecore_ihashget(dev, ino)) != NULLVP) 617 return (0); 618 619 /* Allocate a new vnode/filecore_node. */ 620 if ((error = getnewvnode(VT_FILECORE, mp, filecore_vnodeop_p, &vp)) 621 != 0) { 622 *vpp = NULLVP; 623 return (error); 624 } 625 ip = pool_get(&filecore_node_pool, PR_WAITOK); 626 memset(ip, 0, sizeof(struct filecore_node)); 627 vp->v_data = ip; 628 ip->i_vnode = vp; 629 ip->i_dev = dev; 630 ip->i_number = ino; 631 ip->i_block = -1; 632 ip->i_parent = -2; 633 634 /* 635 * Put it onto its hash chain and lock it so that other requests for 636 * this inode will block if they arrive while we are sleeping waiting 637 * for old data structures to be purged or for the contents of the 638 * disk portion of this inode to be read. 639 */ 640 filecore_ihashins(ip); 641 642 if (ino == FILECORE_ROOTINO) { 643 /* Here we need to construct a root directory inode */ 644 memcpy(ip->i_dirent.name, "root", 4); 645 ip->i_dirent.load = 0; 646 ip->i_dirent.exec = 0; 647 ip->i_dirent.len = FILECORE_DIR_SIZE; 648 ip->i_dirent.addr = fcmp->drec.root; 649 ip->i_dirent.attr = FILECORE_ATTR_DIR | FILECORE_ATTR_READ; 650 651 } else { 652 /* Read in Data from Directory Entry */ 653 if ((error = filecore_bread(fcmp, ino & FILECORE_INO_MASK, 654 FILECORE_DIR_SIZE, NOCRED, &bp)) != 0) { 655 vput(vp); 656 #ifdef FILECORE_DEBUG_BR 657 printf("brelse(%p) vf4\n", bp); 658 #endif 659 brelse(bp); 660 *vpp = NULL; 661 return (error); 662 } 663 664 memcpy(&ip->i_dirent, 665 fcdirentry(bp->b_data, ino >> FILECORE_INO_INDEX), 666 sizeof(struct filecore_direntry)); 667 #ifdef FILECORE_DEBUG_BR 668 printf("brelse(%p) vf5\n", bp); 669 #endif 670 brelse(bp); 671 } 672 673 ip->i_mnt = fcmp; 674 ip->i_devvp = fcmp->fc_devvp; 675 ip->i_diroff = 0; 676 VREF(ip->i_devvp); 677 678 /* 679 * Setup type 680 */ 681 vp->v_type = VREG; 682 if (ip->i_dirent.attr & FILECORE_ATTR_DIR) 683 vp->v_type = VDIR; 684 685 /* 686 * Initialize the associated vnode 687 */ 688 switch (vp->v_type) { 689 case VFIFO: 690 case VCHR: 691 case VBLK: 692 /* 693 * Devices not supported. 694 */ 695 vput(vp); 696 return (EOPNOTSUPP); 697 case VLNK: 698 case VNON: 699 case VSOCK: 700 case VDIR: 701 case VBAD: 702 case VREG: 703 break; 704 } 705 706 if (ino == FILECORE_ROOTINO) 707 vp->v_flag |= VROOT; 708 709 /* 710 * XXX need generation number? 711 */ 712 713 genfs_node_init(vp, &filecore_genfsops); 714 vp->v_size = ip->i_size; 715 *vpp = vp; 716 return (0); 717 } 718 719 /* 720 * Vnode pointer to File handle 721 */ 722 /* ARGSUSED */ 723 int 724 filecore_vptofh(vp, fhp) 725 struct vnode *vp; 726 struct fid *fhp; 727 { 728 struct filecore_node *ip = VTOI(vp); 729 struct ifid *ifhp; 730 731 ifhp = (struct ifid *)fhp; 732 ifhp->ifid_len = sizeof(struct ifid); 733 ifhp->ifid_ino = ip->i_number; 734 return 0; 735 } 736 737 SYSCTL_SETUP(sysctl_vfs_filecore_setup, "sysctl vfs.filecore subtree setup") 738 { 739 740 sysctl_createv(clog, 0, NULL, NULL, 741 CTLFLAG_PERMANENT, 742 CTLTYPE_NODE, "vfs", NULL, 743 NULL, 0, NULL, 0, 744 CTL_VFS, CTL_EOL); 745 sysctl_createv(clog, 0, NULL, NULL, 746 CTLFLAG_PERMANENT, 747 CTLTYPE_NODE, "filecore", 748 SYSCTL_DESCR("Acorn FILECORE file system"), 749 NULL, 0, NULL, 0, 750 CTL_VFS, 19, CTL_EOL); 751 /* 752 * XXX the "19" above could be dynamic, thereby eliminating 753 * one more instance of the "number to vfs" mapping problem, 754 * but "19" is the order as taken from sys/mount.h 755 */ 756 } 757