Example #1
0
/*
 * VOP_RECLAIM
 *
 * Reclaim should make an effort to returning errors other than EBUSY.
 */
static
int
emufs_reclaim(struct vnode *v)
{
    struct emufs_vnode *ev = v->vn_data;
    struct emufs_fs *ef = v->vn_fs->fs_data;
    unsigned ix, i, num;
    int result;

    /*
     * Need both of these locks, e_lock to protect the device
     * and vfs_biglock to protect the fs-related material.
     */

    vfs_biglock_acquire();
    lock_acquire(ef->ef_emu->e_lock);

    if (ev->ev_v.vn_refcount != 1) {
        lock_release(ef->ef_emu->e_lock);
        vfs_biglock_release();
        return EBUSY;
    }

    /* emu_close retries on I/O error */
    result = emu_close(ev->ev_emu, ev->ev_handle);
    if (result) {
        lock_release(ef->ef_emu->e_lock);
        vfs_biglock_release();
        return result;
    }

    num = vnodearray_num(ef->ef_vnodes);
    ix = num;
    for (i=0; i<num; i++) {
        struct vnode *vx;

        vx = vnodearray_get(ef->ef_vnodes, i);
        if (vx == v) {
            ix = i;
            break;
        }
    }
    if (ix == num) {
        panic("emu%d: reclaim vnode %u not in vnode pool\n",
              ef->ef_emu->e_unit, ev->ev_handle);
    }

    vnodearray_remove(ef->ef_vnodes, ix);
    VOP_CLEANUP(&ev->ev_v);

    lock_release(ef->ef_emu->e_lock);
    vfs_biglock_release();

    kfree(ev);
    return 0;
}
Example #2
0
/*
 * Reclaim - drop a vnode that's no longer in use.
 */
static
int
semfs_reclaim(struct vnode *vn)
{
	struct semfs_vnode *semv = vn->vn_data;
	struct semfs *semfs = semv->semv_semfs;
	struct vnode *vn2;
	struct semfs_sem *sem;
	unsigned i, num;

	lock_acquire(semfs->semfs_tablelock);

	/* vnode refcount is protected by the vnode's ->vn_countlock */
	spinlock_acquire(&vn->vn_countlock);
	if (vn->vn_refcount > 1) {
		/* consume the reference VOP_DECREF passed us */
		vn->vn_refcount--;

		spinlock_release(&vn->vn_countlock);
		lock_release(semfs->semfs_tablelock);
		return EBUSY;
	}

	spinlock_release(&vn->vn_countlock);

	/* remove from the table */
	num = vnodearray_num(semfs->semfs_vnodes);
	for (i=0; i<num; i++) {
		vn2 = vnodearray_get(semfs->semfs_vnodes, i);
		if (vn2 == vn) {
			vnodearray_remove(semfs->semfs_vnodes, i);
			break;
		}
	}

	if (semv->semv_semnum != SEMFS_ROOTDIR) {
		sem = semfs_semarray_get(semfs->semfs_sems, semv->semv_semnum);
		KASSERT(sem->sems_hasvnode);
		sem->sems_hasvnode = false;
		if (sem->sems_linked == false) {
			semfs_semarray_set(semfs->semfs_sems,
					   semv->semv_semnum, NULL);
			semfs_sem_destroy(sem);
		}
	}

	/* done with the table */
	lock_release(semfs->semfs_tablelock);

	/* destroy it */
	semfs_vnode_destroy(semv);
	return 0;
}
Example #3
0
/*
 * Called when the vnode refcount (in-memory usage count) hits zero.
 *
 * This function should try to avoid returning errors other than EBUSY.
 */
static
int
sfs_reclaim(struct vnode *v)
{
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_fs *sfs = v->vn_fs->fs_data;
	unsigned ix, i, num;
	int result;

	vfs_biglock_acquire();

	/*
	 * Make sure someone else hasn't picked up the vnode since the
	 * decision was made to reclaim it. (You must also synchronize
	 * this with sfs_loadvnode.)
	 */
	if (v->vn_refcount != 1) {

		/* consume the reference VOP_DECREF gave us */
		KASSERT(v->vn_refcount>1);
		v->vn_refcount--;

		vfs_biglock_release();
		return EBUSY;
	}

	/* If there are no on-disk references to the file either, erase it. */
	if (sv->sv_i.sfi_linkcount==0) {
		result = VOP_TRUNCATE(&sv->sv_v, 0);
		if (result) {
			vfs_biglock_release();
			return result;
		}
	}

	/* Sync the inode to disk */
	result = sfs_sync_inode(sv);
	if (result) {
		vfs_biglock_release();
		return result;
	}

	/* If there are no on-disk references, discard the inode */
	if (sv->sv_i.sfi_linkcount==0) {
		sfs_bfree(sfs, sv->sv_ino);
	}

	/* Remove the vnode structure from the table in the struct sfs_fs. */
	num = vnodearray_num(sfs->sfs_vnodes);
	ix = num;
	for (i=0; i<num; i++) {
		struct vnode *v2 = vnodearray_get(sfs->sfs_vnodes, i);
		struct sfs_vnode *sv2 = v2->vn_data;
		if (sv2 == sv) {
			ix = i;
			break;
		}
	}
	if (ix == num) {
		panic("sfs: reclaim vnode %u not in vnode pool\n",
		      sv->sv_ino);
	}
	vnodearray_remove(sfs->sfs_vnodes, ix);

	VOP_CLEANUP(&sv->sv_v);

	vfs_biglock_release();

	/* Release the storage for the vnode structure itself. */
	kfree(sv);

	/* Done */
	return 0;
}
Example #4
0
/*
 * VOP_RECLAIM
 *
 * Reclaim should make an effort to returning errors other than EBUSY.
 */
static
int
emufs_reclaim(struct vnode *v)
{
	struct emufs_vnode *ev = v->vn_data;
	struct emufs_fs *ef = v->vn_fs->fs_data;
	unsigned ix, i, num;
	int result;

	/*
	 * Need both of these locks: e_lock to protect the device,
	 * and vn_countlock for the reference count.
	 */

	lock_acquire(ef->ef_emu->e_lock);
	spinlock_acquire(&ev->ev_v.vn_countlock);

	if (ev->ev_v.vn_refcount > 1) {
		/* consume the reference VOP_DECREF passed us */
		ev->ev_v.vn_refcount--;

		spinlock_release(&ev->ev_v.vn_countlock);
		lock_release(ef->ef_emu->e_lock);
		return EBUSY;
	}
	KASSERT(ev->ev_v.vn_refcount == 1);

	/*
	 * Since we hold e_lock and are the last ref, nobody can increment
	 * the refcount, so we can release vn_countlock.
	 */
	spinlock_release(&ev->ev_v.vn_countlock);

	/* emu_close retries on I/O error */
	result = emu_close(ev->ev_emu, ev->ev_handle);
	if (result) {
		lock_release(ef->ef_emu->e_lock);
		return result;
	}

	num = vnodearray_num(ef->ef_vnodes);
	ix = num;
	for (i=0; i<num; i++) {
		struct vnode *vx;

		vx = vnodearray_get(ef->ef_vnodes, i);
		if (vx == v) {
			ix = i;
			break;
		}
	}
	if (ix == num) {
		panic("emu%d: reclaim vnode %u not in vnode pool\n",
		      ef->ef_emu->e_unit, ev->ev_handle);
	}

	vnodearray_remove(ef->ef_vnodes, ix);
	vnode_cleanup(&ev->ev_v);

	lock_release(ef->ef_emu->e_lock);

	kfree(ev);
	return 0;
}