Skip to content

Commit

Permalink
try long hold approach
Browse files Browse the repository at this point in the history
  • Loading branch information
pcd1193182 committed Dec 16, 2019
1 parent 4de9f5a commit 059e68a
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 19 deletions.
4 changes: 3 additions & 1 deletion include/sys/dsl_dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ struct dsl_dir {
dsl_deadlist_t dd_livelist;
bplist_t dd_pending_frees;
bplist_t dd_pending_allocs;

kmutex_t dd_activity_lock;
kcondvar_t dd_activity_cv;
boolean_t dd_activity_cancelled;

/* protected by dd_lock; keep at end of struct for better locality */
char dd_myname[ZFS_MAX_DATASET_NAME_LEN];
Expand Down Expand Up @@ -194,7 +196,7 @@ boolean_t dsl_dir_is_zapified(dsl_dir_t *dd);
void dsl_dir_livelist_open(dsl_dir_t *dd, uint64_t obj);
void dsl_dir_livelist_close(dsl_dir_t *dd);
void dsl_dir_remove_livelist(dsl_dir_t *dd, dmu_tx_t *tx, boolean_t total);
int dsl_dir_wait(dsl_dir_t *dd, zfs_wait_activity_t activity,
int dsl_dir_wait(dsl_dir_t *dd, dsl_dataset_t *ds, zfs_wait_activity_t activity,
boolean_t *waited);

/* internal reserved dir name */
Expand Down
7 changes: 7 additions & 0 deletions module/os/linux/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include <sys/zfs_fuid.h>
#include <sys/sunddi.h>
#include <sys/dmu_objset.h>
#include <sys/dsl_dir.h>
#include <sys/spa_boot.h>
#include <sys/objlist.h>
#include <sys/zpl.h>
Expand Down Expand Up @@ -1319,6 +1320,8 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
"num_entries in unlinked set: %llu",
zs.zs_num_entries);
zfs_unlinked_drain(zfsvfs);
dsl_dir_t *dd = zfsvfs->z_os->os_dsl_dataset->ds_dir;
dd->dd_activity_cancelled = B_FALSE;
}

