Skip to content

Commit

Permalink
Add MUTEX_FSTRANS mutex type
Browse files Browse the repository at this point in the history
There are regions in the ZFS code where it is desirable to be able
to be set PF_FSTRANS while a specific mutex is held.  The ZFS code
could be updated to set/clear this flag in all the correct places,
but this is undesirable for a few reasons.

1) It would require changes to a significant amount of the ZFS
   code.  This would complicate applying patches from upstream.

2) It would be easy to accidentally miss a critical region in
   the initial patch or to have an future change introduce a
   new one.

Both of these concerns can be addressed by adding a new mutex type
which is responsible for managing PF_FSTRANS, support for which was
added to the SPL in commit 9099312 - Merge branch 'kmem-rework'.

Signed-off-by: Brian Behlendorf <[email protected]>
Signed-off-by: Tim Chase <[email protected]>
Issue openzfs#435
  • Loading branch information
behlendorf committed Mar 3, 2015
1 parent 5f920fb commit d0d5dd7
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 21 deletions.
50 changes: 30 additions & 20 deletions include/sys/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,19 @@
typedef enum {
MUTEX_DEFAULT = 0,
MUTEX_SPIN = 1,
MUTEX_ADAPTIVE = 2
MUTEX_ADAPTIVE = 2,
MUTEX_FSTRANS = 3,
} kmutex_type_t;

typedef struct {
struct mutex m_mutex;
kmutex_type_t m_type;
spinlock_t m_lock; /* used for serializing mutex_exit */
kthread_t *m_owner;
unsigned int m_saved_flags;
} kmutex_t;

#define MUTEX(mp) (&((mp)->m_mutex))

static inline void
spl_mutex_set_owner(kmutex_t *mp)
{
mp->m_owner = current;
}

static inline void
spl_mutex_clear_owner(kmutex_t *mp)
{
mp->m_owner = NULL;
}

#define mutex_owner(mp) (ACCESS_ONCE((mp)->m_owner))
#define mutex_owned(mp) (mutex_owner(mp) == current)
#define MUTEX_HELD(mp) mutex_owned(mp)
Expand All @@ -70,11 +60,18 @@ spl_mutex_clear_owner(kmutex_t *mp)
#define mutex_init(mp, name, type, ibc) \
{ \
static struct lock_class_key __key; \
ASSERT(type == MUTEX_DEFAULT); \
\
ASSERT3P(mp, !=, NULL); \
ASSERT3P(ibc, ==, NULL); \
ASSERT((type == MUTEX_DEFAULT) || \
(type == MUTEX_ADAPTIVE) || \
(type == MUTEX_FSTRANS)); \
\
__mutex_init(MUTEX(mp), #mp, &__key); \
spin_lock_init(&(mp)->m_lock); \
spl_mutex_clear_owner(mp); \
(mp)->m_type = type; \
(mp)->m_owner = NULL; \
(mp)->m_saved_flags = 0; \
}

#undef mutex_destroy
Expand All @@ -87,8 +84,13 @@ spl_mutex_clear_owner(kmutex_t *mp)
({ \
int _rc_; \
\
if ((_rc_ = mutex_trylock(MUTEX(mp))) == 1) \
spl_mutex_set_owner(mp); \
if ((_rc_ = mutex_trylock(MUTEX(mp))) == 1) { \
(mp)->m_owner = current; \
if ((mp)->m_type == MUTEX_FSTRANS) { \
(mp)->m_saved_flags = current->flags; \
current->flags |= PF_FSTRANS; \
} \
} \
\
_rc_; \
})
Expand All @@ -97,7 +99,11 @@ spl_mutex_clear_owner(kmutex_t *mp)
{ \
ASSERT3P(mutex_owner(mp), !=, current); \
mutex_lock(MUTEX(mp)); \
spl_mutex_set_owner(mp); \
(mp)->m_owner = current; \
if ((mp)->m_type == MUTEX_FSTRANS) { \
(mp)->m_saved_flags = current->flags; \
current->flags |= PF_FSTRANS; \
} \
}

/*
Expand All @@ -122,7 +128,11 @@ spl_mutex_clear_owner(kmutex_t *mp)
#define mutex_exit(mp) \
{ \
spin_lock(&(mp)->m_lock); \
spl_mutex_clear_owner(mp); \
if ((mp)->m_type == MUTEX_FSTRANS) { \
current->flags &= ~(PF_FSTRANS); \
current->flags |= (mp)->m_saved_flags; \
} \
(mp)->m_owner = NULL; \
mutex_unlock(MUTEX(mp)); \
spin_unlock(&(mp)->m_lock); \
}
Expand Down
2 changes: 1 addition & 1 deletion module/splat/splat-atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ splat_atomic_test1(struct file *file, void *arg)

ap.ap_magic = SPLAT_ATOMIC_TEST_MAGIC;
ap.ap_file = file;
mutex_init(&ap.ap_lock, SPLAT_ATOMIC_TEST1_NAME, NULL, NULL);
mutex_init(&ap.ap_lock, SPLAT_ATOMIC_TEST1_NAME, MUTEX_DEFAULT, NULL);
init_waitqueue_head(&ap.ap_waitq);
ap.ap_atomic = SPLAT_ATOMIC_INIT_VALUE;
ap.ap_atomic_exited = 0;
Expand Down

0 comments on commit d0d5dd7

Please sign in to comment.