Skip to content

Commit 89e0edf

Browse files
bcodding-rhJ. Bruce Fields
authored andcommitted
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>
1 parent 9de3ec1 commit 89e0edf

File tree

7 files changed

+123
-5
lines changed

7 files changed

+123
-5
lines changed

fs/lockd/svc4proc.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
4646

4747
/* Set up the missing parts of the file_lock structure */
4848
lock->fl.fl_file = file->f_file;
49-
lock->fl.fl_owner = (fl_owner_t) host;
5049
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+
}
5156
}
5257

5358
return 0;
@@ -94,6 +99,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
9499
else
95100
dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
96101

102+
nlmsvc_release_lockowner(&argp->lock);
97103
nlmsvc_release_host(host);
98104
nlm_release_file(file);
99105
return rc;
@@ -142,6 +148,7 @@ __nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
142148
else
143149
dprintk("lockd: LOCK status %d\n", ntohl(resp->status));
144150

151+
nlmsvc_release_lockowner(&argp->lock);
145152
nlmsvc_release_host(host);
146153
nlm_release_file(file);
147154
return rc;
@@ -178,6 +185,7 @@ __nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp)
178185
resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock);
179186

180187
dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
188+
nlmsvc_release_lockowner(&argp->lock);
181189
nlmsvc_release_host(host);
182190
nlm_release_file(file);
183191
return rpc_success;
@@ -217,6 +225,7 @@ __nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp)
217225
resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock);
218226

219227
dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
228+
nlmsvc_release_lockowner(&argp->lock);
220229
nlmsvc_release_host(host);
221230
nlm_release_file(file);
222231
return rpc_success;
@@ -365,6 +374,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp)
365374
resp->status = nlmsvc_share_file(host, file, argp);
366375

367376
dprintk("lockd: SHARE status %d\n", ntohl(resp->status));
377+
nlmsvc_release_lockowner(&argp->lock);
368378
nlmsvc_release_host(host);
369379
nlm_release_file(file);
370380
return rpc_success;
@@ -399,6 +409,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp)
399409
resp->status = nlmsvc_unshare_file(host, file, argp);
400410

401411
dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status));
412+
nlmsvc_release_lockowner(&argp->lock);
402413
nlmsvc_release_host(host);
403414
nlm_release_file(file);
404415
return rpc_success;

fs/lockd/svclock.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,93 @@ void nlmsvc_traverse_blocks(struct nlm_host *host,
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+
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+
335422
/*
336423
* Initialize arguments for GRANTED call. The nlm_rqst structure
337424
* has been cleared already.
@@ -509,6 +596,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
509596
{
510597
int error;
511598
__be32 ret;
599+
struct nlm_lockowner *test_owner;
512600

513601
dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
514602
locks_inode(file->f_file)->i_sb->s_id,
@@ -522,6 +610,9 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
522610
goto out;
523611
}
524612

613+
/* If there's a conflicting lock, remember to clean up the test lock */
614+
test_owner = (struct nlm_lockowner *)lock->fl.fl_owner;
615+
525616
error = vfs_test_lock(file->f_file, &lock->fl);
526617
if (error) {
527618
/* We can't currently deal with deferred test requests */
@@ -548,6 +639,11 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
548639
conflock->fl.fl_start = lock->fl.fl_start;
549640
conflock->fl.fl_end = lock->fl.fl_end;
550641
locks_release_private(&lock->fl);
642+
643+
/* Clean up the test lock */
644+
lock->fl.fl_owner = NULL;
645+
nlmsvc_put_lockowner(test_owner);
646+
551647
ret = nlm_lck_denied;
552648
out:
553649
return ret;

fs/lockd/svcproc.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,13 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
7676

7777
/* Set up the missing parts of the file_lock structure */
7878
lock->fl.fl_file = file->f_file;
79-
lock->fl.fl_owner = (fl_owner_t) host;
8079
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+
}
8186
}
8287

8388
return 0;
@@ -125,6 +130,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
125130
dprintk("lockd: TEST status %d vers %d\n",
126131
ntohl(resp->status), rqstp->rq_vers);
127132

133+
nlmsvc_release_lockowner(&argp->lock);
128134
nlmsvc_release_host(host);
129135
nlm_release_file(file);
130136
return rc;
@@ -173,6 +179,7 @@ __nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
173179
else
174180
dprintk("lockd: LOCK status %d\n", ntohl(resp->status));
175181

182+
nlmsvc_release_lockowner(&argp->lock);
176183
nlmsvc_release_host(host);
177184
nlm_release_file(file);
178185
return rc;
@@ -210,6 +217,7 @@ __nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp)
210217
resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock));
211218

212219
dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
220+
nlmsvc_release_lockowner(&argp->lock);
213221
nlmsvc_release_host(host);
214222
nlm_release_file(file);
215223
return rpc_success;
@@ -250,6 +258,7 @@ __nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp)
250258
resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock));
251259

252260
dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
261+
nlmsvc_release_lockowner(&argp->lock);
253262
nlmsvc_release_host(host);
254263
nlm_release_file(file);
255264
return rpc_success;
@@ -408,6 +417,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp)
408417
resp->status = cast_status(nlmsvc_share_file(host, file, argp));
409418

410419
dprintk("lockd: SHARE status %d\n", ntohl(resp->status));
420+
nlmsvc_release_lockowner(&argp->lock);
411421
nlmsvc_release_host(host);
412422
nlm_release_file(file);
413423
return rpc_success;
@@ -442,6 +452,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp)
442452
resp->status = cast_status(nlmsvc_unshare_file(host, file, argp));
443453

444454
dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status));
455+
nlmsvc_release_lockowner(&argp->lock);
445456
nlmsvc_release_host(host);
446457
nlm_release_file(file);
447458
return rpc_success;

fs/lockd/svcsubs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,
180180
/* update current lock count */
181181
file->f_locks++;
182182

183-
lockhost = (struct nlm_host *) fl->fl_owner;
183+
lockhost = ((struct nlm_lockowner *)fl->fl_owner)->host;
184184
if (match(lockhost, host)) {
185185
struct file_lock lock = *fl;
186186

fs/lockd/xdr.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ nlm_decode_lock(__be32 *p, struct nlm_lock *lock)
126126
lock->svid = ntohl(*p++);
127127

128128
locks_init_lock(fl);
129-
fl->fl_owner = current->files;
130129
fl->fl_pid = (pid_t)lock->svid;
131130
fl->fl_flags = FL_POSIX;
132131
fl->fl_type = F_RDLCK; /* as good as anything else */

fs/lockd/xdr4.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
118118
lock->svid = ntohl(*p++);
119119

120120
locks_init_lock(fl);
121-
fl->fl_owner = current->files;
122121
fl->fl_pid = (pid_t)lock->svid;
123122
fl->fl_flags = FL_POSIX;
124123
fl->fl_type = F_RDLCK; /* as good as anything else */

include/linux/lockd/lockd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,15 @@ void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
282282
nlm_host_match_fn_t match);
283283
void nlmsvc_grant_reply(struct nlm_cookie *, __be32);
284284
void nlmsvc_release_call(struct nlm_rqst *);
285+
void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
285286

286287
/*
287288
* File handling for the server personality
288289
*/
289290
__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
290291
struct nfs_fh *);
291292
void nlm_release_file(struct nlm_file *);
293+
void nlmsvc_release_lockowner(struct nlm_lock *);
292294
void nlmsvc_mark_resources(struct net *);
293295
void nlmsvc_free_host_resources(struct nlm_host *);
294296
void nlmsvc_invalidate_all(void);

0 commit comments

Comments
 (0)