/* * Routine for "mounting" an emufs - we're not really mounted in the * sense that the VFS understands that term, because we're not * connected to a block device. * * Basically, we just add ourselves to the name list in the VFS layer. */ static int emufs_addtovfs(struct emu_softc *sc, const char *devname) { struct emufs_fs *ef; int result; ef = kmalloc(sizeof(struct emufs_fs)); if (ef==NULL) { return ENOMEM; } ef->ef_fs.fs_sync = emufs_sync; ef->ef_fs.fs_getvolname = emufs_getvolname; ef->ef_fs.fs_getroot = emufs_getroot; ef->ef_fs.fs_unmount = emufs_unmount; ef->ef_fs.fs_data = ef; ef->ef_emu = sc; ef->ef_root = NULL; ef->ef_vnodes = vnodearray_create(); if (ef->ef_vnodes == NULL) { kfree(ef); return ENOMEM; } result = emufs_loadvnode(ef, EMU_ROOTHANDLE, 1, &ef->ef_root); if (result) { kfree(ef); return result; } KASSERT(ef->ef_root!=NULL); result = vfs_addfs(devname, &ef->ef_fs); if (result) { VOP_DECREF(&ef->ef_root->ev_v); kfree(ef); } return result; }
static int sfs_domount(void *options, struct device *dev, struct fs **ret) { int result; struct sfs_fs *sfs; vfs_biglock_acquire(); /* We don't pass any options through mount */ (void)options; /* * Make sure our on-disk structures aren't messed up */ KASSERT(sizeof(struct sfs_super)==SFS_BLOCKSIZE); KASSERT(sizeof(struct sfs_inode)==SFS_BLOCKSIZE); KASSERT(SFS_BLOCKSIZE % sizeof(struct sfs_dir) == 0); /* * We can't mount on devices with the wrong sector size. * * (Note: for all intents and purposes here, "sector" and * "block" are interchangeable terms. Technically a filesystem * block may be composed of several hardware sectors, but we * don't do that in sfs.) */ if (dev->d_blocksize != SFS_BLOCKSIZE) { vfs_biglock_release(); return ENXIO; } /* Allocate object */ sfs = kmalloc(sizeof(struct sfs_fs)); if (sfs==NULL) { vfs_biglock_release(); return ENOMEM; } /* Allocate array */ sfs->sfs_vnodes = vnodearray_create(); if (sfs->sfs_vnodes == NULL) { kfree(sfs); vfs_biglock_release(); return ENOMEM; } /* Set the device so we can use sfs_rblock() */ sfs->sfs_device = dev; /* Load superblock */ result = sfs_rblock(sfs, &sfs->sfs_super, SFS_SB_LOCATION); if (result) { vnodearray_destroy(sfs->sfs_vnodes); kfree(sfs); vfs_biglock_release(); return result; } /* Make some simple sanity checks */ if (sfs->sfs_super.sp_magic != SFS_MAGIC) { kprintf("sfs: Wrong magic number in superblock " "(0x%x, should be 0x%x)\n", sfs->sfs_super.sp_magic, SFS_MAGIC); vnodearray_destroy(sfs->sfs_vnodes); kfree(sfs); vfs_biglock_release(); return EINVAL; } if (sfs->sfs_super.sp_nblocks > dev->d_blocks) { kprintf("sfs: warning - fs has %u blocks, device has %u\n", sfs->sfs_super.sp_nblocks, dev->d_blocks); } /* Ensure null termination of the volume name */ sfs->sfs_super.sp_volname[sizeof(sfs->sfs_super.sp_volname)-1] = 0; /* Load free space bitmap */ sfs->sfs_freemap = bitmap_create(SFS_FS_BITMAPSIZE(sfs)); if (sfs->sfs_freemap == NULL) { vnodearray_destroy(sfs->sfs_vnodes); kfree(sfs); vfs_biglock_release(); return ENOMEM; } result = sfs_mapio(sfs, UIO_READ); if (result) { bitmap_destroy(sfs->sfs_freemap); vnodearray_destroy(sfs->sfs_vnodes); kfree(sfs); vfs_biglock_release(); return result; } /* Set up abstract fs calls */ sfs->sfs_absfs.fs_sync = sfs_sync; sfs->sfs_absfs.fs_getvolname = sfs_getvolname; sfs->sfs_absfs.fs_getroot = sfs_getroot; sfs->sfs_absfs.fs_unmount = sfs_unmount; sfs->sfs_absfs.fs_data = sfs; /* the other fields */ sfs->sfs_superdirty = false; sfs->sfs_freemapdirty = false; /* Hand back the abstract fs */ *ret = &sfs->sfs_absfs; vfs_biglock_release(); return 0; }