summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2013-07-29 21:50:08 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2013-07-29 21:50:08 +0000
commit9749e7cccd7d3d25268c6868b7cec197852879c5 (patch)
treeb00100709600c4007e28bbed6e78790f09e5b47d
parent78e78e4a1a42fe8915a50b36c14133ec19018ac8 (diff)
parent36f7455d36b60be70d7aae5959fa19e71954678e (diff)
downloadillumos-joyent-9749e7cccd7d3d25268c6868b7cec197852879c5.tar.gz
[illumos-gate merge]
commit 36f7455d36b60be70d7aae5959fa19e71954678e 3909 "zfs send -D" does not work commit 2f3d878000c3b33cde13e16c4f0a1ab15d883a18 3834 incremental replication of 'holey' file systems is slow commit 34f2f8cf94052481c81be2e134b94a00b501bf21 3888 zfs recv -F should destroy any snapshots created since the incremental source commit eb341807e07639369211020c815f2b9002798a8a 3778 1000BASE-LX support in ixgbe commit 69c7619071dc71a079b65cd199d237df0f487d15 3856 want FW config version number for igb and ixgbe commit bc2cf0f56ec3597d482c5feb91417385d8e8374c 3913 there is no dialup, only zuul commit ca48f36f20f6098ceb19d5b084b6b3d4b8eca9fa 3894 zfs should not allow snapshot of inconsistent dataset commit 91948b51b8e978ddc88a36b2bc3ae83c20cdc9aa 3875 panic in zfs_root() after failed rollback commit 9889d1c6ca2bae13060bd0690ee771c8bb53303d 3706 mdb segfault when random address is passed to "list" walker commit 21072fc3aa88bec97f3089899d4c2916ac8f0695 3911 mdb is unable to display recursive stack
-rw-r--r--exception_lists/cstyle3
-rw-r--r--usr/src/cmd/halt/halt.c3
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/list.c15
-rw-r--r--usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c10
-rw-r--r--usr/src/lib/libzfs/common/libzfs_sendrecv.c4
-rw-r--r--usr/src/man/man1m/halt.1m3
-rw-r--r--usr/src/uts/common/fs/zfs/dbuf.c20
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_objset.c1
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_send.c173
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_tx.c49
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_dataset.c23
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_destroy.c5
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dmu_impl.h6
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dmu_send.h3
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dsl_dataset.h5
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dsl_destroy.h21
-rw-r--r--usr/src/uts/common/io/ixgbe/ixgbe_82599.c2
-rw-r--r--usr/src/uts/common/io/ixgbe/ixgbe_phy.c21
-rw-r--r--usr/src/uts/common/io/ixgbe/ixgbe_type.h2
19 files changed, 269 insertions, 100 deletions
diff --git a/exception_lists/cstyle b/exception_lists/cstyle
index 9d8a350096..28624d8c56 100644
--- a/exception_lists/cstyle
+++ b/exception_lists/cstyle
@@ -655,6 +655,9 @@ usr/src/uts/common/gssapi/mechs/krb5/mech/util_validate.c
usr/src/uts/common/gssapi/mechs/krb5/mech/val_cred.c
usr/src/uts/common/gssapi/mechs/krb5/mech/verify.c
usr/src/uts/common/gssapi/mechs/krb5/mech/wrap_size_limit.c
+usr/src/uts/common/io/igb/igb_api.c
+usr/src/uts/common/io/igb/igb_nvm.c
+usr/src/uts/common/io/igb/igb_defines.h
usr/src/uts/common/io/ixgbe/ixgbe_82598.c
usr/src/uts/common/io/ixgbe/ixgbe_82598.h
usr/src/uts/common/io/ixgbe/ixgbe_82599.c
diff --git a/usr/src/cmd/halt/halt.c b/usr/src/cmd/halt/halt.c
index 7ae9555ef3..aa6909b643 100644
--- a/usr/src/cmd/halt/halt.c
+++ b/usr/src/cmd/halt/halt.c
@@ -23,6 +23,9 @@
* Use is subject to license terms.
* Copyright 2011 Joyent, Inc. All rights reserved.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
diff --git a/usr/src/cmd/mdb/common/modules/genunix/list.c b/usr/src/cmd/mdb/common/modules/genunix/list.c
index 58e21ebc6f..1a04d83e37 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/list.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/list.c
@@ -22,8 +22,9 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
#include <mdb/mdb_modapi.h>
#include <sys/list.h>
@@ -66,14 +67,20 @@ list_walk_init_range(mdb_walk_state_t *wsp, uintptr_t begin, uintptr_t end,
if (element_name == NULL)
element_name = "list element";
- lwd = mdb_alloc(sizeof (list_walk_data_t), UM_SLEEP);
if (mdb_vread(&list, sizeof (list_t), wsp->walk_addr) == -1) {
mdb_warn("failed to read %s at %#lx", list_name,
wsp->walk_addr);
- mdb_free(lwd, sizeof (list_walk_data_t));
return (WALK_ERR);
}
+ if (list.list_size < list.list_offset + sizeof (list_node_t)) {
+ mdb_warn("invalid or uninitialized %s at %#lx\n", list_name,
+ wsp->walk_addr);
+ return (WALK_ERR);
+ }
+
+ lwd = mdb_alloc(sizeof (list_walk_data_t), UM_SLEEP);
+
lwd->lw_size = list.list_size;
lwd->lw_offset = list.list_offset;
lwd->lw_obj = mdb_alloc(list.list_size, UM_SLEEP);
diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c
index 60aa1ec991..432f22210c 100644
--- a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c
+++ b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c
@@ -24,6 +24,7 @@
* Use is subject to license terms.
*/
/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
@@ -228,7 +229,7 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
uintptr_t fp = gsp->kregs[KREG_RBP];
uintptr_t pc = gsp->kregs[KREG_RIP];
- uintptr_t lastfp, curpc;
+ uintptr_t lastfp;
ssize_t size;
ssize_t insnsize;
@@ -250,8 +251,6 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
while (fp != 0) {
int args_style = 0;
- curpc = pc;
-
if (!fp_is_aligned(fp, xpv_panic))
return (set_errno(EMDB_STKALIGN));
@@ -376,14 +375,11 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
if (xpv_panic)
if ((fp != 0) && (fp < lastfp) &&
((lastfp ^ ~fp) < 0xfff))
- fp = ~fp;
+ fp = ~fp;
kregs[KREG_RBP] = fp;
kregs[KREG_RIP] = pc = fr.fr_savpc;
- if (curpc == pc)
- break;
-
got_pc = (pc != 0);
}
diff --git a/usr/src/lib/libzfs/common/libzfs_sendrecv.c b/usr/src/lib/libzfs/common/libzfs_sendrecv.c
index cf6d32f7b0..fefaa0d513 100644
--- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c
+++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c
@@ -1566,8 +1566,8 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
if (tid != 0) {
if (err != 0)
(void) pthread_cancel(tid);
- (void) pthread_join(tid, NULL);
(void) close(pipefd[0]);
+ (void) pthread_join(tid, NULL);
}
if (sdd.cleanup_fd != -1) {
@@ -1603,8 +1603,8 @@ err_out:
VERIFY(0 == close(sdd.cleanup_fd));
if (tid != 0) {
(void) pthread_cancel(tid);
- (void) pthread_join(tid, NULL);
(void) close(pipefd[0]);
+ (void) pthread_join(tid, NULL);
}
return (err);
}
diff --git a/usr/src/man/man1m/halt.1m b/usr/src/man/man1m/halt.1m
index 86c7cfee68..e2bc05695b 100644
--- a/usr/src/man/man1m/halt.1m
+++ b/usr/src/man/man1m/halt.1m
@@ -1,9 +1,10 @@
'\" te
.\" Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright (c) 2013, Joyent, Inc. All rights reserved.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH HALT 1M "Nov 2, 2004"
+.TH HALT 1M "Jul 26, 2013"
.SH NAME
halt, poweroff \- stop the processor
.SH SYNOPSIS
diff --git a/usr/src/uts/common/fs/zfs/dbuf.c b/usr/src/uts/common/fs/zfs/dbuf.c
index 9f4c8a8e35..d4acbb5b3c 100644
--- a/usr/src/uts/common/fs/zfs/dbuf.c
+++ b/usr/src/uts/common/fs/zfs/dbuf.c
@@ -28,6 +28,7 @@
#include <sys/zfs_context.h>
#include <sys/dmu.h>
+#include <sys/dmu_send.h>
#include <sys/dmu_impl.h>
#include <sys/dbuf.h>
#include <sys/dmu_objset.h>
@@ -808,9 +809,12 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
/*
* Evict (if its unreferenced) or clear (if its referenced) any level-0
* data blocks in the free range, so that any future readers will find
- * empty blocks. Also, if we happen accross any level-1 dbufs in the
+ * empty blocks. Also, if we happen across any level-1 dbufs in the
* range that have not already been marked dirty, mark them dirty so
* they stay in memory.
+ *
+ * This is a no-op if the dataset is in the middle of an incremental
+ * receive; see comment below for details.
*/
void
dbuf_free_range(dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *tx)
@@ -826,6 +830,20 @@ dbuf_free_range(dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *tx)
last_l1 = end >> epbs;
}
dprintf_dnode(dn, "start=%llu end=%llu\n", start, end);
+
+ if (dmu_objset_is_receiving(dn->dn_objset)) {
+ /*
+ * When processing a free record from a zfs receive,
+ * there should have been no previous modifications to the
+ * data in this range. Therefore there should be no dbufs
+ * in the range. Searching dn_dbufs for these non-existent
+ * dbufs can be very expensive, so simply ignore this.
+ */
+ VERIFY3P(dbuf_find(dn, 0, start), ==, NULL);
+ VERIFY3P(dbuf_find(dn, 0, end), ==, NULL);
+ return;
+ }
+
mutex_enter(&dn->dn_dbufs_mtx);
for (db = list_head(&dn->dn_dbufs); db; db = db_next) {
db_next = list_next(&dn->dn_dbufs, db);
diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c
index 401facd04e..46bf3bfeb2 100644
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c
@@ -534,7 +534,6 @@ dmu_objset_refresh_ownership(objset_t *os, void *tag)
dsl_pool_t *dp;
dsl_dataset_t *ds, *newds;
char name[MAXNAMELEN];
- int err;
ds = os->os_dsl_dataset;
VERIFY3P(ds, !=, NULL);
diff --git a/usr/src/uts/common/fs/zfs/dmu_send.c b/usr/src/uts/common/fs/zfs/dmu_send.c
index 83cac19497..ba1b9c753b 100644
--- a/usr/src/uts/common/fs/zfs/dmu_send.c
+++ b/usr/src/uts/common/fs/zfs/dmu_send.c
@@ -80,6 +80,32 @@ dump_free(dmu_sendarg_t *dsp, uint64_t object, uint64_t offset,
{
struct drr_free *drrf = &(dsp->dsa_drr->drr_u.drr_free);
+ /*
+ * When we receive a free record, dbuf_free_range() assumes
+ * that the receiving system doesn't have any dbufs in the range
+ * being freed. This is always true because there is a one-record
+ * constraint: we only send one WRITE record for any given
+ * object+offset. We know that the one-record constraint is
+ * true because we always send data in increasing order by
+ * object,offset.
+ *
+ * If the increasing-order constraint ever changes, we should find
+ * another way to assert that the one-record constraint is still
+ * satisfied.
+ */
+ ASSERT(object > dsp->dsa_last_data_object ||
+ (object == dsp->dsa_last_data_object &&
+ offset > dsp->dsa_last_data_offset));
+
+ /*
+ * If we are doing a non-incremental send, then there can't
+ * be any data in the dataset we're receiving into. Therefore
+ * a free record would simply be a no-op. Save space by not
+ * sending it to begin with.
+ */
+ if (!dsp->dsa_incremental)
+ return (0);
+
if (length != -1ULL && offset + length < offset)
length = -1ULL;
@@ -146,6 +172,15 @@ dump_data(dmu_sendarg_t *dsp, dmu_object_type_t type,
{
struct drr_write *drrw = &(dsp->dsa_drr->drr_u.drr_write);
+ /*
+ * We send data in increasing object, offset order.
+ * See comment in dump_free() for details.
+ */
+ ASSERT(object > dsp->dsa_last_data_object ||
+ (object == dsp->dsa_last_data_object &&
+ offset > dsp->dsa_last_data_offset));
+ dsp->dsa_last_data_object = object;
+ dsp->dsa_last_data_offset = offset + blksz - 1;
/*
* If there is any kind of pending aggregation (currently either
@@ -213,6 +248,10 @@ dump_freeobjects(dmu_sendarg_t *dsp, uint64_t firstobj, uint64_t numobjs)
{
struct drr_freeobjects *drrfo = &(dsp->dsa_drr->drr_u.drr_freeobjects);
+ /* See comment in dump_free(). */
+ if (!dsp->dsa_incremental)
+ return (0);
+
/*
* If there is a pending op, but it's not PENDING_FREEOBJECTS,
* push it out, since free block aggregation can only be done for
@@ -289,9 +328,9 @@ dump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp)
if (dump_bytes(dsp, DN_BONUS(dnp), P2ROUNDUP(dnp->dn_bonuslen, 8)) != 0)
return (SET_ERROR(EINTR));
- /* free anything past the end of the file */
+ /* Free anything past the end of the file. */
if (dump_free(dsp, object, (dnp->dn_maxblkid + 1) *
- (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL))
+ (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL) != 0)
return (SET_ERROR(EINTR));
if (dsp->dsa_err != 0)
return (SET_ERROR(EINTR));
@@ -474,6 +513,7 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds,
dsp->dsa_toguid = ds->ds_phys->ds_guid;
ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0);
dsp->dsa_pending_op = PENDING_NONE;
+ dsp->dsa_incremental = (fromtxg != 0);
mutex_enter(&ds->ds_sendstream_lock);
list_insert_head(&ds->ds_sendstreams, dsp);
@@ -654,6 +694,7 @@ typedef struct dmu_recv_begin_arg {
const char *drba_origin;
dmu_recv_cookie_t *drba_cookie;
cred_t *drba_cred;
+ uint64_t drba_snapobj;
} dmu_recv_begin_arg_t;
static int
@@ -664,11 +705,6 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
int error;
dsl_pool_t *dp = ds->ds_dir->dd_pool;
- /* must not have any changes since most recent snapshot */
- if (!drba->drba_cookie->drc_force &&
- dsl_dataset_modified_since_lastsnap(ds))
- return (SET_ERROR(ETXTBSY));
-
/* temporary clone name must not exist */
error = zap_lookup(dp->dp_meta_objset,
ds->ds_dir->dd_phys->dd_child_dir_zapobj, recv_clone_name,
@@ -684,41 +720,47 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
return (error == 0 ? EEXIST : error);
if (fromguid != 0) {
- /* if incremental, most recent snapshot must match fromguid */
- if (ds->ds_prev == NULL)
+ dsl_dataset_t *snap;
+ uint64_t obj = ds->ds_phys->ds_prev_snap_obj;
+
+ /* Find snapshot in this dir that matches fromguid. */
+ while (obj != 0) {
+ error = dsl_dataset_hold_obj(dp, obj, FTAG,
+ &snap);
+ if (error != 0)
+ return (SET_ERROR(ENODEV));
+ if (snap->ds_dir != ds->ds_dir) {
+ dsl_dataset_rele(snap, FTAG);
+ return (SET_ERROR(ENODEV));
+ }
+ if (snap->ds_phys->ds_guid == fromguid)
+ break;
+ obj = snap->ds_phys->ds_prev_snap_obj;
+ dsl_dataset_rele(snap, FTAG);
+ }
+ if (obj == 0)
return (SET_ERROR(ENODEV));
- /*
- * most recent snapshot must match fromguid, or there are no
- * changes since the fromguid one
- */
- if (ds->ds_prev->ds_phys->ds_guid != fromguid) {
- uint64_t birth = ds->ds_prev->ds_phys->ds_bp.blk_birth;
- uint64_t obj = ds->ds_prev->ds_phys->ds_prev_snap_obj;
- while (obj != 0) {
- dsl_dataset_t *snap;
- error = dsl_dataset_hold_obj(dp, obj, FTAG,
- &snap);
- if (error != 0)
- return (SET_ERROR(ENODEV));
- if (snap->ds_phys->ds_creation_txg < birth) {
- dsl_dataset_rele(snap, FTAG);
- return (SET_ERROR(ENODEV));
- }
- if (snap->ds_phys->ds_guid == fromguid) {
- dsl_dataset_rele(snap, FTAG);
- break; /* it's ok */
- }
- obj = snap->ds_phys->ds_prev_snap_obj;
+ if (drba->drba_cookie->drc_force) {
+ drba->drba_snapobj = obj;
+ } else {
+ /*
+ * If we are not forcing, there must be no
+ * changes since fromsnap.
+ */
+ if (dsl_dataset_modified_since_snap(ds, snap)) {
dsl_dataset_rele(snap, FTAG);
+ return (SET_ERROR(ETXTBSY));
}
- if (obj == 0)
- return (SET_ERROR(ENODEV));
+ drba->drba_snapobj = ds->ds_prev->ds_object;
}
+
+ dsl_dataset_rele(snap, FTAG);
} else {
/* if full, most recent snapshot must be $ORIGIN */
if (ds->ds_phys->ds_prev_snap_txg >= TXG_INITIAL)
return (SET_ERROR(ENODEV));
+ drba->drba_snapobj = ds->ds_phys->ds_prev_snap_obj;
}
return (0);
@@ -827,8 +869,14 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
error = dsl_dataset_hold(dp, tofs, FTAG, &ds);
if (error == 0) {
/* create temporary clone */
+ dsl_dataset_t *snap = NULL;
+ if (drba->drba_snapobj != 0) {
+ VERIFY0(dsl_dataset_hold_obj(dp,
+ drba->drba_snapobj, FTAG, &snap));
+ }
dsobj = dsl_dataset_create_sync(ds->ds_dir, recv_clone_name,
- ds->ds_prev, crflags, drba->drba_cred, tx);
+ snap, crflags, drba->drba_cred, tx);
+ dsl_dataset_rele(snap, FTAG);
dsl_dataset_rele(ds, FTAG);
} else {
dsl_dir_t *dd;
@@ -1546,6 +1594,32 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx)
error = dsl_dataset_hold(dp, drc->drc_tofs, FTAG, &origin_head);
if (error != 0)
return (error);
+ if (drc->drc_force) {
+ /*
+ * We will destroy any snapshots in tofs (i.e. before
+ * origin_head) that are after the origin (which is
+ * the snap before drc_ds, because drc_ds can not
+ * have any snaps of its own).
+ */
+ uint64_t obj = origin_head->ds_phys->ds_prev_snap_obj;
+ while (obj != drc->drc_ds->ds_phys->ds_prev_snap_obj) {
+ dsl_dataset_t *snap;
+ error = dsl_dataset_hold_obj(dp, obj, FTAG,
+ &snap);
+ if (error != 0)
+ return (error);
+ if (snap->ds_dir != origin_head->ds_dir)
+ error = SET_ERROR(EINVAL);
+ if (error == 0) {
+ error = dsl_destroy_snapshot_check_impl(
+ snap, B_FALSE);
+ }
+ obj = snap->ds_phys->ds_prev_snap_obj;
+ dsl_dataset_rele(snap, FTAG);
+ if (error != 0)
+ return (error);
+ }
+ }
error = dsl_dataset_clone_swap_check_impl(drc->drc_ds,
origin_head, drc->drc_force, drc->drc_owner, tx);
if (error != 0) {
@@ -1580,6 +1654,27 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
VERIFY0(dsl_dataset_hold(dp, drc->drc_tofs, FTAG,
&origin_head));
+
+ if (drc->drc_force) {
+ /*
+ * Destroy any snapshots of drc_tofs (origin_head)
+ * after the origin (the snap before drc_ds).
+ */
+ uint64_t obj = origin_head->ds_phys->ds_prev_snap_obj;
+ while (obj != drc->drc_ds->ds_phys->ds_prev_snap_obj) {
+ dsl_dataset_t *snap;
+ VERIFY0(dsl_dataset_hold_obj(dp, obj, FTAG,
+ &snap));
+ ASSERT3P(snap->ds_dir, ==, origin_head->ds_dir);
+ obj = snap->ds_phys->ds_prev_snap_obj;
+ dsl_destroy_snapshot_sync_impl(snap,
+ B_FALSE, tx);
+ dsl_dataset_rele(snap, FTAG);
+ }
+ }
+ VERIFY3P(drc->drc_ds->ds_prev, ==,
+ origin_head->ds_prev);
+
dsl_dataset_clone_swap_sync_impl(drc->drc_ds,
origin_head, tx);
dsl_dataset_snapshot_sync_impl(origin_head,
@@ -1710,3 +1805,13 @@ dmu_recv_end(dmu_recv_cookie_t *drc, void *owner)
else
return (dmu_recv_existing_end(drc));
}
+
+/*
+ * Return TRUE if this objset is currently being received into.
+ */
+boolean_t
+dmu_objset_is_receiving(objset_t *os)
+{
+ return (os->os_dsl_dataset != NULL &&
+ os->os_dsl_dataset->ds_owner == dmu_recv_tag);
+}
diff --git a/usr/src/uts/common/fs/zfs/dmu_tx.c b/usr/src/uts/common/fs/zfs/dmu_tx.c
index e30c6d345e..84e518dfd1 100644
--- a/usr/src/uts/common/fs/zfs/dmu_tx.c
+++ b/usr/src/uts/common/fs/zfs/dmu_tx.c
@@ -589,8 +589,7 @@ dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off, uint64_t len)
{
dmu_tx_hold_t *txh;
dnode_t *dn;
- uint64_t start, end, i;
- int err, shift;
+ int err;
zio_t *zio;
ASSERT(tx->tx_txg == 0);
@@ -601,34 +600,48 @@ dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off, uint64_t len)
return;
dn = txh->txh_dnode;
- /* first block */
- if (off != 0)
- dmu_tx_count_write(txh, off, 1);
- /* last block */
- if (len != DMU_OBJECT_END)
- dmu_tx_count_write(txh, off+len, 1);
-
- dmu_tx_count_dnode(txh);
-
if (off >= (dn->dn_maxblkid+1) * dn->dn_datablksz)
return;
if (len == DMU_OBJECT_END)
len = (dn->dn_maxblkid+1) * dn->dn_datablksz - off;
+ dmu_tx_count_dnode(txh);
+
/*
- * For i/o error checking, read the first and last level-0
- * blocks, and all the level-1 blocks. The above count_write's
- * have already taken care of the level-0 blocks.
+ * For i/o error checking, we read the first and last level-0
+ * blocks if they are not aligned, and all the level-1 blocks.
+ *
+ * Note: dbuf_free_range() assumes that we have not instantiated
+ * any level-0 dbufs that will be completely freed. Therefore we must
+ * exercise care to not read or count the first and last blocks
+ * if they are blocksize-aligned.
+ */
+ if (dn->dn_datablkshift == 0) {
+ dmu_tx_count_write(txh, off, len);
+ } else {
+ /* first block will be modified if it is not aligned */
+ if (!IS_P2ALIGNED(off, 1 << dn->dn_datablkshift))
+ dmu_tx_count_write(txh, off, 1);
+ /* last block will be modified if it is not aligned */
+ if (!IS_P2ALIGNED(off + len, 1 << dn->dn_datablkshift))
+ dmu_tx_count_write(txh, off+len, 1);
+ }
+
+ /*
+ * Check level-1 blocks.
*/
if (dn->dn_nlevels > 1) {
- shift = dn->dn_datablkshift + dn->dn_indblkshift -
+ int shift = dn->dn_datablkshift + dn->dn_indblkshift -
SPA_BLKPTRSHIFT;
- start = off >> shift;
- end = dn->dn_datablkshift ? ((off+len) >> shift) : 0;
+ uint64_t start = off >> shift;
+ uint64_t end = (off + len) >> shift;
+
+ ASSERT(dn->dn_datablkshift != 0);
+ ASSERT(dn->dn_indblkshift != 0);
zio = zio_root(tx->tx_pool->dp_spa,
NULL, NULL, ZIO_FLAG_CANFAIL);
- for (i = start; i <= end; i++) {
+ for (uint64_t i = start; i <= end; i++) {
uint64_t ibyte = i << shift;
err = dnode_next_offset(dn, 0, &ibyte, 2, 1, 0);
i = ibyte >> shift;
diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c
index a03d06bd24..be117151ad 100644
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c
@@ -1533,16 +1533,16 @@ dsl_dataset_space(dsl_dataset_t *ds,
}
boolean_t
-dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds)
+dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap)
{
dsl_pool_t *dp = ds->ds_dir->dd_pool;
ASSERT(dsl_pool_config_held(dp));
- if (ds->ds_prev == NULL)
+ if (snap == NULL)
return (B_FALSE);
if (ds->ds_phys->ds_bp.blk_birth >
- ds->ds_prev->ds_phys->ds_creation_txg) {
- objset_t *os, *os_prev;
+ snap->ds_phys->ds_creation_txg) {
+ objset_t *os, *os_snap;
/*
* It may be that only the ZIL differs, because it was
* reset in the head. Don't count that as being
@@ -1550,10 +1550,10 @@ dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds)
*/
if (dmu_objset_from_ds(ds, &os) != 0)
return (B_TRUE);
- if (dmu_objset_from_ds(ds->ds_prev, &os_prev) != 0)
+ if (dmu_objset_from_ds(snap, &os_snap) != 0)
return (B_TRUE);
return (bcmp(&os->os_phys->os_meta_dnode,
- &os_prev->os_phys->os_meta_dnode,
+ &os_snap->os_phys->os_meta_dnode,
sizeof (os->os_phys->os_meta_dnode)) != 0);
}
return (B_FALSE);
@@ -2356,15 +2356,14 @@ dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
dsl_dataset_is_snapshot(origin_head))
return (SET_ERROR(EINVAL));
- /* the branch point should be just before them */
- if (clone->ds_prev != origin_head->ds_prev)
+ /* if we are not forcing, the branch point should be just before them */
+ if (!force && clone->ds_prev != origin_head->ds_prev)
return (SET_ERROR(EINVAL));
/* clone should be the clone (unless they are unrelated) */
if (clone->ds_prev != NULL &&
clone->ds_prev != clone->ds_dir->dd_pool->dp_origin_snap &&
- origin_head->ds_object !=
- clone->ds_prev->ds_phys->ds_next_snap_obj)
+ origin_head->ds_dir != clone->ds_prev->ds_dir)
return (SET_ERROR(EINVAL));
/* the clone should be a child of the origin */
@@ -2372,7 +2371,8 @@ dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
return (SET_ERROR(EINVAL));
/* origin_head shouldn't be modified unless 'force' */
- if (!force && dsl_dataset_modified_since_lastsnap(origin_head))
+ if (!force &&
+ dsl_dataset_modified_since_snap(origin_head, origin_head->ds_prev))
return (SET_ERROR(ETXTBSY));
/* origin_head should have no long holds (e.g. is not mounted) */
@@ -2409,6 +2409,7 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
ASSERT(clone->ds_reserved == 0);
ASSERT(origin_head->ds_quota == 0 ||
clone->ds_phys->ds_unique_bytes <= origin_head->ds_quota);
+ ASSERT3P(clone->ds_prev, ==, origin_head->ds_prev);
dmu_buf_will_dirty(clone->ds_dbuf, tx);
dmu_buf_will_dirty(origin_head->ds_dbuf, tx);
diff --git a/usr/src/uts/common/fs/zfs/dsl_destroy.c b/usr/src/uts/common/fs/zfs/dsl_destroy.c
index f968215db0..ef46df8e17 100644
--- a/usr/src/uts/common/fs/zfs/dsl_destroy.c
+++ b/usr/src/uts/common/fs/zfs/dsl_destroy.c
@@ -46,10 +46,7 @@ typedef struct dmu_snapshots_destroy_arg {
nvlist_t *dsda_errlist;
} dmu_snapshots_destroy_arg_t;
-/*
- * ds must be owned.
- */
-static int
+int
dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
{
if (!dsl_dataset_is_snapshot(ds))
diff --git a/usr/src/uts/common/fs/zfs/sys/dmu_impl.h b/usr/src/uts/common/fs/zfs/sys/dmu_impl.h
index defcdb29ca..98057ee36f 100644
--- a/usr/src/uts/common/fs/zfs/sys/dmu_impl.h
+++ b/usr/src/uts/common/fs/zfs/sys/dmu_impl.h
@@ -21,7 +21,10 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ */
+/*
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#ifndef _SYS_DMU_IMPL_H
@@ -290,6 +293,9 @@ typedef struct dmu_sendarg {
uint64_t dsa_toguid;
int dsa_err;
dmu_pendop_t dsa_pending_op;
+ boolean_t dsa_incremental;
+ uint64_t dsa_last_data_object;
+ uint64_t dsa_last_data_offset;
} dmu_sendarg_t;
diff --git a/usr/src/uts/common/fs/zfs/sys/dmu_send.h b/usr/src/uts/common/fs/zfs/sys/dmu_send.h
index 6442b20f7b..65514b7620 100644
--- a/usr/src/uts/common/fs/zfs/sys/dmu_send.h
+++ b/usr/src/uts/common/fs/zfs/sys/dmu_send.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
@@ -63,5 +63,6 @@ int dmu_recv_begin(char *tofs, char *tosnap, struct drr_begin *drrb,
int dmu_recv_stream(dmu_recv_cookie_t *drc, struct vnode *vp, offset_t *voffp,
int cleanup_fd, uint64_t *action_handlep);
int dmu_recv_end(dmu_recv_cookie_t *drc, void *owner);
+boolean_t dmu_objset_is_receiving(objset_t *os);
#endif /* _DMU_SEND_H */
diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h b/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h
index 2a6e0b85a3..fa7cad7f76 100644
--- a/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
@@ -206,7 +206,8 @@ void dsl_dataset_set_blkptr(dsl_dataset_t *ds, blkptr_t *bp, dmu_tx_t *tx);
spa_t *dsl_dataset_get_spa(dsl_dataset_t *ds);
-boolean_t dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds);
+boolean_t dsl_dataset_modified_since_snap(dsl_dataset_t *ds,
+ dsl_dataset_t *snap);
void dsl_dataset_sync(dsl_dataset_t *os, zio_t *zio, dmu_tx_t *tx);
diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_destroy.h b/usr/src/uts/common/fs/zfs/sys/dsl_destroy.h
index c5a70bb90e..3f638643b6 100644
--- a/usr/src/uts/common/fs/zfs/sys/dsl_destroy.h
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_destroy.h
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
@@ -35,15 +35,16 @@ struct nvlist;
struct dsl_dataset;
struct dmu_tx;
-int dsl_destroy_snapshots_nvl(struct nvlist *snaps, boolean_t defer,
- struct nvlist *errlist);
-int dsl_destroy_snapshot(const char *name, boolean_t defer);
-int dsl_destroy_head(const char *name);
-int dsl_destroy_head_check_impl(struct dsl_dataset *ds, int expected_holds);
-void dsl_destroy_head_sync_impl(struct dsl_dataset *ds, struct dmu_tx *tx);
-int dsl_destroy_inconsistent(const char *dsname, void *arg);
-void dsl_destroy_snapshot_sync_impl(struct dsl_dataset *ds,
- boolean_t defer, struct dmu_tx *tx);
+int dsl_destroy_snapshots_nvl(struct nvlist *, boolean_t,
+ struct nvlist *);
+int dsl_destroy_snapshot(const char *, boolean_t);
+int dsl_destroy_head(const char *);
+int dsl_destroy_head_check_impl(struct dsl_dataset *, int);
+void dsl_destroy_head_sync_impl(struct dsl_dataset *, struct dmu_tx *);
+int dsl_destroy_inconsistent(const char *, void *);
+int dsl_destroy_snapshot_check_impl(struct dsl_dataset *, boolean_t);
+void dsl_destroy_snapshot_sync_impl(struct dsl_dataset *,
+ boolean_t, struct dmu_tx *);
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_82599.c b/usr/src/uts/common/io/ixgbe/ixgbe_82599.c
index d833aea3f5..fdcaf29cd0 100644
--- a/usr/src/uts/common/io/ixgbe/ixgbe_82599.c
+++ b/usr/src/uts/common/io/ixgbe/ixgbe_82599.c
@@ -306,6 +306,8 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
/* Check if 1G SFP module. */
if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
*speed = IXGBE_LINK_SPEED_1GB_FULL;
diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_phy.c b/usr/src/uts/common/io/ixgbe/ixgbe_phy.c
index a09edafa8d..b89f69222f 100644
--- a/usr/src/uts/common/io/ixgbe/ixgbe_phy.c
+++ b/usr/src/uts/common/io/ixgbe/ixgbe_phy.c
@@ -1085,6 +1085,13 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
else
hw->phy.sfp_type =
ixgbe_sfp_type_1g_sx_core1;
+ } else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) {
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_1g_lx_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_1g_lx_core1;
} else {
hw->phy.sfp_type = ixgbe_sfp_type_unknown;
}
@@ -1178,6 +1185,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
if (comp_codes_10g == 0 &&
!(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
hw->phy.type = ixgbe_phy_sfp_unsupported;
@@ -1193,10 +1202,12 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
(void) ixgbe_get_device_caps(hw, &enforce_sfp);
if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
- !((hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0) ||
- (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1) ||
- (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0) ||
- (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1))) {
+ !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
/* Make sure we're a supported PHY type */
if (hw->phy.type == ixgbe_phy_sfp_intel) {
status = IXGBE_SUCCESS;
@@ -1273,10 +1284,12 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
* SR modules
*/
if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0 ||
+ sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
sfp_type == ixgbe_sfp_type_1g_sx_core0)
sfp_type = ixgbe_sfp_type_srlr_core0;
else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1 ||
+ sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
sfp_type == ixgbe_sfp_type_1g_sx_core1)
sfp_type = ixgbe_sfp_type_srlr_core1;
diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_type.h b/usr/src/uts/common/io/ixgbe/ixgbe_type.h
index c6892c405a..b823b51797 100644
--- a/usr/src/uts/common/io/ixgbe/ixgbe_type.h
+++ b/usr/src/uts/common/io/ixgbe/ixgbe_type.h
@@ -2750,6 +2750,8 @@ enum ixgbe_sfp_type {
ixgbe_sfp_type_1g_cu_core1 = 10,
ixgbe_sfp_type_1g_sx_core0 = 11,
ixgbe_sfp_type_1g_sx_core1 = 12,
+ ixgbe_sfp_type_1g_lx_core0 = 13,
+ ixgbe_sfp_type_1g_lx_core1 = 14,
ixgbe_sfp_type_not_present = 0xFFFE,
ixgbe_sfp_type_unknown = 0xFFFF
};