aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/file.c3
-rw-r--r--fs/gfs2/locking/dlm/plock.c109
-rw-r--r--fs/gfs2/locking/nolock/main.c8
-rw-r--r--fs/gfs2/ops_file.c12
-rw-r--r--fs/lockd/svc4proc.c6
-rw-r--r--fs/lockd/svclock.c275
-rw-r--r--fs/lockd/svcproc.c7
-rw-r--r--fs/lockd/svcsubs.c2
-rw-r--r--fs/locks.c264
-rw-r--r--fs/nfs/file.c7
-rw-r--r--fs/nfs/nfs4proc.c1
-rw-r--r--fs/nfsd/nfs4state.c30
-rw-r--r--include/linux/fcntl.h4
-rw-r--r--include/linux/fs.h9
-rw-r--r--include/linux/lockd/lockd.h14
15 files changed, 546 insertions, 205 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2fd06927e851..acfad65a6e8e 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -738,8 +738,7 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
738 738
739 if (cmd == F_GETLK) { 739 if (cmd == F_GETLK) {
740 if (fc->no_lock) { 740 if (fc->no_lock) {
741 if (!posix_test_lock(file, fl, fl)) 741 posix_test_lock(file, fl);
742 fl->fl_type = F_UNLCK;
743 err = 0; 742 err = 0;
744 } else 743 } else
745 err = fuse_getlk(file, fl); 744 err = fuse_getlk(file, fl);
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
index 1dd4215b83d0..f82495e18c2d 100644
--- a/fs/gfs2/locking/dlm/plock.c
+++ b/fs/gfs2/locking/dlm/plock.c
@@ -25,6 +25,15 @@ struct plock_op {
25 struct gdlm_plock_info info; 25 struct gdlm_plock_info info;
26}; 26};
27 27
28struct plock_xop {
29 struct plock_op xop;
30 void *callback;
31 void *fl;
32 void *file;
33 struct file_lock flc;
34};
35
36
28static inline void set_version(struct gdlm_plock_info *info) 37static inline void set_version(struct gdlm_plock_info *info)
29{ 38{
30 info->version[0] = GDLM_PLOCK_VERSION_MAJOR; 39 info->version[0] = GDLM_PLOCK_VERSION_MAJOR;
@@ -64,12 +73,14 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
64{ 73{
65 struct gdlm_ls *ls = lockspace; 74 struct gdlm_ls *ls = lockspace;
66 struct plock_op *op; 75 struct plock_op *op;
76 struct plock_xop *xop;
67 int rv; 77 int rv;
68 78
69 op = kzalloc(sizeof(*op), GFP_KERNEL); 79 xop = kzalloc(sizeof(*xop), GFP_KERNEL);
70 if (!op) 80 if (!xop)
71 return -ENOMEM; 81 return -ENOMEM;
72 82
83 op = &xop->xop;
73 op->info.optype = GDLM_PLOCK_OP_LOCK; 84 op->info.optype = GDLM_PLOCK_OP_LOCK;
74 op->info.pid = fl->fl_pid; 85 op->info.pid = fl->fl_pid;
75 op->info.ex = (fl->fl_type == F_WRLCK); 86 op->info.ex = (fl->fl_type == F_WRLCK);
@@ -79,9 +90,21 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
79 op->info.start = fl->fl_start; 90 op->info.start = fl->fl_start;
80 op->info.end = fl->fl_end; 91 op->info.end = fl->fl_end;
81 op->info.owner = (__u64)(long) fl->fl_owner; 92 op->info.owner = (__u64)(long) fl->fl_owner;
93 if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
94 xop->callback = fl->fl_lmops->fl_grant;
95 locks_init_lock(&xop->flc);
96 locks_copy_lock(&xop->flc, fl);
97 xop->fl = fl;
98 xop->file = file;
99 } else
100 xop->callback = NULL;
82 101
83 send_op(op); 102 send_op(op);
84 wait_event(recv_wq, (op->done != 0)); 103
104 if (xop->callback == NULL)
105 wait_event(recv_wq, (op->done != 0));
106 else
107 return -EINPROGRESS;
85 108
86 spin_lock(&ops_lock); 109 spin_lock(&ops_lock);
87 if (!list_empty(&op->list)) { 110 if (!list_empty(&op->list)) {
@@ -99,7 +122,63 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
99 (unsigned long long)name->ln_number); 122 (unsigned long long)name->ln_number);
100 } 123 }
101 124
102 kfree(op); 125 kfree(xop);
126 return rv;
127}
128
129/* Returns failure iff a succesful lock operation should be canceled */
130static int gdlm_plock_callback(struct plock_op *op)
131{
132 struct file *file;
133 struct file_lock *fl;
134 struct file_lock *flc;
135 int (*notify)(void *, void *, int) = NULL;
136 struct plock_xop *xop = (struct plock_xop *)op;
137 int rv = 0;
138
139 spin_lock(&ops_lock);
140 if (!list_empty(&op->list)) {
141 printk(KERN_INFO "plock op on list\n");
142 list_del(&op->list);
143 }
144 spin_unlock(&ops_lock);
145
146 /* check if the following 2 are still valid or make a copy */
147 file = xop->file;
148 flc = &xop->flc;
149 fl = xop->fl;
150 notify = xop->callback;
151
152 if (op->info.rv) {
153 notify(flc, NULL, op->info.rv);
154 goto out;
155 }
156
157 /* got fs lock; bookkeep locally as well: */
158 flc->fl_flags &= ~FL_SLEEP;
159 if (posix_lock_file(file, flc, NULL)) {
160 /*
161 * This can only happen in the case of kmalloc() failure.
162 * The filesystem's own lock is the authoritative lock,
163 * so a failure to get the lock locally is not a disaster.
164 * As long as GFS cannot reliably cancel locks (especially
165 * in a low-memory situation), we're better off ignoring
166 * this failure than trying to recover.
167 */
168 log_error("gdlm_plock: vfs lock error file %p fl %p",
169 file, fl);
170 }
171
172 rv = notify(flc, NULL, 0);
173 if (rv) {
174 /* XXX: We need to cancel the fs lock here: */
175 printk("gfs2 lock granted after lock request failed;"
176 " dangling lock!\n");
177 goto out;
178 }
179
180out:
181 kfree(xop);
103 return rv; 182 return rv;
104} 183}
105 184
@@ -138,6 +217,9 @@ int gdlm_punlock(void *lockspace, struct lm_lockname *name,
138 217
139 rv = op->info.rv; 218 rv = op->info.rv;
140 219
220 if (rv == -ENOENT)
221 rv = 0;
222
141 kfree(op); 223 kfree(op);
142 return rv; 224 return rv;
143} 225}
@@ -161,6 +243,7 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
161 op->info.start = fl->fl_start; 243 op->info.start = fl->fl_start;
162 op->info.end = fl->fl_end; 244 op->info.end = fl->fl_end;
163 245
246
164 send_op(op); 247 send_op(op);
165 wait_event(recv_wq, (op->done != 0)); 248 wait_event(recv_wq, (op->done != 0));
166 249
@@ -173,9 +256,10 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
173 256
174 rv = op->info.rv; 257 rv = op->info.rv;
175 258
176 if (rv == 0) 259 fl->fl_type = F_UNLCK;
177 fl->fl_type = F_UNLCK; 260 if (rv == -ENOENT)
178 else if (rv > 0) { 261 rv = 0;
262 else if (rv == 0 && op->info.pid != fl->fl_pid) {
179 fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK; 263 fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
180 fl->fl_pid = op->info.pid; 264 fl->fl_pid = op->info.pid;
181 fl->fl_start = op->info.start; 265 fl->fl_start = op->info.start;
@@ -243,9 +327,14 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
243 } 327 }
244 spin_unlock(&ops_lock); 328 spin_unlock(&ops_lock);
245 329
246 if (found) 330 if (found) {
247 wake_up(&recv_wq); 331 struct plock_xop *xop;
248 else 332 xop = (struct plock_xop *)op;
333 if (xop->callback)
334 count = gdlm_plock_callback(op);
335 else
336 wake_up(&recv_wq);
337 } else
249 printk(KERN_INFO "gdlm dev_write no op %x %llx\n", info.fsid, 338 printk(KERN_INFO "gdlm dev_write no op %x %llx\n", info.fsid,
250 (unsigned long long)info.number); 339 (unsigned long long)info.number);
251 return count; 340 return count;
diff --git a/fs/gfs2/locking/nolock/main.c b/fs/gfs2/locking/nolock/main.c
index acfbc941f319..5cc1dfa7944a 100644
--- a/fs/gfs2/locking/nolock/main.c
+++ b/fs/gfs2/locking/nolock/main.c
@@ -164,13 +164,7 @@ static void nolock_unhold_lvb(void *lock, char *lvb)
164static int nolock_plock_get(void *lockspace, struct lm_lockname *name, 164static int nolock_plock_get(void *lockspace, struct lm_lockname *name,
165 struct file *file, struct file_lock *fl) 165 struct file *file, struct file_lock *fl)
166{ 166{
167 struct file_lock tmp; 167 posix_test_lock(file, fl);
168 int ret;
169
170 ret = posix_test_lock(file, fl, &tmp);
171 fl->fl_type = F_UNLCK;
172 if (ret)
173 memcpy(fl, &tmp, sizeof(struct file_lock));
174 168
175 return 0; 169 return 0;
176} 170}
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index b50180e22779..329c4dcdecdb 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -513,18 +513,18 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
513 513
514 if (sdp->sd_args.ar_localflocks) { 514 if (sdp->sd_args.ar_localflocks) {
515 if (IS_GETLK(cmd)) { 515 if (IS_GETLK(cmd)) {
516 struct file_lock tmp; 516 posix_test_lock(file, fl);
517 int ret;
518 ret = posix_test_lock(file, fl, &tmp);
519 fl->fl_type = F_UNLCK;
520 if (ret)
521 memcpy(fl, &tmp, sizeof(struct file_lock));
522 return 0; 517 return 0;
523 } else { 518 } else {
524 return posix_lock_file_wait(file, fl); 519 return posix_lock_file_wait(file, fl);
525 } 520 }
526 } 521 }
527 522
523 if (cmd == F_CANCELLK) {
524 /* Hack: */
525 cmd = F_SETLK;
526 fl->fl_type = F_UNLCK;
527 }
528 if (IS_GETLK(cmd)) 528 if (IS_GETLK(cmd))
529 return gfs2_lm_plock_get(sdp, &name, file, fl); 529 return gfs2_lm_plock_get(sdp, &name, file, fl);
530 else if (fl->fl_type == F_UNLCK) 530 else if (fl->fl_type == F_UNLCK)
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 47a66aa5d55b..bf27b6c6cb6b 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -99,7 +99,9 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
99 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 99 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
100 100
101 /* Now check for conflicting locks */ 101 /* Now check for conflicting locks */
102 resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock); 102 resp->status = nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie);
103 if (resp->status == nlm_drop_reply)
104 return rpc_drop_reply;
103 105
104 dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); 106 dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
105 nlm_release_host(host); 107 nlm_release_host(host);
@@ -143,6 +145,8 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
143 /* Now try to lock the file */ 145 /* Now try to lock the file */
144 resp->status = nlmsvc_lock(rqstp, file, &argp->lock, 146 resp->status = nlmsvc_lock(rqstp, file, &argp->lock,
145 argp->block, &argp->cookie); 147 argp->block, &argp->cookie);
148 if (resp->status == nlm_drop_reply)
149 return rpc_drop_reply;
146 150
147 dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); 151 dprintk("lockd: LOCK status %d\n", ntohl(resp->status));
148 nlm_release_host(host); 152 nlm_release_host(host);
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index cf51f849e76c..b3efa4536cc5 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -173,7 +173,7 @@ found:
173 */ 173 */
174static inline struct nlm_block * 174static inline struct nlm_block *
175nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, 175nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
176 struct nlm_lock *lock, struct nlm_cookie *cookie) 176 struct nlm_lock *lock, struct nlm_cookie *cookie)
177{ 177{
178 struct nlm_block *block; 178 struct nlm_block *block;
179 struct nlm_host *host; 179 struct nlm_host *host;
@@ -210,6 +210,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
210 block->b_daemon = rqstp->rq_server; 210 block->b_daemon = rqstp->rq_server;
211 block->b_host = host; 211 block->b_host = host;
212 block->b_file = file; 212 block->b_file = file;
213 block->b_fl = NULL;
213 file->f_count++; 214 file->f_count++;
214 215
215 /* Add to file's list of blocks */ 216 /* Add to file's list of blocks */
@@ -261,6 +262,7 @@ static void nlmsvc_free_block(struct kref *kref)
261 nlmsvc_freegrantargs(block->b_call); 262 nlmsvc_freegrantargs(block->b_call);
262 nlm_release_call(block->b_call); 263 nlm_release_call(block->b_call);
263 nlm_release_file(block->b_file); 264 nlm_release_file(block->b_file);
265 kfree(block->b_fl);
264 kfree(block); 266 kfree(block);
265} 267}
266 268
@@ -331,6 +333,31 @@ static void nlmsvc_freegrantargs(struct nlm_rqst *call)
331} 333}
332 334
333/* 335/*
336 * Deferred lock request handling for non-blocking lock
337 */
338static u32
339nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block)
340{
341 u32 status = nlm_lck_denied_nolocks;
342
343 block->b_flags |= B_QUEUED;
344
345 nlmsvc_insert_block(block, NLM_TIMEOUT);
346
347 block->b_cache_req = &rqstp->rq_chandle;
348 if (rqstp->rq_chandle.defer) {
349 block->b_deferred_req =
350 rqstp->rq_chandle.defer(block->b_cache_req);
351 if (block->b_deferred_req != NULL)
352 status = nlm_drop_reply;
353 }
354 dprintk("lockd: nlmsvc_defer_lock_rqst block %p flags %d status %d\n",
355 block, block->b_flags, status);
356
357 return status;
358}
359
360/*
334 * Attempt to establish a lock, and if it can't be granted, block it 361 * Attempt to establish a lock, and if it can't be granted, block it
335 * if required. 362 * if required.
336 */ 363 */
@@ -338,7 +365,7 @@ __be32
338nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, 365nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
339 struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) 366 struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
340{ 367{
341 struct nlm_block *block, *newblock = NULL; 368 struct nlm_block *block = NULL;
342 int error; 369 int error;
343 __be32 ret; 370 __be32 ret;
344 371
@@ -351,29 +378,58 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
351 wait); 378 wait);
352 379
353 380
354 lock->fl.fl_flags &= ~FL_SLEEP;
355again:
356 /* Lock file against concurrent access */ 381 /* Lock file against concurrent access */
357 mutex_lock(&file->f_mutex); 382 mutex_lock(&file->f_mutex);
358 /* Get existing block (in case client is busy-waiting) */ 383 /* Get existing block (in case client is busy-waiting)
384 * or create new block
385 */
359 block = nlmsvc_lookup_block(file, lock); 386 block = nlmsvc_lookup_block(file, lock);
360 if (block == NULL) { 387 if (block == NULL) {
361 if (newblock != NULL) 388 block = nlmsvc_create_block(rqstp, file, lock, cookie);
362 lock = &newblock->b_call->a_args.lock; 389 ret = nlm_lck_denied_nolocks;
363 } else 390 if (block == NULL)
391 goto out;
364 lock = &block->b_call->a_args.lock; 392 lock = &block->b_call->a_args.lock;
393 } else
394 lock->fl.fl_flags &= ~FL_SLEEP;
365 395
366 error = posix_lock_file(file->f_file, &lock->fl); 396 if (block->b_flags & B_QUEUED) {
367 lock->fl.fl_flags &= ~FL_SLEEP; 397 dprintk("lockd: nlmsvc_lock deferred block %p flags %d\n",
398 block, block->b_flags);
399 if (block->b_granted) {
400 nlmsvc_unlink_block(block);
401 ret = nlm_granted;
402 goto out;
403 }
404 if (block->b_flags & B_TIMED_OUT) {
405 nlmsvc_unlink_block(block);
406 ret = nlm_lck_denied;
407 goto out;
408 }
409 ret = nlm_drop_reply;
410 goto out;
411 }
368 412
369 dprintk("lockd: posix_lock_file returned %d\n", error); 413 if (!wait)
414 lock->fl.fl_flags &= ~FL_SLEEP;
415 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
416 lock->fl.fl_flags &= ~FL_SLEEP;
370 417
418 dprintk("lockd: vfs_lock_file returned %d\n", error);
371 switch(error) { 419 switch(error) {
372 case 0: 420 case 0:
373 ret = nlm_granted; 421 ret = nlm_granted;
374 goto out; 422 goto out;
375 case -EAGAIN: 423 case -EAGAIN:
424 ret = nlm_lck_denied;
376 break; 425 break;
426 case -EINPROGRESS:
427 if (wait)
428 break;
429 /* Filesystem lock operation is in progress
430 Add it to the queue waiting for callback */
431 ret = nlmsvc_defer_lock_rqst(rqstp, block);
432 goto out;
377 case -EDEADLK: 433 case -EDEADLK:
378 ret = nlm_deadlock; 434 ret = nlm_deadlock;
379 goto out; 435 goto out;
@@ -387,26 +443,11 @@ again:
387 goto out; 443 goto out;
388 444
389 ret = nlm_lck_blocked; 445 ret = nlm_lck_blocked;
390 if (block != NULL)
391 goto out;
392
393 /* If we don't have a block, create and initialize it. Then
394 * retry because we may have slept in kmalloc. */
395 /* We have to release f_mutex as nlmsvc_create_block may try to
396 * to claim it while doing host garbage collection */
397 if (newblock == NULL) {
398 mutex_unlock(&file->f_mutex);
399 dprintk("lockd: blocking on this lock (allocating).\n");
400 if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie)))
401 return nlm_lck_denied_nolocks;
402 goto again;
403 }
404 446
405 /* Append to list of blocked */ 447 /* Append to list of blocked */
406 nlmsvc_insert_block(newblock, NLM_NEVER); 448 nlmsvc_insert_block(block, NLM_NEVER);
407out: 449out:
408 mutex_unlock(&file->f_mutex); 450 mutex_unlock(&file->f_mutex);
409 nlmsvc_release_block(newblock);
410 nlmsvc_release_block(block); 451 nlmsvc_release_block(block);
411 dprintk("lockd: nlmsvc_lock returned %u\n", ret); 452 dprintk("lockd: nlmsvc_lock returned %u\n", ret);
412 return ret; 453 return ret;
@@ -416,9 +457,14 @@ out:
416 * Test for presence of a conflicting lock. 457 * Test for presence of a conflicting lock.
417 */ 458 */
418__be32 459__be32
419nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, 460nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
420 struct nlm_lock *conflock) 461 struct nlm_lock *lock, struct nlm_lock *conflock,
462 struct nlm_cookie *cookie)
421{ 463{
464 struct nlm_block *block = NULL;
465 int error;
466 __be32 ret;
467
422 dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", 468 dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
423 file->f_file->f_path.dentry->d_inode->i_sb->s_id, 469 file->f_file->f_path.dentry->d_inode->i_sb->s_id,
424 file->f_file->f_path.dentry->d_inode->i_ino, 470 file->f_file->f_path.dentry->d_inode->i_ino,
@@ -426,19 +472,70 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
426 (long long)lock->fl.fl_start, 472 (long long)lock->fl.fl_start,
427 (long long)lock->fl.fl_end); 473 (long long)lock->fl.fl_end);
428 474
429 if (posix_test_lock(file->f_file, &lock->fl, &conflock->fl)) { 475 /* Get existing block (in case client is busy-waiting) */
430 dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", 476 block = nlmsvc_lookup_block(file, lock);
431 conflock->fl.fl_type, 477
432 (long long)conflock->fl.fl_start, 478 if (block == NULL) {
433 (long long)conflock->fl.fl_end); 479 struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
434 conflock->caller = "somehost"; /* FIXME */ 480
435 conflock->len = strlen(conflock->caller); 481 if (conf == NULL)
436 conflock->oh.len = 0; /* don't return OH info */ 482 return nlm_granted;
437 conflock->svid = conflock->fl.fl_pid; 483 block = nlmsvc_create_block(rqstp, file, lock, cookie);
438 return nlm_lck_denied; 484 if (block == NULL) {
485 kfree(conf);
486 return nlm_granted;
487 }
488 block->b_fl = conf;
489 }
490 if (block->b_flags & B_QUEUED) {
491 dprintk("lockd: nlmsvc_testlock deferred block %p flags %d fl %p\n",
492 block, block->b_flags, block->b_fl);
493 if (block->b_flags & B_TIMED_OUT) {
494 nlmsvc_unlink_block(block);
495 return nlm_lck_denied;
496 }
497 if (block->b_flags & B_GOT_CALLBACK) {
498 if (block->b_fl != NULL
499 && block->b_fl->fl_type != F_UNLCK) {
500 lock->fl = *block->b_fl;
501 goto conf_lock;
502 }
503 else {
504 nlmsvc_unlink_block(block);
505 return nlm_granted;
506 }
507 }
508 return nlm_drop_reply;
439 } 509 }
440 510
441 return nlm_granted; 511 error = vfs_test_lock(file->f_file, &lock->fl);
512 if (error == -EINPROGRESS)
513 return nlmsvc_defer_lock_rqst(rqstp, block);
514 if (error) {
515 ret = nlm_lck_denied_nolocks;
516 goto out;
517 }
518 if (lock->fl.fl_type == F_UNLCK) {
519 ret = nlm_granted;
520 goto out;
521 }
522
523conf_lock:
524 dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
525 lock->fl.fl_type, (long long)lock->fl.fl_start,
526 (long long)lock->fl.fl_end);
527 conflock->caller = "somehost"; /* FIXME */
528 conflock->len = strlen(conflock->caller);
529 conflock->oh.len = 0; /* don't return OH info */
530 conflock->svid = lock->fl.fl_pid;
531 conflock->fl.fl_type = lock->fl.fl_type;
532 conflock->fl.fl_start = lock->fl.fl_start;
533 conflock->fl.fl_end = lock->fl.fl_end;
534 ret = nlm_lck_denied;
535out:
536 if (block)
537 nlmsvc_release_block(block);
538 return ret;
442} 539}
443 540
444/* 541/*
@@ -464,7 +561,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
464 nlmsvc_cancel_blocked(file, lock); 561 nlmsvc_cancel_blocked(file, lock);
465 562
466 lock->fl.fl_type = F_UNLCK; 563 lock->fl.fl_type = F_UNLCK;
467 error = posix_lock_file(file->f_file, &lock->fl); 564 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
468 565
469 return (error < 0)? nlm_lck_denied_nolocks : nlm_granted; 566 return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
470} 567}
@@ -493,6 +590,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
493 block = nlmsvc_lookup_block(file, lock); 590 block = nlmsvc_lookup_block(file, lock);
494 mutex_unlock(&file->f_mutex); 591 mutex_unlock(&file->f_mutex);
495 if (block != NULL) { 592 if (block != NULL) {
593 vfs_cancel_lock(block->b_file->f_file,
594 &block->b_call->a_args.lock.fl);
496 status = nlmsvc_unlink_block(block); 595 status = nlmsvc_unlink_block(block);
497 nlmsvc_release_block(block); 596 nlmsvc_release_block(block);
498 } 597 }
@@ -500,6 +599,63 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
500} 599}
501 600
502/* 601/*
602 * This is a callback from the filesystem for VFS file lock requests.
603 * It will be used if fl_grant is defined and the filesystem can not
604 * respond to the request immediately.
605 * For GETLK request it will copy the reply to the nlm_block.
606 * For SETLK or SETLKW request it will get the local posix lock.
607 * In all cases it will move the block to the head of nlm_blocked q where
608 * nlmsvc_retry_blocked() can send back a reply for SETLKW or revisit the
609 * deferred rpc for GETLK and SETLK.
610 */
611static void
612nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf,
613 int result)
614{
615 block->b_flags |= B_GOT_CALLBACK;
616 if (result == 0)
617 block->b_granted = 1;
618 else
619 block->b_flags |= B_TIMED_OUT;
620 if (conf) {
621 if (block->b_fl)
622 locks_copy_lock(block->b_fl, conf);
623 }
624}
625
626static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf,
627 int result)
628{
629 struct nlm_block *block;
630 int rc = -ENOENT;
631
632 lock_kernel();
633 list_for_each_entry(block, &nlm_blocked, b_list) {
634 if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
635 dprintk("lockd: nlmsvc_notify_blocked block %p flags %d\n",
636 block, block->b_flags);
637 if (block->b_flags & B_QUEUED) {
638 if (block->b_flags & B_TIMED_OUT) {
639 rc = -ENOLCK;
640 break;
641 }
642 nlmsvc_update_deferred_block(block, conf, result);
643 } else if (result == 0)
644 block->b_granted = 1;
645
646 nlmsvc_insert_block(block, 0);
647 svc_wake_up(block->b_daemon);
648 rc = 0;
649 break;
650 }
651 }
652 unlock_kernel();
653 if (rc == -ENOENT)
654 printk(KERN_WARNING "lockd: grant for unknown block\n");
655 return rc;
656}
657
658/*
503 * Unblock a blocked lock request. This is a callback invoked from the 659 * Unblock a blocked lock request. This is a callback invoked from the
504 * VFS layer when a lock on which we blocked is removed. 660 * VFS layer when a lock on which we blocked is removed.
505 * 661 *
@@ -531,6 +687,7 @@ static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2)
531struct lock_manager_operations nlmsvc_lock_operations = { 687struct lock_manager_operations nlmsvc_lock_operations = {
532 .fl_compare_owner = nlmsvc_same_owner, 688 .fl_compare_owner = nlmsvc_same_owner,
533 .fl_notify = nlmsvc_notify_blocked, 689 .fl_notify = nlmsvc_notify_blocked,
690 .fl_grant = nlmsvc_grant_deferred,
534}; 691};
535 692
536/* 693/*
@@ -553,6 +710,8 @@ nlmsvc_grant_blocked(struct nlm_block *block)
553 710
554 dprintk("lockd: grant blocked lock %p\n", block); 711 dprintk("lockd: grant blocked lock %p\n", block);
555 712
713 kref_get(&block->b_count);
714
556 /* Unlink block request from list */ 715 /* Unlink block request from list */
557 nlmsvc_unlink_block(block); 716 nlmsvc_unlink_block(block);
558 717
@@ -566,20 +725,23 @@ nlmsvc_grant_blocked(struct nlm_block *block)
566 725
567 /* Try the lock operation again */ 726 /* Try the lock operation again */
568 lock->fl.fl_flags |= FL_SLEEP; 727 lock->fl.fl_flags |= FL_SLEEP;
569 error = posix_lock_file(file->f_file, &lock->fl); 728 error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
570 lock->fl.fl_flags &= ~FL_SLEEP; 729 lock->fl.fl_flags &= ~FL_SLEEP;
571 730
572 switch (error) { 731 switch (error) {
573 case 0: 732 case 0:
574 break; 733 break;
575 case -EAGAIN: 734 case -EAGAIN:
576 dprintk("lockd: lock still blocked\n"); 735 case -EINPROGRESS:
736 dprintk("lockd: lock still blocked error %d\n", error);
577 nlmsvc_insert_block(block, NLM_NEVER); 737 nlmsvc_insert_block(block, NLM_NEVER);
738 nlmsvc_release_block(block);
578 return; 739 return;
579 default: 740 default:
580 printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", 741 printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
581 -error, __FUNCTION__); 742 -error, __FUNCTION__);
582 nlmsvc_insert_block(block, 10 * HZ); 743 nlmsvc_insert_block(block, 10 * HZ);
744 nlmsvc_release_block(block);
583 return; 745 return;
584 } 746 }
585 747
@@ -592,7 +754,6 @@ callback:
592 nlmsvc_insert_block(block, 30 * HZ); 754 nlmsvc_insert_block(block, 30 * HZ);
593 755
594 /* Call the client */ 756 /* Call the client */
595 kref_get(&block->b_count);
596 nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops); 757 nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops);
597} 758}
598 759
@@ -665,6 +826,23 @@ nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
665 nlmsvc_release_block(block); 826 nlmsvc_release_block(block);
666} 827}
667 828
829/* Helper function to handle retry of a deferred block.
830 * If it is a blocking lock, call grant_blocked.
831 * For a non-blocking lock or test lock, revisit the request.
832 */
833static void
834retry_deferred_block(struct nlm_block *block)
835{
836 if (!(block->b_flags & B_GOT_CALLBACK))
837 block->b_flags |= B_TIMED_OUT;
838 nlmsvc_insert_block(block, NLM_TIMEOUT);
839 dprintk("revisit block %p flags %d\n", block, block->b_flags);
840 if (block->b_deferred_req) {
841 block->b_deferred_req->revisit(block->b_deferred_req, 0);
842 block->b_deferred_req = NULL;
843 }
844}
845
668/* 846/*
669 * Retry all blocked locks that have been notified. This is where lockd 847 * Retry all blocked locks that have been notified. This is where lockd
670 * picks up locks that can be granted, or grant notifications that must 848 * picks up locks that can be granted, or grant notifications that must
@@ -688,9 +866,12 @@ nlmsvc_retry_blocked(void)
688 866
689 dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", 867 dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
690 block, block->b_when); 868 block, block->b_when);
691 kref_get(&block->b_count); 869 if (block->b_flags & B_QUEUED) {
692 nlmsvc_grant_blocked(block); 870 dprintk("nlmsvc_retry_blocked delete block (%p, granted=%d, flags=%d)\n",
693 nlmsvc_release_block(block); 871 block, block->b_granted, block->b_flags);
872 retry_deferred_block(block);
873 } else
874 nlmsvc_grant_blocked(block);
694 } 875 }
695 876
696 return timeout; 877 return timeout;
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 31cb48425733..9cd5c8b37593 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -33,6 +33,7 @@ cast_to_nlm(__be32 status, u32 vers)
33 case nlm_lck_denied_nolocks: 33 case nlm_lck_denied_nolocks:
34 case nlm_lck_blocked: 34 case nlm_lck_blocked:
35 case nlm_lck_denied_grace_period: 35 case nlm_lck_denied_grace_period:
36 case nlm_drop_reply:
36 break; 37 break;
37 case nlm4_deadlock: 38 case nlm4_deadlock:
38 status = nlm_lck_denied; 39 status = nlm_lck_denied;
@@ -127,7 +128,9 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
127 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 128 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
128 129
129 /* Now check for conflicting locks */ 130 /* Now check for conflicting locks */
130 resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock)); 131 resp->status = cast_status(nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie));
132 if (resp->status == nlm_drop_reply)
133 return rpc_drop_reply;
131 134
132 dprintk("lockd: TEST status %d vers %d\n", 135 dprintk("lockd: TEST status %d vers %d\n",
133 ntohl(resp->status), rqstp->rq_vers); 136 ntohl(resp->status), rqstp->rq_vers);
@@ -172,6 +175,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
172 /* Now try to lock the file */ 175 /* Now try to lock the file */
173 resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, 176 resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock,
174 argp->block, &argp->cookie)); 177 argp->block, &argp->cookie));
178 if (resp->status == nlm_drop_reply)
179 return rpc_drop_reply;
175 180
176 dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); 181 dprintk("lockd: LOCK status %d\n", ntohl(resp->status));
177 nlm_release_host(host); 182 nlm_release_host(host);
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index c0df00c74ce3..84ebba33b98d 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -182,7 +182,7 @@ again:
182 lock.fl_type = F_UNLCK; 182 lock.fl_type = F_UNLCK;
183 lock.fl_start = 0; 183 lock.fl_start = 0;
184 lock.fl_end = OFFSET_MAX; 184 lock.fl_end = OFFSET_MAX;
185 if (posix_lock_file(file->f_file, &lock) < 0) { 185 if (vfs_lock_file(file->f_file, F_SETLK, &lock, NULL) < 0) {
186 printk("lockd: unlock failure in %s:%d\n", 186 printk("lockd: unlock failure in %s:%d\n",
187 __FILE__, __LINE__); 187 __FILE__, __LINE__);
188 return 1; 188 return 1;
diff --git a/fs/locks.c b/fs/locks.c
index 325578074742..671a034dc999 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -665,11 +665,11 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
665} 665}
666 666
667int 667int
668posix_test_lock(struct file *filp, struct file_lock *fl, 668posix_test_lock(struct file *filp, struct file_lock *fl)
669 struct file_lock *conflock)
670{ 669{
671 struct file_lock *cfl; 670 struct file_lock *cfl;
672 671
672 fl->fl_type = F_UNLCK;
673 lock_kernel(); 673 lock_kernel();
674 for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) { 674 for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
675 if (!IS_POSIX(cfl)) 675 if (!IS_POSIX(cfl))
@@ -678,7 +678,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl,
678 break; 678 break;
679 } 679 }
680 if (cfl) { 680 if (cfl) {
681 __locks_copy_lock(conflock, cfl); 681 __locks_copy_lock(fl, cfl);
682 unlock_kernel(); 682 unlock_kernel();
683 return 1; 683 return 1;
684 } 684 }
@@ -800,7 +800,7 @@ out:
800 return error; 800 return error;
801} 801}
802 802
803static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) 803static int __posix_lock_file(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
804{ 804{
805 struct file_lock *fl; 805 struct file_lock *fl;
806 struct file_lock *new_fl = NULL; 806 struct file_lock *new_fl = NULL;
@@ -1006,6 +1006,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
1006 * posix_lock_file - Apply a POSIX-style lock to a file 1006 * posix_lock_file - Apply a POSIX-style lock to a file
1007 * @filp: The file to apply the lock to 1007 * @filp: The file to apply the lock to
1008 * @fl: The lock to be applied 1008 * @fl: The lock to be applied
1009 * @conflock: Place to return a copy of the conflicting lock, if found.
1009 * 1010 *
1010 * Add a POSIX style lock to a file. 1011 * Add a POSIX style lock to a file.
1011 * We merge adjacent & overlapping locks whenever possible. 1012 * We merge adjacent & overlapping locks whenever possible.
@@ -1015,26 +1016,12 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
1015 * whether or not a lock was successfully freed by testing the return 1016 * whether or not a lock was successfully freed by testing the return
1016 * value for -ENOENT. 1017 * value for -ENOENT.
1017 */ 1018 */
1018int posix_lock_file(struct file *filp, struct file_lock *fl) 1019int posix_lock_file(struct file *filp, struct file_lock *fl,
1019{
1020 return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL);
1021}
1022EXPORT_SYMBOL(posix_lock_file);
1023
1024/**
1025 * posix_lock_file_conf - Apply a POSIX-style lock to a file
1026 * @filp: The file to apply the lock to
1027 * @fl: The lock to be applied
1028 * @conflock: Place to return a copy of the conflicting lock, if found.
1029 *
1030 * Except for the conflock parameter, acts just like posix_lock_file.
1031 */
1032int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
1033 struct file_lock *conflock) 1020 struct file_lock *conflock)
1034{ 1021{
1035 return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock); 1022 return __posix_lock_file(filp->f_path.dentry->d_inode, fl, conflock);
1036} 1023}
1037EXPORT_SYMBOL(posix_lock_file_conf); 1024EXPORT_SYMBOL(posix_lock_file);
1038 1025
1039/** 1026/**
1040 * posix_lock_file_wait - Apply a POSIX-style lock to a file 1027 * posix_lock_file_wait - Apply a POSIX-style lock to a file
@@ -1050,7 +1037,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
1050 int error; 1037 int error;
1051 might_sleep (); 1038 might_sleep ();
1052 for (;;) { 1039 for (;;) {
1053 error = posix_lock_file(filp, fl); 1040 error = posix_lock_file(filp, fl, NULL);
1054 if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) 1041 if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
1055 break; 1042 break;
1056 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); 1043 error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
@@ -1122,7 +1109,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
1122 fl.fl_end = offset + count - 1; 1109 fl.fl_end = offset + count - 1;
1123 1110
1124 for (;;) { 1111 for (;;) {
1125 error = __posix_lock_file_conf(inode, &fl, NULL); 1112 error = __posix_lock_file(inode, &fl, NULL);
1126 if (error != -EAGAIN) 1113 if (error != -EAGAIN)
1127 break; 1114 break;
1128 if (!(fl.fl_flags & FL_SLEEP)) 1115 if (!(fl.fl_flags & FL_SLEEP))
@@ -1610,12 +1597,62 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
1610 return error; 1597 return error;
1611} 1598}
1612 1599
1600/**
1601 * vfs_test_lock - test file byte range lock
1602 * @filp: The file to test lock for
1603 * @fl: The lock to test
1604 * @conf: Place to return a copy of the conflicting lock, if found
1605 *
1606 * Returns -ERRNO on failure. Indicates presence of conflicting lock by
1607 * setting conf->fl_type to something other than F_UNLCK.
1608 */
1609int vfs_test_lock(struct file *filp, struct file_lock *fl)
1610{
1611 if (filp->f_op && filp->f_op->lock)
1612 return filp->f_op->lock(filp, F_GETLK, fl);
1613 posix_test_lock(filp, fl);
1614 return 0;
1615}
1616EXPORT_SYMBOL_GPL(vfs_test_lock);
1617
1618static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
1619{
1620 flock->l_pid = fl->fl_pid;
1621#if BITS_PER_LONG == 32
1622 /*
1623 * Make sure we can represent the posix lock via
1624 * legacy 32bit flock.
1625 */
1626 if (fl->fl_start > OFFT_OFFSET_MAX)
1627 return -EOVERFLOW;
1628 if (fl->fl_end != OFFSET_MAX && fl->fl_end > OFFT_OFFSET_MAX)
1629 return -EOVERFLOW;
1630#endif
1631 flock->l_start = fl->fl_start;
1632 flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
1633 fl->fl_end - fl->fl_start + 1;
1634 flock->l_whence = 0;
1635 return 0;
1636}
1637
1638#if BITS_PER_LONG == 32
1639static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
1640{
1641 flock->l_pid = fl->fl_pid;
1642 flock->l_start = fl->fl_start;
1643 flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
1644 fl->fl_end - fl->fl_start + 1;
1645 flock->l_whence = 0;
1646 flock->l_type = fl->fl_type;
1647}
1648#endif
1649
1613/* Report the first existing lock that would conflict with l. 1650/* Report the first existing lock that would conflict with l.
1614 * This implements the F_GETLK command of fcntl(). 1651 * This implements the F_GETLK command of fcntl().
1615 */ 1652 */
1616int fcntl_getlk(struct file *filp, struct flock __user *l) 1653int fcntl_getlk(struct file *filp, struct flock __user *l)
1617{ 1654{
1618 struct file_lock *fl, cfl, file_lock; 1655 struct file_lock file_lock;
1619 struct flock flock; 1656 struct flock flock;
1620 int error; 1657 int error;
1621 1658
@@ -1630,38 +1667,15 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
1630 if (error) 1667 if (error)
1631 goto out; 1668 goto out;
1632 1669
1633 if (filp->f_op && filp->f_op->lock) { 1670 error = vfs_test_lock(filp, &file_lock);
1634 error = filp->f_op->lock(filp, F_GETLK, &file_lock); 1671 if (error)
1635 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) 1672 goto out;
1636 file_lock.fl_ops->fl_release_private(&file_lock);
1637 if (error < 0)
1638 goto out;
1639 else
1640 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
1641 } else {
1642 fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
1643 }
1644 1673
1645 flock.l_type = F_UNLCK; 1674 flock.l_type = file_lock.fl_type;
1646 if (fl != NULL) { 1675 if (file_lock.fl_type != F_UNLCK) {
1647 flock.l_pid = fl->fl_pid; 1676 error = posix_lock_to_flock(&flock, &file_lock);
1648#if BITS_PER_LONG == 32 1677 if (error)
1649 /*
1650 * Make sure we can represent the posix lock via
1651 * legacy 32bit flock.
1652 */
1653 error = -EOVERFLOW;
1654 if (fl->fl_start > OFFT_OFFSET_MAX)
1655 goto out;
1656 if ((fl->fl_end != OFFSET_MAX)
1657 && (fl->fl_end > OFFT_OFFSET_MAX))
1658 goto out; 1678 goto out;
1659#endif
1660 flock.l_start = fl->fl_start;
1661 flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
1662 fl->fl_end - fl->fl_start + 1;
1663 flock.l_whence = 0;
1664 flock.l_type = fl->fl_type;
1665 } 1679 }
1666 error = -EFAULT; 1680 error = -EFAULT;
1667 if (!copy_to_user(l, &flock, sizeof(flock))) 1681 if (!copy_to_user(l, &flock, sizeof(flock)))
@@ -1670,6 +1684,48 @@ out:
1670 return error; 1684 return error;
1671} 1685}
1672 1686
1687/**
1688 * vfs_lock_file - file byte range lock
1689 * @filp: The file to apply the lock to
1690 * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.)
1691 * @fl: The lock to be applied
1692 * @conf: Place to return a copy of the conflicting lock, if found.
1693 *
1694 * A caller that doesn't care about the conflicting lock may pass NULL
1695 * as the final argument.
1696 *
1697 * If the filesystem defines a private ->lock() method, then @conf will
1698 * be left unchanged; so a caller that cares should initialize it to
1699 * some acceptable default.
1700 *
1701 * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX
1702 * locks, the ->lock() interface may return asynchronously, before the lock has
1703 * been granted or denied by the underlying filesystem, if (and only if)
1704 * fl_grant is set. Callers expecting ->lock() to return asynchronously
1705 * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
1706 * the request is for a blocking lock. When ->lock() does return asynchronously,
1707 * it must return -EINPROGRESS, and call ->fl_grant() when the lock
1708 * request completes.
1709 * If the request is for non-blocking lock the file system should return
1710 * -EINPROGRESS then try to get the lock and call the callback routine with
1711 * the result. If the request timed out the callback routine will return a
1712 * nonzero return code and the file system should release the lock. The file
1713 * system is also responsible to keep a corresponding posix lock when it
1714 * grants a lock so the VFS can find out which locks are locally held and do
1715 * the correct lock cleanup when required.
1716 * The underlying filesystem must not drop the kernel lock or call
1717 * ->fl_grant() before returning to the caller with a -EINPROGRESS
1718 * return code.
1719 */
1720int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
1721{
1722 if (filp->f_op && filp->f_op->lock)
1723 return filp->f_op->lock(filp, cmd, fl);
1724 else
1725 return posix_lock_file(filp, fl, conf);
1726}
1727EXPORT_SYMBOL_GPL(vfs_lock_file);
1728
1673/* Apply the lock described by l to an open file descriptor. 1729/* Apply the lock described by l to an open file descriptor.
1674 * This implements both the F_SETLK and F_SETLKW commands of fcntl(). 1730 * This implements both the F_SETLK and F_SETLKW commands of fcntl().
1675 */ 1731 */
@@ -1732,21 +1788,17 @@ again:
1732 if (error) 1788 if (error)
1733 goto out; 1789 goto out;
1734 1790
1735 if (filp->f_op && filp->f_op->lock != NULL) 1791 for (;;) {
1736 error = filp->f_op->lock(filp, cmd, file_lock); 1792 error = vfs_lock_file(filp, cmd, file_lock, NULL);
1737 else { 1793 if (error != -EAGAIN || cmd == F_SETLK)
1738 for (;;) {
1739 error = posix_lock_file(filp, file_lock);
1740 if ((error != -EAGAIN) || (cmd == F_SETLK))
1741 break;
1742 error = wait_event_interruptible(file_lock->fl_wait,
1743 !file_lock->fl_next);
1744 if (!error)
1745 continue;
1746
1747 locks_delete_block(file_lock);
1748 break; 1794 break;
1749 } 1795 error = wait_event_interruptible(file_lock->fl_wait,
1796 !file_lock->fl_next);
1797 if (!error)
1798 continue;
1799
1800 locks_delete_block(file_lock);
1801 break;
1750 } 1802 }
1751 1803
1752 /* 1804 /*
@@ -1769,7 +1821,7 @@ out:
1769 */ 1821 */
1770int fcntl_getlk64(struct file *filp, struct flock64 __user *l) 1822int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
1771{ 1823{
1772 struct file_lock *fl, cfl, file_lock; 1824 struct file_lock file_lock;
1773 struct flock64 flock; 1825 struct flock64 flock;
1774 int error; 1826 int error;
1775 1827
@@ -1784,27 +1836,14 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
1784 if (error) 1836 if (error)
1785 goto out; 1837 goto out;
1786 1838
1787 if (filp->f_op && filp->f_op->lock) { 1839 error = vfs_test_lock(filp, &file_lock);
1788 error = filp->f_op->lock(filp, F_GETLK, &file_lock); 1840 if (error)
1789 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) 1841 goto out;
1790 file_lock.fl_ops->fl_release_private(&file_lock); 1842
1791 if (error < 0) 1843 flock.l_type = file_lock.fl_type;
1792 goto out; 1844 if (file_lock.fl_type != F_UNLCK)
1793 else 1845 posix_lock_to_flock64(&flock, &file_lock);
1794 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); 1846
1795 } else {
1796 fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
1797 }
1798
1799 flock.l_type = F_UNLCK;
1800 if (fl != NULL) {
1801 flock.l_pid = fl->fl_pid;
1802 flock.l_start = fl->fl_start;
1803 flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
1804 fl->fl_end - fl->fl_start + 1;
1805 flock.l_whence = 0;
1806 flock.l_type = fl->fl_type;
1807 }
1808 error = -EFAULT; 1847 error = -EFAULT;
1809 if (!copy_to_user(l, &flock, sizeof(flock))) 1848 if (!copy_to_user(l, &flock, sizeof(flock)))
1810 error = 0; 1849 error = 0;
@@ -1875,21 +1914,17 @@ again:
1875 if (error) 1914 if (error)
1876 goto out; 1915 goto out;
1877 1916
1878 if (filp->f_op && filp->f_op->lock != NULL) 1917 for (;;) {
1879 error = filp->f_op->lock(filp, cmd, file_lock); 1918 error = vfs_lock_file(filp, cmd, file_lock, NULL);
1880 else { 1919 if (error != -EAGAIN || cmd == F_SETLK64)
1881 for (;;) {
1882 error = posix_lock_file(filp, file_lock);
1883 if ((error != -EAGAIN) || (cmd == F_SETLK64))
1884 break;
1885 error = wait_event_interruptible(file_lock->fl_wait,
1886 !file_lock->fl_next);
1887 if (!error)
1888 continue;
1889
1890 locks_delete_block(file_lock);
1891 break; 1920 break;
1892 } 1921 error = wait_event_interruptible(file_lock->fl_wait,
1922 !file_lock->fl_next);
1923 if (!error)
1924 continue;
1925
1926 locks_delete_block(file_lock);
1927 break;
1893 } 1928 }
1894 1929
1895 /* 1930 /*
@@ -1934,10 +1969,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
1934 lock.fl_ops = NULL; 1969 lock.fl_ops = NULL;
1935 lock.fl_lmops = NULL; 1970 lock.fl_lmops = NULL;
1936 1971
1937 if (filp->f_op && filp->f_op->lock != NULL) 1972 vfs_lock_file(filp, F_SETLK, &lock, NULL);
1938 filp->f_op->lock(filp, F_SETLK, &lock);
1939 else
1940 posix_lock_file(filp, &lock);
1941 1973
1942 if (lock.fl_ops && lock.fl_ops->fl_release_private) 1974 if (lock.fl_ops && lock.fl_ops->fl_release_private)
1943 lock.fl_ops->fl_release_private(&lock); 1975 lock.fl_ops->fl_release_private(&lock);
@@ -2014,6 +2046,22 @@ posix_unblock_lock(struct file *filp, struct file_lock *waiter)
2014 2046
2015EXPORT_SYMBOL(posix_unblock_lock); 2047EXPORT_SYMBOL(posix_unblock_lock);
2016 2048
2049/**
2050 * vfs_cancel_lock - file byte range unblock lock
2051 * @filp: The file to apply the unblock to
2052 * @fl: The lock to be unblocked
2053 *
2054 * Used by lock managers to cancel blocked requests
2055 */
2056int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
2057{
2058 if (filp->f_op && filp->f_op->lock)
2059 return filp->f_op->lock(filp, F_CANCELLK, fl);
2060 return 0;
2061}
2062
2063EXPORT_SYMBOL_GPL(vfs_cancel_lock);
2064
2017static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) 2065static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
2018{ 2066{
2019 struct inode *inode = NULL; 2067 struct inode *inode = NULL;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 8e66b5a2d490..5eaee6dd040b 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -391,17 +391,12 @@ out_swapfile:
391 391
392static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) 392static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
393{ 393{
394 struct file_lock cfl;
395 struct inode *inode = filp->f_mapping->host; 394 struct inode *inode = filp->f_mapping->host;
396 int status = 0; 395 int status = 0;
397 396
398 lock_kernel(); 397 lock_kernel();
399 /* Try local locking first */ 398 /* Try local locking first */
400 if (posix_test_lock(filp, fl, &cfl)) { 399 if (posix_test_lock(filp, fl)) {
401 fl->fl_start = cfl.fl_start;
402 fl->fl_end = cfl.fl_end;
403 fl->fl_type = cfl.fl_type;
404 fl->fl_pid = cfl.fl_pid;
405 goto out; 400 goto out;
406 } 401 }
407 402
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3b5ca1b15fe9..d6a30e965787 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3017,6 +3017,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
3017 case -NFS4ERR_DENIED: 3017 case -NFS4ERR_DENIED:
3018 status = 0; 3018 status = 0;
3019 } 3019 }
3020 request->fl_ops->fl_release_private(request);
3020out: 3021out:
3021 up_read(&clp->cl_sem); 3022 up_read(&clp->cl_sem);
3022 return status; 3023 return status;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index af360705e551..678f3be88ac0 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -50,6 +50,7 @@
50#include <linux/nfsd/xdr4.h> 50#include <linux/nfsd/xdr4.h>
51#include <linux/namei.h> 51#include <linux/namei.h>
52#include <linux/mutex.h> 52#include <linux/mutex.h>
53#include <linux/lockd/bind.h>
53 54
54#define NFSDDBG_FACILITY NFSDDBG_PROC 55#define NFSDDBG_FACILITY NFSDDBG_PROC
55 56
@@ -2657,6 +2658,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2657 struct file_lock conflock; 2658 struct file_lock conflock;
2658 __be32 status = 0; 2659 __be32 status = 0;
2659 unsigned int strhashval; 2660 unsigned int strhashval;
2661 unsigned int cmd;
2660 int err; 2662 int err;
2661 2663
2662 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", 2664 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
@@ -2739,10 +2741,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2739 case NFS4_READ_LT: 2741 case NFS4_READ_LT:
2740 case NFS4_READW_LT: 2742 case NFS4_READW_LT:
2741 file_lock.fl_type = F_RDLCK; 2743 file_lock.fl_type = F_RDLCK;
2744 cmd = F_SETLK;
2742 break; 2745 break;
2743 case NFS4_WRITE_LT: 2746 case NFS4_WRITE_LT:
2744 case NFS4_WRITEW_LT: 2747 case NFS4_WRITEW_LT:
2745 file_lock.fl_type = F_WRLCK; 2748 file_lock.fl_type = F_WRLCK;
2749 cmd = F_SETLK;
2746 break; 2750 break;
2747 default: 2751 default:
2748 status = nfserr_inval; 2752 status = nfserr_inval;
@@ -2769,9 +2773,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2769 2773
2770 /* XXX?: Just to divert the locks_release_private at the start of 2774 /* XXX?: Just to divert the locks_release_private at the start of
2771 * locks_copy_lock: */ 2775 * locks_copy_lock: */
2772 conflock.fl_ops = NULL; 2776 locks_init_lock(&conflock);
2773 conflock.fl_lmops = NULL; 2777 err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
2774 err = posix_lock_file_conf(filp, &file_lock, &conflock);
2775 switch (-err) { 2778 switch (-err) {
2776 case 0: /* success! */ 2779 case 0: /* success! */
2777 update_stateid(&lock_stp->st_stateid); 2780 update_stateid(&lock_stp->st_stateid);
@@ -2788,7 +2791,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2788 status = nfserr_deadlock; 2791 status = nfserr_deadlock;
2789 break; 2792 break;
2790 default: 2793 default:
2791 dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",err); 2794 dprintk("NFSD: nfsd4_lock: vfs_lock_file() failed! status %d\n",err);
2792 status = nfserr_resource; 2795 status = nfserr_resource;
2793 break; 2796 break;
2794 } 2797 }
@@ -2813,7 +2816,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2813 struct inode *inode; 2816 struct inode *inode;
2814 struct file file; 2817 struct file file;
2815 struct file_lock file_lock; 2818 struct file_lock file_lock;
2816 struct file_lock conflock; 2819 int error;
2817 __be32 status; 2820 __be32 status;
2818 2821
2819 if (nfs4_in_grace()) 2822 if (nfs4_in_grace())
@@ -2869,18 +2872,23 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2869 2872
2870 nfs4_transform_lock_offset(&file_lock); 2873 nfs4_transform_lock_offset(&file_lock);
2871 2874
2872 /* posix_test_lock uses the struct file _only_ to resolve the inode. 2875 /* vfs_test_lock uses the struct file _only_ to resolve the inode.
2873 * since LOCKT doesn't require an OPEN, and therefore a struct 2876 * since LOCKT doesn't require an OPEN, and therefore a struct
2874 * file may not exist, pass posix_test_lock a struct file with 2877 * file may not exist, pass vfs_test_lock a struct file with
2875 * only the dentry:inode set. 2878 * only the dentry:inode set.
2876 */ 2879 */
2877 memset(&file, 0, sizeof (struct file)); 2880 memset(&file, 0, sizeof (struct file));
2878 file.f_path.dentry = cstate->current_fh.fh_dentry; 2881 file.f_path.dentry = cstate->current_fh.fh_dentry;
2879 2882
2880 status = nfs_ok; 2883 status = nfs_ok;
2881 if (posix_test_lock(&file, &file_lock, &conflock)) { 2884 error = vfs_test_lock(&file, &file_lock);
2885 if (error) {
2886 status = nfserrno(error);
2887 goto out;
2888 }
2889 if (file_lock.fl_type != F_UNLCK) {
2882 status = nfserr_denied; 2890 status = nfserr_denied;
2883 nfs4_set_lock_denied(&conflock, &lockt->lt_denied); 2891 nfs4_set_lock_denied(&file_lock, &lockt->lt_denied);
2884 } 2892 }
2885out: 2893out:
2886 nfs4_unlock_state(); 2894 nfs4_unlock_state();
@@ -2933,9 +2941,9 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2933 /* 2941 /*
2934 * Try to unlock the file in the VFS. 2942 * Try to unlock the file in the VFS.
2935 */ 2943 */
2936 err = posix_lock_file(filp, &file_lock); 2944 err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL);
2937 if (err) { 2945 if (err) {
2938 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); 2946 dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
2939 goto out_nfserr; 2947 goto out_nfserr;
2940 } 2948 }
2941 /* 2949 /*
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 996f5611cd59..40b93265d4ba 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -3,6 +3,10 @@
3 3
4#include <asm/fcntl.h> 4#include <asm/fcntl.h>
5 5
6/* Cancel a blocking posix lock; internal use only until we expose an
7 * asynchronous lock api to userspace: */
8#define F_CANCELLK (F_LINUX_SPECIFIC_BASE+5)
9
6#define F_SETLEASE (F_LINUX_SPECIFIC_BASE+0) 10#define F_SETLEASE (F_LINUX_SPECIFIC_BASE+0)
7#define F_GETLEASE (F_LINUX_SPECIFIC_BASE+1) 11#define F_GETLEASE (F_LINUX_SPECIFIC_BASE+1)
8 12
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 55a74ffa7e3b..bc6d27cecaac 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -786,6 +786,7 @@ struct file_lock_operations {
786struct lock_manager_operations { 786struct lock_manager_operations {
787 int (*fl_compare_owner)(struct file_lock *, struct file_lock *); 787 int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
788 void (*fl_notify)(struct file_lock *); /* unblock callback */ 788 void (*fl_notify)(struct file_lock *); /* unblock callback */
789 int (*fl_grant)(struct file_lock *, struct file_lock *, int);
789 void (*fl_copy_lock)(struct file_lock *, struct file_lock *); 790 void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
790 void (*fl_release_private)(struct file_lock *); 791 void (*fl_release_private)(struct file_lock *);
791 void (*fl_break)(struct file_lock *); 792 void (*fl_break)(struct file_lock *);
@@ -857,11 +858,13 @@ extern void locks_init_lock(struct file_lock *);
857extern void locks_copy_lock(struct file_lock *, struct file_lock *); 858extern void locks_copy_lock(struct file_lock *, struct file_lock *);
858extern void locks_remove_posix(struct file *, fl_owner_t); 859extern void locks_remove_posix(struct file *, fl_owner_t);
859extern void locks_remove_flock(struct file *); 860extern void locks_remove_flock(struct file *);
860extern int posix_test_lock(struct file *, struct file_lock *, struct file_lock *); 861extern int posix_test_lock(struct file *, struct file_lock *);
861extern int posix_lock_file_conf(struct file *, struct file_lock *, struct file_lock *); 862extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
862extern int posix_lock_file(struct file *, struct file_lock *);
863extern int posix_lock_file_wait(struct file *, struct file_lock *); 863extern int posix_lock_file_wait(struct file *, struct file_lock *);
864extern int posix_unblock_lock(struct file *, struct file_lock *); 864extern int posix_unblock_lock(struct file *, struct file_lock *);
865extern int vfs_test_lock(struct file *, struct file_lock *);
866extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
867extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
865extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); 868extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
866extern int __break_lease(struct inode *inode, unsigned int flags); 869extern int __break_lease(struct inode *inode, unsigned int flags);
867extern void lease_get_mtime(struct inode *, struct timespec *time); 870extern void lease_get_mtime(struct inode *, struct timespec *time);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index f6a81e0b1b93..05707e2fccae 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -119,6 +119,9 @@ struct nlm_file {
119 * couldn't be granted because of a conflicting lock). 119 * couldn't be granted because of a conflicting lock).
120 */ 120 */
121#define NLM_NEVER (~(unsigned long) 0) 121#define NLM_NEVER (~(unsigned long) 0)
122/* timeout on non-blocking call: */
123#define NLM_TIMEOUT (7 * HZ)
124
122struct nlm_block { 125struct nlm_block {
123 struct kref b_count; /* Reference count */ 126 struct kref b_count; /* Reference count */
124 struct list_head b_list; /* linked list of all blocks */ 127 struct list_head b_list; /* linked list of all blocks */
@@ -130,6 +133,13 @@ struct nlm_block {
130 unsigned int b_id; /* block id */ 133 unsigned int b_id; /* block id */
131 unsigned char b_granted; /* VFS granted lock */ 134 unsigned char b_granted; /* VFS granted lock */
132 struct nlm_file * b_file; /* file in question */ 135 struct nlm_file * b_file; /* file in question */
136 struct cache_req * b_cache_req; /* deferred request handling */
137 struct file_lock * b_fl; /* set for GETLK */
138 struct cache_deferred_req * b_deferred_req;
139 unsigned int b_flags; /* block flags */
140#define B_QUEUED 1 /* lock queued */
141#define B_GOT_CALLBACK 2 /* got lock or conflicting lock */
142#define B_TIMED_OUT 4 /* filesystem too slow to respond */
133}; 143};
134 144
135/* 145/*
@@ -185,8 +195,8 @@ typedef int (*nlm_host_match_fn_t)(struct nlm_host *cur, struct nlm_host *ref)
185__be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, 195__be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
186 struct nlm_lock *, int, struct nlm_cookie *); 196 struct nlm_lock *, int, struct nlm_cookie *);
187__be32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); 197__be32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
188__be32 nlmsvc_testlock(struct nlm_file *, struct nlm_lock *, 198__be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *,
189 struct nlm_lock *); 199 struct nlm_lock *, struct nlm_lock *, struct nlm_cookie *);
190__be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *); 200__be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
191unsigned long nlmsvc_retry_blocked(void); 201unsigned long nlmsvc_retry_blocked(void);
192void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, 202void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,