Example #1
0
static
int
sfs_sync(struct fs *fs)
{
	struct sfs_fs *sfs;
	unsigned i, num;
	int result;

	vfs_biglock_acquire();

	/*
	 * Get the sfs_fs from the generic abstract fs.
	 *
	 * Note that the abstract struct fs, which is all the VFS
	 * layer knows about, is actually a member of struct sfs_fs.
	 * The pointer in the struct fs points back to the top of the
	 * struct sfs_fs - essentially the same object. This can be a
	 * little confusing at first.
	 *
	 * The following diagram may help:
	 *
	 *     struct sfs_fs        <-------------\
     *           :                            |
     *           :   sfs_absfs (struct fs)    |   <------\
     *           :      :                     |          |
     *           :      :  various members    |          |
     *           :      :                     |          |
     *           :      :  fs_data  ----------/          |
     *           :      :                             ...|...
     *           :                                   .  VFS  .
     *           :                                   . layer .
     *           :   other members                    .......
     *           :
     *           :
	 *
	 * This construct is repeated with vnodes and devices and other
	 * similar things all over the place in OS/161, so taking the
	 * time to straighten it out in your mind is worthwhile.
	 */

	sfs = fs->fs_data;

	/* Go over the array of loaded vnodes, syncing as we go. */
	num = vnodearray_num(sfs->sfs_vnodes);
	for (i=0; i<num; i++) {
		struct vnode *v = vnodearray_get(sfs->sfs_vnodes, i);
		VOP_FSYNC(v);
	}

	/* If the free block map needs to be written, write it. */
	if (sfs->sfs_freemapdirty) {
		result = sfs_mapio(sfs, UIO_WRITE);
		if (result) {
			vfs_biglock_release();
			return result;
		}
		sfs->sfs_freemapdirty = false;
	}

	/* If the superblock needs to be written, write it. */
	if (sfs->sfs_superdirty) {
		result = sfs_wblock(sfs, &sfs->sfs_super, SFS_SB_LOCATION);
		if (result) {
			vfs_biglock_release();
			return result;
		}
		sfs->sfs_superdirty = false;
	}

	vfs_biglock_release();
	return 0;
}
Example #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;
}
Example #3
0
static
int
sfs_sync(struct fs *fs)
{
    struct sfs_fs *sfs;
    int i, num, result;
    struct array *tmp;

    /*
     * Get the sfs_fs from the generic abstract fs.
     *
     * Note that the abstract struct fs, which is all the VFS
     * layer knows about, is actually a member of struct sfs_fs.
     * The pointer in the struct fs points back to the top of the
     * struct sfs_fs - essentially the same object. This can be a
     * little confusing at first.
     *
     * The following diagram may help:
     *
     *     struct sfs_fs        <-------------\
         *           :                            |
         *           :   sfs_absfs (struct fs)    |   <------\
         *           :      :                     |          |
         *           :      :  various members    |          |
         *           :      :                     |          |
         *           :      :  fs_data  ----------/          |
         *           :      :                             ...|...
         *           :                                   .  VFS  .
         *           :                                   . layer .
         *           :   other members                    .......
         *           :
         *           :
     *
     * This construct is repeated with vnodes and devices and other
     * similar things all over the place in OS/161, so taking the
     * time to straighten it out in your mind is worthwhile.
     */

    sfs = fs->fs_data;


    /*
     * This is kind of a hack. We can't acquire vnode locks while
     * holding sfs_vnlock, because that violates the ordering
     * constraints (see sfs_vnode.c) - so we *copy* the array of
     * loaded vnodes into a temporary array and sync those.
     */

    tmp = array_create();
    if (tmp == NULL) {
        return ENOMEM;
    }
    lock_acquire(sfs->sfs_vnlock);

    /* Go over the array of loaded vnodes. */
    num = array_getnum(sfs->sfs_vnodes);
    for (i=0; i<num; i++) {
        struct sfs_vnode *sv = array_getguy(sfs->sfs_vnodes, i);
        VOP_INCREF(&sv->sv_v);
        if (array_add(tmp, sv) != 0) {
            // XXX
            panic("sfs_sync: array_add failed\n");
        }
    }

    lock_release(sfs->sfs_vnlock);

    /* Now sync. */
    num = array_getnum(tmp);
    for (i=0; i<num; i++) {
        struct sfs_vnode *sv = array_getguy(tmp, i);
        result = VOP_FSYNC(&sv->sv_v);
        if (result) {
            kprintf("SFS: Warning: syncing inode %d: %s\n",
                    sv->sv_ino, strerror(result));
        }
        VOP_DECREF(&sv->sv_v);
    }
    array_destroy(tmp);

    lock_acquire(sfs->sfs_bitlock);

    /* If the free block map needs to be written, write it. */
    if (sfs->sfs_freemapdirty) {
        result = sfs_mapio(sfs, UIO_WRITE);
        if (result) {
            kprintf("SFS: Warning: syncing bitmap: %s\n",
                    strerror(result));
        }
        else {
            /* Only clear the dirty bit if we succeeded */
            sfs->sfs_freemapdirty = 0;
        }
    }

    /* If the superblock needs to be written, write it. */
    if (sfs->sfs_superdirty) {
        result = sfs_wblock(sfs, &sfs->sfs_super, SFS_SB_LOCATION);
        if (result) {
            kprintf("SFS: Warning: syncing superblock: %s\n",
                    strerror(result));
        }
        else {
            /* Only clear the dirty bit if we succeeded */
            sfs->sfs_superdirty = 0;
        }
    }

    lock_release(sfs->sfs_bitlock);

    return 0;
}