diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/lockd/svclock.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/lockd/svclock.c')
-rw-r--r-- | fs/lockd/svclock.c | 72 |
1 files changed, 57 insertions, 15 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 84055d31bfc5..6e31695d046f 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/smp_lock.h> | ||
29 | #include <linux/sunrpc/clnt.h> | 28 | #include <linux/sunrpc/clnt.h> |
30 | #include <linux/sunrpc/svc.h> | 29 | #include <linux/sunrpc/svc.h> |
31 | #include <linux/lockd/nlm.h> | 30 | #include <linux/lockd/nlm.h> |
@@ -47,17 +46,19 @@ static void nlmsvc_remove_block(struct nlm_block *block); | |||
47 | static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); | 46 | static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); |
48 | static void nlmsvc_freegrantargs(struct nlm_rqst *call); | 47 | static void nlmsvc_freegrantargs(struct nlm_rqst *call); |
49 | static const struct rpc_call_ops nlmsvc_grant_ops; | 48 | static const struct rpc_call_ops nlmsvc_grant_ops; |
49 | static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie); | ||
50 | 50 | ||
51 | /* | 51 | /* |
52 | * The list of blocked locks to retry | 52 | * The list of blocked locks to retry |
53 | */ | 53 | */ |
54 | static LIST_HEAD(nlm_blocked); | 54 | static LIST_HEAD(nlm_blocked); |
55 | static DEFINE_SPINLOCK(nlm_blocked_lock); | ||
55 | 56 | ||
56 | /* | 57 | /* |
57 | * Insert a blocked lock into the global list | 58 | * Insert a blocked lock into the global list |
58 | */ | 59 | */ |
59 | static void | 60 | static void |
60 | nlmsvc_insert_block(struct nlm_block *block, unsigned long when) | 61 | nlmsvc_insert_block_locked(struct nlm_block *block, unsigned long when) |
61 | { | 62 | { |
62 | struct nlm_block *b; | 63 | struct nlm_block *b; |
63 | struct list_head *pos; | 64 | struct list_head *pos; |
@@ -87,6 +88,13 @@ nlmsvc_insert_block(struct nlm_block *block, unsigned long when) | |||
87 | block->b_when = when; | 88 | block->b_when = when; |
88 | } | 89 | } |
89 | 90 | ||
91 | static void nlmsvc_insert_block(struct nlm_block *block, unsigned long when) | ||
92 | { | ||
93 | spin_lock(&nlm_blocked_lock); | ||
94 | nlmsvc_insert_block_locked(block, when); | ||
95 | spin_unlock(&nlm_blocked_lock); | ||
96 | } | ||
97 | |||
90 | /* | 98 | /* |
91 | * Remove a block from the global list | 99 | * Remove a block from the global list |
92 | */ | 100 | */ |
@@ -94,7 +102,9 @@ static inline void | |||
94 | nlmsvc_remove_block(struct nlm_block *block) | 102 | nlmsvc_remove_block(struct nlm_block *block) |
95 | { | 103 | { |
96 | if (!list_empty(&block->b_list)) { | 104 | if (!list_empty(&block->b_list)) { |
105 | spin_lock(&nlm_blocked_lock); | ||
97 | list_del_init(&block->b_list); | 106 | list_del_init(&block->b_list); |
107 | spin_unlock(&nlm_blocked_lock); | ||
98 | nlmsvc_release_block(block); | 108 | nlmsvc_release_block(block); |
99 | } | 109 | } |
100 | } | 110 | } |
@@ -224,7 +234,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host, | |||
224 | failed_free: | 234 | failed_free: |
225 | kfree(block); | 235 | kfree(block); |
226 | failed: | 236 | failed: |
227 | nlm_release_call(call); | 237 | nlmsvc_release_call(call); |
228 | return NULL; | 238 | return NULL; |
229 | } | 239 | } |
230 | 240 | ||
@@ -257,7 +267,7 @@ static void nlmsvc_free_block(struct kref *kref) | |||
257 | mutex_unlock(&file->f_mutex); | 267 | mutex_unlock(&file->f_mutex); |
258 | 268 | ||
259 | nlmsvc_freegrantargs(block->b_call); | 269 | nlmsvc_freegrantargs(block->b_call); |
260 | nlm_release_call(block->b_call); | 270 | nlmsvc_release_call(block->b_call); |
261 | nlm_release_file(block->b_file); | 271 | nlm_release_file(block->b_file); |
262 | kfree(block->b_fl); | 272 | kfree(block->b_fl); |
263 | kfree(block); | 273 | kfree(block); |
@@ -651,7 +661,7 @@ static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf, | |||
651 | struct nlm_block *block; | 661 | struct nlm_block *block; |
652 | int rc = -ENOENT; | 662 | int rc = -ENOENT; |
653 | 663 | ||
654 | lock_kernel(); | 664 | spin_lock(&nlm_blocked_lock); |
655 | list_for_each_entry(block, &nlm_blocked, b_list) { | 665 | list_for_each_entry(block, &nlm_blocked, b_list) { |
656 | if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { | 666 | if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { |
657 | dprintk("lockd: nlmsvc_notify_blocked block %p flags %d\n", | 667 | dprintk("lockd: nlmsvc_notify_blocked block %p flags %d\n", |
@@ -665,13 +675,13 @@ static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf, | |||
665 | } else if (result == 0) | 675 | } else if (result == 0) |
666 | block->b_granted = 1; | 676 | block->b_granted = 1; |
667 | 677 | ||
668 | nlmsvc_insert_block(block, 0); | 678 | nlmsvc_insert_block_locked(block, 0); |
669 | svc_wake_up(block->b_daemon); | 679 | svc_wake_up(block->b_daemon); |
670 | rc = 0; | 680 | rc = 0; |
671 | break; | 681 | break; |
672 | } | 682 | } |
673 | } | 683 | } |
674 | unlock_kernel(); | 684 | spin_unlock(&nlm_blocked_lock); |
675 | if (rc == -ENOENT) | 685 | if (rc == -ENOENT) |
676 | printk(KERN_WARNING "lockd: grant for unknown block\n"); | 686 | printk(KERN_WARNING "lockd: grant for unknown block\n"); |
677 | return rc; | 687 | return rc; |
@@ -690,14 +700,16 @@ nlmsvc_notify_blocked(struct file_lock *fl) | |||
690 | struct nlm_block *block; | 700 | struct nlm_block *block; |
691 | 701 | ||
692 | dprintk("lockd: VFS unblock notification for block %p\n", fl); | 702 | dprintk("lockd: VFS unblock notification for block %p\n", fl); |
703 | spin_lock(&nlm_blocked_lock); | ||
693 | list_for_each_entry(block, &nlm_blocked, b_list) { | 704 | list_for_each_entry(block, &nlm_blocked, b_list) { |
694 | if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { | 705 | if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { |
695 | nlmsvc_insert_block(block, 0); | 706 | nlmsvc_insert_block_locked(block, 0); |
707 | spin_unlock(&nlm_blocked_lock); | ||
696 | svc_wake_up(block->b_daemon); | 708 | svc_wake_up(block->b_daemon); |
697 | return; | 709 | return; |
698 | } | 710 | } |
699 | } | 711 | } |
700 | 712 | spin_unlock(&nlm_blocked_lock); | |
701 | printk(KERN_WARNING "lockd: notification for unknown block!\n"); | 713 | printk(KERN_WARNING "lockd: notification for unknown block!\n"); |
702 | } | 714 | } |
703 | 715 | ||
@@ -803,7 +815,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) | |||
803 | 815 | ||
804 | dprintk("lockd: GRANT_MSG RPC callback\n"); | 816 | dprintk("lockd: GRANT_MSG RPC callback\n"); |
805 | 817 | ||
806 | lock_kernel(); | 818 | spin_lock(&nlm_blocked_lock); |
807 | /* if the block is not on a list at this point then it has | 819 | /* if the block is not on a list at this point then it has |
808 | * been invalidated. Don't try to requeue it. | 820 | * been invalidated. Don't try to requeue it. |
809 | * | 821 | * |
@@ -825,19 +837,20 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) | |||
825 | /* Call was successful, now wait for client callback */ | 837 | /* Call was successful, now wait for client callback */ |
826 | timeout = 60 * HZ; | 838 | timeout = 60 * HZ; |
827 | } | 839 | } |
828 | nlmsvc_insert_block(block, timeout); | 840 | nlmsvc_insert_block_locked(block, timeout); |
829 | svc_wake_up(block->b_daemon); | 841 | svc_wake_up(block->b_daemon); |
830 | out: | 842 | out: |
831 | unlock_kernel(); | 843 | spin_unlock(&nlm_blocked_lock); |
832 | } | 844 | } |
833 | 845 | ||
846 | /* | ||
847 | * FIXME: nlmsvc_release_block() grabs a mutex. This is not allowed for an | ||
848 | * .rpc_release rpc_call_op | ||
849 | */ | ||
834 | static void nlmsvc_grant_release(void *data) | 850 | static void nlmsvc_grant_release(void *data) |
835 | { | 851 | { |
836 | struct nlm_rqst *call = data; | 852 | struct nlm_rqst *call = data; |
837 | |||
838 | lock_kernel(); | ||
839 | nlmsvc_release_block(call->a_block); | 853 | nlmsvc_release_block(call->a_block); |
840 | unlock_kernel(); | ||
841 | } | 854 | } |
842 | 855 | ||
843 | static const struct rpc_call_ops nlmsvc_grant_ops = { | 856 | static const struct rpc_call_ops nlmsvc_grant_ops = { |
@@ -922,3 +935,32 @@ nlmsvc_retry_blocked(void) | |||
922 | 935 | ||
923 | return timeout; | 936 | return timeout; |
924 | } | 937 | } |
938 | |||
939 | #ifdef RPC_DEBUG | ||
940 | static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie) | ||
941 | { | ||
942 | /* | ||
943 | * We can get away with a static buffer because we're only | ||
944 | * called with BKL held. | ||
945 | */ | ||
946 | static char buf[2*NLM_MAXCOOKIELEN+1]; | ||
947 | unsigned int i, len = sizeof(buf); | ||
948 | char *p = buf; | ||
949 | |||
950 | len--; /* allow for trailing \0 */ | ||
951 | if (len < 3) | ||
952 | return "???"; | ||
953 | for (i = 0 ; i < cookie->len ; i++) { | ||
954 | if (len < 2) { | ||
955 | strcpy(p-3, "..."); | ||
956 | break; | ||
957 | } | ||
958 | sprintf(p, "%02x", cookie->data[i]); | ||
959 | p += 2; | ||
960 | len -= 2; | ||
961 | } | ||
962 | *p = '\0'; | ||
963 | |||
964 | return buf; | ||
965 | } | ||
966 | #endif | ||