| .. | .. |
|---|
| 276 | 276 | dprintk("lockd: unlinking block %p...\n", block); |
|---|
| 277 | 277 | |
|---|
| 278 | 278 | /* Remove block from list */ |
|---|
| 279 | | - status = posix_unblock_lock(&block->b_call->a_args.lock.fl); |
|---|
| 279 | + status = locks_delete_block(&block->b_call->a_args.lock.fl); |
|---|
| 280 | 280 | nlmsvc_remove_block(block); |
|---|
| 281 | 281 | return status; |
|---|
| 282 | 282 | } |
|---|
| .. | .. |
|---|
| 332 | 332 | mutex_unlock(&file->f_mutex); |
|---|
| 333 | 333 | } |
|---|
| 334 | 334 | |
|---|
| 335 | +static struct nlm_lockowner * |
|---|
| 336 | +nlmsvc_get_lockowner(struct nlm_lockowner *lockowner) |
|---|
| 337 | +{ |
|---|
| 338 | + refcount_inc(&lockowner->count); |
|---|
| 339 | + return lockowner; |
|---|
| 340 | +} |
|---|
| 341 | + |
|---|
| 342 | +static void nlmsvc_put_lockowner(struct nlm_lockowner *lockowner) |
|---|
| 343 | +{ |
|---|
| 344 | + if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock)) |
|---|
| 345 | + return; |
|---|
| 346 | + list_del(&lockowner->list); |
|---|
| 347 | + spin_unlock(&lockowner->host->h_lock); |
|---|
| 348 | + nlmsvc_release_host(lockowner->host); |
|---|
| 349 | + kfree(lockowner); |
|---|
| 350 | +} |
|---|
| 351 | + |
|---|
| 352 | +static struct nlm_lockowner *__nlmsvc_find_lockowner(struct nlm_host *host, pid_t pid) |
|---|
| 353 | +{ |
|---|
| 354 | + struct nlm_lockowner *lockowner; |
|---|
| 355 | + list_for_each_entry(lockowner, &host->h_lockowners, list) { |
|---|
| 356 | + if (lockowner->pid != pid) |
|---|
| 357 | + continue; |
|---|
| 358 | + return nlmsvc_get_lockowner(lockowner); |
|---|
| 359 | + } |
|---|
| 360 | + return NULL; |
|---|
| 361 | +} |
|---|
| 362 | + |
|---|
| 363 | +static struct nlm_lockowner *nlmsvc_find_lockowner(struct nlm_host *host, pid_t pid) |
|---|
| 364 | +{ |
|---|
| 365 | + struct nlm_lockowner *res, *new = NULL; |
|---|
| 366 | + |
|---|
| 367 | + spin_lock(&host->h_lock); |
|---|
| 368 | + res = __nlmsvc_find_lockowner(host, pid); |
|---|
| 369 | + |
|---|
| 370 | + if (res == NULL) { |
|---|
| 371 | + spin_unlock(&host->h_lock); |
|---|
| 372 | + new = kmalloc(sizeof(*res), GFP_KERNEL); |
|---|
| 373 | + spin_lock(&host->h_lock); |
|---|
| 374 | + res = __nlmsvc_find_lockowner(host, pid); |
|---|
| 375 | + if (res == NULL && new != NULL) { |
|---|
| 376 | + res = new; |
|---|
| 377 | + /* fs/locks.c will manage the refcount through lock_ops */ |
|---|
| 378 | + refcount_set(&new->count, 1); |
|---|
| 379 | + new->pid = pid; |
|---|
| 380 | + new->host = nlm_get_host(host); |
|---|
| 381 | + list_add(&new->list, &host->h_lockowners); |
|---|
| 382 | + new = NULL; |
|---|
| 383 | + } |
|---|
| 384 | + } |
|---|
| 385 | + |
|---|
| 386 | + spin_unlock(&host->h_lock); |
|---|
| 387 | + kfree(new); |
|---|
| 388 | + return res; |
|---|
| 389 | +} |
|---|
| 390 | + |
|---|
| 391 | +void |
|---|
| 392 | +nlmsvc_release_lockowner(struct nlm_lock *lock) |
|---|
| 393 | +{ |
|---|
| 394 | + if (lock->fl.fl_owner) |
|---|
| 395 | + nlmsvc_put_lockowner(lock->fl.fl_owner); |
|---|
| 396 | +} |
|---|
| 397 | + |
|---|
| 398 | +void nlmsvc_locks_init_private(struct file_lock *fl, struct nlm_host *host, |
|---|
| 399 | + pid_t pid) |
|---|
| 400 | +{ |
|---|
| 401 | + fl->fl_owner = nlmsvc_find_lockowner(host, pid); |
|---|
| 402 | +} |
|---|
| 403 | + |
|---|
| 335 | 404 | /* |
|---|
| 336 | 405 | * Initialize arguments for GRANTED call. The nlm_rqst structure |
|---|
| 337 | 406 | * has been cleared already. |
|---|
| .. | .. |
|---|
| 345 | 414 | |
|---|
| 346 | 415 | /* set default data area */ |
|---|
| 347 | 416 | call->a_args.lock.oh.data = call->a_owner; |
|---|
| 348 | | - call->a_args.lock.svid = lock->fl.fl_pid; |
|---|
| 417 | + call->a_args.lock.svid = ((struct nlm_lockowner *)lock->fl.fl_owner)->pid; |
|---|
| 349 | 418 | |
|---|
| 350 | 419 | if (lock->oh.len > NLMCLNT_OHSIZE) { |
|---|
| 351 | 420 | void *data = kmalloc(lock->oh.len, GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 509 | 578 | { |
|---|
| 510 | 579 | int error; |
|---|
| 511 | 580 | __be32 ret; |
|---|
| 581 | + struct nlm_lockowner *test_owner; |
|---|
| 512 | 582 | |
|---|
| 513 | 583 | dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", |
|---|
| 514 | 584 | locks_inode(file->f_file)->i_sb->s_id, |
|---|
| .. | .. |
|---|
| 521 | 591 | ret = nlm_lck_denied_grace_period; |
|---|
| 522 | 592 | goto out; |
|---|
| 523 | 593 | } |
|---|
| 594 | + |
|---|
| 595 | + /* If there's a conflicting lock, remember to clean up the test lock */ |
|---|
| 596 | + test_owner = (struct nlm_lockowner *)lock->fl.fl_owner; |
|---|
| 524 | 597 | |
|---|
| 525 | 598 | error = vfs_test_lock(file->f_file, &lock->fl); |
|---|
| 526 | 599 | if (error) { |
|---|
| .. | .. |
|---|
| 548 | 621 | conflock->fl.fl_start = lock->fl.fl_start; |
|---|
| 549 | 622 | conflock->fl.fl_end = lock->fl.fl_end; |
|---|
| 550 | 623 | locks_release_private(&lock->fl); |
|---|
| 624 | + |
|---|
| 625 | + /* Clean up the test lock */ |
|---|
| 626 | + lock->fl.fl_owner = NULL; |
|---|
| 627 | + nlmsvc_put_lockowner(test_owner); |
|---|
| 628 | + |
|---|
| 551 | 629 | ret = nlm_lck_denied; |
|---|
| 552 | 630 | out: |
|---|
| 553 | 631 | return ret; |
|---|
| .. | .. |
|---|
| 692 | 770 | printk(KERN_WARNING "lockd: notification for unknown block!\n"); |
|---|
| 693 | 771 | } |
|---|
| 694 | 772 | |
|---|
| 695 | | -static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2) |
|---|
| 773 | +static fl_owner_t nlmsvc_get_owner(fl_owner_t owner) |
|---|
| 696 | 774 | { |
|---|
| 697 | | - return fl1->fl_owner == fl2->fl_owner && fl1->fl_pid == fl2->fl_pid; |
|---|
| 775 | + return nlmsvc_get_lockowner(owner); |
|---|
| 698 | 776 | } |
|---|
| 699 | 777 | |
|---|
| 700 | | -/* |
|---|
| 701 | | - * Since NLM uses two "keys" for tracking locks, we need to hash them down |
|---|
| 702 | | - * to one for the blocked_hash. Here, we're just xor'ing the host address |
|---|
| 703 | | - * with the pid in order to create a key value for picking a hash bucket. |
|---|
| 704 | | - */ |
|---|
| 705 | | -static unsigned long |
|---|
| 706 | | -nlmsvc_owner_key(struct file_lock *fl) |
|---|
| 778 | +static void nlmsvc_put_owner(fl_owner_t owner) |
|---|
| 707 | 779 | { |
|---|
| 708 | | - return (unsigned long)fl->fl_owner ^ (unsigned long)fl->fl_pid; |
|---|
| 780 | + nlmsvc_put_lockowner(owner); |
|---|
| 709 | 781 | } |
|---|
| 710 | 782 | |
|---|
| 711 | 783 | const struct lock_manager_operations nlmsvc_lock_operations = { |
|---|
| 712 | | - .lm_compare_owner = nlmsvc_same_owner, |
|---|
| 713 | | - .lm_owner_key = nlmsvc_owner_key, |
|---|
| 714 | 784 | .lm_notify = nlmsvc_notify_blocked, |
|---|
| 715 | 785 | .lm_grant = nlmsvc_grant_deferred, |
|---|
| 786 | + .lm_get_owner = nlmsvc_get_owner, |
|---|
| 787 | + .lm_put_owner = nlmsvc_put_owner, |
|---|
| 716 | 788 | }; |
|---|
| 717 | 789 | |
|---|
| 718 | 790 | /* |
|---|