Project

General

Profile

Bug #3740 » zfs-send-hold-opt.patch

Patch to fix reported issue - Steven Hartland, 2013-04-23 03:35 PM

View differences:

sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c 2013-04-23 14:41:10.247007393 +0000
147 147
	if (minor != 0) {
148 148
		VERIFY0(dsl_pool_user_hold(dp, ds->ds_object,
149 149
		    htag, now, tx));
150
		dsl_register_onexit_hold_cleanup(ds, htag, minor);
151 150
	}
152 151

  
153 152
	spa_history_log_internal_ds(ds, "hold", tx,
......
186 185
{
187 186
	dsl_dataset_user_hold_arg_t dduha;
188 187
	nvpair_t *pair;
188
	int ret;
189 189

  
190 190
	pair = nvlist_next_nvpair(holds, NULL);
191 191
	if (pair == NULL)
......
195 195
	dduha.dduha_errlist = errlist;
196 196
	dduha.dduha_minor = cleanup_minor;
197 197

  
198
	return (dsl_sync_task(nvpair_name(pair), dsl_dataset_user_hold_check,
199
	    dsl_dataset_user_hold_sync, &dduha, fnvlist_num_pairs(holds)));
198
	ret = dsl_sync_task(nvpair_name(pair), dsl_dataset_user_hold_check,
199
	    dsl_dataset_user_hold_sync, &dduha, fnvlist_num_pairs(holds));
200
	if (ret == 0)
201
		dsl_register_onexit_hold_cleanup(holds, cleanup_minor);
202

  
203
	return (ret);
200 204
}
201 205

  
202 206
typedef struct dsl_dataset_user_release_arg {
......
449 453
	fnvlist_free(ddurta.ddurta_holds);
450 454
}
451 455

  
452
typedef struct zfs_hold_cleanup_arg {
453
	char zhca_spaname[MAXNAMELEN];
454
	uint64_t zhca_spa_load_guid;
455
	uint64_t zhca_dsobj;
456
	char zhca_htag[MAXNAMELEN];
457
} zfs_hold_cleanup_arg_t;
458

  
459 456
static void
460 457
dsl_dataset_user_release_onexit(void *arg)
461 458
{
462
	zfs_hold_cleanup_arg_t *ca = arg;
463
	spa_t *spa;
464
	int error;
459
	nvlist_t *holds = arg;
465 460

  
466
	error = spa_open(ca->zhca_spaname, &spa, FTAG);
467
	if (error != 0) {
468
		zfs_dbgmsg("couldn't release hold on pool=%s ds=%llu tag=%s "
469
		    "because pool is no longer loaded",
470
		    ca->zhca_spaname, ca->zhca_dsobj, ca->zhca_htag);
471
		return;
472
	}
473
	if (spa_load_guid(spa) != ca->zhca_spa_load_guid) {
474
		zfs_dbgmsg("couldn't release hold on pool=%s ds=%llu tag=%s "
475
		    "because pool is no longer loaded (guid doesn't match)",
476
		    ca->zhca_spaname, ca->zhca_dsobj, ca->zhca_htag);
477
		spa_close(spa, FTAG);
478
		return;
479
	}
480

  
481
	dsl_dataset_user_release_tmp(spa_get_dsl(spa),
482
	    ca->zhca_dsobj, ca->zhca_htag);
483
	kmem_free(ca, sizeof (zfs_hold_cleanup_arg_t));
484
	spa_close(spa, FTAG);
461
	(void)dsl_dataset_user_release(holds, NULL);
462
	fnvlist_free(holds);
485 463
}
486 464

  
487 465
void
488
dsl_register_onexit_hold_cleanup(dsl_dataset_t *ds, const char *htag,
489
    minor_t minor)
466
dsl_register_onexit_hold_cleanup(nvlist_t *holds, minor_t minor)
490 467
{
491
	zfs_hold_cleanup_arg_t *ca = kmem_alloc(sizeof (*ca), KM_SLEEP);
492
	spa_t *spa = dsl_dataset_get_spa(ds);
493
	(void) strlcpy(ca->zhca_spaname, spa_name(spa),
494
	    sizeof (ca->zhca_spaname));
495
	ca->zhca_spa_load_guid = spa_load_guid(spa);
496
	ca->zhca_dsobj = ds->ds_object;
497
	(void) strlcpy(ca->zhca_htag, htag, sizeof (ca->zhca_htag));
468
	nvlist_t *ca;
469
	nvpair_t *pair;
470
	char *htag;
471

  
472
	ca = fnvlist_alloc();
473
	/*
474
	 * Convert from hold format: nvl of snapname -> holdname
475
	 * to release format: nvl of snapname -> { holdname, ... }
476
	 */
477
	for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
478
	    pair = nvlist_next_nvpair(holds, pair)) {
479
		if (nvpair_value_string(pair, &htag) == 0) {
480
			nvlist_t *snapholds;
481

  
482
			snapholds = fnvlist_alloc();
483
			fnvlist_add_boolean(snapholds, htag);
484
			fnvlist_add_nvlist(ca, nvpair_name(pair), snapholds);
485
		}
486
	}
498 487
	VERIFY0(zfs_onexit_add_cb(minor,
499 488
	    dsl_dataset_user_release_onexit, ca, NULL));
500 489
}
501
-- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h.orig	2013-04-23 13:07:36.990900411 +0000
490
++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h	2013-04-23 13:07:58.639898371 +0000
......
187 187
void dsl_dataset_disown(dsl_dataset_t *ds, void *tag);
188 188
void dsl_dataset_name(dsl_dataset_t *ds, char *name);
189 189
boolean_t dsl_dataset_tryown(dsl_dataset_t *ds, void *tag);
190
void dsl_register_onexit_hold_cleanup(dsl_dataset_t *ds, const char *htag,
191
    minor_t minor);
