FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
/*
 * Delete the entire contents of a directory.  Return a count
 * of the number of entries that could not be deleted. If we encounter
 * an error, return a count of at least one so that the directory stays
 * in the unlinked set.
 *
 * NOTE: this function assumes that the directory is inactive,
 *	so there is no need to lock its entries before deletion.
 *	Also, it assumes the directory contents is *only* regular
 *	files.
 */
Delete the entire contents of a directory.  Return a count
of the number of entries that could not be deleted. If we encounter
an error, return a count of at least one so that the directory stays
in the unlinked set.

this function assumes that the directory is inactive,
so there is no need to lock its entries before deletion.
Also, it assumes the directory contents is *only* regular
files.
Delete the entire contents of a directory . Return a count of the number of entries that could not be deleted . If we encounter an error return a count of at least one so that the directory stays in the unlinked set . this function assumes that the directory is inactive so there is no need to lock its entries before deletion . Also it assumes the directory contents is * only * regular files .
static int
zfs_purgedir(znode_t *dzp)
{
	zap_cursor_t	zc;
	zap_attribute_t	zap;
	znode_t		*xzp;
	dmu_tx_t	*tx;
	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
	int skipped = 0;
	int error;
	for (zap_cursor_init(&zc, zfsvfs->z_os, dzp->z_id);
	    (error = zap_cursor_retrieve(&zc, &zap)) == 0;
	    zap_cursor_advance(&zc)) {
		error = zfs_zget(zfsvfs,
		    ZFS_DIRENT_OBJ(zap.za_first_integer), &xzp);
		if (error) {
			skipped += 1;
			continue;
		}
		vn_lock(ZTOV(xzp), LK_EXCLUSIVE | LK_RETRY);
		ASSERT((ZTOV(xzp)->v_type == VREG) ||
		    (ZTOV(xzp)->v_type == VLNK));
		tx = dmu_tx_create(zfsvfs->z_os);
		dmu_tx_hold_sa(tx, dzp->z_sa_hdl, B_FALSE);
		dmu_tx_hold_zap(tx, dzp->z_id, FALSE, zap.za_name);
		dmu_tx_hold_sa(tx, xzp->z_sa_hdl, B_FALSE);
		dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
		zfs_sa_upgrade_txholds(tx, xzp);
		dmu_tx_mark_netfree(tx);
		error = dmu_tx_assign(tx, TXG_WAIT);
		if (error) {
			dmu_tx_abort(tx);
			vput(ZTOV(xzp));
			skipped += 1;
			continue;
		}
		error = zfs_link_destroy(dzp, zap.za_name, xzp, tx, 0, NULL);
		if (error)
			skipped += 1;
		dmu_tx_commit(tx);
		vput(ZTOV(xzp));
	}
	zap_cursor_fini(&zc);
	if (error != ENOENT)
		skipped += 1;
	return (skipped);
}
static int zfs_purgedir ( znode_t * dzp ) { zap_cursor_t zc ; zap_attribute_t zap ; znode_t * xzp ; dmu_tx_t * tx ; zfsvfs_t * zfsvfs = dzp -> z_zfsvfs ; int skipped = 0 ; int error ; for ( zap_cursor_init ( & zc , zfsvfs -> z_os , dzp -> z_id ) ; ( error = zap_cursor_retrieve ( & zc , & zap ) ) == 0 ; zap_cursor_advance ( & zc ) ) { error = zfs_zget ( zfsvfs , ZFS_DIRENT_OBJ ( zap . za_first_integer ) , & xzp ) ; if ( error ) { skipped += 1 ; continue ; } vn_lock ( ZTOV ( xzp ) , LK_EXCLUSIVE | LK_RETRY ) ; ASSERT ( ( ZTOV ( xzp ) -> v_type == VREG ) || ( ZTOV ( xzp ) -> v_type == VLNK ) ) ; tx = dmu_tx_create ( zfsvfs -> z_os ) ; dmu_tx_hold_sa ( tx , dzp -> z_sa_hdl , B_FALSE ) ; dmu_tx_hold_zap ( tx , dzp -> z_id , FALSE , zap . za_name ) ; dmu_tx_hold_sa ( tx , xzp -> z_sa_hdl , B_FALSE ) ; dmu_tx_hold_zap ( tx , zfsvfs -> z_unlinkedobj , FALSE , NULL ) ; zfs_sa_upgrade_txholds ( tx , xzp ) ; dmu_tx_mark_netfree ( tx ) ; error = dmu_tx_assign ( tx , TXG_WAIT ) ; if ( error ) { dmu_tx_abort ( tx ) ; vput ( ZTOV ( xzp ) ) ; skipped += 1 ; continue ; } error = zfs_link_destroy ( dzp , zap . za_name , xzp , tx , 0 , NULL ) ; if ( error ) skipped += 1 ; dmu_tx_commit ( tx ) ; vput ( ZTOV ( xzp ) ) ; } zap_cursor_fini ( & zc ) ; if ( error != ENOENT ) skipped += 1 ; return ( skipped ) ; }
Delete the entire contents of a directory.
Delete the entire contents of a directory .
/* Is this really needed ? */