Skip to content
This repository has been archived by the owner on Feb 26, 2020. It is now read-only.

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.  This lets us make a
a small change to the ZFS source where the mutex is initialized
and then be certain that all future use of that mutex will be safe.

Signed-off-by: Brian Behlendorf <[email protected]>
  • Loading branch information
behlendorf committed Feb 25, 2015
1 parent a7bfc17 commit a352a1e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 4 deletions.
35 changes: 32 additions & 3 deletions include/sys/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,22 @@
#define _SPL_MUTEX_H

#include <sys/types.h>
#include <sys/kmem.h>
#include <linux/mutex.h>
#include <linux/compiler_compat.h>

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;
spinlock_t m_lock; /* used for serializing mutex_exit */
kthread_t *m_owner;
fstrans_cookie_t *m_fstrans;
} kmutex_t;

#define MUTEX(mp) (&((mp)->m_mutex))
Expand All @@ -55,6 +58,25 @@ spl_mutex_clear_owner(kmutex_t *mp)
mp->m_owner = NULL;
}

/*
* MUTEX_FSTRANS helpers functions. When mp->m_fstrans is set it indicates
* a fstrans mutex type. These mutexes behave identically to default mutexes
* except they set PF_FSTRANS in the task for the critical region.
*/
static inline void
spl_mutex_set_fstrans(kmutex_t *mp)
{
if (mp->m_fstrans)
*(mp->m_fstrans) = spl_fstrans_mark();
}

static inline void
spl_mutex_clear_fstrans(kmutex_t *mp)
{
if (mp->m_fstrans)
spl_fstrans_unmark(*(mp->m_fstrans));
}

#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 +92,14 @@ spl_mutex_clear_owner(kmutex_t *mp)
#define mutex_init(mp, name, type, ibc) \
{ \
static struct lock_class_key __key; \
ASSERT(type == MUTEX_DEFAULT); \
\
__mutex_init(MUTEX(mp), #mp, &__key); \
spin_lock_init(&(mp)->m_lock); \
spl_mutex_clear_owner(mp); \
(mp)->m_fstrans = NULL; \
\
if (unlikely(type == MUTEX_FSTRANS)) \
VERIFY((mp)->m_fstrans = ibc); \
}

#undef mutex_destroy
Expand All @@ -87,8 +112,10 @@ spl_mutex_clear_owner(kmutex_t *mp)
({ \
int _rc_; \
\
if ((_rc_ = mutex_trylock(MUTEX(mp))) == 1) \
if ((_rc_ = mutex_trylock(MUTEX(mp))) == 1) { \
spl_mutex_set_owner(mp); \
spl_mutex_set_fstrans(mp); \
} \
\
_rc_; \
})
Expand All @@ -98,6 +125,7 @@ spl_mutex_clear_owner(kmutex_t *mp)
ASSERT3P(mutex_owner(mp), !=, current); \
mutex_lock(MUTEX(mp)); \
spl_mutex_set_owner(mp); \
spl_mutex_set_fstrans(mp); \
}

/*
Expand All @@ -122,6 +150,7 @@ spl_mutex_clear_owner(kmutex_t *mp)
#define mutex_exit(mp) \
{ \
spin_lock(&(mp)->m_lock); \
spl_mutex_clear_fstrans(mp); \
spl_mutex_clear_owner(mp); \
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 a352a1e

Please sign in to comment.