usr/src/uts/common/fs/zfs/dsl_dir.c
author ahrens
Fri, 10 Mar 2006 16:27:46 -0800
changeset 1596 2e2377ccbf85
parent 1544 938876158511
child 2082 76b439ec3ac1
permissions -rw-r--r--
6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr 6396359 infinite loop due to dangling dbufs (hang on unmount)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
     5
 * Common Development and Distribution License (the "License").
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
     6
 * You may not use this file except in compliance with the License.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
/*
1356
e021b5e4aa0e 6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents: 928
diff changeset
    22
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
#include <sys/dmu.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
#include <sys/dmu_tx.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
#include <sys/dsl_dataset.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
#include <sys/dsl_dir.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
#include <sys/dsl_prop.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
#include <sys/spa.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
#include <sys/zap.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
#include <sys/zio.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
#include <sys/arc.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
#include "zfs_namecheck.h"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
static uint64_t dsl_dir_space_accounted(dsl_dir_t *dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
static uint64_t dsl_dir_estimated_space(dsl_dir_t *dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
static int dsl_dir_set_reservation_sync(dsl_dir_t *dd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
    void *arg, dmu_tx_t *tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
static uint64_t dsl_dir_space_available(dsl_dir_t *dd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
    dsl_dir_t *ancestor, int64_t delta, int ondiskonly);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
dsl_dir_evict(dmu_buf_t *db, void *arg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
	dsl_dir_t *dd = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
	dsl_pool_t *dp = dd->dd_pool;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
	int t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
	for (t = 0; t < TXG_SIZE; t++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
		ASSERT(!txg_list_member(&dp->dp_dirty_dirs, dd, t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
		ASSERT(dd->dd_tempreserved[t] == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
		ASSERT(dd->dd_space_towrite[t] == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
	ASSERT3U(dd->dd_used_bytes, ==, dd->dd_phys->dd_used_bytes);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
	ASSERT(dd->dd_sync_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
	if (dd->dd_parent)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
		dsl_dir_close(dd->dd_parent, dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
	spa_close(dd->dd_pool->dp_spa, dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
	 * The props callback list should be empty since they hold the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
	 * dir open.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
	list_destroy(&dd->dd_prop_cbs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
	kmem_free(dd, sizeof (dsl_dir_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
    78
int
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
    80
    const char *tail, void *tag, dsl_dir_t **ddp)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
	dmu_buf_t *dbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
	dsl_dir_t *dd;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
    84
	int err;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
	ASSERT(RW_LOCK_HELD(&dp->dp_config_rwlock) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
	    dsl_pool_sync_context(dp));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
    89
	err = dmu_bonus_hold(dp->dp_meta_objset, ddobj, tag, &dbuf);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
    90
	if (err)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
    91
		return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
	dd = dmu_buf_get_user(dbuf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
		dmu_object_info_t doi;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
		dmu_object_info_from_db(dbuf, &doi);
928
36d72fe4da29 6349314 dmu_object_type names incorrect for DSL Directories and DSL Datasets
tabriz
parents: 885
diff changeset
    97
		ASSERT3U(doi.doi_type, ==, DMU_OT_DSL_DIR);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
	/* XXX assert bonus buffer size is correct */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
	if (dd == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
		dsl_dir_t *winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
		int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
		dd = kmem_zalloc(sizeof (dsl_dir_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
		dd->dd_object = ddobj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
		dd->dd_dbuf = dbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
		dd->dd_pool = dp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
		dd->dd_phys = dbuf->db_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
		dd->dd_used_bytes = dd->dd_phys->dd_used_bytes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
		list_create(&dd->dd_prop_cbs, sizeof (dsl_prop_cb_record_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
		    offsetof(dsl_prop_cb_record_t, cbr_node));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
		if (dd->dd_phys->dd_parent_obj) {
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   116
			err = dsl_dir_open_obj(dp, dd->dd_phys->dd_parent_obj,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   117
			    NULL, dd, &dd->dd_parent);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   118
			if (err) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   119
				kmem_free(dd, sizeof (dsl_dir_t));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   120
				dmu_buf_rele(dbuf, tag);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   121
				return (err);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   122
			}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
			if (tail) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
				uint64_t foundobj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
				err = zap_lookup(dp->dp_meta_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
				    dd->dd_parent->dd_phys->
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   129
				    dd_child_dir_zapobj,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
				    tail, sizeof (foundobj), 1, &foundobj);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   131
				ASSERT(err || foundobj == ddobj);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   132
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
				(void) strcpy(dd->dd_myname, tail);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
			} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
				err = zap_value_search(dp->dp_meta_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
				    dd->dd_parent->dd_phys->
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
				    dd_child_dir_zapobj,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
				    ddobj, dd->dd_myname);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   139
			}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   140
			if (err) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   141
				dsl_dir_close(dd->dd_parent, dd);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   142
				kmem_free(dd, sizeof (dsl_dir_t));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   143
				dmu_buf_rele(dbuf, tag);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   144
				return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
			(void) strcpy(dd->dd_myname, spa_name(dp->dp_spa));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
		winner = dmu_buf_set_user_ie(dbuf, dd, &dd->dd_phys,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
		    dsl_dir_evict);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
		if (winner) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
			if (dd->dd_parent)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
				dsl_dir_close(dd->dd_parent, dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
			kmem_free(dd, sizeof (dsl_dir_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
			dd = winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
			spa_open_ref(dp->dp_spa, dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
	 * The dsl_dir_t has both open-to-close and instantiate-to-evict
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
	 * holds on the spa.  We need the open-to-close holds because
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
	 * otherwise the spa_refcnt wouldn't change when we open a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
	 * dir which the spa also has open, so we could incorrectly
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   167
	 * think it was OK to unload/export/destroy the pool.  We need
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
	 * the instantiate-to-evict hold because the dsl_dir_t has a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
	 * pointer to the dd_pool, which has a pointer to the spa_t.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
	spa_open_ref(dp->dp_spa, tag);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
	ASSERT3P(dd->dd_pool, ==, dp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
	ASSERT3U(dd->dd_object, ==, ddobj);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
	ASSERT3P(dd->dd_dbuf, ==, dbuf);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   175
	*ddp = dd;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   176
	return (0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
dsl_dir_close(dsl_dir_t *dd, void *tag)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
	dprintf_dd(dd, "%s\n", "");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
	spa_close(dd->dd_pool->dp_spa, tag);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   184
	dmu_buf_rele(dd->dd_dbuf, tag);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
/* buf must be long enough (MAXNAMELEN should do) */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
dsl_dir_name(dsl_dir_t *dd, char *buf)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
	if (dd->dd_parent) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
		dsl_dir_name(dd->dd_parent, buf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
		(void) strcat(buf, "/");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
		buf[0] = '\0';
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
	if (!MUTEX_HELD(&dd->dd_lock)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
		 * recursive mutex so that we can use
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
		 * dprintf_dd() with dd_lock held
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
		mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
		(void) strcat(buf, dd->dd_myname);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
		mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
		(void) strcat(buf, dd->dd_myname);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
dsl_dir_is_private(dsl_dir_t *dd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
	int rv = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
	if (dd->dd_parent && dsl_dir_is_private(dd->dd_parent))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
		rv = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
	if (dataset_name_hidden(dd->dd_myname))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
		rv = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
	return (rv);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
getcomponent(const char *path, char *component, const char **nextp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
	char *p;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
	if (path == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
	/* This would be a good place to reserve some namespace... */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
	p = strpbrk(path, "/@");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
	if (p && (p[1] == '/' || p[1] == '@')) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
		/* two separators in a row */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
		return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
	if (p == NULL || p == path) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
		 * if the first thing is an @ or /, it had better be an
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
		 * @ and it had better not have any more ats or slashes,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
		 * and it had better have something after the @.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
		if (p != NULL &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
		    (p[0] != '@' || strpbrk(path+1, "/@") || p[1] == '\0'))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
			return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
		if (strlen(path) >= MAXNAMELEN)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
			return (ENAMETOOLONG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
		(void) strcpy(component, path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
		p = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
	} else if (p[0] == '/') {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
		if (p-path >= MAXNAMELEN)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
			return (ENAMETOOLONG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
		(void) strncpy(component, path, p - path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
		component[p-path] = '\0';
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
		p++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
	} else if (p[0] == '@') {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
		 * if the next separator is an @, there better not be
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
		 * any more slashes.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
		if (strchr(path, '/'))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
			return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
		if (p-path >= MAXNAMELEN)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
			return (ENAMETOOLONG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
		(void) strncpy(component, path, p - path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
		component[p-path] = '\0';
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
		ASSERT(!"invalid p");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
	*nextp = p;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
 * same as dsl_open_dir, ignore the first component of name and use the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
 * spa instead
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
 */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   276
int
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   277
dsl_dir_open_spa(spa_t *spa, const char *name, void *tag,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   278
    dsl_dir_t **ddp, const char **tailp)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
	char buf[MAXNAMELEN];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
	const char *next, *nextnext = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
	dsl_dir_t *dd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
	dsl_pool_t *dp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
	uint64_t ddobj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
	int openedspa = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
	dprintf("%s\n", name);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
	if (name == NULL)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   291
		return (ENOENT);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
	err = getcomponent(name, buf, &next);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
	if (err)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   294
		return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
	if (spa == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
		err = spa_open(buf, &spa, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
		if (err) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
			dprintf("spa_open(%s) failed\n", buf);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   299
			return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
		openedspa = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   303
		/* XXX this assertion belongs in spa_open */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
		ASSERT(!dsl_pool_sync_context(spa_get_dsl(spa)));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
	dp = spa_get_dsl(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
	rw_enter(&dp->dp_config_rwlock, RW_READER);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   310
	err = dsl_dir_open_obj(dp, dp->dp_root_dir_obj, NULL, tag, &dd);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   311
	if (err) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   312
		rw_exit(&dp->dp_config_rwlock);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   313
		if (openedspa)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   314
			spa_close(spa, FTAG);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   315
		return (err);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   316
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   317
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
	while (next != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
		dsl_dir_t *child_ds;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
		err = getcomponent(next, buf, &nextnext);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   321
		if (err)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   322
			break;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
		ASSERT(next[0] != '\0');
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
		if (next[0] == '@')
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   326
		if (dd->dd_phys->dd_child_dir_zapobj == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   327
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   328
		dprintf("looking up %s in obj%lld\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
		    buf, dd->dd_phys->dd_child_dir_zapobj);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   331
		err = zap_lookup(dp->dp_meta_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   332
		    dd->dd_phys->dd_child_dir_zapobj,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   333
		    buf, sizeof (ddobj), 1, &ddobj);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   334
		if (err) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   335
			if (err == ENOENT)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   336
				err = 0;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   337
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   338
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   339
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   340
		err = dsl_dir_open_obj(dp, ddobj, buf, tag, &child_ds);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   341
		if (err)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   342
			break;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
		dsl_dir_close(dd, tag);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
		dd = child_ds;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
		next = nextnext;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
	rw_exit(&dp->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   349
	if (err) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   350
		dsl_dir_close(dd, tag);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   351
		if (openedspa)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   352
			spa_close(spa, FTAG);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   353
		return (err);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   354
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   355
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   356
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
	 * It's an error if there's more than one component left, or
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   358
	 * tailp==NULL and there's any component left.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
	if (next != NULL &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
	    (tailp == NULL || (nextnext && nextnext[0] != '\0'))) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
		/* bad path name */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
		dsl_dir_close(dd, tag);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
		dprintf("next=%p (%s) tail=%p\n", next, next?next:"", tailp);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   365
		err = ENOENT;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
	if (tailp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
		*tailp = next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
	if (openedspa)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
		spa_close(spa, FTAG);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   371
	*ddp = dd;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   372
	return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   375
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   376
 * Return the dsl_dir_t, and possibly the last component which couldn't
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   377
 * be found in *tail.  Return NULL if the path is bogus, or if
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
 * tail==NULL and we couldn't parse the whole name.  (*tail)[0] == '@'
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   379
 * means that the last component is a snapshot.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   380
 */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   381
int
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   382
dsl_dir_open(const char *name, void *tag, dsl_dir_t **ddp, const char **tailp)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   383
{
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   384
	return (dsl_dir_open_spa(NULL, name, tag, ddp, tailp));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   385
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   387
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
dsl_dir_create_sync(dsl_dir_t *pds, const char *name, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   389
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   390
	objset_t *mos = pds->dd_pool->dp_meta_objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
	uint64_t ddobj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
	dsl_dir_phys_t *dsphys;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
	dmu_buf_t *dbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
	ASSERT(dmu_tx_is_syncing(tx));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
	if (pds->dd_phys->dd_child_dir_zapobj == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   399
		dmu_buf_will_dirty(pds->dd_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   400
		pds->dd_phys->dd_child_dir_zapobj = zap_create(mos,
885
d925b21dba78 6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents: 789
diff changeset
   401
		    DMU_OT_DSL_DIR_CHILD_MAP, DMU_OT_NONE, 0, tx);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   404
	rw_enter(&pds->dd_pool->dp_config_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   405
	err = zap_lookup(mos, pds->dd_phys->dd_child_dir_zapobj,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
	    name, sizeof (uint64_t), 1, &ddobj);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
	if (err != ENOENT) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   408
		rw_exit(&pds->dd_pool->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
		return (err ? err : EEXIST);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
928
36d72fe4da29 6349314 dmu_object_type names incorrect for DSL Directories and DSL Datasets
tabriz
parents: 885
diff changeset
   412
	ddobj = dmu_object_alloc(mos, DMU_OT_DSL_DIR, 0,
36d72fe4da29 6349314 dmu_object_type names incorrect for DSL Directories and DSL Datasets
tabriz
parents: 885
diff changeset
   413
	    DMU_OT_DSL_DIR, sizeof (dsl_dir_phys_t), tx);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
	err = zap_add(mos, pds->dd_phys->dd_child_dir_zapobj,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
	    name, sizeof (uint64_t), 1, &ddobj, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
	ASSERT3U(err, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
	dprintf("dataset_create: zap_add %s->%lld to %lld returned %d\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
	    name, ddobj, pds->dd_phys->dd_child_dir_zapobj, err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   420
	VERIFY(0 == dmu_bonus_hold(mos, ddobj, FTAG, &dbuf));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
	dmu_buf_will_dirty(dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
	dsphys = dbuf->db_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   424
	dsphys->dd_creation_time = gethrestime_sec();
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
	dsphys->dd_parent_obj = pds->dd_object;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   426
	dsphys->dd_props_zapobj = zap_create(mos,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   427
	    DMU_OT_DSL_PROPS, DMU_OT_NONE, 0, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
	dsphys->dd_child_dir_zapobj = zap_create(mos,
885
d925b21dba78 6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents: 789
diff changeset
   429
	    DMU_OT_DSL_DIR_CHILD_MAP, DMU_OT_NONE, 0, tx);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   430
	dmu_buf_rele(dbuf, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   431
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   432
	rw_exit(&pds->dd_pool->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   437
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
dsl_dir_destroy_sync(dsl_dir_t *pds, void *arg, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   440
	const char *name = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   441
	dsl_dir_t *dd = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   442
	dsl_pool_t *dp = pds->dd_pool;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
	objset_t *mos = dp->dp_meta_objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
	uint64_t val, obj, child_zapobj, props_zapobj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
	int t, err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
	rw_enter(&dp->dp_config_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
	err = zap_lookup(mos, pds->dd_phys->dd_child_dir_zapobj, name,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
	    8, 1, &obj);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
	if (err)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   452
		goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   454
	err = dsl_dir_open_obj(dp, obj, name, FTAG, &dd);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   455
	if (err)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   456
		goto out;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
	ASSERT3U(dd->dd_phys->dd_parent_obj, ==, pds->dd_object);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
	if (dmu_buf_refcount(dd->dd_dbuf) > 1) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
		err = EBUSY;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   461
		goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   462
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   464
	for (t = 0; t < TXG_SIZE; t++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
		 * if they were dirty, they'd also be open.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
		 * dp_config_rwlock ensures that it stays that way.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
		ASSERT(!txg_list_member(&dp->dp_dirty_dirs, dd, t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
	child_zapobj = dd->dd_phys->dd_child_dir_zapobj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   473
	props_zapobj = dd->dd_phys->dd_props_zapobj;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   474
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   475
	if (child_zapobj != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   476
		uint64_t count;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
		err = EEXIST;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
		(void) zap_count(mos, child_zapobj, &count);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
		if (count != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
			goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
	if (dd->dd_phys->dd_head_dataset_obj != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
		err = dsl_dataset_destroy_sync(dd, NULL, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
		if (err)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
			goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
	ASSERT(dd->dd_phys->dd_head_dataset_obj == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
	/* The point of no (unsuccessful) return */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
	/* Make sure parent's used gets updated */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
	val = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
	err = dsl_dir_set_reservation_sync(dd, &val, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
	ASSERT(err == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
	ASSERT3U(dd->dd_used_bytes, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
	ASSERT3U(dd->dd_phys->dd_reserved, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
	dsl_dir_close(dd, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
	dd = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
	err = dmu_object_free(mos, obj, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
	ASSERT(err == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   504
	if (child_zapobj)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   505
		err = zap_destroy(mos, child_zapobj, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   506
	ASSERT(err == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
	if (props_zapobj)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
		err = zap_destroy(mos, props_zapobj, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
	ASSERT(err == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
	err = zap_remove(mos, pds->dd_phys->dd_child_dir_zapobj, name, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
	ASSERT(err == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   514
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   515
out:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   516
	rw_exit(&dp->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   517
	if (dd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   518
		dsl_dir_close(dd, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   520
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   521
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   522
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   523
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
dsl_dir_create_root(objset_t *mos, uint64_t *ddobjp, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   525
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
	dsl_dir_phys_t *dsp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   527
	dmu_buf_t *dbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   528
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   529
928
36d72fe4da29 6349314 dmu_object_type names incorrect for DSL Directories and DSL Datasets
tabriz
parents: 885
diff changeset
   530
	*ddobjp = dmu_object_alloc(mos, DMU_OT_DSL_DIR, 0,
36d72fe4da29 6349314 dmu_object_type names incorrect for DSL Directories and DSL Datasets
tabriz
parents: 885
diff changeset
   531
	    DMU_OT_DSL_DIR, sizeof (dsl_dir_phys_t), tx);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   532
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   533
	error = zap_add(mos, DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_ROOT_DATASET,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   534
	    sizeof (uint64_t), 1, ddobjp, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   535
	ASSERT3U(error, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   536
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   537
	VERIFY(0 == dmu_bonus_hold(mos, *ddobjp, FTAG, &dbuf));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
	dmu_buf_will_dirty(dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   539
	dsp = dbuf->db_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   540
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   541
	dsp->dd_creation_time = gethrestime_sec();
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   542
	dsp->dd_props_zapobj = zap_create(mos,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   543
	    DMU_OT_DSL_PROPS, DMU_OT_NONE, 0, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   544
	dsp->dd_child_dir_zapobj = zap_create(mos,
885
d925b21dba78 6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents: 789
diff changeset
   545
	    DMU_OT_DSL_DIR_CHILD_MAP, DMU_OT_NONE, 0, tx);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   546
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   547
	dmu_buf_rele(dbuf, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   549
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   550
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   551
dsl_dir_stats(dsl_dir_t *dd, dmu_objset_stats_t *dds)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   552
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   553
	bzero(dds, sizeof (dmu_objset_stats_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   554
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
	dds->dds_available = dsl_dir_space_available(dd, NULL, 0, TRUE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   557
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   558
	dds->dds_space_used = dd->dd_used_bytes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   559
	dds->dds_compressed_bytes = dd->dd_phys->dd_compressed_bytes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   560
	dds->dds_uncompressed_bytes = dd->dd_phys->dd_uncompressed_bytes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
	dds->dds_quota = dd->dd_phys->dd_quota;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   562
	dds->dds_reserved = dd->dd_phys->dd_reserved;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   565
	dds->dds_creation_time = dd->dd_phys->dd_creation_time;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
	if (dd->dd_phys->dd_clone_parent_obj) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
		dsl_dataset_t *ds;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   569
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   570
		rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   571
		VERIFY(0 == dsl_dataset_open_obj(dd->dd_pool,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   572
		    dd->dd_phys->dd_clone_parent_obj,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   573
		    NULL, DS_MODE_NONE, FTAG, &ds));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   574
		dsl_dataset_name(ds, dds->dds_clone_of);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
		dsl_dataset_close(ds, DS_MODE_NONE, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
		rw_exit(&dd->dd_pool->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   580
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   581
dsl_dir_sync_task(dsl_dir_t *dd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   582
    int (*func)(dsl_dir_t *, void*, dmu_tx_t *), void *arg, uint64_t space)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
	dmu_tx_t *tx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
	dsl_pool_t *dp = dd->dd_pool;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
	int err = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
	uint64_t txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
	dprintf_dd(dd, "func=%p space=%llu\n", func, space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
again:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
	tx = dmu_tx_create_ds(dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
	dmu_tx_hold_space(tx, space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
	err = dmu_tx_assign(tx, TXG_WAIT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
	if (err == ENOSPC || err == EDQUOT) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
		dsl_dir_t *rds;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   597
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   598
		 * They can get their space from either this dd, or the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   599
		 * root dd.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   600
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   601
		for (rds = dd; rds->dd_parent; rds = rds->dd_parent)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   602
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
		dmu_tx_abort(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
		tx = dmu_tx_create_ds(rds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   605
		dmu_tx_hold_space(tx, space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
		err = dmu_tx_assign(tx, TXG_WAIT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
	if (err) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
		dmu_tx_abort(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
		return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
	txg = dmu_tx_get_txg(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
	if (dd->dd_sync_txg != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   616
		mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   617
		dmu_tx_commit(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   618
		txg_wait_synced(dp, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   619
		goto again;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   620
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
	/* We're good to go */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   623
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
	dd->dd_sync_txg = txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
	dd->dd_sync_func = func;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
	dd->dd_sync_arg = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   627
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   628
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   629
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   630
	dsl_dir_dirty(dd, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   631
	dmu_tx_commit(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   632
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   633
	txg_wait_synced(dp, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   634
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   635
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   636
	ASSERT(dd->dd_sync_txg == txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   637
	ASSERT(dd->dd_sync_func == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   638
	err = dd->dd_sync_err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   639
	dd->dd_sync_txg = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   640
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   641
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   642
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   643
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   644
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   645
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   646
dsl_dir_dirty(dsl_dir_t *dd, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   647
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   648
	dsl_pool_t *dp = dd->dd_pool;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
	ASSERT(dd->dd_phys);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
	if (txg_list_add(&dp->dp_dirty_dirs, dd, tx->tx_txg) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   653
		/* up the hold count until we can be written out */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   654
		dmu_buf_add_ref(dd->dd_dbuf, dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   656
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
static int64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
parent_delta(dsl_dir_t *dd, uint64_t used, int64_t delta)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   660
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
	uint64_t old_accounted = MAX(used, dd->dd_phys->dd_reserved);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   662
	uint64_t new_accounted = MAX(used + delta, dd->dd_phys->dd_reserved);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   663
	return (new_accounted - old_accounted);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   664
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   665
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   666
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   667
dsl_dir_sync(dsl_dir_t *dd, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   668
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   669
	if (dd->dd_sync_txg == tx->tx_txg && dd->dd_sync_func) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   670
		dd->dd_sync_err = dd->dd_sync_func(dd, dd->dd_sync_arg, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   671
		dd->dd_sync_func = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   672
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   673
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
	ASSERT(dmu_tx_is_syncing(tx));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   675
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   676
	dmu_buf_will_dirty(dd->dd_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   677
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   678
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   679
	ASSERT3U(dd->dd_tempreserved[tx->tx_txg&TXG_MASK], ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   680
	dprintf_dd(dd, "txg=%llu towrite=%lluK\n", tx->tx_txg,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   681
	    dd->dd_space_towrite[tx->tx_txg&TXG_MASK] / 1024);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   682
	dd->dd_space_towrite[tx->tx_txg&TXG_MASK] = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   683
	dd->dd_phys->dd_used_bytes = dd->dd_used_bytes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   684
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   685
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
	/* release the hold from dsl_dir_dirty */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   687
	dmu_buf_rele(dd->dd_dbuf, dd);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   688
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   689
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   690
static uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   691
dsl_dir_estimated_space(dsl_dir_t *dd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   692
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   693
	int64_t space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
	ASSERT(MUTEX_HELD(&dd->dd_lock));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   698
	space = dd->dd_phys->dd_used_bytes;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
	ASSERT(space >= 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   700
	for (i = 0; i < TXG_SIZE; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   701
		space += dd->dd_space_towrite[i&TXG_MASK];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   702
		ASSERT3U(dd->dd_space_towrite[i&TXG_MASK], >=, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   703
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   704
	return (space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   705
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   707
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   708
 * How much space would dd have available if ancestor had delta applied
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   709
 * to it?  If ondiskonly is set, we're only interested in what's
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   710
 * on-disk, not estimated pending changes.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   711
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   712
static uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
dsl_dir_space_available(dsl_dir_t *dd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
    dsl_dir_t *ancestor, int64_t delta, int ondiskonly)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
	uint64_t parentspace, myspace, quota, used;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   718
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
	 * If there are no restrictions otherwise, assume we have
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   720
	 * unlimited space available.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   721
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   722
	quota = UINT64_MAX;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   723
	parentspace = UINT64_MAX;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   724
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   725
	if (dd->dd_parent != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   726
		parentspace = dsl_dir_space_available(dd->dd_parent,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   727
		    ancestor, delta, ondiskonly);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   728
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   729
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   730
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   731
	if (dd->dd_phys->dd_quota != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   732
		quota = dd->dd_phys->dd_quota;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   733
	if (ondiskonly) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   734
		used = dd->dd_used_bytes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   735
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   736
		used = dsl_dir_estimated_space(dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   737
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   738
	if (dd == ancestor)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   739
		used += delta;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   740
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   741
	if (dd->dd_parent == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   742
		uint64_t poolsize = dsl_pool_adjustedsize(dd->dd_pool, B_FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   743
		quota = MIN(quota, poolsize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   744
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   745
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   746
	if (dd->dd_phys->dd_reserved > used && parentspace != UINT64_MAX) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   747
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   748
		 * We have some space reserved, in addition to what our
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   749
		 * parent gave us.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   750
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   751
		parentspace += dd->dd_phys->dd_reserved - used;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   752
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   753
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   754
	if (used > quota) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   755
		/* over quota */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   756
		myspace = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   757
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   758
		{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   759
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   760
			 * While it's OK to be a little over quota, if
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   761
			 * we think we are using more space than there
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   762
			 * is in the pool (which is already 6% more than
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   763
			 * dsl_pool_adjustedsize()), something is very
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   764
			 * wrong.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   765
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   766
			uint64_t space = spa_get_space(dd->dd_pool->dp_spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   767
			ASSERT3U(used, <=, space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   768
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   769
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   770
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   771
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   772
		 * the lesser of parent's space and the space
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   773
		 * left in our quota
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   774
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   775
		myspace = MIN(parentspace, quota - used);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   776
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   777
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   778
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   779
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   780
	return (myspace);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   781
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   782
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   783
struct tempreserve {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   784
	list_node_t tr_node;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   785
	dsl_dir_t *tr_ds;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   786
	uint64_t tr_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   787
};
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   788
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   789
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   790
 * Reserve space in this dsl_dir, to be used in this tx's txg.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   791
 * After the space has been dirtied (and thus
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   792
 * dsl_dir_willuse_space() has been called), the reservation should
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   793
 * be canceled, using dsl_dir_tempreserve_clear().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   794
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   795
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   796
dsl_dir_tempreserve_impl(dsl_dir_t *dd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   797
    uint64_t asize, boolean_t netfree, list_t *tr_list, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   798
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   799
	uint64_t txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   800
	uint64_t est_used, quota, parent_rsrv;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   801
	int edquot = EDQUOT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   802
	int txgidx = txg & TXG_MASK;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   803
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   804
	struct tempreserve *tr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   805
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   806
	ASSERT3U(txg, !=, 0);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   807
	ASSERT3S(asize, >=, 0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   808
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   809
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   810
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   811
	 * Check against the dsl_dir's quota.  We don't add in the delta
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   812
	 * when checking for over-quota because they get one free hit.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   813
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   814
	est_used = dsl_dir_estimated_space(dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   815
	for (i = 0; i < TXG_SIZE; i++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   816
		est_used += dd->dd_tempreserved[i];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   817
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   818
	quota = UINT64_MAX;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   819
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   820
	if (dd->dd_phys->dd_quota)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   821
		quota = dd->dd_phys->dd_quota;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   822
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   823
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   824
	 * If this transaction will result in a net free of space, we want
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   825
	 * to let it through, but we have to be careful: the space that it
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   826
	 * frees won't become available until *after* this txg syncs.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   827
	 * Therefore, to ensure that it's possible to remove files from
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   828
	 * a full pool without inducing transient overcommits, we throttle
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   829
	 * netfree transactions against a quota that is slightly larger,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   830
	 * but still within the pool's allocation slop.  In cases where
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   831
	 * we're very close to full, this will allow a steady trickle of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   832
	 * removes to get through.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   833
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   834
	if (dd->dd_parent == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   835
		uint64_t poolsize = dsl_pool_adjustedsize(dd->dd_pool, netfree);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   836
		if (poolsize < quota) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   837
			quota = poolsize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   838
			edquot = ENOSPC;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   839
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   840
	} else if (netfree) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   841
		quota = UINT64_MAX;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   842
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   843
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   844
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   845
	 * If they are requesting more space, and our current estimate
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   846
	 * is over quota.  They get to try again unless the actual
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   847
	 * on-disk is over quota and there are no pending changes (which
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   848
	 * may free up space for us).
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   849
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   850
	if (asize > 0 && est_used > quota) {
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   851
		if (dd->dd_space_towrite[txg & TXG_MASK] != 0 ||
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   852
		    dd->dd_space_towrite[(txg-1) & TXG_MASK] != 0 ||
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   853
		    dd->dd_space_towrite[(txg-2) & TXG_MASK] != 0 ||
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   854
		    dd->dd_used_bytes < quota)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   855
			edquot = ERESTART;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   856
		dprintf_dd(dd, "failing: used=%lluK est_used = %lluK "
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   857
		    "quota=%lluK tr=%lluK err=%d\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   858
		    dd->dd_used_bytes>>10, est_used>>10,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   859
		    quota>>10, asize>>10, edquot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   860
		mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   861
		return (edquot);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   862
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   863
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   864
	/* We need to up our estimated delta before dropping dd_lock */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   865
	dd->dd_tempreserved[txgidx] += asize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   866
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   867
	parent_rsrv = parent_delta(dd, est_used, asize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   868
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   869
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   870
	tr = kmem_alloc(sizeof (struct tempreserve), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   871
	tr->tr_ds = dd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   872
	tr->tr_size = asize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   873
	list_insert_tail(tr_list, tr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   874
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   875
	/* see if it's OK with our parent */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   876
	if (dd->dd_parent && parent_rsrv) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   877
		return (dsl_dir_tempreserve_impl(dd->dd_parent,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   878
		    parent_rsrv, netfree, tr_list, tx));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   879
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   880
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   881
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   882
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   883
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   884
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   885
 * Reserve space in this dsl_dir, to be used in this tx's txg.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   886
 * After the space has been dirtied (and thus
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   887
 * dsl_dir_willuse_space() has been called), the reservation should
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   888
 * be canceled, using dsl_dir_tempreserve_clear().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   889
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   890
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   891
dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t lsize,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   892
    uint64_t asize, uint64_t fsize, void **tr_cookiep, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   893
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   894
	int err = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   895
	list_t *tr_list;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   896
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   897
	tr_list = kmem_alloc(sizeof (list_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   898
	list_create(tr_list, sizeof (struct tempreserve),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   899
	    offsetof(struct tempreserve, tr_node));
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   900
	ASSERT3S(asize, >=, 0);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
   901
	ASSERT3S(fsize, >=, 0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   902
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   903
	err = dsl_dir_tempreserve_impl(dd, asize, fsize >= asize,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   904
	    tr_list, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   905
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   906
	if (err == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   907
		struct tempreserve *tr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   908
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   909
		err = arc_tempreserve_space(lsize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   910
		if (err == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   911
			tr = kmem_alloc(sizeof (struct tempreserve), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   912
			tr->tr_ds = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   913
			tr->tr_size = lsize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   914
			list_insert_tail(tr_list, tr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   915
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   916
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   917
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   918
	if (err)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   919
		dsl_dir_tempreserve_clear(tr_list, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   920
	else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   921
		*tr_cookiep = tr_list;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   922
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   923
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   924
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   925
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   926
 * Clear a temporary reservation that we previously made with
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   927
 * dsl_dir_tempreserve_space().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   928
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   929
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   930
dsl_dir_tempreserve_clear(void *tr_cookie, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   931
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   932
	int txgidx = tx->tx_txg & TXG_MASK;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   933
	list_t *tr_list = tr_cookie;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   934
	struct tempreserve *tr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   935
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   936
	ASSERT3U(tx->tx_txg, !=, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   937
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   938
	while (tr = list_head(tr_list)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   939
		if (tr->tr_ds == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   940
			arc_tempreserve_clear(tr->tr_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   941
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   942
			mutex_enter(&tr->tr_ds->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   943
			ASSERT3U(tr->tr_ds->dd_tempreserved[txgidx], >=,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   944
			    tr->tr_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   945
			tr->tr_ds->dd_tempreserved[txgidx] -= tr->tr_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   946
			mutex_exit(&tr->tr_ds->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   947
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   948
		list_remove(tr_list, tr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   949
		kmem_free(tr, sizeof (struct tempreserve));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   950
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   951
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   952
	kmem_free(tr_list, sizeof (list_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   953
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   954
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   955
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   956
 * Call in open context when we think we're going to write/free space,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   957
 * eg. when dirtying data.  Be conservative (ie. OK to write less than
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   958
 * this or free more than this, but don't write more or free less).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   959
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   960
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   961
dsl_dir_willuse_space(dsl_dir_t *dd, int64_t space, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   962
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   963
	int64_t parent_space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   964
	uint64_t est_used;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   965
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   966
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   967
	if (space > 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   968
		dd->dd_space_towrite[tx->tx_txg & TXG_MASK] += space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   969
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   970
	est_used = dsl_dir_estimated_space(dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   971
	parent_space = parent_delta(dd, est_used, space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   972
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   973
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   974
	/* Make sure that we clean up dd_space_to* */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   975
	dsl_dir_dirty(dd, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   976
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   977
	/* XXX this is potentially expensive and unnecessary... */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   978
	if (parent_space && dd->dd_parent)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   979
		dsl_dir_willuse_space(dd->dd_parent, parent_space, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   980
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   981
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   982
/* call from syncing context when we actually write/free space for this dd */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   983
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   984
dsl_dir_diduse_space(dsl_dir_t *dd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   985
    int64_t used, int64_t compressed, int64_t uncompressed, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   986
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   987
	int64_t accounted_delta;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   988
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   989
	ASSERT(dmu_tx_is_syncing(tx));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   990
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   991
	dsl_dir_dirty(dd, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   992
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   993
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   994
	accounted_delta = parent_delta(dd, dd->dd_used_bytes, used);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   995
	ASSERT(used >= 0 || dd->dd_used_bytes >= -used);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   996
	ASSERT(compressed >= 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   997
	    dd->dd_phys->dd_compressed_bytes >= -compressed);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   998
	ASSERT(uncompressed >= 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   999
	    dd->dd_phys->dd_uncompressed_bytes >= -uncompressed);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1000
	dd->dd_used_bytes += used;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1001
	dd->dd_phys->dd_uncompressed_bytes += uncompressed;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1002
	dd->dd_phys->dd_compressed_bytes += compressed;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1003
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1004
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1005
	if (dd->dd_parent != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1006
		dsl_dir_diduse_space(dd->dd_parent,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1007
		    accounted_delta, compressed, uncompressed, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1008
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1009
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1010
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1011
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1012
dsl_dir_set_quota_sync(dsl_dir_t *dd, void *arg, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1013
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1014
	uint64_t *quotap = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1015
	uint64_t new_quota = *quotap;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1016
	int err = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1017
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1018
	dmu_buf_will_dirty(dd->dd_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1019
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1020
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1021
	if (new_quota != 0 && (new_quota < dd->dd_phys->dd_reserved ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1022
	    new_quota < dsl_dir_estimated_space(dd))) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1023
		err = ENOSPC;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1024
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1025
		dd->dd_phys->dd_quota = new_quota;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1026
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1027
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1028
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1029
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1030
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1031
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1032
dsl_dir_set_quota(const char *ddname, uint64_t quota)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1033
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1034
	dsl_dir_t *dd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1035
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1036
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1037
	err = dsl_dir_open(ddname, FTAG, &dd, NULL);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1038
	if (err)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1039
		return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1040
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1041
	 * If someone removes a file, then tries to set the quota, we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1042
	 * want to make sure the file freeing takes effect.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1043
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1044
	txg_wait_open(dd->dd_pool, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1045
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1046
	err = dsl_dir_sync_task(dd, dsl_dir_set_quota_sync, &quota, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1047
	dsl_dir_close(dd, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1048
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1049
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1050
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1051
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1052
dsl_dir_set_reservation_sync(dsl_dir_t *dd, void *arg, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1053
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1054
	uint64_t *reservationp = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1055
	uint64_t new_reservation = *reservationp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1056
	uint64_t used, avail;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1057
	int64_t delta;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1058
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1059
	if (new_reservation > INT64_MAX)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1060
		return (EOVERFLOW);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1061
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1062
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1063
	used = dd->dd_used_bytes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1064
	delta = MAX(used, new_reservation) -
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1065
	    MAX(used, dd->dd_phys->dd_reserved);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1066
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1067
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1068
	if (dd->dd_parent) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1069
		avail = dsl_dir_space_available(dd->dd_parent,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1070
		    NULL, 0, FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1071
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1072
		avail = dsl_pool_adjustedsize(dd->dd_pool, B_FALSE) - used;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1073
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1074
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1075
	if (delta > 0 && delta > avail)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1076
		return (ENOSPC);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1077
	if (delta > 0 && dd->dd_phys->dd_quota > 0 &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1078
	    new_reservation > dd->dd_phys->dd_quota)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1079
		return (ENOSPC);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1080
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1081
	dmu_buf_will_dirty(dd->dd_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1082
	dd->dd_phys->dd_reserved = new_reservation;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1083
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1084
	if (dd->dd_parent != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1085
		/* Roll up this additional usage into our ancestors */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1086
		dsl_dir_diduse_space(dd->dd_parent, delta, 0, 0, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1087
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1088
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1089
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1090
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1091
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1092
dsl_dir_set_reservation(const char *ddname, uint64_t reservation)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1093
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1094
	dsl_dir_t *dd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1095
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1096
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1097
	err = dsl_dir_open(ddname, FTAG, &dd, NULL);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1098
	if (err)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1099
		return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1100
	err = dsl_dir_sync_task(dd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1101
	    dsl_dir_set_reservation_sync, &reservation, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1102
	dsl_dir_close(dd, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1103
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1104
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1105
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1106
static dsl_dir_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1107
closest_common_ancestor(dsl_dir_t *ds1, dsl_dir_t *ds2)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1108
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1109
	for (; ds1; ds1 = ds1->dd_parent) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1110
		dsl_dir_t *dd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1111
		for (dd = ds2; dd; dd = dd->dd_parent) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1112
			if (ds1 == dd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1113
				return (dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1114
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1115
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1116
	return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1117
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1118
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1119
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1120
 * If delta is applied to dd, how much of that delta would be applied to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1121
 * ancestor?  Syncing context only.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1122
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1123
static int64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1124
would_change(dsl_dir_t *dd, int64_t delta, dsl_dir_t *ancestor)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1125
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1126
	if (dd == ancestor)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1127
		return (delta);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1128
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1129
	mutex_enter(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1130
	delta = parent_delta(dd, dd->dd_used_bytes, delta);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1131
	mutex_exit(&dd->dd_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1132
	return (would_change(dd->dd_parent, delta, ancestor));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1133
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1134
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1135
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1136
dsl_dir_rename_sync(dsl_dir_t *dd, void *arg, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1137
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1138
	const char *newname = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1139
	dsl_pool_t *dp = dd->dd_pool;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1140
	objset_t *mos = dp->dp_meta_objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1141
	dsl_dir_t *newpds;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1142
	const char *tail;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1143
	int err, len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1144
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1145
	/* can't rename to different pool */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1146
	len = strlen(dp->dp_root_dir->dd_myname);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1147
	if (strncmp(dp->dp_root_dir->dd_myname, newname, len != 0) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1148
	    newname[len] != '/') {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1149
		return (ENXIO);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1150
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1151
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1152
	/* new parent should exist */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1153
	err = dsl_dir_open_spa(dp->dp_spa, newname, FTAG, &newpds, &tail);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1154
	if (err)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1155
		return (err);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1156
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1157
	/* new name should not already exist */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1158
	if (tail == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1159
		dsl_dir_close(newpds, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1160
		return (EEXIST);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1161
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1162
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1163
	rw_enter(&dp->dp_config_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1164
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1165
	/* There should be 2 references: the open and the dirty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1166
	if (dmu_buf_refcount(dd->dd_dbuf) > 2) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1167
		rw_exit(&dp->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1168
		dsl_dir_close(newpds, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1169
		return (EBUSY);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1170
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1171
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1172
	if (newpds != dd->dd_parent) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1173
		dsl_dir_t *ancestor;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1174
		int64_t adelta;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1175
		uint64_t myspace, avail;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1176
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1177
		ancestor = closest_common_ancestor(dd, newpds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1178
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1179
		/* no rename into our descendent */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1180
		if (ancestor == dd) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1181
			dsl_dir_close(newpds, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1182
			rw_exit(&dp->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1183
			return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1184
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1185
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1186
		myspace = MAX(dd->dd_used_bytes, dd->dd_phys->dd_reserved);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1187
		adelta = would_change(dd->dd_parent, -myspace, ancestor);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1188
		avail = dsl_dir_space_available(newpds,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1189
		    ancestor, adelta, FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1190
		if (avail < myspace) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1191
			dsl_dir_close(newpds, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1192
			rw_exit(&dp->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1193
			return (ENOSPC);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1194
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1195
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1196
		/* The point of no (unsuccessful) return */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1197
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1198
		dsl_dir_diduse_space(dd->dd_parent, -myspace,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1199
		    -dd->dd_phys->dd_compressed_bytes,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1200
		    -dd->dd_phys->dd_uncompressed_bytes, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1201
		dsl_dir_diduse_space(newpds, myspace,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1202
		    dd->dd_phys->dd_compressed_bytes,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1203
		    dd->dd_phys->dd_uncompressed_bytes, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1204
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1205
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1206
	/* The point of no (unsuccessful) return */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1207
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1208
	dmu_buf_will_dirty(dd->dd_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1209
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1210
	/* remove from old parent zapobj */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1211
	err = zap_remove(mos, dd->dd_parent->dd_phys->dd_child_dir_zapobj,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1212
	    dd->dd_myname, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1213
	ASSERT3U(err, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1214
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1215
	(void) strcpy(dd->dd_myname, tail);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1216
	dsl_dir_close(dd->dd_parent, dd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1217
	dd->dd_phys->dd_parent_obj = newpds->dd_object;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1218
	VERIFY(0 == dsl_dir_open_obj(dd->dd_pool,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1356
diff changeset
  1219
	    newpds->dd_object, NULL, dd, &dd->dd_parent));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1220
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1221
	/* add to new parent zapobj */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1222
	err = zap_add(mos, newpds->dd_phys->dd_child_dir_zapobj,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1223
	    dd->dd_myname, 8, 1, &dd->dd_object, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1224
	ASSERT3U(err, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1225
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1226
	dsl_dir_close(newpds, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1227
	rw_exit(&dp->dp_config_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1228
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1229
}