Skip to content

Commit

Permalink
dcache: get/release read lock in read_seqbegin_or_lock() & friend
Browse files Browse the repository at this point in the history
This patch modifies read_seqbegin_or_lock() and need_seqretry() to use
newly introduced read_seqlock_excl() and read_sequnlock_excl()
primitives so that they won't change the sequence number even if they
fall back to take the lock.  This is OK as no change to the protected
data structure is being made.

It will prevent one fallback to lock taking from cascading into a series
of lock taking reducing performance because of the sequence number
change.  It will also allow other sequence readers to go forward while
an exclusive reader lock is taken.

This patch also updates some of the inaccurate comments in the code.

Signed-off-by: Waiman Long <[email protected]>
To: Alexander Viro <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
longman88 authored and torvalds committed Sep 12, 2013
1 parent 1370e97 commit 1812997
Showing 1 changed file with 16 additions and 15 deletions.
31 changes: 16 additions & 15 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ static struct kmem_cache *dentry_cache __read_mostly;

/**
* read_seqbegin_or_lock - begin a sequence number check or locking block
* lock: sequence lock
* seq : sequence number to be checked
* @lock: sequence lock
* @seq : sequence number to be checked
*
* First try it once optimistically without taking the lock. If that fails,
* take the lock. The sequence number is also used as a marker for deciding
Expand All @@ -103,7 +103,7 @@ static inline void read_seqbegin_or_lock(seqlock_t *lock, int *seq)
if (!(*seq & 1)) /* Even */
*seq = read_seqbegin(lock);
else /* Odd */
write_seqlock(lock);
read_seqlock_excl(lock);
}

static inline int need_seqretry(seqlock_t *lock, int seq)
Expand All @@ -114,7 +114,7 @@ static inline int need_seqretry(seqlock_t *lock, int seq)
static inline void done_seqretry(seqlock_t *lock, int seq)
{
if (seq & 1)
write_sequnlock(lock);
read_sequnlock_excl(lock);
}

/*
Expand Down Expand Up @@ -2673,9 +2673,9 @@ static int prepend(char **buffer, int *buflen, const char *str, int namelen)

/**
* prepend_name - prepend a pathname in front of current buffer pointer
* buffer: buffer pointer
* buflen: allocated length of the buffer
* name: name string and length qstr structure
* @buffer: buffer pointer
* @buflen: allocated length of the buffer
* @name: name string and length qstr structure
*
* With RCU path tracing, it may race with d_move(). Use ACCESS_ONCE() to
* make sure that either the old or the new name pointer and length are
Expand Down Expand Up @@ -2713,14 +2713,15 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name)
* @buffer: pointer to the end of the buffer
* @buflen: pointer to buffer length
*
* The function tries to write out the pathname without taking any lock other
* than the RCU read lock to make sure that dentries won't go away. It only
* checks the sequence number of the global rename_lock as any change in the
* dentry's d_seq will be preceded by changes in the rename_lock sequence
* number. If the sequence number had been change, it will restart the whole
* pathname back-tracing sequence again. It performs a total of 3 trials of
* lockless back-tracing sequences before falling back to take the
* rename_lock.
* The function will first try to write out the pathname without taking any
* lock other than the RCU read lock to make sure that dentries won't go away.
* It only checks the sequence number of the global rename_lock as any change
* in the dentry's d_seq will be preceded by changes in the rename_lock
* sequence number. If the sequence number had been changed, it will restart
* the whole pathname back-tracing sequence again by taking the rename_lock.
* In this case, there is no need to take the RCU read lock as the recursive
* parent pointer references will keep the dentry chain alive as long as no
* rename operation is performed.
*/
static int prepend_path(const struct path *path,
const struct path *root,
Expand Down

0 comments on commit 1812997

Please sign in to comment.