aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2013-06-21 08:58:17 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-06-29 04:57:44 -0400
commit139ca04ee572fea6c0c105e88aba3a534efcd7c4 (patch)
treeb75d2c4b93099413b1910909ee8b884370590c71 /fs
parent4e8c765d384e549f9b542ea0bd42e2aa227e1404 (diff)
locks: convert fl_link to a hlist_node
Testing has shown that iterating over the blocked_list for deadlock detection turns out to be a bottleneck. In order to alleviate that, begin the process of turning it into a hashtable. We start by turning the fl_link into a hlist_node and the global lists into hlists. A later patch will do the conversion of the blocked_list to a hashtable. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: J. Bruce Fields <bfields@fieldses.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/locks.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 84e269fc4c69..941b7146b6be 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -157,13 +157,13 @@ int lease_break_time = 45;
157 * The global file_lock_list is only used for displaying /proc/locks. Protected 157 * The global file_lock_list is only used for displaying /proc/locks. Protected
158 * by the file_lock_lock. 158 * by the file_lock_lock.
159 */ 159 */
160static LIST_HEAD(file_lock_list); 160static HLIST_HEAD(file_lock_list);
161 161
162/* 162/*
163 * The blocked_list is used to find POSIX lock loops for deadlock detection. 163 * The blocked_list is used to find POSIX lock loops for deadlock detection.
164 * Protected by file_lock_lock. 164 * Protected by file_lock_lock.
165 */ 165 */
166static LIST_HEAD(blocked_list); 166static HLIST_HEAD(blocked_list);
167 167
168/* 168/*
169 * This lock protects the blocked_list, and the file_lock_list. Generally, if 169 * This lock protects the blocked_list, and the file_lock_list. Generally, if
@@ -188,7 +188,7 @@ static struct kmem_cache *filelock_cache __read_mostly;
188 188
189static void locks_init_lock_heads(struct file_lock *fl) 189static void locks_init_lock_heads(struct file_lock *fl)
190{ 190{
191 INIT_LIST_HEAD(&fl->fl_link); 191 INIT_HLIST_NODE(&fl->fl_link);
192 INIT_LIST_HEAD(&fl->fl_block); 192 INIT_LIST_HEAD(&fl->fl_block);
193 init_waitqueue_head(&fl->fl_wait); 193 init_waitqueue_head(&fl->fl_wait);
194} 194}
@@ -222,7 +222,7 @@ void locks_free_lock(struct file_lock *fl)
222{ 222{
223 BUG_ON(waitqueue_active(&fl->fl_wait)); 223 BUG_ON(waitqueue_active(&fl->fl_wait));
224 BUG_ON(!list_empty(&fl->fl_block)); 224 BUG_ON(!list_empty(&fl->fl_block));
225 BUG_ON(!list_empty(&fl->fl_link)); 225 BUG_ON(!hlist_unhashed(&fl->fl_link));
226 226
227 locks_release_private(fl); 227 locks_release_private(fl);
228 kmem_cache_free(filelock_cache, fl); 228 kmem_cache_free(filelock_cache, fl);
@@ -500,7 +500,7 @@ static inline void
500locks_insert_global_locks(struct file_lock *fl) 500locks_insert_global_locks(struct file_lock *fl)
501{ 501{
502 spin_lock(&file_lock_lock); 502 spin_lock(&file_lock_lock);
503 list_add_tail(&fl->fl_link, &file_lock_list); 503 hlist_add_head(&fl->fl_link, &file_lock_list);
504 spin_unlock(&file_lock_lock); 504 spin_unlock(&file_lock_lock);
505} 505}
506 506
@@ -508,20 +508,20 @@ static inline void
508locks_delete_global_locks(struct file_lock *fl) 508locks_delete_global_locks(struct file_lock *fl)
509{ 509{
510 spin_lock(&file_lock_lock); 510 spin_lock(&file_lock_lock);
511 list_del_init(&fl->fl_link); 511 hlist_del_init(&fl->fl_link);
512 spin_unlock(&file_lock_lock); 512 spin_unlock(&file_lock_lock);
513} 513}
514 514
515static inline void 515static inline void
516locks_insert_global_blocked(struct file_lock *waiter) 516locks_insert_global_blocked(struct file_lock *waiter)
517{ 517{
518 list_add(&waiter->fl_link, &blocked_list); 518 hlist_add_head(&waiter->fl_link, &blocked_list);
519} 519}
520 520
521static inline void 521static inline void
522locks_delete_global_blocked(struct file_lock *waiter) 522locks_delete_global_blocked(struct file_lock *waiter)
523{ 523{
524 list_del_init(&waiter->fl_link); 524 hlist_del_init(&waiter->fl_link);
525} 525}
526 526
527/* Remove waiter from blocker's block list. 527/* Remove waiter from blocker's block list.
@@ -748,7 +748,7 @@ static struct file_lock *what_owner_is_waiting_for(struct file_lock *block_fl)
748{ 748{
749 struct file_lock *fl; 749 struct file_lock *fl;
750 750
751 list_for_each_entry(fl, &blocked_list, fl_link) { 751 hlist_for_each_entry(fl, &blocked_list, fl_link) {
752 if (posix_same_owner(fl, block_fl)) 752 if (posix_same_owner(fl, block_fl))
753 return fl->fl_next; 753 return fl->fl_next;
754 } 754 }
@@ -2300,7 +2300,7 @@ static int locks_show(struct seq_file *f, void *v)
2300{ 2300{
2301 struct file_lock *fl, *bfl; 2301 struct file_lock *fl, *bfl;
2302 2302
2303 fl = list_entry(v, struct file_lock, fl_link); 2303 fl = hlist_entry(v, struct file_lock, fl_link);
2304 2304
2305 lock_get_status(f, fl, *((loff_t *)f->private), ""); 2305 lock_get_status(f, fl, *((loff_t *)f->private), "");
2306 2306
@@ -2316,14 +2316,14 @@ static void *locks_start(struct seq_file *f, loff_t *pos)
2316 2316
2317 spin_lock(&file_lock_lock); 2317 spin_lock(&file_lock_lock);
2318 *p = (*pos + 1); 2318 *p = (*pos + 1);
2319 return seq_list_start(&file_lock_list, *pos); 2319 return seq_hlist_start(&file_lock_list, *pos);
2320} 2320}
2321 2321
2322static void *locks_next(struct seq_file *f, void *v, loff_t *pos) 2322static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
2323{ 2323{
2324 loff_t *p = f->private; 2324 loff_t *p = f->private;
2325 ++*p; 2325 ++*p;
2326 return seq_list_next(v, &file_lock_list, pos); 2326 return seq_hlist_next(v, &file_lock_list, pos);
2327} 2327}
2328 2328
2329static void locks_stop(struct seq_file *f, void *v) 2329static void locks_stop(struct seq_file *f, void *v)