Exemple #1
0
void
zfs_delete_thread(void *arg)
{
	zfsvfs_t	*zfsvfs = arg;
	zfs_delete_t 	*zd = &zfsvfs->z_delete_head;
	znode_t		*zp;
	callb_cpr_t	cprinfo;
	int		drained;

	CALLB_CPR_INIT(&cprinfo, &zd->z_mutex, callb_generic_cpr, "zfs_delete");

	mutex_enter(&zd->z_mutex);

	if (!zd->z_drained && !zd->z_draining) {
		zd->z_draining = B_TRUE;
		mutex_exit(&zd->z_mutex);
		drained = zfs_drain_dq(zfsvfs);
		mutex_enter(&zd->z_mutex);
		zd->z_draining = B_FALSE;
		zd->z_drained = drained;
		cv_broadcast(&zd->z_quiesce_cv);
	}

	while (zd->z_thread_count <= zd->z_thread_target) {
		zp = list_head(&zd->z_znodes);
		if (zp == NULL) {
			ASSERT(zd->z_znode_count == 0);
			CALLB_CPR_SAFE_BEGIN(&cprinfo);
			cv_wait(&zd->z_cv, &zd->z_mutex);
			CALLB_CPR_SAFE_END(&cprinfo, &zd->z_mutex);
			continue;
		}
		ASSERT(zd->z_znode_count != 0);
		list_remove(&zd->z_znodes, zp);
		if (--zd->z_znode_count == 0)
			cv_broadcast(&zd->z_quiesce_cv);
		mutex_exit(&zd->z_mutex);
		zfs_rmnode(zp);
		(void) zfs_delete_thread_target(zfsvfs, -1);
		mutex_enter(&zd->z_mutex);
	}

	ASSERT(zd->z_thread_count != 0);
	if (--zd->z_thread_count == 0)
		cv_broadcast(&zd->z_cv);

	CALLB_CPR_EXIT(&cprinfo);	/* NB: drops z_mutex */
	thread_exit();
}
Exemple #2
0
void
zfs_zinactive(znode_t *zp)
{
	zfs_sb_t *zsb = ZTOZSB(zp);
	uint64_t z_id = zp->z_id;
	boolean_t drop_mutex = 0;

	ASSERT(zp->z_sa_hdl);

	/*
	 * Don't allow a zfs_zget() while were trying to release this znode.
	 *
	 * Linux allows direct memory reclaim which means that any KM_SLEEP
	 * allocation may trigger inode eviction.  This can lead to a deadlock
	 * through the ->shrink_icache_memory()->evict()->zfs_inactive()->
	 * zfs_zinactive() call path.  To avoid this deadlock the process
	 * must not reacquire the mutex when it is already holding it.
	 */
	if (!ZFS_OBJ_HOLD_OWNED(zsb, z_id)) {
		ZFS_OBJ_HOLD_ENTER(zsb, z_id);
		drop_mutex = 1;
	}

	mutex_enter(&zp->z_lock);

	/*
	 * If this was the last reference to a file with no links,
	 * remove the file from the file system.
	 */
	if (zp->z_unlinked) {
		mutex_exit(&zp->z_lock);

		if (drop_mutex)
			ZFS_OBJ_HOLD_EXIT(zsb, z_id);

		zfs_rmnode(zp);
		return;
	}

	mutex_exit(&zp->z_lock);
	zfs_znode_dmu_fini(zp);

	if (drop_mutex)
		ZFS_OBJ_HOLD_EXIT(zsb, z_id);
}