190
void dsl_register_onexit_hold_cleanup(nvlist_t *holds, minor_t minor);
192 191
uint64_t dsl_dataset_create_sync(dsl_dir_t *pds, const char *lastname,
193 192
    dsl_dataset_t *origin, uint64_t flags, cred_t *, dmu_tx_t *);
194 193
uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
195
-- cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h.orig	2013-04-22 19:04:23.398365244 +0000
194
++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	2013-04-22 22:17:19.693569140 +0000
......
612 612
extern int zfs_promote(zfs_handle_t *);
613 613
extern int zfs_hold(zfs_handle_t *, const char *, const char *,
614 614
    boolean_t, boolean_t, int);
615
extern int zfs_hold_add(zfs_handle_t *, const char *, const char *,
616
    nvlist_t *);
617
extern int zfs_hold_apply(zfs_handle_t *, boolean_t, int, nvlist_t **);
615 618
extern int zfs_release(zfs_handle_t *, const char *, const char *, boolean_t);
616 619
extern int zfs_get_holds(zfs_handle_t *, nvlist_t **);
617 620
extern uint64_t zvol_volsize_to_reservation(uint64_t, nvlist_t *);
618
-- cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c.orig	2013-04-22 20:37:43.752983581 +0000
621
++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	2013-04-23 10:52:11.640421015 +0000
......
4188 4188
}
4189 4189

  
4190 4190
int
4191
zfs_hold_add(zfs_handle_t *zhp, const char *snapname, const char *tag,
4192
    boolean_t enoent_ok, nvlist_t *holds)
4193
{
4194
	zfs_handle_t *szhp;
4195
	char name[ZFS_MAXNAMELEN];
4196
	char errbuf[1024];
4197
	int ret;
4198

  
4199
	(void) snprintf(name, sizeof (name),
4200
	    "%s@%s", zhp->zfs_name, snapname);
4201

  
4202
	szhp = make_dataset_handle(zhp->zfs_hdl, name);
4203
	if (szhp) {
4204
		fnvlist_add_string(holds, name, tag);
4205
		zfs_close(szhp);
4206
		return (0);
4207
	}
4208

  
4209
	ret = ENOENT;
4210
	if (enoent_ok)
4211
		return (ret);
4212

  
4213
	(void) snprintf(errbuf, sizeof (errbuf),
4214
	    dgettext(TEXT_DOMAIN, "cannot hold snapshot '%s@%s'"),
4215
	    zhp->zfs_name, snapname);
4216
	(void) zfs_standard_error(zhp->zfs_hdl, ret, errbuf);
4217

  
4218
	return (ret);
4219
}
4220

  
4221
int
4191 4222
zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4192 4223
    boolean_t recursive, boolean_t enoent_ok, int cleanup_fd)
