Print this page
Optimize creation and removal of temporary "user holds" placed on
snapshots by a zfs send, by ensuring all the required holds and
releases are done in a single dsl_sync_task.
Creation now collates the required holds during a dry run and
then uses a single lzc_hold call via zfs_hold_apply instead of
processing each snapshot in turn.
Defered (on exit) cleanup by the kernel is also now done in
dsl_sync_task by reusing dsl_dataset_user_release.
On a test with 11 volumes in a tree each with 8 snapshots on a
single HDD zpool this reduces the time required to perform a full
send from 20 seconds to under 0.8 seconds.
For reference eliminating the hold entirely reduces this 0.15
seconds.
While I'm here:-
* Remove some unused structures
* Fix nvlist_t leak in zfs_release_one


 170 #define MAX_TAG_PREFIX_LEN      17
 171 
 172 #define dsl_dataset_is_snapshot(ds) \
 173         ((ds)->ds_phys->ds_num_children != 0)
 174 
 175 #define DS_UNIQUE_IS_ACCURATE(ds)       \
 176         (((ds)->ds_phys->ds_flags & DS_FLAG_UNIQUE_ACCURATE) != 0)
 177 
 178 int dsl_dataset_hold(struct dsl_pool *dp, const char *name, void *tag,
 179     dsl_dataset_t **dsp);
 180 int dsl_dataset_hold_obj(struct dsl_pool *dp, uint64_t dsobj, void *tag,
 181     dsl_dataset_t **);
 182 void dsl_dataset_rele(dsl_dataset_t *ds, void *tag);
 183 int dsl_dataset_own(struct dsl_pool *dp, const char *name,
 184     void *tag, dsl_dataset_t **dsp);
 185 int dsl_dataset_own_obj(struct dsl_pool *dp, uint64_t dsobj,
 186     void *tag, dsl_dataset_t **dsp);
 187 void dsl_dataset_disown(dsl_dataset_t *ds, void *tag);
 188 void dsl_dataset_name(dsl_dataset_t *ds, char *name);
 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);
 192 uint64_t dsl_dataset_create_sync(dsl_dir_t *pds, const char *lastname,
 193     dsl_dataset_t *origin, uint64_t flags, cred_t *, dmu_tx_t *);
 194 uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
 195     uint64_t flags, dmu_tx_t *tx);
 196 int dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors);
 197 int dsl_dataset_promote(const char *name, char *conflsnap);
 198 int dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
 199     boolean_t force);
 200 int dsl_dataset_rename_snapshot(const char *fsname,
 201     const char *oldsnapname, const char *newsnapname, boolean_t recursive);
 202 int dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
 203     minor_t cleanup_minor, const char *htag);
 204 
 205 blkptr_t *dsl_dataset_get_blkptr(dsl_dataset_t *ds);
 206 void dsl_dataset_set_blkptr(dsl_dataset_t *ds, blkptr_t *bp, dmu_tx_t *tx);
 207 
 208 spa_t *dsl_dataset_get_spa(dsl_dataset_t *ds);
 209 
 210 boolean_t dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds);
 211 




 170 #define MAX_TAG_PREFIX_LEN      17
 171 
 172 #define dsl_dataset_is_snapshot(ds) \
 173         ((ds)->ds_phys->ds_num_children != 0)
 174 
 175 #define DS_UNIQUE_IS_ACCURATE(ds)       \
 176         (((ds)->ds_phys->ds_flags & DS_FLAG_UNIQUE_ACCURATE) != 0)
 177 
 178 int dsl_dataset_hold(struct dsl_pool *dp, const char *name, void *tag,
 179     dsl_dataset_t **dsp);
 180 int dsl_dataset_hold_obj(struct dsl_pool *dp, uint64_t dsobj, void *tag,
 181     dsl_dataset_t **);
 182 void dsl_dataset_rele(dsl_dataset_t *ds, void *tag);
 183 int dsl_dataset_own(struct dsl_pool *dp, const char *name,
 184     void *tag, dsl_dataset_t **dsp);
 185 int dsl_dataset_own_obj(struct dsl_pool *dp, uint64_t dsobj,
 186     void *tag, dsl_dataset_t **dsp);
 187 void dsl_dataset_disown(dsl_dataset_t *ds, void *tag);
 188 void dsl_dataset_name(dsl_dataset_t *ds, char *name);
 189 boolean_t dsl_dataset_tryown(dsl_dataset_t *ds, void *tag);
 190 void dsl_register_onexit_hold_cleanup(nvlist_t *holds, minor_t minor);

 191 uint64_t dsl_dataset_create_sync(dsl_dir_t *pds, const char *lastname,
 192     dsl_dataset_t *origin, uint64_t flags, cred_t *, dmu_tx_t *);
 193 uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
 194     uint64_t flags, dmu_tx_t *tx);
 195 int dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors);
 196 int dsl_dataset_promote(const char *name, char *conflsnap);
 197 int dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
 198     boolean_t force);
 199 int dsl_dataset_rename_snapshot(const char *fsname,
 200     const char *oldsnapname, const char *newsnapname, boolean_t recursive);
 201 int dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
 202     minor_t cleanup_minor, const char *htag);
 203 
 204 blkptr_t *dsl_dataset_get_blkptr(dsl_dataset_t *ds);
 205 void dsl_dataset_set_blkptr(dsl_dataset_t *ds, blkptr_t *bp, dmu_tx_t *tx);
 206 
 207 spa_t *dsl_dataset_get_spa(dsl_dataset_t *ds);
 208 
 209 boolean_t dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds);
 210