aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:39 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:39 -0500
commit6849c0cab69f5d1a0fc7b05fa5bfb3dec53f86df (patch)
tree8bf595be663cc641b000846737c3ba1b6419eb6a
parent09c7938c5640a6f22bef074ca6b803dccfdb93e3 (diff)
lockd: Add refcounting to struct nlm_block
Otherwise, the block may disappear from underneath us when in nlmsvc_retry_blocked. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/lockd/svclock.c94
-rw-r--r--include/linux/lockd/lockd.h3
2 files changed, 47 insertions, 50 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 1d3a74df93f3..20caeceffb14 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -39,6 +39,7 @@
39#define nlm_deadlock nlm_lck_denied 39#define nlm_deadlock nlm_lck_denied
40#endif 40#endif
41 41
42static void nlmsvc_release_block(struct nlm_block *block);
42static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); 43static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
43static int nlmsvc_remove_block(struct nlm_block *block); 44static int nlmsvc_remove_block(struct nlm_block *block);
44 45
@@ -58,6 +59,7 @@ nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
58 struct nlm_block **bp, *b; 59 struct nlm_block **bp, *b;
59 60
60 dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when); 61 dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when);
62 kref_get(&block->b_count);
61 if (block->b_queued) 63 if (block->b_queued)
62 nlmsvc_remove_block(block); 64 nlmsvc_remove_block(block);
63 bp = &nlm_blocked; 65 bp = &nlm_blocked;
@@ -90,6 +92,7 @@ nlmsvc_remove_block(struct nlm_block *block)
90 if (b == block) { 92 if (b == block) {
91 *bp = block->b_next; 93 *bp = block->b_next;
92 block->b_queued = 0; 94 block->b_queued = 0;
95 nlmsvc_release_block(block);
93 return 1; 96 return 1;
94 } 97 }
95 } 98 }
@@ -123,6 +126,7 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove)
123 *head = block->b_next; 126 *head = block->b_next;
124 block->b_queued = 0; 127 block->b_queued = 0;
125 } 128 }
129 kref_get(&block->b_count);
126 return block; 130 return block;
127 } 131 }
128 } 132 }
@@ -155,6 +159,8 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin)
155 break; 159 break;
156 } 160 }
157 161
162 if (block != NULL)
163 kref_get(&block->b_count);
158 return block; 164 return block;
159} 165}
160 166
@@ -188,6 +194,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
188 memset(block, 0, sizeof(*block)); 194 memset(block, 0, sizeof(*block));
189 locks_init_lock(&block->b_call.a_args.lock.fl); 195 locks_init_lock(&block->b_call.a_args.lock.fl);
190 locks_init_lock(&block->b_call.a_res.lock.fl); 196 locks_init_lock(&block->b_call.a_res.lock.fl);
197 kref_init(&block->b_count);
191 198
192 if (!nlmclnt_setgrantargs(&block->b_call, lock)) 199 if (!nlmclnt_setgrantargs(&block->b_call, lock))
193 goto failed_free; 200 goto failed_free;
@@ -228,27 +235,24 @@ failed:
228 * It is the caller's responsibility to check whether the file 235 * It is the caller's responsibility to check whether the file
229 * can be closed hereafter. 236 * can be closed hereafter.
230 */ 237 */
231static int 238static int nlmsvc_unlink_block(struct nlm_block *block)
232nlmsvc_delete_block(struct nlm_block *block)
233{ 239{
234 struct file_lock *fl = &block->b_call.a_args.lock.fl;
235 struct nlm_file *file = block->b_file;
236 struct nlm_block **bp;
237 int status; 240 int status;
238 241 dprintk("lockd: unlinking block %p...\n", block);
239 dprintk("lockd: deleting block %p...\n", block);
240 242
241 /* Remove block from list */ 243 /* Remove block from list */
244 status = posix_unblock_lock(block->b_file->f_file, &block->b_call.a_args.lock.fl);
242 nlmsvc_remove_block(block); 245 nlmsvc_remove_block(block);
243 status = posix_unblock_lock(file->f_file, fl); 246 return status;
247}
244 248
245 /* If the block is in the middle of a GRANT callback, 249static void nlmsvc_free_block(struct kref *kref)
246 * don't kill it yet. */ 250{
247 if (block->b_incall) { 251 struct nlm_block *block = container_of(kref, struct nlm_block, b_count);
248 nlmsvc_insert_block(block, NLM_NEVER); 252 struct nlm_file *file = block->b_file;
249 block->b_done = 1; 253 struct nlm_block **bp;
250 return status; 254
251 } 255 dprintk("lockd: freeing block %p...\n", block);
252 256
253 /* Remove block from file's list of blocks */ 257 /* Remove block from file's list of blocks */
254 for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { 258 for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) {
@@ -262,7 +266,12 @@ nlmsvc_delete_block(struct nlm_block *block)
262 nlm_release_host(block->b_host); 266 nlm_release_host(block->b_host);
263 nlmclnt_freegrantargs(&block->b_call); 267 nlmclnt_freegrantargs(&block->b_call);
264 kfree(block); 268 kfree(block);
265 return status; 269}
270
271static void nlmsvc_release_block(struct nlm_block *block)
272{
273 if (block != NULL)
274 kref_put(&block->b_count, nlmsvc_free_block);
266} 275}
267 276
268/* 277/*
@@ -282,7 +291,7 @@ nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action)
282 block->b_host->h_inuse = 1; 291 block->b_host->h_inuse = 1;
283 else if (action == NLM_ACT_UNLOCK) { 292 else if (action == NLM_ACT_UNLOCK) {
284 if (host == NULL || host == block->b_host) 293 if (host == NULL || host == block->b_host)
285 nlmsvc_delete_block(block); 294 nlmsvc_unlink_block(block);
286 } 295 }
287 } 296 }
288 up(&file->f_sema); 297 up(&file->f_sema);
@@ -318,9 +327,9 @@ again:
318 block = nlmsvc_lookup_block(file, lock, 0); 327 block = nlmsvc_lookup_block(file, lock, 0);
319 if (block == NULL) { 328 if (block == NULL) {
320 if (newblock != NULL) 329 if (newblock != NULL)
321 lock = &newblock->b_call.a_args.lock.fl; 330 lock = &newblock->b_call.a_args.lock;
322 } else 331 } else
323 lock = &block->b_call.a_args.lock.fl; 332 lock = &block->b_call.a_args.lock;
324 333
325 error = posix_lock_file(file->f_file, &lock->fl); 334 error = posix_lock_file(file->f_file, &lock->fl);
326 lock->fl.fl_flags &= ~FL_SLEEP; 335 lock->fl.fl_flags &= ~FL_SLEEP;
@@ -363,12 +372,10 @@ again:
363 372
364 /* Append to list of blocked */ 373 /* Append to list of blocked */
365 nlmsvc_insert_block(newblock, NLM_NEVER); 374 nlmsvc_insert_block(newblock, NLM_NEVER);
366 newblock = NULL;
367
368out: 375out:
369 up(&file->f_sema); 376 up(&file->f_sema);
370 if (newblock != NULL) 377 nlmsvc_release_block(newblock);
371 nlmsvc_delete_block(newblock); 378 nlmsvc_release_block(block);
372 dprintk("lockd: nlmsvc_lock returned %u\n", ret); 379 dprintk("lockd: nlmsvc_lock returned %u\n", ret);
373 return ret; 380 return ret;
374} 381}
@@ -450,8 +457,10 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
450 (long long)lock->fl.fl_end); 457 (long long)lock->fl.fl_end);
451 458
452 down(&file->f_sema); 459 down(&file->f_sema);
453 if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) 460 if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) {
454 status = nlmsvc_delete_block(block); 461 status = nlmsvc_unlink_block(block);
462 nlmsvc_release_block(block);
463 }
455 up(&file->f_sema); 464 up(&file->f_sema);
456 return status ? nlm_lck_denied : nlm_granted; 465 return status ? nlm_lck_denied : nlm_granted;
457} 466}
@@ -514,7 +523,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
514 down(&file->f_sema); 523 down(&file->f_sema);
515 524
516 /* Unlink block request from list */ 525 /* Unlink block request from list */
517 nlmsvc_remove_block(block); 526 nlmsvc_unlink_block(block);
518 527
519 /* If b_granted is true this means we've been here before. 528 /* If b_granted is true this means we've been here before.
520 * Just retry the grant callback, possibly refreshing the RPC 529 * Just retry the grant callback, possibly refreshing the RPC
@@ -525,7 +534,6 @@ nlmsvc_grant_blocked(struct nlm_block *block)
525 } 534 }
526 535
527 /* Try the lock operation again */ 536 /* Try the lock operation again */
528 posix_unblock_lock(file->f_file, &lock->fl);
529 lock->fl.fl_flags |= FL_SLEEP; 537 lock->fl.fl_flags |= FL_SLEEP;
530 error = posix_lock_file(file->f_file, &lock->fl); 538 error = posix_lock_file(file->f_file, &lock->fl);
531 lock->fl.fl_flags &= ~FL_SLEEP; 539 lock->fl.fl_flags &= ~FL_SLEEP;
@@ -548,16 +556,15 @@ callback:
548 /* Lock was granted by VFS. */ 556 /* Lock was granted by VFS. */
549 dprintk("lockd: GRANTing blocked lock.\n"); 557 dprintk("lockd: GRANTing blocked lock.\n");
550 block->b_granted = 1; 558 block->b_granted = 1;
551 block->b_incall = 1;
552 559
553 /* Schedule next grant callback in 30 seconds */ 560 /* Schedule next grant callback in 30 seconds */
554 nlmsvc_insert_block(block, 30 * HZ); 561 nlmsvc_insert_block(block, 30 * HZ);
555 562
556 /* Call the client */ 563 /* Call the client */
557 nlm_get_host(block->b_call.a_host); 564 kref_get(&block->b_count);
558 if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG, 565 if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG,
559 &nlmsvc_grant_ops) < 0) 566 &nlmsvc_grant_ops) < 0)
560 nlm_release_host(block->b_call.a_host); 567 nlmsvc_release_block(block);
561out_unlock: 568out_unlock:
562 up(&file->f_sema); 569 up(&file->f_sema);
563} 570}
@@ -573,20 +580,10 @@ out_unlock:
573static void nlmsvc_grant_callback(struct rpc_task *task, void *data) 580static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
574{ 581{
575 struct nlm_rqst *call = data; 582 struct nlm_rqst *call = data;
576 struct nlm_block *block; 583 struct nlm_block *block = container_of(call, struct nlm_block, b_call);
577 unsigned long timeout; 584 unsigned long timeout;
578 struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client);
579 585
580 dprintk("lockd: GRANT_MSG RPC callback\n"); 586 dprintk("lockd: GRANT_MSG RPC callback\n");
581 dprintk("callback: looking for cookie %s, host (%u.%u.%u.%u)\n",
582 nlmdbg_cookie2a(&call->a_args.cookie),
583 NIPQUAD(peer_addr->sin_addr.s_addr));
584 if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) {
585 dprintk("lockd: no block for cookie %s, host (%u.%u.%u.%u)\n",
586 nlmdbg_cookie2a(&call->a_args.cookie),
587 NIPQUAD(peer_addr->sin_addr.s_addr));
588 return;
589 }
590 587
591 /* Technically, we should down the file semaphore here. Since we 588 /* Technically, we should down the file semaphore here. Since we
592 * move the block towards the head of the queue only, no harm 589 * move the block towards the head of the queue only, no harm
@@ -603,9 +600,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
603 } 600 }
604 nlmsvc_insert_block(block, timeout); 601 nlmsvc_insert_block(block, timeout);
605 svc_wake_up(block->b_daemon); 602 svc_wake_up(block->b_daemon);
606 block->b_incall = 0; 603 nlmsvc_release_block(block);
607
608 nlm_release_host(call->a_host);
609} 604}
610 605
611static const struct rpc_call_ops nlmsvc_grant_ops = { 606static const struct rpc_call_ops nlmsvc_grant_ops = {
@@ -631,20 +626,19 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status
631 626
632 file->f_count++; 627 file->f_count++;
633 down(&file->f_sema); 628 down(&file->f_sema);
634 block = nlmsvc_find_block(cookie, &rqstp->rq_addr);
635 if (block) { 629 if (block) {
636 if (status == NLM_LCK_DENIED_GRACE_PERIOD) { 630 if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
637 /* Try again in a couple of seconds */ 631 /* Try again in a couple of seconds */
638 nlmsvc_insert_block(block, 10 * HZ); 632 nlmsvc_insert_block(block, 10 * HZ);
639 up(&file->f_sema);
640 } else { 633 } else {
641 /* Lock is now held by client, or has been rejected. 634 /* Lock is now held by client, or has been rejected.
642 * In both cases, the block should be removed. */ 635 * In both cases, the block should be removed. */
643 nlmsvc_delete_block(block); 636 nlmsvc_unlink_block(block);
644 up(&file->f_sema);
645 } 637 }
646 } 638 }
639 up(&file->f_sema);
647 nlm_release_file(file); 640 nlm_release_file(file);
641 nlmsvc_release_block(block);
648} 642}
649 643
650/* 644/*
@@ -667,10 +661,12 @@ nlmsvc_retry_blocked(void)
667 break; 661 break;
668 dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", 662 dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n",
669 block, block->b_when, block->b_done); 663 block, block->b_when, block->b_done);
664 kref_get(&block->b_count);
670 if (block->b_done) 665 if (block->b_done)
671 nlmsvc_delete_block(block); 666 nlmsvc_unlink_block(block);
672 else 667 else
673 nlmsvc_grant_blocked(block); 668 nlmsvc_grant_blocked(block);
669 nlmsvc_release_block(block);
674 } 670 }
675 671
676 if ((block = nlm_blocked) && block->b_when != NLM_NEVER) 672 if ((block = nlm_blocked) && block->b_when != NLM_NEVER)
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index ef21ed296039..08ab9773f762 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -14,6 +14,7 @@
14#include <linux/config.h> 14#include <linux/config.h>
15#include <linux/in.h> 15#include <linux/in.h>
16#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/kref.h>
17#include <linux/utsname.h> 18#include <linux/utsname.h>
18#include <linux/nfsd/nfsfh.h> 19#include <linux/nfsd/nfsfh.h>
19#include <linux/lockd/bind.h> 20#include <linux/lockd/bind.h>
@@ -110,6 +111,7 @@ struct nlm_file {
110 */ 111 */
111#define NLM_NEVER (~(unsigned long) 0) 112#define NLM_NEVER (~(unsigned long) 0)
112struct nlm_block { 113struct nlm_block {
114 struct kref b_count; /* Reference count */
113 struct nlm_block * b_next; /* linked list (all blocks) */ 115 struct nlm_block * b_next; /* linked list (all blocks) */
114 struct nlm_block * b_fnext; /* linked list (per file) */ 116 struct nlm_block * b_fnext; /* linked list (per file) */
115 struct nlm_rqst b_call; /* RPC args & callback info */ 117 struct nlm_rqst b_call; /* RPC args & callback info */
@@ -119,7 +121,6 @@ struct nlm_block {
119 unsigned int b_id; /* block id */ 121 unsigned int b_id; /* block id */
120 unsigned char b_queued; /* re-queued */ 122 unsigned char b_queued; /* re-queued */
121 unsigned char b_granted; /* VFS granted lock */ 123 unsigned char b_granted; /* VFS granted lock */
122 unsigned char b_incall; /* doing callback */
123 unsigned char b_done; /* callback complete */ 124 unsigned char b_done; /* callback complete */
124 struct nlm_file * b_file; /* file in question */ 125 struct nlm_file * b_file; /* file in question */
125}; 126};
ref='#n2832'>2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207






































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
ÐÏࡱá