0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <linux/types.h>
0025 #include <linux/slab.h>
0026 #include <linux/errno.h>
0027 #include <linux/kernel.h>
0028 #include <linux/sched.h>
0029 #include <linux/sunrpc/clnt.h>
0030 #include <linux/sunrpc/svc_xprt.h>
0031 #include <linux/lockd/nlm.h>
0032 #include <linux/lockd/lockd.h>
0033 #include <linux/kthread.h>
0034 #include <linux/exportfs.h>
0035
0036 #define NLMDBG_FACILITY NLMDBG_SVCLOCK
0037
0038 #ifdef CONFIG_LOCKD_V4
0039 #define nlm_deadlock nlm4_deadlock
0040 #else
0041 #define nlm_deadlock nlm_lck_denied
0042 #endif
0043
0044 static void nlmsvc_release_block(struct nlm_block *block);
0045 static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
0046 static void nlmsvc_remove_block(struct nlm_block *block);
0047
0048 static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock);
0049 static void nlmsvc_freegrantargs(struct nlm_rqst *call);
0050 static const struct rpc_call_ops nlmsvc_grant_ops;
0051
0052
0053
0054
0055 static LIST_HEAD(nlm_blocked);
0056 static DEFINE_SPINLOCK(nlm_blocked_lock);
0057
0058 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
0059 static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie)
0060 {
0061
0062
0063
0064
0065 static char buf[2*NLM_MAXCOOKIELEN+1];
0066 unsigned int i, len = sizeof(buf);
0067 char *p = buf;
0068
0069 len--;
0070 if (len < 3)
0071 return "???";
0072 for (i = 0 ; i < cookie->len ; i++) {
0073 if (len < 2) {
0074 strcpy(p-3, "...");
0075 break;
0076 }
0077 sprintf(p, "%02x", cookie->data[i]);
0078 p += 2;
0079 len -= 2;
0080 }
0081 *p = '\0';
0082
0083 return buf;
0084 }
0085 #endif
0086
0087
0088
0089
0090 static void
0091 nlmsvc_insert_block_locked(struct nlm_block *block, unsigned long when)
0092 {
0093 struct nlm_block *b;
0094 struct list_head *pos;
0095
0096 dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when);
0097 if (list_empty(&block->b_list)) {
0098 kref_get(&block->b_count);
0099 } else {
0100 list_del_init(&block->b_list);
0101 }
0102
0103 pos = &nlm_blocked;
0104 if (when != NLM_NEVER) {
0105 if ((when += jiffies) == NLM_NEVER)
0106 when ++;
0107 list_for_each(pos, &nlm_blocked) {
0108 b = list_entry(pos, struct nlm_block, b_list);
0109 if (time_after(b->b_when,when) || b->b_when == NLM_NEVER)
0110 break;
0111 }
0112
0113
0114
0115 }
0116
0117 list_add_tail(&block->b_list, pos);
0118 block->b_when = when;
0119 }
0120
0121 static void nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
0122 {
0123 spin_lock(&nlm_blocked_lock);
0124 nlmsvc_insert_block_locked(block, when);
0125 spin_unlock(&nlm_blocked_lock);
0126 }
0127
0128
0129
0130
0131 static inline void
0132 nlmsvc_remove_block(struct nlm_block *block)
0133 {
0134 if (!list_empty(&block->b_list)) {
0135 spin_lock(&nlm_blocked_lock);
0136 list_del_init(&block->b_list);
0137 spin_unlock(&nlm_blocked_lock);
0138 nlmsvc_release_block(block);
0139 }
0140 }
0141
0142
0143
0144
0145 static struct nlm_block *
0146 nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
0147 {
0148 struct nlm_block *block;
0149 struct file_lock *fl;
0150
0151 dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n",
0152 file, lock->fl.fl_pid,
0153 (long long)lock->fl.fl_start,
0154 (long long)lock->fl.fl_end, lock->fl.fl_type);
0155 list_for_each_entry(block, &nlm_blocked, b_list) {
0156 fl = &block->b_call->a_args.lock.fl;
0157 dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
0158 block->b_file, fl->fl_pid,
0159 (long long)fl->fl_start,
0160 (long long)fl->fl_end, fl->fl_type,
0161 nlmdbg_cookie2a(&block->b_call->a_args.cookie));
0162 if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) {
0163 kref_get(&block->b_count);
0164 return block;
0165 }
0166 }
0167
0168 return NULL;
0169 }
0170
0171 static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
0172 {
0173 if (a->len != b->len)
0174 return 0;
0175 if (memcmp(a->data, b->data, a->len))
0176 return 0;
0177 return 1;
0178 }
0179
0180
0181
0182
0183 static inline struct nlm_block *
0184 nlmsvc_find_block(struct nlm_cookie *cookie)
0185 {
0186 struct nlm_block *block;
0187
0188 list_for_each_entry(block, &nlm_blocked, b_list) {
0189 if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie))
0190 goto found;
0191 }
0192
0193 return NULL;
0194
0195 found:
0196 dprintk("nlmsvc_find_block(%s): block=%p\n", nlmdbg_cookie2a(cookie), block);
0197 kref_get(&block->b_count);
0198 return block;
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 static struct nlm_block *
0217 nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
0218 struct nlm_file *file, struct nlm_lock *lock,
0219 struct nlm_cookie *cookie)
0220 {
0221 struct nlm_block *block;
0222 struct nlm_rqst *call = NULL;
0223
0224 call = nlm_alloc_call(host);
0225 if (call == NULL)
0226 return NULL;
0227
0228
0229 block = kzalloc(sizeof(*block), GFP_KERNEL);
0230 if (block == NULL)
0231 goto failed;
0232 kref_init(&block->b_count);
0233 INIT_LIST_HEAD(&block->b_list);
0234 INIT_LIST_HEAD(&block->b_flist);
0235
0236 if (!nlmsvc_setgrantargs(call, lock))
0237 goto failed_free;
0238
0239
0240 call->a_args.lock.fl.fl_flags |= FL_SLEEP;
0241 call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations;
0242 nlmclnt_next_cookie(&call->a_args.cookie);
0243
0244 dprintk("lockd: created block %p...\n", block);
0245
0246
0247 block->b_daemon = rqstp->rq_server;
0248 block->b_host = host;
0249 block->b_file = file;
0250 file->f_count++;
0251
0252
0253 list_add(&block->b_flist, &file->f_blocks);
0254
0255
0256 block->b_call = call;
0257 call->a_flags = RPC_TASK_ASYNC;
0258 call->a_block = block;
0259
0260 return block;
0261
0262 failed_free:
0263 kfree(block);
0264 failed:
0265 nlmsvc_release_call(call);
0266 return NULL;
0267 }
0268
0269
0270
0271
0272
0273
0274 static int nlmsvc_unlink_block(struct nlm_block *block)
0275 {
0276 int status;
0277 dprintk("lockd: unlinking block %p...\n", block);
0278
0279
0280 status = locks_delete_block(&block->b_call->a_args.lock.fl);
0281 nlmsvc_remove_block(block);
0282 return status;
0283 }
0284
0285 static void nlmsvc_free_block(struct kref *kref)
0286 {
0287 struct nlm_block *block = container_of(kref, struct nlm_block, b_count);
0288 struct nlm_file *file = block->b_file;
0289
0290 dprintk("lockd: freeing block %p...\n", block);
0291
0292
0293 list_del_init(&block->b_flist);
0294 mutex_unlock(&file->f_mutex);
0295
0296 nlmsvc_freegrantargs(block->b_call);
0297 nlmsvc_release_call(block->b_call);
0298 nlm_release_file(block->b_file);
0299 kfree(block);
0300 }
0301
0302 static void nlmsvc_release_block(struct nlm_block *block)
0303 {
0304 if (block != NULL)
0305 kref_put_mutex(&block->b_count, nlmsvc_free_block, &block->b_file->f_mutex);
0306 }
0307
0308
0309
0310
0311
0312 void nlmsvc_traverse_blocks(struct nlm_host *host,
0313 struct nlm_file *file,
0314 nlm_host_match_fn_t match)
0315 {
0316 struct nlm_block *block, *next;
0317
0318 restart:
0319 mutex_lock(&file->f_mutex);
0320 list_for_each_entry_safe(block, next, &file->f_blocks, b_flist) {
0321 if (!match(block->b_host, host))
0322 continue;
0323
0324
0325 if (list_empty(&block->b_list))
0326 continue;
0327 kref_get(&block->b_count);
0328 mutex_unlock(&file->f_mutex);
0329 nlmsvc_unlink_block(block);
0330 nlmsvc_release_block(block);
0331 goto restart;
0332 }
0333 mutex_unlock(&file->f_mutex);
0334 }
0335
0336 static struct nlm_lockowner *
0337 nlmsvc_get_lockowner(struct nlm_lockowner *lockowner)
0338 {
0339 refcount_inc(&lockowner->count);
0340 return lockowner;
0341 }
0342
0343 void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner)
0344 {
0345 if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
0346 return;
0347 list_del(&lockowner->list);
0348 spin_unlock(&lockowner->host->h_lock);
0349 nlmsvc_release_host(lockowner->host);
0350 kfree(lockowner);
0351 }
0352
0353 static struct nlm_lockowner *__nlmsvc_find_lockowner(struct nlm_host *host, pid_t pid)
0354 {
0355 struct nlm_lockowner *lockowner;
0356 list_for_each_entry(lockowner, &host->h_lockowners, list) {
0357 if (lockowner->pid != pid)
0358 continue;
0359 return nlmsvc_get_lockowner(lockowner);
0360 }
0361 return NULL;
0362 }
0363
0364 static struct nlm_lockowner *nlmsvc_find_lockowner(struct nlm_host *host, pid_t pid)
0365 {
0366 struct nlm_lockowner *res, *new = NULL;
0367
0368 spin_lock(&host->h_lock);
0369 res = __nlmsvc_find_lockowner(host, pid);
0370
0371 if (res == NULL) {
0372 spin_unlock(&host->h_lock);
0373 new = kmalloc(sizeof(*res), GFP_KERNEL);
0374 spin_lock(&host->h_lock);
0375 res = __nlmsvc_find_lockowner(host, pid);
0376 if (res == NULL && new != NULL) {
0377 res = new;
0378
0379 refcount_set(&new->count, 1);
0380 new->pid = pid;
0381 new->host = nlm_get_host(host);
0382 list_add(&new->list, &host->h_lockowners);
0383 new = NULL;
0384 }
0385 }
0386
0387 spin_unlock(&host->h_lock);
0388 kfree(new);
0389 return res;
0390 }
0391
0392 void
0393 nlmsvc_release_lockowner(struct nlm_lock *lock)
0394 {
0395 if (lock->fl.fl_owner)
0396 nlmsvc_put_lockowner(lock->fl.fl_owner);
0397 }
0398
0399 void nlmsvc_locks_init_private(struct file_lock *fl, struct nlm_host *host,
0400 pid_t pid)
0401 {
0402 fl->fl_owner = nlmsvc_find_lockowner(host, pid);
0403 }
0404
0405
0406
0407
0408
0409 static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
0410 {
0411 locks_copy_lock(&call->a_args.lock.fl, &lock->fl);
0412 memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh));
0413 call->a_args.lock.caller = utsname()->nodename;
0414 call->a_args.lock.oh.len = lock->oh.len;
0415
0416
0417 call->a_args.lock.oh.data = call->a_owner;
0418 call->a_args.lock.svid = ((struct nlm_lockowner *)lock->fl.fl_owner)->pid;
0419
0420 if (lock->oh.len > NLMCLNT_OHSIZE) {
0421 void *data = kmalloc(lock->oh.len, GFP_KERNEL);
0422 if (!data)
0423 return 0;
0424 call->a_args.lock.oh.data = (u8 *) data;
0425 }
0426
0427 memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len);
0428 return 1;
0429 }
0430
0431 static void nlmsvc_freegrantargs(struct nlm_rqst *call)
0432 {
0433 if (call->a_args.lock.oh.data != call->a_owner)
0434 kfree(call->a_args.lock.oh.data);
0435
0436 locks_release_private(&call->a_args.lock.fl);
0437 }
0438
0439
0440
0441
0442 static __be32
0443 nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block)
0444 {
0445 __be32 status = nlm_lck_denied_nolocks;
0446
0447 block->b_flags |= B_QUEUED;
0448
0449 nlmsvc_insert_block(block, NLM_TIMEOUT);
0450
0451 block->b_cache_req = &rqstp->rq_chandle;
0452 if (rqstp->rq_chandle.defer) {
0453 block->b_deferred_req =
0454 rqstp->rq_chandle.defer(block->b_cache_req);
0455 if (block->b_deferred_req != NULL)
0456 status = nlm_drop_reply;
0457 }
0458 dprintk("lockd: nlmsvc_defer_lock_rqst block %p flags %d status %d\n",
0459 block, block->b_flags, ntohl(status));
0460
0461 return status;
0462 }
0463
0464
0465
0466
0467
0468 __be32
0469 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
0470 struct nlm_host *host, struct nlm_lock *lock, int wait,
0471 struct nlm_cookie *cookie, int reclaim)
0472 {
0473 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
0474 struct inode *inode = nlmsvc_file_inode(file);
0475 #endif
0476 struct nlm_block *block = NULL;
0477 int error;
0478 int mode;
0479 int async_block = 0;
0480 __be32 ret;
0481
0482 dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
0483 inode->i_sb->s_id, inode->i_ino,
0484 lock->fl.fl_type, lock->fl.fl_pid,
0485 (long long)lock->fl.fl_start,
0486 (long long)lock->fl.fl_end,
0487 wait);
0488
0489 if (nlmsvc_file_file(file)->f_op->lock) {
0490 async_block = wait;
0491 wait = 0;
0492 }
0493
0494
0495 mutex_lock(&file->f_mutex);
0496
0497
0498
0499 block = nlmsvc_lookup_block(file, lock);
0500 if (block == NULL) {
0501 block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
0502 ret = nlm_lck_denied_nolocks;
0503 if (block == NULL)
0504 goto out;
0505 lock = &block->b_call->a_args.lock;
0506 } else
0507 lock->fl.fl_flags &= ~FL_SLEEP;
0508
0509 if (block->b_flags & B_QUEUED) {
0510 dprintk("lockd: nlmsvc_lock deferred block %p flags %d\n",
0511 block, block->b_flags);
0512 if (block->b_granted) {
0513 nlmsvc_unlink_block(block);
0514 ret = nlm_granted;
0515 goto out;
0516 }
0517 if (block->b_flags & B_TIMED_OUT) {
0518 nlmsvc_unlink_block(block);
0519 ret = nlm_lck_denied;
0520 goto out;
0521 }
0522 ret = nlm_drop_reply;
0523 goto out;
0524 }
0525
0526 if (locks_in_grace(SVC_NET(rqstp)) && !reclaim) {
0527 ret = nlm_lck_denied_grace_period;
0528 goto out;
0529 }
0530 if (reclaim && !locks_in_grace(SVC_NET(rqstp))) {
0531 ret = nlm_lck_denied_grace_period;
0532 goto out;
0533 }
0534
0535 if (!wait)
0536 lock->fl.fl_flags &= ~FL_SLEEP;
0537 mode = lock_to_openmode(&lock->fl);
0538 error = vfs_lock_file(file->f_file[mode], F_SETLK, &lock->fl, NULL);
0539 lock->fl.fl_flags &= ~FL_SLEEP;
0540
0541 dprintk("lockd: vfs_lock_file returned %d\n", error);
0542 switch (error) {
0543 case 0:
0544 ret = nlm_granted;
0545 goto out;
0546 case -EAGAIN:
0547
0548
0549
0550
0551
0552 if (wait)
0553 break;
0554 ret = async_block ? nlm_lck_blocked : nlm_lck_denied;
0555 goto out;
0556 case FILE_LOCK_DEFERRED:
0557 if (wait)
0558 break;
0559
0560
0561 ret = nlmsvc_defer_lock_rqst(rqstp, block);
0562 goto out;
0563 case -EDEADLK:
0564 ret = nlm_deadlock;
0565 goto out;
0566 default:
0567 ret = nlm_lck_denied_nolocks;
0568 goto out;
0569 }
0570
0571 ret = nlm_lck_blocked;
0572
0573
0574 nlmsvc_insert_block(block, NLM_NEVER);
0575 out:
0576 mutex_unlock(&file->f_mutex);
0577 nlmsvc_release_block(block);
0578 dprintk("lockd: nlmsvc_lock returned %u\n", ret);
0579 return ret;
0580 }
0581
0582
0583
0584
0585 __be32
0586 nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
0587 struct nlm_host *host, struct nlm_lock *lock,
0588 struct nlm_lock *conflock, struct nlm_cookie *cookie)
0589 {
0590 int error;
0591 int mode;
0592 __be32 ret;
0593
0594 dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
0595 nlmsvc_file_inode(file)->i_sb->s_id,
0596 nlmsvc_file_inode(file)->i_ino,
0597 lock->fl.fl_type,
0598 (long long)lock->fl.fl_start,
0599 (long long)lock->fl.fl_end);
0600
0601 if (locks_in_grace(SVC_NET(rqstp))) {
0602 ret = nlm_lck_denied_grace_period;
0603 goto out;
0604 }
0605
0606 mode = lock_to_openmode(&lock->fl);
0607 error = vfs_test_lock(file->f_file[mode], &lock->fl);
0608 if (error) {
0609
0610 if (error == FILE_LOCK_DEFERRED)
0611 WARN_ON_ONCE(1);
0612
0613 ret = nlm_lck_denied_nolocks;
0614 goto out;
0615 }
0616
0617 if (lock->fl.fl_type == F_UNLCK) {
0618 ret = nlm_granted;
0619 goto out;
0620 }
0621
0622 dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
0623 lock->fl.fl_type, (long long)lock->fl.fl_start,
0624 (long long)lock->fl.fl_end);
0625 conflock->caller = "somehost";
0626 conflock->len = strlen(conflock->caller);
0627 conflock->oh.len = 0;
0628 conflock->svid = lock->fl.fl_pid;
0629 conflock->fl.fl_type = lock->fl.fl_type;
0630 conflock->fl.fl_start = lock->fl.fl_start;
0631 conflock->fl.fl_end = lock->fl.fl_end;
0632 locks_release_private(&lock->fl);
0633
0634 ret = nlm_lck_denied;
0635 out:
0636 return ret;
0637 }
0638
0639
0640
0641
0642
0643
0644
0645
0646 __be32
0647 nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
0648 {
0649 int error = 0;
0650
0651 dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
0652 nlmsvc_file_inode(file)->i_sb->s_id,
0653 nlmsvc_file_inode(file)->i_ino,
0654 lock->fl.fl_pid,
0655 (long long)lock->fl.fl_start,
0656 (long long)lock->fl.fl_end);
0657
0658
0659 nlmsvc_cancel_blocked(net, file, lock);
0660
0661 lock->fl.fl_type = F_UNLCK;
0662 if (file->f_file[O_RDONLY])
0663 error = vfs_lock_file(file->f_file[O_RDONLY], F_SETLK,
0664 &lock->fl, NULL);
0665 if (file->f_file[O_WRONLY])
0666 error = vfs_lock_file(file->f_file[O_WRONLY], F_SETLK,
0667 &lock->fl, NULL);
0668
0669 return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
0670 }
0671
0672
0673
0674
0675
0676
0677
0678
0679 __be32
0680 nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
0681 {
0682 struct nlm_block *block;
0683 int status = 0;
0684 int mode;
0685
0686 dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
0687 nlmsvc_file_inode(file)->i_sb->s_id,
0688 nlmsvc_file_inode(file)->i_ino,
0689 lock->fl.fl_pid,
0690 (long long)lock->fl.fl_start,
0691 (long long)lock->fl.fl_end);
0692
0693 if (locks_in_grace(net))
0694 return nlm_lck_denied_grace_period;
0695
0696 mutex_lock(&file->f_mutex);
0697 block = nlmsvc_lookup_block(file, lock);
0698 mutex_unlock(&file->f_mutex);
0699 if (block != NULL) {
0700 mode = lock_to_openmode(&lock->fl);
0701 vfs_cancel_lock(block->b_file->f_file[mode],
0702 &block->b_call->a_args.lock.fl);
0703 status = nlmsvc_unlink_block(block);
0704 nlmsvc_release_block(block);
0705 }
0706 return status ? nlm_lck_denied : nlm_granted;
0707 }
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718 static void
0719 nlmsvc_update_deferred_block(struct nlm_block *block, int result)
0720 {
0721 block->b_flags |= B_GOT_CALLBACK;
0722 if (result == 0)
0723 block->b_granted = 1;
0724 else
0725 block->b_flags |= B_TIMED_OUT;
0726 }
0727
0728 static int nlmsvc_grant_deferred(struct file_lock *fl, int result)
0729 {
0730 struct nlm_block *block;
0731 int rc = -ENOENT;
0732
0733 spin_lock(&nlm_blocked_lock);
0734 list_for_each_entry(block, &nlm_blocked, b_list) {
0735 if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
0736 dprintk("lockd: nlmsvc_notify_blocked block %p flags %d\n",
0737 block, block->b_flags);
0738 if (block->b_flags & B_QUEUED) {
0739 if (block->b_flags & B_TIMED_OUT) {
0740 rc = -ENOLCK;
0741 break;
0742 }
0743 nlmsvc_update_deferred_block(block, result);
0744 } else if (result == 0)
0745 block->b_granted = 1;
0746
0747 nlmsvc_insert_block_locked(block, 0);
0748 svc_wake_up(block->b_daemon);
0749 rc = 0;
0750 break;
0751 }
0752 }
0753 spin_unlock(&nlm_blocked_lock);
0754 if (rc == -ENOENT)
0755 printk(KERN_WARNING "lockd: grant for unknown block\n");
0756 return rc;
0757 }
0758
0759
0760
0761
0762
0763
0764
0765
0766 static void
0767 nlmsvc_notify_blocked(struct file_lock *fl)
0768 {
0769 struct nlm_block *block;
0770
0771 dprintk("lockd: VFS unblock notification for block %p\n", fl);
0772 spin_lock(&nlm_blocked_lock);
0773 list_for_each_entry(block, &nlm_blocked, b_list) {
0774 if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
0775 nlmsvc_insert_block_locked(block, 0);
0776 spin_unlock(&nlm_blocked_lock);
0777 svc_wake_up(block->b_daemon);
0778 return;
0779 }
0780 }
0781 spin_unlock(&nlm_blocked_lock);
0782 printk(KERN_WARNING "lockd: notification for unknown block!\n");
0783 }
0784
0785 static fl_owner_t nlmsvc_get_owner(fl_owner_t owner)
0786 {
0787 return nlmsvc_get_lockowner(owner);
0788 }
0789
0790 static void nlmsvc_put_owner(fl_owner_t owner)
0791 {
0792 nlmsvc_put_lockowner(owner);
0793 }
0794
0795 const struct lock_manager_operations nlmsvc_lock_operations = {
0796 .lm_notify = nlmsvc_notify_blocked,
0797 .lm_grant = nlmsvc_grant_deferred,
0798 .lm_get_owner = nlmsvc_get_owner,
0799 .lm_put_owner = nlmsvc_put_owner,
0800 };
0801
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811
0812
0813 static void
0814 nlmsvc_grant_blocked(struct nlm_block *block)
0815 {
0816 struct nlm_file *file = block->b_file;
0817 struct nlm_lock *lock = &block->b_call->a_args.lock;
0818 int mode;
0819 int error;
0820 loff_t fl_start, fl_end;
0821
0822 dprintk("lockd: grant blocked lock %p\n", block);
0823
0824 kref_get(&block->b_count);
0825
0826
0827 nlmsvc_unlink_block(block);
0828
0829
0830
0831
0832 if (block->b_granted) {
0833 nlm_rebind_host(block->b_host);
0834 goto callback;
0835 }
0836
0837
0838
0839
0840
0841 lock->fl.fl_flags |= FL_SLEEP;
0842 fl_start = lock->fl.fl_start;
0843 fl_end = lock->fl.fl_end;
0844 mode = lock_to_openmode(&lock->fl);
0845 error = vfs_lock_file(file->f_file[mode], F_SETLK, &lock->fl, NULL);
0846 lock->fl.fl_flags &= ~FL_SLEEP;
0847 lock->fl.fl_start = fl_start;
0848 lock->fl.fl_end = fl_end;
0849
0850 switch (error) {
0851 case 0:
0852 break;
0853 case FILE_LOCK_DEFERRED:
0854 dprintk("lockd: lock still blocked error %d\n", error);
0855 nlmsvc_insert_block(block, NLM_NEVER);
0856 nlmsvc_release_block(block);
0857 return;
0858 default:
0859 printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
0860 -error, __func__);
0861 nlmsvc_insert_block(block, 10 * HZ);
0862 nlmsvc_release_block(block);
0863 return;
0864 }
0865
0866 callback:
0867
0868 dprintk("lockd: GRANTing blocked lock.\n");
0869 block->b_granted = 1;
0870
0871
0872
0873
0874 nlmsvc_insert_block(block, NLM_NEVER);
0875
0876
0877
0878
0879 error = nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG,
0880 &nlmsvc_grant_ops);
0881
0882
0883 if (error < 0)
0884 nlmsvc_insert_block(block, 10 * HZ);
0885 }
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895 static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
0896 {
0897 struct nlm_rqst *call = data;
0898 struct nlm_block *block = call->a_block;
0899 unsigned long timeout;
0900
0901 dprintk("lockd: GRANT_MSG RPC callback\n");
0902
0903 spin_lock(&nlm_blocked_lock);
0904
0905
0906
0907
0908
0909
0910
0911
0912 if (list_empty(&block->b_list))
0913 goto out;
0914
0915
0916
0917
0918 if (task->tk_status < 0) {
0919
0920 timeout = 10 * HZ;
0921 } else {
0922
0923 timeout = 60 * HZ;
0924 }
0925 nlmsvc_insert_block_locked(block, timeout);
0926 svc_wake_up(block->b_daemon);
0927 out:
0928 spin_unlock(&nlm_blocked_lock);
0929 }
0930
0931
0932
0933
0934
0935 static void nlmsvc_grant_release(void *data)
0936 {
0937 struct nlm_rqst *call = data;
0938 nlmsvc_release_block(call->a_block);
0939 }
0940
0941 static const struct rpc_call_ops nlmsvc_grant_ops = {
0942 .rpc_call_done = nlmsvc_grant_callback,
0943 .rpc_release = nlmsvc_grant_release,
0944 };
0945
0946
0947
0948
0949
0950 void
0951 nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
0952 {
0953 struct nlm_block *block;
0954
0955 dprintk("grant_reply: looking for cookie %x, s=%d \n",
0956 *(unsigned int *)(cookie->data), status);
0957 if (!(block = nlmsvc_find_block(cookie)))
0958 return;
0959
0960 if (status == nlm_lck_denied_grace_period) {
0961
0962 nlmsvc_insert_block(block, 10 * HZ);
0963 } else {
0964
0965
0966
0967
0968 nlmsvc_unlink_block(block);
0969 }
0970 nlmsvc_release_block(block);
0971 }
0972
0973
0974
0975
0976
0977 static void
0978 retry_deferred_block(struct nlm_block *block)
0979 {
0980 if (!(block->b_flags & B_GOT_CALLBACK))
0981 block->b_flags |= B_TIMED_OUT;
0982 nlmsvc_insert_block(block, NLM_TIMEOUT);
0983 dprintk("revisit block %p flags %d\n", block, block->b_flags);
0984 if (block->b_deferred_req) {
0985 block->b_deferred_req->revisit(block->b_deferred_req, 0);
0986 block->b_deferred_req = NULL;
0987 }
0988 }
0989
0990
0991
0992
0993
0994
0995 unsigned long
0996 nlmsvc_retry_blocked(void)
0997 {
0998 unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
0999 struct nlm_block *block;
1000
1001 spin_lock(&nlm_blocked_lock);
1002 while (!list_empty(&nlm_blocked) && !kthread_should_stop()) {
1003 block = list_entry(nlm_blocked.next, struct nlm_block, b_list);
1004
1005 if (block->b_when == NLM_NEVER)
1006 break;
1007 if (time_after(block->b_when, jiffies)) {
1008 timeout = block->b_when - jiffies;
1009 break;
1010 }
1011 spin_unlock(&nlm_blocked_lock);
1012
1013 dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
1014 block, block->b_when);
1015 if (block->b_flags & B_QUEUED) {
1016 dprintk("nlmsvc_retry_blocked delete block (%p, granted=%d, flags=%d)\n",
1017 block, block->b_granted, block->b_flags);
1018 retry_deferred_block(block);
1019 } else
1020 nlmsvc_grant_blocked(block);
1021 spin_lock(&nlm_blocked_lock);
1022 }
1023 spin_unlock(&nlm_blocked_lock);
1024
1025 return timeout;
1026 }