Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lockd: Convert NLM service fl_owner to nlm_lockowner

Do as the NLM client: allocate and track a struct nlm_lockowner for use as
the fl_owner for locks created by the NLM sever. This allows us to keep
the svid within this structure for matching locks, and will allow us to
track the pid of lockd in a future patch. It should also allow easier
reference of the nlm_host in conflicting locks, and simplify lock hashing
and comparison.

Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
[bfields@redhat.com: fix type of some error returns]
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Benjamin Coddington and committed by
J. Bruce Fields
89e0edfb 9de3ec1d

+123 -5
+12 -1
fs/lockd/svc4proc.c
··· 46 46 47 47 /* Set up the missing parts of the file_lock structure */ 48 48 lock->fl.fl_file = file->f_file; 49 - lock->fl.fl_owner = (fl_owner_t) host; 50 49 lock->fl.fl_lmops = &nlmsvc_lock_operations; 50 + nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid); 51 + if (!lock->fl.fl_owner) { 52 + /* lockowner allocation has failed */ 53 + nlmsvc_release_host(host); 54 + return nlm_lck_denied_nolocks; 55 + } 51 56 } 52 57 53 58 return 0; ··· 99 94 else 100 95 dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); 101 96 97 + nlmsvc_release_lockowner(&argp->lock); 102 98 nlmsvc_release_host(host); 103 99 nlm_release_file(file); 104 100 return rc; ··· 148 142 else 149 143 dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); 150 144 145 + nlmsvc_release_lockowner(&argp->lock); 151 146 nlmsvc_release_host(host); 152 147 nlm_release_file(file); 153 148 return rc; ··· 185 178 resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock); 186 179 187 180 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 181 + nlmsvc_release_lockowner(&argp->lock); 188 182 nlmsvc_release_host(host); 189 183 nlm_release_file(file); 190 184 return rpc_success; ··· 225 217 resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock); 226 218 227 219 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 220 + nlmsvc_release_lockowner(&argp->lock); 228 221 nlmsvc_release_host(host); 229 222 nlm_release_file(file); 230 223 return rpc_success; ··· 374 365 resp->status = nlmsvc_share_file(host, file, argp); 375 366 376 367 dprintk("lockd: SHARE status %d\n", ntohl(resp->status)); 368 + nlmsvc_release_lockowner(&argp->lock); 377 369 nlmsvc_release_host(host); 378 370 nlm_release_file(file); 379 371 return rpc_success; ··· 409 399 resp->status = nlmsvc_unshare_file(host, file, argp); 410 400 411 401 dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status)); 402 + nlmsvc_release_lockowner(&argp->lock); 412 403 nlmsvc_release_host(host); 413 404 nlm_release_file(file); 414 405 return rpc_success;
+96
fs/lockd/svclock.c
··· 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 + static void nlmsvc_locks_copy_lock(struct file_lock *new, struct file_lock *fl) 399 + { 400 + struct nlm_lockowner *nlm_lo = (struct nlm_lockowner *)fl->fl_owner; 401 + new->fl_owner = nlmsvc_get_lockowner(nlm_lo); 402 + } 403 + 404 + static void nlmsvc_locks_release_private(struct file_lock *fl) 405 + { 406 + nlmsvc_put_lockowner((struct nlm_lockowner *)fl->fl_owner); 407 + } 408 + 409 + const struct file_lock_operations nlmsvc_lock_ops = { 410 + .fl_copy_lock = nlmsvc_locks_copy_lock, 411 + .fl_release_private = nlmsvc_locks_release_private, 412 + }; 413 + 414 + void nlmsvc_locks_init_private(struct file_lock *fl, struct nlm_host *host, 415 + pid_t pid) 416 + { 417 + fl->fl_owner = nlmsvc_find_lockowner(host, pid); 418 + if (fl->fl_owner != NULL) 419 + fl->fl_ops = &nlmsvc_lock_ops; 420 + } 421 + 335 422 /* 336 423 * Initialize arguments for GRANTED call. The nlm_rqst structure 337 424 * has been cleared already. ··· 596 509 { 597 510 int error; 598 511 __be32 ret; 512 + struct nlm_lockowner *test_owner; 599 513 600 514 dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", 601 515 locks_inode(file->f_file)->i_sb->s_id, ··· 609 521 ret = nlm_lck_denied_grace_period; 610 522 goto out; 611 523 } 524 + 525 + /* If there's a conflicting lock, remember to clean up the test lock */ 526 + test_owner = (struct nlm_lockowner *)lock->fl.fl_owner; 612 527 613 528 error = vfs_test_lock(file->f_file, &lock->fl); 614 529 if (error) { ··· 639 548 conflock->fl.fl_start = lock->fl.fl_start; 640 549 conflock->fl.fl_end = lock->fl.fl_end; 641 550 locks_release_private(&lock->fl); 551 + 552 + /* Clean up the test lock */ 553 + lock->fl.fl_owner = NULL; 554 + nlmsvc_put_lockowner(test_owner); 555 + 642 556 ret = nlm_lck_denied; 643 557 out: 644 558 return ret;
+12 -1
fs/lockd/svcproc.c
··· 76 76 77 77 /* Set up the missing parts of the file_lock structure */ 78 78 lock->fl.fl_file = file->f_file; 79 - lock->fl.fl_owner = (fl_owner_t) host; 80 79 lock->fl.fl_lmops = &nlmsvc_lock_operations; 80 + nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid); 81 + if (!lock->fl.fl_owner) { 82 + /* lockowner allocation has failed */ 83 + nlmsvc_release_host(host); 84 + return nlm_lck_denied_nolocks; 85 + } 81 86 } 82 87 83 88 return 0; ··· 130 125 dprintk("lockd: TEST status %d vers %d\n", 131 126 ntohl(resp->status), rqstp->rq_vers); 132 127 128 + nlmsvc_release_lockowner(&argp->lock); 133 129 nlmsvc_release_host(host); 134 130 nlm_release_file(file); 135 131 return rc; ··· 179 173 else 180 174 dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); 181 175 176 + nlmsvc_release_lockowner(&argp->lock); 182 177 nlmsvc_release_host(host); 183 178 nlm_release_file(file); 184 179 return rc; ··· 217 210 resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock)); 218 211 219 212 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 213 + nlmsvc_release_lockowner(&argp->lock); 220 214 nlmsvc_release_host(host); 221 215 nlm_release_file(file); 222 216 return rpc_success; ··· 258 250 resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock)); 259 251 260 252 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 253 + nlmsvc_release_lockowner(&argp->lock); 261 254 nlmsvc_release_host(host); 262 255 nlm_release_file(file); 263 256 return rpc_success; ··· 417 408 resp->status = cast_status(nlmsvc_share_file(host, file, argp)); 418 409 419 410 dprintk("lockd: SHARE status %d\n", ntohl(resp->status)); 411 + nlmsvc_release_lockowner(&argp->lock); 420 412 nlmsvc_release_host(host); 421 413 nlm_release_file(file); 422 414 return rpc_success; ··· 452 442 resp->status = cast_status(nlmsvc_unshare_file(host, file, argp)); 453 443 454 444 dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status)); 445 + nlmsvc_release_lockowner(&argp->lock); 455 446 nlmsvc_release_host(host); 456 447 nlm_release_file(file); 457 448 return rpc_success;
+1 -1
fs/lockd/svcsubs.c
··· 180 180 /* update current lock count */ 181 181 file->f_locks++; 182 182 183 - lockhost = (struct nlm_host *) fl->fl_owner; 183 + lockhost = ((struct nlm_lockowner *)fl->fl_owner)->host; 184 184 if (match(lockhost, host)) { 185 185 struct file_lock lock = *fl; 186 186
-1
fs/lockd/xdr.c
··· 126 126 lock->svid = ntohl(*p++); 127 127 128 128 locks_init_lock(fl); 129 - fl->fl_owner = current->files; 130 129 fl->fl_pid = (pid_t)lock->svid; 131 130 fl->fl_flags = FL_POSIX; 132 131 fl->fl_type = F_RDLCK; /* as good as anything else */
-1
fs/lockd/xdr4.c
··· 118 118 lock->svid = ntohl(*p++); 119 119 120 120 locks_init_lock(fl); 121 - fl->fl_owner = current->files; 122 121 fl->fl_pid = (pid_t)lock->svid; 123 122 fl->fl_flags = FL_POSIX; 124 123 fl->fl_type = F_RDLCK; /* as good as anything else */
+2
include/linux/lockd/lockd.h
··· 282 282 nlm_host_match_fn_t match); 283 283 void nlmsvc_grant_reply(struct nlm_cookie *, __be32); 284 284 void nlmsvc_release_call(struct nlm_rqst *); 285 + void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t); 285 286 286 287 /* 287 288 * File handling for the server personality ··· 290 289 __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, 291 290 struct nfs_fh *); 292 291 void nlm_release_file(struct nlm_file *); 292 + void nlmsvc_release_lockowner(struct nlm_lock *); 293 293 void nlmsvc_mark_resources(struct net *); 294 294 void nlmsvc_free_host_resources(struct nlm_host *); 295 295 void nlmsvc_invalidate_all(void);