kern/157728: [zfs] zfs (v28) incremental receive may leave
behind temporary clones
Martin Matuska
mm at FreeBSD.org
Sat Jul 16 14:20:10 UTC 2011
The following reply was made to PR kern/157728; it has been noted by GNATS.
From: Martin Matuska <mm at FreeBSD.org>
To: bug-followup at FreeBSD.org, mm at FreeBSD.org
Cc:
Subject: Re: kern/157728: [zfs] zfs (v28) incremental receive may leave behind
temporary clones
Date: Sat, 16 Jul 2011 16:13:12 +0200
I have debugged this a little and have now more information.
The snapshot is set for deferred destroy but the temporary clone does
not get deleted, because of an extra hold:
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c: #3558,
zfs_ioc_recv():
end_err = dmu_recv_end(&drc);
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c: #1621,
dmu_recv_end():
return (dmu_recv_existing_end(drc));
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c: #1581,
dmu_recv_existing_end():
(void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
This dataset does not get destroyed , error EBUSY.
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c: #1158,
dsl_dataset_destroy():
dstg = dsl_sync_task_group_create(ds->ds_dir->dd_pool);
dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
dsl_dataset_destroy_sync, &dsda, tag, 0);
dsl_sync_task_create(dstg, dsl_dir_destroy_check,
dsl_dir_destroy_sync, &dummy_ds, FTAG, 0);
err = dsl_sync_task_group_wait(dstg);
dsl_sync_task_group_destroy(dstg);
dsl_sync_task_group_wait() calls:
- dsl_dataset_destroy_check (returns 0)
- dsl_dir_destroy_check (returns EBUSY, should return 0) <-- error comes
from here
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c: #466,
dsl_dir_destroy_check():
if (dmu_buf_refcount(dd->dd_dbuf) > 2)
return (EBUSY); <--- EBUSY comes from here
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c: #2101
#pragma weak dmu_buf_refcount = dbuf_refcount
uint64_t
dbuf_refcount(dmu_buf_impl_t *db)
{
return (refcount_count(&db->db_holds));
}
If we issue zfs list or zfs get (recursive or on the dataset) the
db->db_holds for the clone has a value of 3, otherwise a value of 2.
With 3, destroying the temporary clone fails and deferred destroy of the
snapshot fails, too.
Looks like a extra hold is placed on the temporary clone.
--
Martin Matuska
FreeBSD committer
http://blog.vx.sk
More information about the freebsd-fs
mailing list