Skip to content

Commit 8e7fe49

Browse files
authored
FreeBSD: convert teardown inactive lock to a read-mostly sleepable lock
The lock is taken all the time and as a regular read-write lock avoidably serves as a mount point-wide contention point. This forward ports FreeBSD revision r357322. To quote aforementioned commit: Sample result doing an incremental -j 40 build: before: 173.30s user 458.97s system 2595% cpu 24.358 total after: 168.58s user 254.92s system 2211% cpu 19.147 total Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Mateusz Guzik <[email protected]> Closes #10896
1 parent c2c7ca0 commit 8e7fe49

File tree

4 files changed

+82
-19
lines changed

4 files changed

+82
-19
lines changed

include/os/freebsd/zfs/sys/zfs_vfsops_os.h

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,31 @@
2727
#ifndef _SYS_FS_ZFS_VFSOPS_H
2828
#define _SYS_FS_ZFS_VFSOPS_H
2929

30+
#if __FreeBSD_version >= 1300109
31+
#define TEARDOWN_INACTIVE_RMS
32+
#endif
33+
3034
#include <sys/dataset_kstats.h>
3135
#include <sys/list.h>
3236
#include <sys/vfs.h>
3337
#include <sys/zil.h>
3438
#include <sys/sa.h>
3539
#include <sys/rrwlock.h>
40+
#ifdef TEARDOWN_INACTIVE_RMS
41+
#include <sys/rmlock.h>
42+
#endif
3643
#include <sys/zfs_ioctl.h>
3744

