diff options
Diffstat (limited to 'fs/lockd/svclock.c')
-rw-r--r-- | fs/lockd/svclock.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index e703318c41df..e066a3902973 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -276,7 +276,7 @@ static int nlmsvc_unlink_block(struct nlm_block *block) | |||
276 | dprintk("lockd: unlinking block %p...\n", block); | 276 | dprintk("lockd: unlinking block %p...\n", block); |
277 | 277 | ||
278 | /* Remove block from list */ | 278 | /* Remove block from list */ |
279 | status = posix_unblock_lock(block->b_file->f_file, &block->b_call->a_args.lock.fl); | 279 | status = posix_unblock_lock(&block->b_call->a_args.lock.fl); |
280 | nlmsvc_remove_block(block); | 280 | nlmsvc_remove_block(block); |
281 | return status; | 281 | return status; |
282 | } | 282 | } |
@@ -744,8 +744,20 @@ static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2) | |||
744 | return fl1->fl_owner == fl2->fl_owner && fl1->fl_pid == fl2->fl_pid; | 744 | return fl1->fl_owner == fl2->fl_owner && fl1->fl_pid == fl2->fl_pid; |
745 | } | 745 | } |
746 | 746 | ||
747 | /* | ||
748 | * Since NLM uses two "keys" for tracking locks, we need to hash them down | ||
749 | * to one for the blocked_hash. Here, we're just xor'ing the host address | ||
750 | * with the pid in order to create a key value for picking a hash bucket. | ||
751 | */ | ||
752 | static unsigned long | ||
753 | nlmsvc_owner_key(struct file_lock *fl) | ||
754 | { | ||
755 | return (unsigned long)fl->fl_owner ^ (unsigned long)fl->fl_pid; | ||
756 | } | ||
757 | |||
747 | const struct lock_manager_operations nlmsvc_lock_operations = { | 758 | const struct lock_manager_operations nlmsvc_lock_operations = { |
748 | .lm_compare_owner = nlmsvc_same_owner, | 759 | .lm_compare_owner = nlmsvc_same_owner, |
760 | .lm_owner_key = nlmsvc_owner_key, | ||
749 | .lm_notify = nlmsvc_notify_blocked, | 761 | .lm_notify = nlmsvc_notify_blocked, |
750 | .lm_grant = nlmsvc_grant_deferred, | 762 | .lm_grant = nlmsvc_grant_deferred, |
751 | }; | 763 | }; |
@@ -939,6 +951,7 @@ nlmsvc_retry_blocked(void) | |||
939 | unsigned long timeout = MAX_SCHEDULE_TIMEOUT; | 951 | unsigned long timeout = MAX_SCHEDULE_TIMEOUT; |
940 | struct nlm_block *block; | 952 | struct nlm_block *block; |
941 | 953 | ||
954 | spin_lock(&nlm_blocked_lock); | ||
942 | while (!list_empty(&nlm_blocked) && !kthread_should_stop()) { | 955 | while (!list_empty(&nlm_blocked) && !kthread_should_stop()) { |
943 | block = list_entry(nlm_blocked.next, struct nlm_block, b_list); | 956 | block = list_entry(nlm_blocked.next, struct nlm_block, b_list); |
944 | 957 | ||
@@ -948,6 +961,7 @@ nlmsvc_retry_blocked(void) | |||
948 | timeout = block->b_when - jiffies; | 961 | timeout = block->b_when - jiffies; |
949 | break; | 962 | break; |
950 | } | 963 | } |
964 | spin_unlock(&nlm_blocked_lock); | ||
951 | 965 | ||
952 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", | 966 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", |
953 | block, block->b_when); | 967 | block, block->b_when); |
@@ -957,7 +971,9 @@ nlmsvc_retry_blocked(void) | |||
957 | retry_deferred_block(block); | 971 | retry_deferred_block(block); |
958 | } else | 972 | } else |
959 | nlmsvc_grant_blocked(block); | 973 | nlmsvc_grant_blocked(block); |
974 | spin_lock(&nlm_blocked_lock); | ||
960 | } | 975 | } |
976 | spin_unlock(&nlm_blocked_lock); | ||
961 | 977 | ||
962 | return timeout; | 978 | return timeout; |
963 | } | 979 | } |