hc
2024-05-10 748e4f3d702def1a4bff191e0cf93b6a05340f01
kernel/fs/lockd/svclock.c
....@@ -276,7 +276,7 @@
276276 dprintk("lockd: unlinking block %p...\n", block);
277277
278278 /* 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);
280280 nlmsvc_remove_block(block);
281281 return status;
282282 }
....@@ -332,6 +332,75 @@
332332 mutex_unlock(&file->f_mutex);
333333 }
334334
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
+
335404 /*
336405 * Initialize arguments for GRANTED call. The nlm_rqst structure
337406 * has been cleared already.
....@@ -345,7 +414,7 @@
345414
346415 /* set default data area */
347416 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;
349418
350419 if (lock->oh.len > NLMCLNT_OHSIZE) {
351420 void *data = kmalloc(lock->oh.len, GFP_KERNEL);
....@@ -509,6 +578,7 @@
509578 {
510579 int error;
511580 __be32 ret;
581
+ struct nlm_lockowner *test_owner;
512582
513583 dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
514584 locks_inode(file->f_file)->i_sb->s_id,
....@@ -521,6 +591,9 @@
521591 ret = nlm_lck_denied_grace_period;
522592 goto out;
523593 }
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;
524597
525598 error = vfs_test_lock(file->f_file, &lock->fl);
526599 if (error) {
....@@ -548,6 +621,11 @@
548621 conflock->fl.fl_start = lock->fl.fl_start;
549622 conflock->fl.fl_end = lock->fl.fl_end;
550623 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
+
551629 ret = nlm_lck_denied;
552630 out:
553631 return ret;
....@@ -692,27 +770,21 @@
692770 printk(KERN_WARNING "lockd: notification for unknown block!\n");
693771 }
694772
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)
696774 {
697
- return fl1->fl_owner == fl2->fl_owner && fl1->fl_pid == fl2->fl_pid;
775
+ return nlmsvc_get_lockowner(owner);
698776 }
699777
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)
707779 {
708
- return (unsigned long)fl->fl_owner ^ (unsigned long)fl->fl_pid;
780
+ nlmsvc_put_lockowner(owner);
709781 }
710782
711783 const struct lock_manager_operations nlmsvc_lock_operations = {
712
- .lm_compare_owner = nlmsvc_same_owner,
713
- .lm_owner_key = nlmsvc_owner_key,
714784 .lm_notify = nlmsvc_notify_blocked,
715785 .lm_grant = nlmsvc_grant_deferred,
786
+ .lm_get_owner = nlmsvc_get_owner,
787
+ .lm_put_owner = nlmsvc_put_owner,
716788 };
717789
718790 /*