Date: Sat, 16 Jul 2011 14:20:10 GMT From: Martin Matuska <mm@FreeBSD.org> To: freebsd-fs@FreeBSD.org Subject: Re: kern/157728: [zfs] zfs (v28) incremental receive may leave behind temporary clones Message-ID: <201107161420.p6GEKAL2072415@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/157728; it has been noted by GNATS. From: Martin Matuska <mm@FreeBSD.org> To: bug-followup@FreeBSD.org, mm@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107161420.p6GEKAL2072415>