Ejemplo n.º 1
0
/*
 * Called for fsync().
 *
 * Since for now the buffer cache can't sync just one file, sync the
 * whole fs. This is lame.
 *
 * Locking: gets/releases vnode lock. (XXX: really?)
 */
static
int
sfs_fsync(struct vnode *v)
{
	struct sfs_vnode *sv = v->vn_data;

	return FSOP_SYNC(sv->sv_absvn.vn_fs);
}
Ejemplo n.º 2
0
/*
 * Unmount a filesystem/device by name.
 * First calls FSOP_SYNC on the filesystem; then calls FSOP_UNMOUNT.
 */
int
vfs_unmount(const char *devname)
{
	struct knowndev *kd;
	int result;

	vfs_biglock_acquire();

	result = findmount(devname, &kd);
	if (result) {
		goto fail;
	}

	if (kd->kd_fs == NULL) {
		result = EINVAL;
		goto fail;
	}
	KASSERT(kd->kd_rawname != NULL);
	KASSERT(kd->kd_device != NULL);

	/* sync the fs */
	result = FSOP_SYNC(kd->kd_fs);
	if (result) {
		goto fail;
	}

	result = FSOP_UNMOUNT(kd->kd_fs);
	if (result) {
		goto fail;
	}

	kprintf("vfs: Unmounted %s:\n", kd->kd_name);

	/* now drop the filesystem */
	kd->kd_fs = NULL;

	KASSERT(result==0);

 fail:
	vfs_biglock_release();
	return result;
}
Ejemplo n.º 3
0
/*
 * Global sync function - call FSOP_SYNC on all devices.
 */
int
vfs_sync(void)
{
	struct knowndev *dev;
	unsigned i, num;

	vfs_biglock_acquire();

	num = knowndevarray_num(knowndevs);
	for (i=0; i<num; i++) {
		dev = knowndevarray_get(knowndevs, i);
		if (dev->kd_fs != NULL) {
			/*result =*/ FSOP_SYNC(dev->kd_fs);
		}
	}

	vfs_biglock_release();

	return 0;
}
Ejemplo n.º 4
0
// Gets the next physical block available for journal and sets jnl->current
// Must hold the journal lock
static
int
jnl_next_block(struct journal *jnl)
{
    int err;
    
    KASSERT(lock_do_i_hold(jnl->jnl_lock));
    
    daddr_t next_current = jnl->jnl_current + 1;
    daddr_t next_block = jnl->jnl_base + next_current;
    daddr_t next_base = jnl->jnl_base;
    
    if (next_block >= jnl->jnl_top || next_current >= MAX_JNLBLKS) {
        err = jnl_sync(jnl);
        if (err)
            return err;
        return 0;
    }
    
    // We've hit our checkpoint so next block is unavailable
    // In this case, flush all the file system buffers
    while (next_block == jnl->jnl_checkpoint) {
        lock_release(jnl->jnl_lock);
        err = FSOP_SYNC(jnl->jnl_fs);
        if (err) {
            lock_acquire(jnl->jnl_lock);
            return err;
        }
        lock_acquire(jnl->jnl_lock);
    }
    
    jnl->jnl_base = next_base;
    jnl->jnl_current = next_current;
    
    return 0;
}
Ejemplo n.º 5
0
/*
 * Global unmount function.
 */
int
vfs_unmountall(void)
{
	struct knowndev *dev;
	unsigned i, num;
	int result;

	vfs_biglock_acquire();

	num = knowndevarray_num(knowndevs);
	for (i=0; i<num; i++) {
		dev = knowndevarray_get(knowndevs, i);
		if (dev->kd_rawname == NULL) {
			/* not mountable/unmountable */
			continue;
		}
		if (dev->kd_fs == NULL) {
			/* not mounted */
			continue;
		}

		kprintf("vfs: Unmounting %s:\n", dev->kd_name);

		result = FSOP_SYNC(dev->kd_fs);
		if (result) {
			kprintf("vfs: Warning: sync failed for %s: %s, trying "
				"again\n", dev->kd_name, strerror(result));

			result = FSOP_SYNC(dev->kd_fs);
			if (result) {
				kprintf("vfs: Warning: sync failed second time"
					" for %s: %s, giving up...\n",
					dev->kd_name, strerror(result));
				/*
				 * Do not attempt to complete the
				 * unmount as it will likely explode.
				 */
				continue;
			}
		}

		result = FSOP_UNMOUNT(dev->kd_fs);
		if (result == EBUSY) {
			kprintf("vfs: Cannot unmount %s: (busy)\n",
				dev->kd_name);
			continue;
		}
		if (result) {
			kprintf("vfs: Warning: unmount failed for %s:"
				" %s, already synced, dropping...\n",
				dev->kd_name, strerror(result));
			continue;
		}

		/* now drop the filesystem */
		dev->kd_fs = NULL;
	}

	vfs_biglock_release();

	return 0;
}
Ejemplo n.º 6
0
int
sfs_jnlmount(struct sfs_fs *sfs, uint64_t txnid_next, daddr_t checkpoint)
{
    struct journal *jnl = kmalloc(sizeof(struct journal));
    if (jnl == NULL)
        return ENOMEM;
    jnl->jnl_lock = lock_create("SFS Journal Lock");
    if (jnl->jnl_lock == NULL) {
        kfree(jnl);
        return ENOMEM;
    }
    jnl->jnl_txnqueue = transactionarray_create();
    if (jnl->jnl_txnqueue == NULL) {
        lock_destroy(jnl->jnl_lock);
        kfree(jnl);
        return ENOMEM;
    }
    
    // Set other fields
    jnl->jnl_fs = &sfs->sfs_absfs;
    jnl->jnl_bottom = SFS_JNLSTART(sfs->sfs_super.sp_nblocks);
    jnl->jnl_top = jnl->jnl_bottom + SFS_JNLSIZE(sfs->sfs_super.sp_nblocks);
    
    // set default values
    jnl->jnl_txnid_next = txnid_next;
    jnl->jnl_checkpoint = checkpoint;
    
    if (!sfs->sfs_super.sp_clean) {
        // need recovery
        int err = sfs_recover(sfs, &jnl->jnl_checkpoint, &jnl->jnl_txnid_next);
        if (err) {
            transactionarray_destroy(jnl->jnl_txnqueue);
            lock_destroy(jnl->jnl_lock);
            kfree(jnl);
            return err;
        }
        
        // so that FSOP_SYNC will not try to sync the journal
        sfs->sfs_jnl = NULL;
        
        // sync the changes to disk
        err = FSOP_SYNC(&sfs->sfs_absfs);
        if (err) {
            transactionarray_destroy(jnl->jnl_txnqueue);
            lock_destroy(jnl->jnl_lock);
            kfree(jnl);
            return err;
        }
        
        // update the superblock
        sfs->sfs_super.sp_ckpoint = jnl->jnl_checkpoint;
        sfs->sfs_super.sp_txnid = jnl->jnl_txnid_next;
        sfs->sfs_superdirty = true;
        err = sfs_writesuper(sfs);
        if (err) {
            transactionarray_destroy(jnl->jnl_txnqueue);
            lock_destroy(jnl->jnl_lock);
            kfree(jnl);
            return err;
        }
    }
    
    jnl->jnl_base = jnl->jnl_checkpoint;
    jnl->jnl_current = 0;
    jnl->jnl_blkoffset = 0;
    
    sfs->sfs_jnl = jnl;
    return 0;
}