Ejemplo n.º 1
0
/*
 * 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;
}
Ejemplo n.º 2
0
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;
}