blob: aba36e0b14608740caab854474abad50f9001a48 [file] [log] [blame]
David Howellse8d6c552007-07-15 23:40:12 -07001/* AFS file locking support
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
David Howellse8d6c552007-07-15 23:40:12 -070012#include "internal.h"
13
14#define AFS_LOCK_GRANTED 0
15#define AFS_LOCK_PENDING 1
16
David Howellsf044c882017-11-02 15:27:45 +000017struct workqueue_struct *afs_lock_manager;
18
David Howellse8d6c552007-07-15 23:40:12 -070019static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl);
20static void afs_fl_release_private(struct file_lock *fl);
21
Alexey Dobriyan6aed6282009-09-21 17:01:11 -070022static const struct file_lock_operations afs_lock_ops = {
David Howellse8d6c552007-07-15 23:40:12 -070023 .fl_copy_lock = afs_fl_copy_lock,
24 .fl_release_private = afs_fl_release_private,
25};
26
27/*
David Howellse8d6c552007-07-15 23:40:12 -070028 * if the callback is broken on this vnode, then the lock may now be available
29 */
30void afs_lock_may_be_available(struct afs_vnode *vnode)
31{
32 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
33
34 queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0);
35}
36
37/*
38 * the lock will time out in 5 minutes unless we extend it, so schedule
39 * extension in a bit less than that time
40 */
41static void afs_schedule_lock_extension(struct afs_vnode *vnode)
42{
43 queue_delayed_work(afs_lock_manager, &vnode->lock_work,
44 AFS_LOCKWAIT * HZ / 2);
45}
46
47/*
David Howellsff8e2102007-07-31 00:38:49 -070048 * grant one or more locks (readlocks are allowed to jump the queue if the
49 * first lock in the queue is itself a readlock)
50 * - the caller must hold the vnode lock
51 */
52static void afs_grant_locks(struct afs_vnode *vnode, struct file_lock *fl)
53{
54 struct file_lock *p, *_p;
55
56 list_move_tail(&fl->fl_u.afs.link, &vnode->granted_locks);
57 if (fl->fl_type == F_RDLCK) {
58 list_for_each_entry_safe(p, _p, &vnode->pending_locks,
59 fl_u.afs.link) {
60 if (p->fl_type == F_RDLCK) {
61 p->fl_u.afs.state = AFS_LOCK_GRANTED;
62 list_move_tail(&p->fl_u.afs.link,
63 &vnode->granted_locks);
64 wake_up(&p->fl_wait);
65 }
66 }
67 }
68}
69
70/*
David Howellse8d6c552007-07-15 23:40:12 -070071 * do work for a lock, including:
72 * - probing for a lock we're waiting on but didn't get immediately
73 * - extending a lock that's close to timing out
74 */
75void afs_lock_work(struct work_struct *work)
76{
77 struct afs_vnode *vnode =
78 container_of(work, struct afs_vnode, lock_work.work);
79 struct file_lock *fl;
80 afs_lock_type_t type;
81 struct key *key;
82 int ret;
83
84 _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
85
86 spin_lock(&vnode->lock);
87
88 if (test_bit(AFS_VNODE_UNLOCKING, &vnode->flags)) {
89 _debug("unlock");
90 spin_unlock(&vnode->lock);
91
92 /* attempt to release the server lock; if it fails, we just
93 * wait 5 minutes and it'll time out anyway */
94 ret = afs_vnode_release_lock(vnode, vnode->unlock_key);
95 if (ret < 0)
96 printk(KERN_WARNING "AFS:"
97 " Failed to release lock on {%x:%x} error %d\n",
98 vnode->fid.vid, vnode->fid.vnode, ret);
99
100 spin_lock(&vnode->lock);
101 key_put(vnode->unlock_key);
102 vnode->unlock_key = NULL;
103 clear_bit(AFS_VNODE_UNLOCKING, &vnode->flags);
104 }
105
106 /* if we've got a lock, then it must be time to extend that lock as AFS
107 * locks time out after 5 minutes */
108 if (!list_empty(&vnode->granted_locks)) {
109 _debug("extend");
110
111 if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags))
112 BUG();
113 fl = list_entry(vnode->granted_locks.next,
114 struct file_lock, fl_u.afs.link);
115 key = key_get(fl->fl_file->private_data);
116 spin_unlock(&vnode->lock);
117
118 ret = afs_vnode_extend_lock(vnode, key);
119 clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
120 key_put(key);
121 switch (ret) {
122 case 0:
123 afs_schedule_lock_extension(vnode);
124 break;
125 default:
126 /* ummm... we failed to extend the lock - retry
127 * extension shortly */
128 printk(KERN_WARNING "AFS:"
129 " Failed to extend lock on {%x:%x} error %d\n",
130 vnode->fid.vid, vnode->fid.vnode, ret);
131 queue_delayed_work(afs_lock_manager, &vnode->lock_work,
132 HZ * 10);
133 break;
134 }
135 _leave(" [extend]");
136 return;
137 }
138
139 /* if we don't have a granted lock, then we must've been called back by
140 * the server, and so if might be possible to get a lock we're
141 * currently waiting for */
142 if (!list_empty(&vnode->pending_locks)) {
143 _debug("get");
144
145 if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags))
146 BUG();
147 fl = list_entry(vnode->pending_locks.next,
148 struct file_lock, fl_u.afs.link);
149 key = key_get(fl->fl_file->private_data);
150 type = (fl->fl_type == F_RDLCK) ?
151 AFS_LOCK_READ : AFS_LOCK_WRITE;
152 spin_unlock(&vnode->lock);
153
154 ret = afs_vnode_set_lock(vnode, key, type);
155 clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
156 switch (ret) {
157 case -EWOULDBLOCK:
158 _debug("blocked");
159 break;
160 case 0:
161 _debug("acquired");
162 if (type == AFS_LOCK_READ)
163 set_bit(AFS_VNODE_READLOCKED, &vnode->flags);
164 else
165 set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
166 ret = AFS_LOCK_GRANTED;
167 default:
168 spin_lock(&vnode->lock);
169 /* the pending lock may have been withdrawn due to a
170 * signal */
171 if (list_entry(vnode->pending_locks.next,
172 struct file_lock, fl_u.afs.link) == fl) {
173 fl->fl_u.afs.state = ret;
174 if (ret == AFS_LOCK_GRANTED)
David Howellsff8e2102007-07-31 00:38:49 -0700175 afs_grant_locks(vnode, fl);
David Howellse8d6c552007-07-15 23:40:12 -0700176 else
177 list_del_init(&fl->fl_u.afs.link);
178 wake_up(&fl->fl_wait);
179 spin_unlock(&vnode->lock);
180 } else {
181 _debug("withdrawn");
182 clear_bit(AFS_VNODE_READLOCKED, &vnode->flags);
183 clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
184 spin_unlock(&vnode->lock);
185 afs_vnode_release_lock(vnode, key);
186 if (!list_empty(&vnode->pending_locks))
187 afs_lock_may_be_available(vnode);
188 }
189 break;
190 }
191 key_put(key);
192 _leave(" [pend]");
193 return;
194 }
195
196 /* looks like the lock request was withdrawn on a signal */
197 spin_unlock(&vnode->lock);
198 _leave(" [no locks]");
199}
200
201/*
202 * pass responsibility for the unlocking of a vnode on the server to the
203 * manager thread, lest a pending signal in the calling thread interrupt
204 * AF_RXRPC
205 * - the caller must hold the vnode lock
206 */
207static void afs_defer_unlock(struct afs_vnode *vnode, struct key *key)
208{
209 cancel_delayed_work(&vnode->lock_work);
210 if (!test_and_clear_bit(AFS_VNODE_READLOCKED, &vnode->flags) &&
211 !test_and_clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags))
212 BUG();
213 if (test_and_set_bit(AFS_VNODE_UNLOCKING, &vnode->flags))
214 BUG();
215 vnode->unlock_key = key_get(key);
216 afs_lock_may_be_available(vnode);
217}
218
219/*
220 * request a lock on a file on the server
221 */
222static int afs_do_setlk(struct file *file, struct file_lock *fl)
223{
Jeff Layton1c8c6012013-06-21 08:58:15 -0400224 struct inode *inode = file_inode(file);
225 struct afs_vnode *vnode = AFS_FS_I(inode);
David Howellse8d6c552007-07-15 23:40:12 -0700226 afs_lock_type_t type;
227 struct key *key = file->private_data;
228 int ret;
229
230 _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
231
232 /* only whole-file locks are supported */
233 if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
234 return -EINVAL;
235
David Howellse8d6c552007-07-15 23:40:12 -0700236 fl->fl_ops = &afs_lock_ops;
237 INIT_LIST_HEAD(&fl->fl_u.afs.link);
238 fl->fl_u.afs.state = AFS_LOCK_PENDING;
239
240 type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
241
Jeff Layton1c8c6012013-06-21 08:58:15 -0400242 spin_lock(&inode->i_lock);
David Howellse8d6c552007-07-15 23:40:12 -0700243
244 /* make sure we've got a callback on this file and that our view of the
245 * data version is up to date */
David Howellsc435ee32017-11-02 15:27:49 +0000246 ret = afs_validate(vnode, key);
David Howellse8d6c552007-07-15 23:40:12 -0700247 if (ret < 0)
248 goto error;
249
250 if (vnode->status.lock_count != 0 && !(fl->fl_flags & FL_SLEEP)) {
251 ret = -EAGAIN;
252 goto error;
253 }
254
255 spin_lock(&vnode->lock);
256
David Howellsff8e2102007-07-31 00:38:49 -0700257 /* if we've already got a readlock on the server then we can instantly
258 * grant another readlock, irrespective of whether there are any
259 * pending writelocks */
260 if (type == AFS_LOCK_READ &&
261 vnode->flags & (1 << AFS_VNODE_READLOCKED)) {
262 _debug("instant readlock");
263 ASSERTCMP(vnode->flags &
264 ((1 << AFS_VNODE_LOCKING) |
265 (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
266 ASSERT(!list_empty(&vnode->granted_locks));
267 goto sharing_existing_lock;
268 }
269
270 /* if there's no-one else with a lock on this vnode, then we need to
271 * ask the server for a lock */
272 if (list_empty(&vnode->pending_locks) &&
273 list_empty(&vnode->granted_locks)) {
274 _debug("not locked");
275 ASSERTCMP(vnode->flags &
276 ((1 << AFS_VNODE_LOCKING) |
277 (1 << AFS_VNODE_READLOCKED) |
278 (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
279 list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
280 set_bit(AFS_VNODE_LOCKING, &vnode->flags);
281 spin_unlock(&vnode->lock);
282
283 ret = afs_vnode_set_lock(vnode, key, type);
284 clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
285 switch (ret) {
286 case 0:
287 _debug("acquired");
288 goto acquired_server_lock;
289 case -EWOULDBLOCK:
290 _debug("would block");
291 spin_lock(&vnode->lock);
292 ASSERT(list_empty(&vnode->granted_locks));
293 ASSERTCMP(vnode->pending_locks.next, ==,
294 &fl->fl_u.afs.link);
295 goto wait;
296 default:
297 spin_lock(&vnode->lock);
298 list_del_init(&fl->fl_u.afs.link);
David Howellse8d6c552007-07-15 23:40:12 -0700299 spin_unlock(&vnode->lock);
David Howellsff8e2102007-07-31 00:38:49 -0700300 goto error;
David Howellse8d6c552007-07-15 23:40:12 -0700301 }
302 }
303
304 /* otherwise, we need to wait for a local lock to become available */
305 _debug("wait local");
306 list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
307wait:
308 if (!(fl->fl_flags & FL_SLEEP)) {
309 _debug("noblock");
310 ret = -EAGAIN;
311 goto abort_attempt;
312 }
313 spin_unlock(&vnode->lock);
314
315 /* now we need to sleep and wait for the lock manager thread to get the
316 * lock from the server */
317 _debug("sleep");
318 ret = wait_event_interruptible(fl->fl_wait,
319 fl->fl_u.afs.state <= AFS_LOCK_GRANTED);
320 if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) {
321 ret = fl->fl_u.afs.state;
322 if (ret < 0)
323 goto error;
324 spin_lock(&vnode->lock);
325 goto given_lock;
326 }
327
328 /* we were interrupted, but someone may still be in the throes of
329 * giving us the lock */
330 _debug("intr");
331 ASSERTCMP(ret, ==, -ERESTARTSYS);
332
333 spin_lock(&vnode->lock);
334 if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) {
335 ret = fl->fl_u.afs.state;
336 if (ret < 0) {
337 spin_unlock(&vnode->lock);
338 goto error;
339 }
340 goto given_lock;
341 }
342
343abort_attempt:
344 /* we aren't going to get the lock, either because we're unwilling to
345 * wait, or because some signal happened */
346 _debug("abort");
347 if (list_empty(&vnode->granted_locks) &&
348 vnode->pending_locks.next == &fl->fl_u.afs.link) {
349 if (vnode->pending_locks.prev != &fl->fl_u.afs.link) {
350 /* kick the next pending lock into having a go */
351 list_del_init(&fl->fl_u.afs.link);
352 afs_lock_may_be_available(vnode);
353 }
354 } else {
355 list_del_init(&fl->fl_u.afs.link);
356 }
357 spin_unlock(&vnode->lock);
358 goto error;
359
360acquired_server_lock:
361 /* we've acquired a server lock, but it needs to be renewed after 5
362 * mins */
363 spin_lock(&vnode->lock);
364 afs_schedule_lock_extension(vnode);
365 if (type == AFS_LOCK_READ)
366 set_bit(AFS_VNODE_READLOCKED, &vnode->flags);
367 else
368 set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
369sharing_existing_lock:
370 /* the lock has been granted as far as we're concerned... */
371 fl->fl_u.afs.state = AFS_LOCK_GRANTED;
372 list_move_tail(&fl->fl_u.afs.link, &vnode->granted_locks);
373given_lock:
374 /* ... but we do still need to get the VFS's blessing */
375 ASSERT(!(vnode->flags & (1 << AFS_VNODE_LOCKING)));
376 ASSERT((vnode->flags & ((1 << AFS_VNODE_READLOCKED) |
377 (1 << AFS_VNODE_WRITELOCKED))) != 0);
378 ret = posix_lock_file(file, fl, NULL);
379 if (ret < 0)
380 goto vfs_rejected_lock;
381 spin_unlock(&vnode->lock);
382
383 /* again, make sure we've got a callback on this file and, again, make
384 * sure that our view of the data version is up to date (we ignore
385 * errors incurred here and deal with the consequences elsewhere) */
David Howellsc435ee32017-11-02 15:27:49 +0000386 afs_vnode_fetch_status(vnode, NULL, key, false);
David Howellse8d6c552007-07-15 23:40:12 -0700387
388error:
Jeff Layton1c8c6012013-06-21 08:58:15 -0400389 spin_unlock(&inode->i_lock);
David Howellse8d6c552007-07-15 23:40:12 -0700390 _leave(" = %d", ret);
391 return ret;
392
393vfs_rejected_lock:
394 /* the VFS rejected the lock we just obtained, so we have to discard
395 * what we just got */
396 _debug("vfs refused %d", ret);
397 list_del_init(&fl->fl_u.afs.link);
398 if (list_empty(&vnode->granted_locks))
399 afs_defer_unlock(vnode, key);
David Howellse8d6c552007-07-15 23:40:12 -0700400 goto abort_attempt;
401}
402
403/*
404 * unlock on a file on the server
405 */
406static int afs_do_unlk(struct file *file, struct file_lock *fl)
407{
408 struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
409 struct key *key = file->private_data;
410 int ret;
411
412 _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
413
414 /* only whole-file unlocks are supported */
415 if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
416 return -EINVAL;
417
418 fl->fl_ops = &afs_lock_ops;
419 INIT_LIST_HEAD(&fl->fl_u.afs.link);
420 fl->fl_u.afs.state = AFS_LOCK_PENDING;
421
422 spin_lock(&vnode->lock);
423 ret = posix_lock_file(file, fl, NULL);
424 if (ret < 0) {
425 spin_unlock(&vnode->lock);
426 _leave(" = %d [vfs]", ret);
427 return ret;
428 }
429
430 /* discard the server lock only if all granted locks are gone */
431 if (list_empty(&vnode->granted_locks))
432 afs_defer_unlock(vnode, key);
433 spin_unlock(&vnode->lock);
434 _leave(" = 0");
435 return 0;
436}
437
438/*
439 * return information about a lock we currently hold, if indeed we hold one
440 */
441static int afs_do_getlk(struct file *file, struct file_lock *fl)
442{
443 struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
444 struct key *key = file->private_data;
445 int ret, lock_count;
446
447 _enter("");
448
449 fl->fl_type = F_UNLCK;
450
Al Viro59551022016-01-22 15:40:57 -0500451 inode_lock(&vnode->vfs_inode);
David Howellse8d6c552007-07-15 23:40:12 -0700452
453 /* check local lock records first */
454 ret = 0;
Andrew Morton275afca2007-07-19 01:50:35 -0700455 posix_test_lock(file, fl);
456 if (fl->fl_type == F_UNLCK) {
David Howellse8d6c552007-07-15 23:40:12 -0700457 /* no local locks; consult the server */
David Howellsc435ee32017-11-02 15:27:49 +0000458 ret = afs_vnode_fetch_status(vnode, NULL, key, true);
David Howellse8d6c552007-07-15 23:40:12 -0700459 if (ret < 0)
460 goto error;
461 lock_count = vnode->status.lock_count;
462 if (lock_count) {
463 if (lock_count > 0)
464 fl->fl_type = F_RDLCK;
465 else
466 fl->fl_type = F_WRLCK;
467 fl->fl_start = 0;
468 fl->fl_end = OFFSET_MAX;
469 }
470 }
471
472error:
Al Viro59551022016-01-22 15:40:57 -0500473 inode_unlock(&vnode->vfs_inode);
David Howellse8d6c552007-07-15 23:40:12 -0700474 _leave(" = %d [%hd]", ret, fl->fl_type);
475 return ret;
476}
477
478/*
479 * manage POSIX locks on a file
480 */
481int afs_lock(struct file *file, int cmd, struct file_lock *fl)
482{
Al Viro496ad9a2013-01-23 17:07:38 -0500483 struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
David Howellse8d6c552007-07-15 23:40:12 -0700484
485 _enter("{%x:%u},%d,{t=%x,fl=%x,r=%Ld:%Ld}",
486 vnode->fid.vid, vnode->fid.vnode, cmd,
487 fl->fl_type, fl->fl_flags,
488 (long long) fl->fl_start, (long long) fl->fl_end);
489
490 /* AFS doesn't support mandatory locks */
Pavel Emelyanovfc5846e2007-10-01 14:41:14 -0700491 if (__mandatory_lock(&vnode->vfs_inode) && fl->fl_type != F_UNLCK)
David Howellse8d6c552007-07-15 23:40:12 -0700492 return -ENOLCK;
493
494 if (IS_GETLK(cmd))
495 return afs_do_getlk(file, fl);
496 if (fl->fl_type == F_UNLCK)
497 return afs_do_unlk(file, fl);
498 return afs_do_setlk(file, fl);
499}
500
501/*
502 * manage FLOCK locks on a file
503 */
504int afs_flock(struct file *file, int cmd, struct file_lock *fl)
505{
Al Viro496ad9a2013-01-23 17:07:38 -0500506 struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
David Howellse8d6c552007-07-15 23:40:12 -0700507
508 _enter("{%x:%u},%d,{t=%x,fl=%x}",
509 vnode->fid.vid, vnode->fid.vnode, cmd,
510 fl->fl_type, fl->fl_flags);
511
512 /*
513 * No BSD flocks over NFS allowed.
514 * Note: we could try to fake a POSIX lock request here by
515 * using ((u32) filp | 0x80000000) or some such as the pid.
516 * Not sure whether that would be unique, though, or whether
517 * that would break in other places.
518 */
519 if (!(fl->fl_flags & FL_FLOCK))
520 return -ENOLCK;
521
522 /* we're simulating flock() locks using posix locks on the server */
David Howellse8d6c552007-07-15 23:40:12 -0700523 if (fl->fl_type == F_UNLCK)
524 return afs_do_unlk(file, fl);
525 return afs_do_setlk(file, fl);
526}
527
528/*
529 * the POSIX lock management core VFS code copies the lock record and adds the
530 * copy into its own list, so we need to add that copy to the vnode's lock
531 * queue in the same place as the original (which will be deleted shortly
532 * after)
533 */
534static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl)
535{
536 _enter("");
537
538 list_add(&new->fl_u.afs.link, &fl->fl_u.afs.link);
539}
540
541/*
542 * need to remove this lock from the vnode queue when it's removed from the
543 * VFS's list
544 */
545static void afs_fl_release_private(struct file_lock *fl)
546{
547 _enter("");
548
549 list_del_init(&fl->fl_u.afs.link);
550}