3845
#ifdef __cplusplus
3946
extern "C" {
4047
#endif
4148

49+
#ifdef TEARDOWN_INACTIVE_RMS
50+
typedef struct rmslock zfs_teardown_lock_t;
51+
#else
52+
#define zfs_teardown_lock_t krwlock_t
53+
#endif
54+
4255
typedef struct zfsvfs zfsvfs_t;
4356
struct znode;
4457

@@ -67,7 +80,7 @@ struct zfsvfs {
6780
boolean_t z_atime; /* enable atimes mount option */
6881
boolean_t z_unmounted; /* unmounted */
6982
rrmlock_t z_teardown_lock;
70-
krwlock_t z_teardown_inactive_lock;
83+
zfs_teardown_lock_t z_teardown_inactive_lock;
7184
list_t z_all_znodes; /* all vnodes in the fs */
7285
uint64_t z_nr_znodes; /* number of znodes in the fs */
7386
kmutex_t z_znodes_lock; /* lock for z_all_znodes */
@@ -98,6 +111,56 @@ struct zfsvfs {
98111
struct task z_unlinked_drain_task;
99112
};
100113

114+
#ifdef TEARDOWN_INACTIVE_RMS
115+
#define ZFS_INIT_TEARDOWN_INACTIVE(zfsvfs) \
116+
rms_init(&(zfsvfs)->z_teardown_inactive_lock, "zfs teardown inactive")
117+
118+
#define ZFS_DESTROY_TEARDOWN_INACTIVE(zfsvfs) \
119+
rms_destroy(&(zfsvfs)->z_teardown_inactive_lock)
120+
121+
#define ZFS_TRYRLOCK_TEARDOWN_INACTIVE(zfsvfs) \
122+
rms_try_rlock(&(zfsvfs)->z_teardown_inactive_lock)
123+
124+
#define ZFS_RLOCK_TEARDOWN_INACTIVE(zfsvfs) \
125+
rms_rlock(&(zfsvfs)->z_teardown_inactive_lock)
126+
127+
#define ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs) \
128+
rms_runlock(&(zfsvfs)->z_teardown_inactive_lock)
129+
130+
#define ZFS_WLOCK_TEARDOWN_INACTIVE(zfsvfs) \
131+
rms_wlock(&(zfsvfs)->z_teardown_inactive_lock)
132+
133+
#define ZFS_WUNLOCK_TEARDOWN_INACTIVE(zfsvfs) \
134+
rms_wunlock(&(zfsvfs)->z_teardown_inactive_lock)
135+
136+
#define ZFS_TEARDOWN_INACTIVE_WLOCKED(zfsvfs) \
137+
rms_wowned(&(zfsvfs)->z_teardown_inactive_lock)
138+
#else
139+
#define ZFS_INIT_TEARDOWN_INACTIVE(zfsvfs) \
140+
rw_init(&(zfsvfs)->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL)
141+
142+
#define ZFS_DESTROY_TEARDOWN_INACTIVE(zfsvfs) \
143+
rw_destroy(&(zfsvfs)->z_teardown_inactive_lock)
144+
145+
#define ZFS_TRYRLOCK_TEARDOWN_INACTIVE(zfsvfs) \
146+
rw_tryenter(&(zfsvfs)->z_teardown_inactive_lock, RW_READER)
147+
148+
#define ZFS_RLOCK_TEARDOWN_INACTIVE(zfsvfs) \
149+
rw_enter(&(zfsvfs)->z_teardown_inactive_lock, RW_READER)
150+
151+
#define ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs) \
152+
rw_exit(&(zfsvfs)->z_teardown_inactive_lock)
153+
154+
#define ZFS_WLOCK_TEARDOWN_INACTIVE(zfsvfs) \
155+
rw_enter(&(zfsvfs)->z_teardown_inactive_lock, RW_WRITER)
156+
157+
#define ZFS_WUNLOCK_TEARDOWN_INACTIVE(zfsvfs) \
158+
rw_exit(&(zfsvfs)->z_teardown_inactive_lock)
159+
160+
#define ZFS_TEARDOWN_INACTIVE_WLOCKED(zfsvfs) \
161+
RW_WRITE_HELD(&(zfsvfs)->z_teardown_inactive_lock)
162+
#endif
163+
101164
#define ZSB_XATTR 0x0001 /* Enable user xattrs */
102165
/*
103166
* Normal filesystems (those not under .zfs/snapshot) have a total

module/os/freebsd/zfs/zfs_vfsops.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,7 @@ zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os)
975975
#else
976976
rrm_init(&zfsvfs->z_teardown_lock, B_FALSE);
977977
#endif
978-
rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL);
978+
ZFS_INIT_TEARDOWN_INACTIVE(zfsvfs);
979979
rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL);
980980
for (int i = 0; i != ZFS_OBJ_MTX_SZ; i++)
981981
mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
@@ -1126,7 +1126,7 @@ zfsvfs_free(zfsvfs_t *zfsvfs)
11261126
ASSERT(zfsvfs->z_nr_znodes == 0);
11271127
list_destroy(&zfsvfs->z_all_znodes);
11281128
rrm_destroy(&zfsvfs->z_teardown_lock);
1129-
rw_destroy(&zfsvfs->z_teardown_inactive_lock);
1129+
ZFS_DESTROY_TEARDOWN_INACTIVE(zfsvfs);
11301130
rw_destroy(&zfsvfs->z_fuid_lock);
11311131
for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
11321132
mutex_destroy(&zfsvfs->z_hold_mtx[i]);
@@ -1545,15 +1545,15 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
15451545
zfsvfs->z_log = NULL;
15461546
}
15471547

1548-
rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_WRITER);
1548+
ZFS_WLOCK_TEARDOWN_INACTIVE(zfsvfs);
15491549

15501550
/*
15511551
* If we are not unmounting (ie: online recv) and someone already
15521552
* unmounted this file system while we were doing the switcheroo,
15531553
* or a reopen of z_os failed then just bail out now.
15541554
*/
15551555
if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) {
1556-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
1556+
ZFS_WUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
15571557
rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
15581558
return (SET_ERROR(EIO));
15591559
}
@@ -1581,7 +1581,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
15811581
*/
15821582
if (unmounting) {
15831583
zfsvfs->z_unmounted = B_TRUE;
1584-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
1584+
ZFS_WUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
15851585
rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
15861586
}
15871587

@@ -1901,7 +1901,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
19011901
znode_t *zp;
19021902

19031903
ASSERT(RRM_WRITE_HELD(&zfsvfs->z_teardown_lock));
1904-
ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock));
1904+
ASSERT(ZFS_TEARDOWN_INACTIVE_WLOCKED(zfsvfs));
19051905

