diff options
author | Jeff Layton <jlayton@redhat.com> | 2013-06-21 08:58:17 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:57:44 -0400 |
commit | 139ca04ee572fea6c0c105e88aba3a534efcd7c4 (patch) | |
tree | b75d2c4b93099413b1910909ee8b884370590c71 /fs | |
parent | 4e8c765d384e549f9b542ea0bd42e2aa227e1404 (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.c | 24 |
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 | */ |
160 | static LIST_HEAD(file_lock_list); | 160 | static 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 | */ |
166 | static LIST_HEAD(blocked_list); | 166 | static 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 | ||
189 | static void locks_init_lock_heads(struct file_lock *fl) | 189 | static 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 | |||
500 | locks_insert_global_locks(struct file_lock *fl) | 500 | locks_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 | |||
508 | locks_delete_global_locks(struct file_lock *fl) | 508 | locks_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 | ||
515 | static inline void | 515 | static inline void |
516 | locks_insert_global_blocked(struct file_lock *waiter) | 516 | locks_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 | ||
521 | static inline void | 521 | static inline void |
522 | locks_delete_global_blocked(struct file_lock *waiter) | 522 | locks_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 | ||
2322 | static void *locks_next(struct seq_file *f, void *v, loff_t *pos) | 2322 | static 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 | ||
2329 | static void locks_stop(struct seq_file *f, void *v) | 2329 | static void locks_stop(struct seq_file *f, void *v) |