aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWaiman Long <Waiman.Long@hp.com>2013-09-12 10:55:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 12:25:23 -0400
commit1812997720ab90d029548778c55d7315555e1fef (patch)
tree25e3bccce50977e9199df4ee0445a3af9e5da708
parent1370e97bb2eb1ef2df7355204e5a4ba13e12b861 (diff)
dcache: get/release read lock in read_seqbegin_or_lock() & friend
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 <Waiman.Long@hp.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/dcache.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 4d9df3c940e6..f3dcc6351a16 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -90,8 +90,8 @@ static struct kmem_cache *dentry_cache __read_mostly;
90 90
91/** 91/**
92 * read_seqbegin_or_lock - begin a sequence number check or locking block 92 * read_seqbegin_or_lock - begin a sequence number check or locking block
93 * lock: sequence lock 93 * @lock: sequence lock
94 * seq : sequence number to be checked 94 * @seq : sequence number to be checked
95 * 95 *
96 * First try it once optimistically without taking the lock. If that fails, 96 * First try it once optimistically without taking the lock. If that fails,
97 * take the lock. The sequence number is also used as a marker for deciding 97 * take the lock. The sequence number is also used as a marker for deciding
@@ -103,7 +103,7 @@ static inline void read_seqbegin_or_lock(seqlock_t *lock, int *seq)
103 if (!(*seq & 1)) /* Even */ 103 if (!(*seq & 1)) /* Even */
104 *seq = read_seqbegin(lock); 104 *seq = read_seqbegin(lock);
105 else /* Odd */ 105 else /* Odd */
106 write_seqlock(lock); 106 read_seqlock_excl(lock);
107} 107}
108 108
109static inline int need_seqretry(seqlock_t *lock, int seq) 109static inline int need_seqretry(seqlock_t *lock, int seq)
@@ -114,7 +114,7 @@ static inline int need_seqretry(seqlock_t *lock, int seq)
114static inline void done_seqretry(seqlock_t *lock, int seq) 114static inline void done_seqretry(seqlock_t *lock, int seq)
115{ 115{
116 if (seq & 1) 116 if (seq & 1)
117 write_sequnlock(lock); 117 read_sequnlock_excl(lock);
118} 118}
119 119
120/* 120/*
@@ -2673,9 +2673,9 @@ static int prepend(char **buffer, int *buflen, const char *str, int namelen)
2673 2673
2674/** 2674/**
2675 * prepend_name - prepend a pathname in front of current buffer pointer 2675 * prepend_name - prepend a pathname in front of current buffer pointer
2676 * buffer: buffer pointer 2676 * @buffer: buffer pointer
2677 * buflen: allocated length of the buffer 2677 * @buflen: allocated length of the buffer
2678 * name: name string and length qstr structure 2678 * @name: name string and length qstr structure
2679 * 2679 *
2680 * With RCU path tracing, it may race with d_move(). Use ACCESS_ONCE() to 2680 * With RCU path tracing, it may race with d_move(). Use ACCESS_ONCE() to
2681 * make sure that either the old or the new name pointer and length are 2681 * make sure that either the old or the new name pointer and length are
@@ -2713,14 +2713,15 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name)
2713 * @buffer: pointer to the end of the buffer 2713 * @buffer: pointer to the end of the buffer
2714 * @buflen: pointer to buffer length 2714 * @buflen: pointer to buffer length
2715 * 2715 *
2716 * The function tries to write out the pathname without taking any lock other 2716 * The function will first try to write out the pathname without taking any
2717 * than the RCU read lock to make sure that dentries won't go away. It only 2717 * lock other than the RCU read lock to make sure that dentries won't go away.
2718 * checks the sequence number of the global rename_lock as any change in the 2718 * It only checks the sequence number of the global rename_lock as any change
2719 * dentry's d_seq will be preceded by changes in the rename_lock sequence 2719 * in the dentry's d_seq will be preceded by changes in the rename_lock
2720 * number. If the sequence number had been change, it will restart the whole 2720 * sequence number. If the sequence number had been changed, it will restart
2721 * pathname back-tracing sequence again. It performs a total of 3 trials of 2721 * the whole pathname back-tracing sequence again by taking the rename_lock.
2722 * lockless back-tracing sequences before falling back to take the 2722 * In this case, there is no need to take the RCU read lock as the recursive
2723 * rename_lock. 2723 * parent pointer references will keep the dentry chain alive as long as no
2724 * rename operation is performed.
2724 */ 2725 */
2725static int prepend_path(const struct path *path, 2726static int prepend_path(const struct path *path,
2726 const struct path *root, 2727 const struct path *root,