19061906
/*
19071907
* We already own this, so just update the objset_t, as the one we
@@ -1939,7 +1939,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
19391939

19401940
bail:
19411941
/* release the VOPs */
1942-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
1942+
ZFS_WUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
19431943
rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
19441944

19451945
if (err) {
@@ -2056,7 +2056,7 @@ int
20562056
zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
20572057
{
20582058
ASSERT(RRM_WRITE_HELD(&zfsvfs->z_teardown_lock));
2059-
ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock));
2059+
ASSERT(ZFS_TEARDOWN_INACTIVE_WLOCKED(zfsvfs));
20602060

20612061
/*
20622062
* We already own this, so just hold and rele it to update the
@@ -2072,7 +2072,7 @@ zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
20722072
zfsvfs->z_os = os;
20732073

20742074
/* release the VOPs */
2075-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
2075+
ZFS_WUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
20762076
rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
20772077

20782078
/*

module/os/freebsd/zfs/zfs_vnops.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4638,13 +4638,13 @@ zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
46384638
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
46394639
int error;
46404640

4641-
rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER);
4641+
ZFS_RLOCK_TEARDOWN_INACTIVE(zfsvfs);
46424642
if (zp->z_sa_hdl == NULL) {
46434643
/*
46444644
* The fs has been unmounted, or we did a
46454645
* suspend/resume and this file no longer exists.
46464646
*/
4647-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
4647+
ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
46484648
vrecycle(vp);
46494649
return;
46504650
}
@@ -4653,7 +4653,7 @@ zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
46534653
/*
46544654
* Fast path to recycle a vnode of a removed file.
46554655
*/
4656-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
4656+
ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
46574657
vrecycle(vp);
46584658
return;
46594659
}
@@ -4673,7 +4673,7 @@ zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
46734673
dmu_tx_commit(tx);
46744674
}
46754675
}
4676-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
4676+
ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
46774677
}
46784678

46794679

@@ -5823,10 +5823,10 @@ zfs_freebsd_need_inactive(struct vop_need_inactive_args *ap)
58235823
if (vn_need_pageq_flush(vp))
58245824
return (1);
58255825

5826-
if (!rw_tryenter(&zfsvfs->z_teardown_inactive_lock, RW_READER))
5826+
if (!ZFS_TRYRLOCK_TEARDOWN_INACTIVE(zfsvfs))
58275827
return (1);
58285828
need = (zp->z_sa_hdl == NULL || zp->z_unlinked || zp->z_atime_dirty);
5829-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
5829+
ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
58305830

58315831
return (need);
58325832
}
@@ -5857,12 +5857,12 @@ zfs_freebsd_reclaim(struct vop_reclaim_args *ap)
58575857
* zfs_znode_dmu_fini in zfsvfs_teardown during
58585858
* force unmount.
58595859
*/
5860-
rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER);
5860+
ZFS_RLOCK_TEARDOWN_INACTIVE(zfsvfs);
58615861
if (zp->z_sa_hdl == NULL)
58625862
zfs_znode_free(zp);
58635863
else
58645864
zfs_zinactive(zp);
5865-
rw_exit(&zfsvfs->z_teardown_inactive_lock);
5865+
ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs);
58665866

58675867
vp->v_data = NULL;
58685868
return (0);

module/os/freebsd/zfs/zfs_znode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ zfs_znode_dmu_fini(znode_t *zp)
384384
{
385385
ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zp->z_zfsvfs, zp->z_id)) ||
386386
zp->z_unlinked ||
387-
RW_WRITE_HELD(&zp->z_zfsvfs->z_teardown_inactive_lock));
387+
ZFS_TEARDOWN_INACTIVE_WLOCKED(zp->z_zfsvfs));
388388

389389
sa_handle_destroy(zp->z_sa_hdl);
390390
zp->z_sa_hdl = NULL;

0 commit comments

Comments
 (0)