4193 4224
{
......
4207 4238
	if (nvlist_next_nvpair(ha.nvl, NULL) == NULL) {
4208 4239
		fnvlist_free(ha.nvl);
4209 4240
		ret = ENOENT;
4241
		if (enoent_ok)
4242
			return (ret);
4243

  
4210 4244
		(void) snprintf(errbuf, sizeof (errbuf),
4211 4245
		    dgettext(TEXT_DOMAIN, "cannot hold snapshot '%s@%s'"),
4212 4246
		    zhp->zfs_name, snapname);
......
4214 4248
		return (ret);
4215 4249
	}
4216 4250

  
4217
	ret = lzc_hold(ha.nvl, cleanup_fd, &errors);
4218
	fnvlist_free(ha.nvl);
4251
	return zfs_hold_apply(zhp, enoent_ok, cleanup_fd, &ha.nvl);
4252
}
4253

  
4254
int
4255
zfs_hold_apply(zfs_handle_t *zhp, boolean_t enoent_ok, int cleanup_fd, nvlist_t **holds)
4256
{
4257
	int ret;
4258
	nvlist_t *errors;
4259
	libzfs_handle_t *hdl = zhp->zfs_hdl;
4260
	char errbuf[1024];
4261
	nvpair_t *elem;
4262

  
4263
	ret = lzc_hold(*holds, cleanup_fd, &errors);
4264
	fnvlist_free(*holds);
4265
	*holds = NULL;
4219 4266

  
4220 4267
	if (ret == 0)
4221 4268
		return (0);
......
4274 4321
	return (ret);
4275 4322
}
4276 4323

  
4277
struct releasearg {
4278
	nvlist_t *nvl;
4279
	const char *snapname;
4280
	const char *tag;
4281
	boolean_t recursive;
4282
};
4283

  
4284 4324
static int
4285 4325
zfs_release_one(zfs_handle_t *zhp, void *arg)
4286 4326
{
4287
-- cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c.orig	2013-04-22 19:13:01.224334570 +0000
4327
++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c	2013-04-23 14:53:07.257961722 +0000
......
802 802
	int outfd;
803 803
	boolean_t err;
804 804
	nvlist_t *fss;
805
	nvlist_t *snapholds;
805 806
	avl_tree_t *fsavl;
806 807
	snapfilter_cb_t *filter_cb;
807 808
	void *filter_cb_arg;
......
961 962

  
962 963
	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
963 964

  
964
	if (sdd->dryrun)
965
		return (0);
966

  
967
	/*
968
	 * zfs_send() only opens a cleanup_fd for sends that need it,
969
	 * e.g. replication and doall.
970
	 */
971
	if (sdd->cleanup_fd == -1)
965
	/* We process if snapholds is not NULL even if on a dry run. */
966
	if (sdd->snapholds == NULL)
972 967
		return (0);
973 968

  
974 969
	thissnap = strchr(zhp->zfs_name, '@') + 1;
......
981 976
	 * handle that error.
982 977
	 */
983 978
	if (pzhp) {
984
		error = zfs_hold(pzhp, thissnap, sdd->holdtag,
985
		    B_FALSE, B_TRUE, sdd->cleanup_fd);
979
		error = zfs_hold_add(pzhp, thissnap, sdd->holdtag, B_TRUE,
980
		    sdd->snapholds);
986 981
		zfs_close(pzhp);
987 982
	}
988 983

  
......
1552 1547
			err = errno;
1553 1548
			goto stderr_out;
1554 1549
		}
1550
		sdd.snapholds = fnvlist_alloc();
1555 1551
	} else {
1556 1552
		sdd.cleanup_fd = -1;
1553
		sdd.snapholds = NULL;
1557 1554
	}
1558 1555
	if (flags->verbose) {
1559 1556
		/*
......
1575 1572
			    "total estimated size is %s\n"), buf);
1576 1573
		}
1577 1574
	}
1575

  
1576
	if (sdd.snapholds != NULL) {
1577
		/* holds are required */
1578
		if (!flags->verbose) {
1579
			/*
1580
			 * A verbose dry run wasn't done so force a non-verbose
1581
			 * dry run to collate snapshot hold's
1582
			 */
1583
			sdd.dryrun = B_TRUE;
1584
			err = dump_filesystems(zhp, &sdd);
1585
			sdd.dryrun = flags->dryrun;
1586
		}
1587
		if (err != 0)
1588
			goto stderr_out;
1589
		if ((err = zfs_hold_apply(zhp, B_TRUE, sdd.cleanup_fd,
1590
		    &sdd.snapholds)) != 0)
1591
			goto stderr_out;
1592
	}
1593
	
1578 1594
	err = dump_filesystems(zhp, &sdd);
1579 1595
	fsavl_destroy(fsavl);
1580 1596
	nvlist_free(fss);
(1-1/2)