/*
Expand Down Expand Up @@ -1869,6 +1872,9 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0);
}
dmu_objset_evict_dbufs(zfsvfs->z_os);
dsl_dir_t *dd = os->os_dsl_dataset->ds_dir;
dd->dd_activity_cancelled = B_TRUE;
cv_broadcast(&dd->dd_activity_cv);

return (0);
}
Expand Down Expand Up @@ -2256,6 +2262,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
if (err != 0)
goto bail;

ds->ds_dir->dd_activity_cancelled = B_FALSE;
VERIFY(zfsvfs_setup(zfsvfs, B_FALSE) == 0);

zfs_set_fuid_feature(zfsvfs);
Expand Down
26 changes: 10 additions & 16 deletions module/zfs/dsl_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ dsl_dir_evict_async(void *dbu)
dsl_dir_livelist_close(dd);

dsl_prop_fini(dd);
cv_destroy(&dd->dd_activity_cv);
mutex_destroy(&dd->dd_activity_lock);
mutex_destroy(&dd->dd_lock);
kmem_free(dd, sizeof (dsl_dir_t));
}
Expand Down Expand Up @@ -314,6 +316,8 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
if (dsl_deadlist_is_open(&dd->dd_livelist))
dsl_dir_livelist_close(dd);
dsl_prop_fini(dd);
cv_destroy(&dd->dd_activity_cv);
mutex_destroy(&dd->dd_activity_lock);
mutex_destroy(&dd->dd_lock);
kmem_free(dd, sizeof (dsl_dir_t));
dmu_buf_rele(dbuf, tag);
Expand Down Expand Up @@ -2285,41 +2289,31 @@ dsl_dir_remove_livelist(dsl_dir_t *dd, dmu_tx_t *tx, boolean_t total)
}

static int
dsl_dir_activity_in_progress(dsl_dir_t *dd, zfs_wait_activity_t activity,
boolean_t *in_progress)
dsl_dir_activity_in_progress(dsl_dir_t *dd, dsl_dataset_t *ds,
zfs_wait_activity_t activity, boolean_t *in_progress)
{
int error = 0;
zfs_dbgmsg("progress %px %d", dd, activity);

ASSERT(MUTEX_HELD(&dd->dd_activity_lock));

switch (activity) {
case ZFS_WAIT_DELETEQ: {
dsl_dataset_t *ds;
error = dsl_dataset_hold_obj(dd->dd_pool,
dsl_dir_phys(dd)->dd_head_dataset_obj, FTAG, &ds);
if (error != 0)
break;
objset_t *os;
error = dmu_objset_from_ds(ds, &os);
if (error != 0)
break;

uint64_t count, unlinked_obj;
zfs_dbgmsg("os %px", os);
error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1,
&unlinked_obj);
if (error != 0) {
dsl_dataset_rele(ds, FTAG);
break;
}
zfs_dbgmsg("obj %ld", unlinked_obj);
error = zap_count(os, unlinked_obj, &count);

if (error == 0)
*in_progress = (count != 0);

dsl_dataset_rele(ds, FTAG);
break;
}
default:
Expand All @@ -2330,22 +2324,22 @@ dsl_dir_activity_in_progress(dsl_dir_t *dd, zfs_wait_activity_t activity,
}

int
dsl_dir_wait(dsl_dir_t *dd, zfs_wait_activity_t activity, boolean_t *waited)
dsl_dir_wait(dsl_dir_t *dd, dsl_dataset_t *ds, zfs_wait_activity_t activity,
boolean_t *waited)
{
int error = 0;
boolean_t in_progress;
zfs_dbgmsg("waiting %px %d", dd, activity);
mutex_enter(&dd->dd_activity_lock);
for (;;) {
error = dsl_dir_activity_in_progress(dd, activity,
error = dsl_dir_activity_in_progress(dd, ds, activity,
&in_progress);
if (error != 0 || !in_progress)
break;

*waited = B_TRUE;

if (cv_wait_sig(&dd->dd_activity_cv, &dd->dd_activity_lock) ==
0) {
0 || dd->dd_activity_cancelled) {
error = EINTR;
break;
}
Expand Down
16 changes: 14 additions & 2 deletions module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -4114,6 +4114,7 @@ zfs_ioc_wait_fs(const char *name, nvlist_t *innvl, nvlist_t *outnvl)
int error;
dsl_pool_t *dp;
dsl_dir_t *dd;
dsl_dataset_t *ds;

if (nvlist_lookup_int32(innvl, ZFS_WAIT_ACTIVITY, &activity) != 0)
return (EINVAL);
Expand All @@ -4125,10 +4126,21 @@ zfs_ioc_wait_fs(const char *name, nvlist_t *innvl, nvlist_t *outnvl)
return (error);
}

error = dsl_dir_wait(dd, activity, &waited);
dsl_dir_rele(dd, FTAG);
if ((error = dsl_dataset_hold_obj(dd->dd_pool,
dsl_dir_phys(dd)->dd_head_dataset_obj, FTAG, &ds)) != 0) {
dsl_pool_rele(dp, FTAG);
dsl_dir_rele(dd, FTAG);
return (error);
}
dsl_dataset_long_hold(ds, FTAG);
dsl_pool_rele(dp, FTAG);

error = dsl_dir_wait(dd, ds, activity, &waited);

dsl_dataset_long_rele(ds, FTAG);
dsl_dataset_rele(ds, FTAG);
dsl_dir_rele(dd, FTAG);

if (error == 0)
fnvlist_add_boolean_value(outnvl, ZFS_WAIT_WAITED, waited);

Expand Down

0 comments on commit 059e68a

Please sign in to comment.