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

AFS: implement file locking

Implement file locking for AFS.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

David Howells and committed by
Linus Torvalds
e8d6c554 b0fed314

+885 -15
+1
fs/afs/Makefile
··· 8 8 cmservice.o \ 9 9 dir.o \ 10 10 file.o \ 11 + flock.o \ 11 12 fsclient.o \ 12 13 inode.o \ 13 14 main.o \
+8
fs/afs/afs.h
··· 37 37 AFS_FTYPE_SYMLINK = 3, 38 38 } afs_file_type_t; 39 39 40 + typedef enum { 41 + AFS_LOCK_READ = 0, /* read lock request */ 42 + AFS_LOCK_WRITE = 1, /* write lock request */ 43 + } afs_lock_type_t; 44 + 45 + #define AFS_LOCKWAIT (5 * 60) /* time until a lock times out (seconds) */ 46 + 40 47 /* 41 48 * AFS file identifier 42 49 */ ··· 127 120 struct afs_fid parent; /* parent dir ID for non-dirs only */ 128 121 time_t mtime_client; /* last time client changed data */ 129 122 time_t mtime_server; /* last time server changed data */ 123 + s32 lock_count; /* file lock count (0=UNLK -1=WRLCK +ve=#RDLCK */ 130 124 }; 131 125 132 126 /*
+3
fs/afs/afs_fs.h
··· 31 31 FSGETVOLUMEINFO = 148, /* AFS Get information about a volume */ 32 32 FSGETVOLUMESTATUS = 149, /* AFS Get volume status information */ 33 33 FSGETROOTVOLUME = 151, /* AFS Get root volume name */ 34 + FSSETLOCK = 156, /* AFS Request a file lock */ 35 + FSEXTENDLOCK = 157, /* AFS Extend a file lock */ 36 + FSRELEASELOCK = 158, /* AFS Release a file lock */ 34 37 FSLOOKUP = 161, /* AFS lookup file in directory */ 35 38 FSFETCHDATA64 = 65537, /* AFS Fetch file data */ 36 39 FSSTOREDATA64 = 65538, /* AFS Store file data */
+3
fs/afs/callback.c
··· 125 125 spin_unlock(&server->cb_lock); 126 126 127 127 queue_work(afs_callback_update_worker, &vnode->cb_broken_work); 128 + if (list_empty(&vnode->granted_locks) && 129 + !list_empty(&vnode->pending_locks)) 130 + afs_lock_may_be_available(vnode); 128 131 spin_unlock(&vnode->lock); 129 132 } 130 133 }
+1
fs/afs/dir.c
··· 44 44 .open = afs_dir_open, 45 45 .release = afs_release, 46 46 .readdir = afs_readdir, 47 + .lock = afs_lock, 47 48 }; 48 49 49 50 const struct inode_operations afs_dir_inode_operations = {
+2
fs/afs/file.c
··· 34 34 .mmap = generic_file_readonly_mmap, 35 35 .splice_read = generic_file_splice_read, 36 36 .fsync = afs_fsync, 37 + .lock = afs_lock, 38 + .flock = afs_flock, 37 39 }; 38 40 39 41 const struct inode_operations afs_file_inode_operations = {
+558
fs/afs/flock.c
··· 1 + /* 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 + 12 + #include <linux/smp_lock.h> 13 + #include "internal.h" 14 + 15 + #define AFS_LOCK_GRANTED 0 16 + #define AFS_LOCK_PENDING 1 17 + 18 + static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl); 19 + static void afs_fl_release_private(struct file_lock *fl); 20 + 21 + static struct workqueue_struct *afs_lock_manager; 22 + 23 + static struct file_lock_operations afs_lock_ops = { 24 + .fl_copy_lock = afs_fl_copy_lock, 25 + .fl_release_private = afs_fl_release_private, 26 + }; 27 + 28 + /* 29 + * initialise the lock manager thread if it isn't already running 30 + */ 31 + static int afs_init_lock_manager(void) 32 + { 33 + if (!afs_lock_manager) { 34 + afs_lock_manager = create_singlethread_workqueue("kafs_lockd"); 35 + if (!afs_lock_manager) 36 + return -ENOMEM; 37 + } 38 + return 0; 39 + } 40 + 41 + /* 42 + * destroy the lock manager thread if it's running 43 + */ 44 + void __exit afs_kill_lock_manager(void) 45 + { 46 + if (afs_lock_manager) 47 + destroy_workqueue(afs_lock_manager); 48 + } 49 + 50 + /* 51 + * if the callback is broken on this vnode, then the lock may now be available 52 + */ 53 + void afs_lock_may_be_available(struct afs_vnode *vnode) 54 + { 55 + _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); 56 + 57 + queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0); 58 + } 59 + 60 + /* 61 + * the lock will time out in 5 minutes unless we extend it, so schedule 62 + * extension in a bit less than that time 63 + */ 64 + static void afs_schedule_lock_extension(struct afs_vnode *vnode) 65 + { 66 + queue_delayed_work(afs_lock_manager, &vnode->lock_work, 67 + AFS_LOCKWAIT * HZ / 2); 68 + } 69 + 70 + /* 71 + * 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 + */ 75 + void 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) 175 + list_move_tail(&fl->fl_u.afs.link, 176 + &vnode->granted_locks); 177 + else 178 + list_del_init(&fl->fl_u.afs.link); 179 + wake_up(&fl->fl_wait); 180 + spin_unlock(&vnode->lock); 181 + } else { 182 + _debug("withdrawn"); 183 + clear_bit(AFS_VNODE_READLOCKED, &vnode->flags); 184 + clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags); 185 + spin_unlock(&vnode->lock); 186 + afs_vnode_release_lock(vnode, key); 187 + if (!list_empty(&vnode->pending_locks)) 188 + afs_lock_may_be_available(vnode); 189 + } 190 + break; 191 + } 192 + key_put(key); 193 + _leave(" [pend]"); 194 + return; 195 + } 196 + 197 + /* looks like the lock request was withdrawn on a signal */ 198 + spin_unlock(&vnode->lock); 199 + _leave(" [no locks]"); 200 + } 201 + 202 + /* 203 + * pass responsibility for the unlocking of a vnode on the server to the 204 + * manager thread, lest a pending signal in the calling thread interrupt 205 + * AF_RXRPC 206 + * - the caller must hold the vnode lock 207 + */ 208 + static void afs_defer_unlock(struct afs_vnode *vnode, struct key *key) 209 + { 210 + cancel_delayed_work(&vnode->lock_work); 211 + if (!test_and_clear_bit(AFS_VNODE_READLOCKED, &vnode->flags) && 212 + !test_and_clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags)) 213 + BUG(); 214 + if (test_and_set_bit(AFS_VNODE_UNLOCKING, &vnode->flags)) 215 + BUG(); 216 + vnode->unlock_key = key_get(key); 217 + afs_lock_may_be_available(vnode); 218 + } 219 + 220 + /* 221 + * request a lock on a file on the server 222 + */ 223 + static int afs_do_setlk(struct file *file, struct file_lock *fl) 224 + { 225 + struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host); 226 + 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 + 236 + ret = afs_init_lock_manager(); 237 + if (ret < 0) 238 + return ret; 239 + 240 + fl->fl_ops = &afs_lock_ops; 241 + INIT_LIST_HEAD(&fl->fl_u.afs.link); 242 + fl->fl_u.afs.state = AFS_LOCK_PENDING; 243 + 244 + type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE; 245 + 246 + lock_kernel(); 247 + 248 + /* make sure we've got a callback on this file and that our view of the 249 + * data version is up to date */ 250 + ret = afs_vnode_fetch_status(vnode, NULL, key); 251 + if (ret < 0) 252 + goto error; 253 + 254 + if (vnode->status.lock_count != 0 && !(fl->fl_flags & FL_SLEEP)) { 255 + ret = -EAGAIN; 256 + goto error; 257 + } 258 + 259 + spin_lock(&vnode->lock); 260 + 261 + if (list_empty(&vnode->pending_locks)) { 262 + /* if there's no-one else with a lock on this vnode, then we 263 + * need to ask the server for a lock */ 264 + if (list_empty(&vnode->granted_locks)) { 265 + _debug("not locked"); 266 + ASSERTCMP(vnode->flags & 267 + ((1 << AFS_VNODE_LOCKING) | 268 + (1 << AFS_VNODE_READLOCKED) | 269 + (1 << AFS_VNODE_WRITELOCKED)), ==, 0); 270 + list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks); 271 + set_bit(AFS_VNODE_LOCKING, &vnode->flags); 272 + spin_unlock(&vnode->lock); 273 + 274 + ret = afs_vnode_set_lock(vnode, key, type); 275 + clear_bit(AFS_VNODE_LOCKING, &vnode->flags); 276 + switch (ret) { 277 + case 0: 278 + goto acquired_server_lock; 279 + case -EWOULDBLOCK: 280 + spin_lock(&vnode->lock); 281 + ASSERT(list_empty(&vnode->granted_locks)); 282 + ASSERTCMP(vnode->pending_locks.next, ==, 283 + &fl->fl_u.afs.link); 284 + goto wait; 285 + default: 286 + spin_lock(&vnode->lock); 287 + list_del_init(&fl->fl_u.afs.link); 288 + spin_unlock(&vnode->lock); 289 + goto error; 290 + } 291 + } 292 + 293 + /* if we've already got a readlock on the server and no waiting 294 + * writelocks, then we might be able to instantly grant another 295 + * readlock */ 296 + if (type == AFS_LOCK_READ && 297 + vnode->flags & (1 << AFS_VNODE_READLOCKED)) { 298 + _debug("instant readlock"); 299 + ASSERTCMP(vnode->flags & 300 + ((1 << AFS_VNODE_LOCKING) | 301 + (1 << AFS_VNODE_WRITELOCKED)), ==, 0); 302 + ASSERT(!list_empty(&vnode->granted_locks)); 303 + goto sharing_existing_lock; 304 + } 305 + } 306 + 307 + /* otherwise, we need to wait for a local lock to become available */ 308 + _debug("wait local"); 309 + list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks); 310 + wait: 311 + if (!(fl->fl_flags & FL_SLEEP)) { 312 + _debug("noblock"); 313 + ret = -EAGAIN; 314 + goto abort_attempt; 315 + } 316 + spin_unlock(&vnode->lock); 317 + 318 + /* now we need to sleep and wait for the lock manager thread to get the 319 + * lock from the server */ 320 + _debug("sleep"); 321 + ret = wait_event_interruptible(fl->fl_wait, 322 + fl->fl_u.afs.state <= AFS_LOCK_GRANTED); 323 + if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) { 324 + ret = fl->fl_u.afs.state; 325 + if (ret < 0) 326 + goto error; 327 + spin_lock(&vnode->lock); 328 + goto given_lock; 329 + } 330 + 331 + /* we were interrupted, but someone may still be in the throes of 332 + * giving us the lock */ 333 + _debug("intr"); 334 + ASSERTCMP(ret, ==, -ERESTARTSYS); 335 + 336 + spin_lock(&vnode->lock); 337 + if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) { 338 + ret = fl->fl_u.afs.state; 339 + if (ret < 0) { 340 + spin_unlock(&vnode->lock); 341 + goto error; 342 + } 343 + goto given_lock; 344 + } 345 + 346 + abort_attempt: 347 + /* we aren't going to get the lock, either because we're unwilling to 348 + * wait, or because some signal happened */ 349 + _debug("abort"); 350 + if (list_empty(&vnode->granted_locks) && 351 + vnode->pending_locks.next == &fl->fl_u.afs.link) { 352 + if (vnode->pending_locks.prev != &fl->fl_u.afs.link) { 353 + /* kick the next pending lock into having a go */ 354 + list_del_init(&fl->fl_u.afs.link); 355 + afs_lock_may_be_available(vnode); 356 + } 357 + } else { 358 + list_del_init(&fl->fl_u.afs.link); 359 + } 360 + spin_unlock(&vnode->lock); 361 + goto error; 362 + 363 + acquired_server_lock: 364 + /* we've acquired a server lock, but it needs to be renewed after 5 365 + * mins */ 366 + spin_lock(&vnode->lock); 367 + afs_schedule_lock_extension(vnode); 368 + if (type == AFS_LOCK_READ) 369 + set_bit(AFS_VNODE_READLOCKED, &vnode->flags); 370 + else 371 + set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags); 372 + sharing_existing_lock: 373 + /* the lock has been granted as far as we're concerned... */ 374 + fl->fl_u.afs.state = AFS_LOCK_GRANTED; 375 + list_move_tail(&fl->fl_u.afs.link, &vnode->granted_locks); 376 + given_lock: 377 + /* ... but we do still need to get the VFS's blessing */ 378 + ASSERT(!(vnode->flags & (1 << AFS_VNODE_LOCKING))); 379 + ASSERT((vnode->flags & ((1 << AFS_VNODE_READLOCKED) | 380 + (1 << AFS_VNODE_WRITELOCKED))) != 0); 381 + ret = posix_lock_file(file, fl, NULL); 382 + if (ret < 0) 383 + goto vfs_rejected_lock; 384 + spin_unlock(&vnode->lock); 385 + 386 + /* again, make sure we've got a callback on this file and, again, make 387 + * sure that our view of the data version is up to date (we ignore 388 + * errors incurred here and deal with the consequences elsewhere) */ 389 + afs_vnode_fetch_status(vnode, NULL, key); 390 + 391 + error: 392 + unlock_kernel(); 393 + _leave(" = %d", ret); 394 + return ret; 395 + 396 + vfs_rejected_lock: 397 + /* the VFS rejected the lock we just obtained, so we have to discard 398 + * what we just got */ 399 + _debug("vfs refused %d", ret); 400 + list_del_init(&fl->fl_u.afs.link); 401 + if (list_empty(&vnode->granted_locks)) 402 + afs_defer_unlock(vnode, key); 403 + spin_unlock(&vnode->lock); 404 + goto abort_attempt; 405 + } 406 + 407 + /* 408 + * unlock on a file on the server 409 + */ 410 + static int afs_do_unlk(struct file *file, struct file_lock *fl) 411 + { 412 + struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host); 413 + struct key *key = file->private_data; 414 + int ret; 415 + 416 + _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type); 417 + 418 + /* only whole-file unlocks are supported */ 419 + if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX) 420 + return -EINVAL; 421 + 422 + fl->fl_ops = &afs_lock_ops; 423 + INIT_LIST_HEAD(&fl->fl_u.afs.link); 424 + fl->fl_u.afs.state = AFS_LOCK_PENDING; 425 + 426 + spin_lock(&vnode->lock); 427 + ret = posix_lock_file(file, fl, NULL); 428 + if (ret < 0) { 429 + spin_unlock(&vnode->lock); 430 + _leave(" = %d [vfs]", ret); 431 + return ret; 432 + } 433 + 434 + /* discard the server lock only if all granted locks are gone */ 435 + if (list_empty(&vnode->granted_locks)) 436 + afs_defer_unlock(vnode, key); 437 + spin_unlock(&vnode->lock); 438 + _leave(" = 0"); 439 + return 0; 440 + } 441 + 442 + /* 443 + * return information about a lock we currently hold, if indeed we hold one 444 + */ 445 + static int afs_do_getlk(struct file *file, struct file_lock *fl) 446 + { 447 + struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host); 448 + struct key *key = file->private_data; 449 + int ret, lock_count; 450 + 451 + _enter(""); 452 + 453 + fl->fl_type = F_UNLCK; 454 + 455 + mutex_lock(&vnode->vfs_inode.i_mutex); 456 + 457 + /* check local lock records first */ 458 + ret = 0; 459 + if (posix_test_lock(file, fl) == 0) { 460 + /* no local locks; consult the server */ 461 + ret = afs_vnode_fetch_status(vnode, NULL, key); 462 + if (ret < 0) 463 + goto error; 464 + lock_count = vnode->status.lock_count; 465 + if (lock_count) { 466 + if (lock_count > 0) 467 + fl->fl_type = F_RDLCK; 468 + else 469 + fl->fl_type = F_WRLCK; 470 + fl->fl_start = 0; 471 + fl->fl_end = OFFSET_MAX; 472 + } 473 + } 474 + 475 + error: 476 + mutex_unlock(&vnode->vfs_inode.i_mutex); 477 + _leave(" = %d [%hd]", ret, fl->fl_type); 478 + return ret; 479 + } 480 + 481 + /* 482 + * manage POSIX locks on a file 483 + */ 484 + int afs_lock(struct file *file, int cmd, struct file_lock *fl) 485 + { 486 + struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode); 487 + 488 + _enter("{%x:%u},%d,{t=%x,fl=%x,r=%Ld:%Ld}", 489 + vnode->fid.vid, vnode->fid.vnode, cmd, 490 + fl->fl_type, fl->fl_flags, 491 + (long long) fl->fl_start, (long long) fl->fl_end); 492 + 493 + /* AFS doesn't support mandatory locks */ 494 + if ((vnode->vfs_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && 495 + fl->fl_type != F_UNLCK) 496 + return -ENOLCK; 497 + 498 + if (IS_GETLK(cmd)) 499 + return afs_do_getlk(file, fl); 500 + if (fl->fl_type == F_UNLCK) 501 + return afs_do_unlk(file, fl); 502 + return afs_do_setlk(file, fl); 503 + } 504 + 505 + /* 506 + * manage FLOCK locks on a file 507 + */ 508 + int afs_flock(struct file *file, int cmd, struct file_lock *fl) 509 + { 510 + struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode); 511 + 512 + _enter("{%x:%u},%d,{t=%x,fl=%x}", 513 + vnode->fid.vid, vnode->fid.vnode, cmd, 514 + fl->fl_type, fl->fl_flags); 515 + 516 + /* 517 + * No BSD flocks over NFS allowed. 518 + * Note: we could try to fake a POSIX lock request here by 519 + * using ((u32) filp | 0x80000000) or some such as the pid. 520 + * Not sure whether that would be unique, though, or whether 521 + * that would break in other places. 522 + */ 523 + if (!(fl->fl_flags & FL_FLOCK)) 524 + return -ENOLCK; 525 + 526 + /* we're simulating flock() locks using posix locks on the server */ 527 + fl->fl_owner = (fl_owner_t) file; 528 + fl->fl_start = 0; 529 + fl->fl_end = OFFSET_MAX; 530 + 531 + if (fl->fl_type == F_UNLCK) 532 + return afs_do_unlk(file, fl); 533 + return afs_do_setlk(file, fl); 534 + } 535 + 536 + /* 537 + * the POSIX lock management core VFS code copies the lock record and adds the 538 + * copy into its own list, so we need to add that copy to the vnode's lock 539 + * queue in the same place as the original (which will be deleted shortly 540 + * after) 541 + */ 542 + static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl) 543 + { 544 + _enter(""); 545 + 546 + list_add(&new->fl_u.afs.link, &fl->fl_u.afs.link); 547 + } 548 + 549 + /* 550 + * need to remove this lock from the vnode queue when it's removed from the 551 + * VFS's list 552 + */ 553 + static void afs_fl_release_private(struct file_lock *fl) 554 + { 555 + _enter(""); 556 + 557 + list_del_init(&fl->fl_u.afs.link); 558 + }
+154 -1
fs/afs/fsclient.c
··· 67 67 EXTRACT(status->group); 68 68 bp++; /* sync counter */ 69 69 data_version |= (u64) ntohl(*bp++) << 32; 70 - bp++; /* lock count */ 70 + EXTRACT(status->lock_count); 71 71 size |= (u64) ntohl(*bp++) << 32; 72 72 bp++; /* spare 4 */ 73 73 *_bp = bp; ··· 1745 1745 bp = call->request; 1746 1746 bp[0] = htonl(FSGETVOLUMESTATUS); 1747 1747 bp[1] = htonl(vnode->fid.vid); 1748 + 1749 + return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 1750 + } 1751 + 1752 + /* 1753 + * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock 1754 + */ 1755 + static int afs_deliver_fs_xxxx_lock(struct afs_call *call, 1756 + struct sk_buff *skb, bool last) 1757 + { 1758 + const __be32 *bp; 1759 + 1760 + _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 1761 + 1762 + afs_transfer_reply(call, skb); 1763 + if (!last) 1764 + return 0; 1765 + 1766 + if (call->reply_size != call->reply_max) 1767 + return -EBADMSG; 1768 + 1769 + /* unmarshall the reply once we've received all of it */ 1770 + bp = call->buffer; 1771 + /* xdr_decode_AFSVolSync(&bp, call->replyX); */ 1772 + 1773 + _leave(" = 0 [done]"); 1774 + return 0; 1775 + } 1776 + 1777 + /* 1778 + * FS.SetLock operation type 1779 + */ 1780 + static const struct afs_call_type afs_RXFSSetLock = { 1781 + .name = "FS.SetLock", 1782 + .deliver = afs_deliver_fs_xxxx_lock, 1783 + .abort_to_error = afs_abort_to_error, 1784 + .destructor = afs_flat_call_destructor, 1785 + }; 1786 + 1787 + /* 1788 + * FS.ExtendLock operation type 1789 + */ 1790 + static const struct afs_call_type afs_RXFSExtendLock = { 1791 + .name = "FS.ExtendLock", 1792 + .deliver = afs_deliver_fs_xxxx_lock, 1793 + .abort_to_error = afs_abort_to_error, 1794 + .destructor = afs_flat_call_destructor, 1795 + }; 1796 + 1797 + /* 1798 + * FS.ReleaseLock operation type 1799 + */ 1800 + static const struct afs_call_type afs_RXFSReleaseLock = { 1801 + .name = "FS.ReleaseLock", 1802 + .deliver = afs_deliver_fs_xxxx_lock, 1803 + .abort_to_error = afs_abort_to_error, 1804 + .destructor = afs_flat_call_destructor, 1805 + }; 1806 + 1807 + /* 1808 + * get a lock on a file 1809 + */ 1810 + int afs_fs_set_lock(struct afs_server *server, 1811 + struct key *key, 1812 + struct afs_vnode *vnode, 1813 + afs_lock_type_t type, 1814 + const struct afs_wait_mode *wait_mode) 1815 + { 1816 + struct afs_call *call; 1817 + __be32 *bp; 1818 + 1819 + _enter(""); 1820 + 1821 + call = afs_alloc_flat_call(&afs_RXFSSetLock, 5 * 4, 6 * 4); 1822 + if (!call) 1823 + return -ENOMEM; 1824 + 1825 + call->key = key; 1826 + call->reply = vnode; 1827 + call->service_id = FS_SERVICE; 1828 + call->port = htons(AFS_FS_PORT); 1829 + 1830 + /* marshall the parameters */ 1831 + bp = call->request; 1832 + *bp++ = htonl(FSSETLOCK); 1833 + *bp++ = htonl(vnode->fid.vid); 1834 + *bp++ = htonl(vnode->fid.vnode); 1835 + *bp++ = htonl(vnode->fid.unique); 1836 + *bp++ = htonl(type); 1837 + 1838 + return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 1839 + } 1840 + 1841 + /* 1842 + * extend a lock on a file 1843 + */ 1844 + int afs_fs_extend_lock(struct afs_server *server, 1845 + struct key *key, 1846 + struct afs_vnode *vnode, 1847 + const struct afs_wait_mode *wait_mode) 1848 + { 1849 + struct afs_call *call; 1850 + __be32 *bp; 1851 + 1852 + _enter(""); 1853 + 1854 + call = afs_alloc_flat_call(&afs_RXFSExtendLock, 4 * 4, 6 * 4); 1855 + if (!call) 1856 + return -ENOMEM; 1857 + 1858 + call->key = key; 1859 + call->reply = vnode; 1860 + call->service_id = FS_SERVICE; 1861 + call->port = htons(AFS_FS_PORT); 1862 + 1863 + /* marshall the parameters */ 1864 + bp = call->request; 1865 + *bp++ = htonl(FSEXTENDLOCK); 1866 + *bp++ = htonl(vnode->fid.vid); 1867 + *bp++ = htonl(vnode->fid.vnode); 1868 + *bp++ = htonl(vnode->fid.unique); 1869 + 1870 + return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 1871 + } 1872 + 1873 + /* 1874 + * release a lock on a file 1875 + */ 1876 + int afs_fs_release_lock(struct afs_server *server, 1877 + struct key *key, 1878 + struct afs_vnode *vnode, 1879 + const struct afs_wait_mode *wait_mode) 1880 + { 1881 + struct afs_call *call; 1882 + __be32 *bp; 1883 + 1884 + _enter(""); 1885 + 1886 + call = afs_alloc_flat_call(&afs_RXFSReleaseLock, 4 * 4, 6 * 4); 1887 + if (!call) 1888 + return -ENOMEM; 1889 + 1890 + call->key = key; 1891 + call->reply = vnode; 1892 + call->service_id = FS_SERVICE; 1893 + call->port = htons(AFS_FS_PORT); 1894 + 1895 + /* marshall the parameters */ 1896 + bp = call->request; 1897 + *bp++ = htonl(FSRELEASELOCK); 1898 + *bp++ = htonl(vnode->fid.vid); 1899 + *bp++ = htonl(vnode->fid.vnode); 1900 + *bp++ = htonl(vnode->fid.unique); 1748 1901 1749 1902 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); 1750 1903 }
+30
fs/afs/internal.h
··· 351 351 #define AFS_VNODE_ZAP_DATA 3 /* set if vnode's data should be invalidated */ 352 352 #define AFS_VNODE_DELETED 4 /* set if vnode deleted on server */ 353 353 #define AFS_VNODE_MOUNTPOINT 5 /* set if vnode is a mountpoint symlink */ 354 + #define AFS_VNODE_LOCKING 6 /* set if waiting for lock on vnode */ 355 + #define AFS_VNODE_READLOCKED 7 /* set if vnode is read-locked on the server */ 356 + #define AFS_VNODE_WRITELOCKED 8 /* set if vnode is write-locked on the server */ 357 + #define AFS_VNODE_UNLOCKING 9 /* set if vnode is being unlocked on the server */ 354 358 355 359 long acl_order; /* ACL check count (callback break count) */ 356 360 357 361 struct list_head writebacks; /* alterations in pagecache that need writing */ 362 + struct list_head pending_locks; /* locks waiting to be granted */ 363 + struct list_head granted_locks; /* locks granted on this file */ 364 + struct delayed_work lock_work; /* work to be done in locking */ 365 + struct key *unlock_key; /* key to be used in unlocking */ 358 366 359 367 /* outstanding callback notification on this file */ 360 368 struct rb_node server_rb; /* link in server->fs_vnodes */ ··· 482 474 extern int afs_release(struct inode *, struct file *); 483 475 484 476 /* 477 + * flock.c 478 + */ 479 + extern void __exit afs_kill_lock_manager(void); 480 + extern void afs_lock_work(struct work_struct *); 481 + extern void afs_lock_may_be_available(struct afs_vnode *); 482 + extern int afs_lock(struct file *, int, struct file_lock *); 483 + extern int afs_flock(struct file *, int, struct file_lock *); 484 + 485 + /* 485 486 * fsclient.c 486 487 */ 487 488 extern int afs_fs_fetch_file_status(struct afs_server *, struct key *, ··· 530 513 struct afs_vnode *, 531 514 struct afs_volume_status *, 532 515 const struct afs_wait_mode *); 516 + extern int afs_fs_set_lock(struct afs_server *, struct key *, 517 + struct afs_vnode *, afs_lock_type_t, 518 + const struct afs_wait_mode *); 519 + extern int afs_fs_extend_lock(struct afs_server *, struct key *, 520 + struct afs_vnode *, 521 + const struct afs_wait_mode *); 522 + extern int afs_fs_release_lock(struct afs_server *, struct key *, 523 + struct afs_vnode *, 524 + const struct afs_wait_mode *); 533 525 534 526 /* 535 527 * inode.c ··· 707 681 extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *); 708 682 extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *, 709 683 struct afs_volume_status *); 684 + extern int afs_vnode_set_lock(struct afs_vnode *, struct key *, 685 + afs_lock_type_t); 686 + extern int afs_vnode_extend_lock(struct afs_vnode *, struct key *); 687 + extern int afs_vnode_release_lock(struct afs_vnode *, struct key *); 710 688 711 689 /* 712 690 * volume.c
+1
fs/afs/main.c
··· 168 168 printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); 169 169 170 170 afs_fs_exit(); 171 + afs_kill_lock_manager(); 171 172 afs_close_socket(); 172 173 afs_purge_servers(); 173 174 afs_callback_update_kill();
+1
fs/afs/misc.c
··· 35 35 case VOVERQUOTA: return -EDQUOT; 36 36 case VBUSY: return -EBUSY; 37 37 case VMOVED: return -ENXIO; 38 + case 0x2f6df0a: return -EWOULDBLOCK; 38 39 case 0x2f6df0c: return -EACCES; 39 40 case 0x2f6df0f: return -EBUSY; 40 41 case 0x2f6df10: return -EEXIST;
+3
fs/afs/super.c
··· 460 460 spin_lock_init(&vnode->writeback_lock); 461 461 spin_lock_init(&vnode->lock); 462 462 INIT_LIST_HEAD(&vnode->writebacks); 463 + INIT_LIST_HEAD(&vnode->pending_locks); 464 + INIT_LIST_HEAD(&vnode->granted_locks); 465 + INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work); 463 466 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); 464 467 } 465 468
+116 -14
fs/afs/vnode.c
··· 887 887 vnode->fid.unique, 888 888 key_serial(key)); 889 889 890 - /* this op will fetch the status */ 891 - spin_lock(&vnode->lock); 892 - vnode->update_cnt++; 893 - spin_unlock(&vnode->lock); 894 - 895 890 do { 896 891 /* pick a server to query */ 897 892 server = afs_volume_pick_fileserver(vnode); ··· 900 905 } while (!afs_volume_release_fileserver(vnode, server, ret)); 901 906 902 907 /* adjust the flags */ 903 - if (ret == 0) { 904 - afs_vnode_finalise_status_update(vnode, server); 908 + if (ret == 0) 905 909 afs_put_server(server); 906 - } else { 907 - afs_vnode_status_update_failed(vnode, ret); 908 - } 909 910 910 911 _leave(" = %d", ret); 911 912 return ret; 912 913 913 914 no_server: 914 - spin_lock(&vnode->lock); 915 - vnode->update_cnt--; 916 - ASSERTCMP(vnode->update_cnt, >=, 0); 917 - spin_unlock(&vnode->lock); 915 + return PTR_ERR(server); 916 + } 917 + 918 + /* 919 + * get a lock on a file 920 + */ 921 + int afs_vnode_set_lock(struct afs_vnode *vnode, struct key *key, 922 + afs_lock_type_t type) 923 + { 924 + struct afs_server *server; 925 + int ret; 926 + 927 + _enter("%s{%x:%u.%u},%x,%u", 928 + vnode->volume->vlocation->vldb.name, 929 + vnode->fid.vid, 930 + vnode->fid.vnode, 931 + vnode->fid.unique, 932 + key_serial(key), type); 933 + 934 + do { 935 + /* pick a server to query */ 936 + server = afs_volume_pick_fileserver(vnode); 937 + if (IS_ERR(server)) 938 + goto no_server; 939 + 940 + _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); 941 + 942 + ret = afs_fs_set_lock(server, key, vnode, type, &afs_sync_call); 943 + 944 + } while (!afs_volume_release_fileserver(vnode, server, ret)); 945 + 946 + /* adjust the flags */ 947 + if (ret == 0) 948 + afs_put_server(server); 949 + 950 + _leave(" = %d", ret); 951 + return ret; 952 + 953 + no_server: 954 + return PTR_ERR(server); 955 + } 956 + 957 + /* 958 + * extend a lock on a file 959 + */ 960 + int afs_vnode_extend_lock(struct afs_vnode *vnode, struct key *key) 961 + { 962 + struct afs_server *server; 963 + int ret; 964 + 965 + _enter("%s{%x:%u.%u},%x", 966 + vnode->volume->vlocation->vldb.name, 967 + vnode->fid.vid, 968 + vnode->fid.vnode, 969 + vnode->fid.unique, 970 + key_serial(key)); 971 + 972 + do { 973 + /* pick a server to query */ 974 + server = afs_volume_pick_fileserver(vnode); 975 + if (IS_ERR(server)) 976 + goto no_server; 977 + 978 + _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); 979 + 980 + ret = afs_fs_extend_lock(server, key, vnode, &afs_sync_call); 981 + 982 + } while (!afs_volume_release_fileserver(vnode, server, ret)); 983 + 984 + /* adjust the flags */ 985 + if (ret == 0) 986 + afs_put_server(server); 987 + 988 + _leave(" = %d", ret); 989 + return ret; 990 + 991 + no_server: 992 + return PTR_ERR(server); 993 + } 994 + 995 + /* 996 + * release a lock on a file 997 + */ 998 + int afs_vnode_release_lock(struct afs_vnode *vnode, struct key *key) 999 + { 1000 + struct afs_server *server; 1001 + int ret; 1002 + 1003 + _enter("%s{%x:%u.%u},%x", 1004 + vnode->volume->vlocation->vldb.name, 1005 + vnode->fid.vid, 1006 + vnode->fid.vnode, 1007 + vnode->fid.unique, 1008 + key_serial(key)); 1009 + 1010 + do { 1011 + /* pick a server to query */ 1012 + server = afs_volume_pick_fileserver(vnode); 1013 + if (IS_ERR(server)) 1014 + goto no_server; 1015 + 1016 + _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); 1017 + 1018 + ret = afs_fs_release_lock(server, key, vnode, &afs_sync_call); 1019 + 1020 + } while (!afs_volume_release_fileserver(vnode, server, ret)); 1021 + 1022 + /* adjust the flags */ 1023 + if (ret == 0) 1024 + afs_put_server(server); 1025 + 1026 + _leave(" = %d", ret); 1027 + return ret; 1028 + 1029 + no_server: 918 1030 return PTR_ERR(server); 919 1031 }
+4
include/linux/fs.h
··· 820 820 union { 821 821 struct nfs_lock_info nfs_fl; 822 822 struct nfs4_lock_info nfs4_fl; 823 + struct { 824 + struct list_head link; /* link in AFS vnode's pending_locks list */ 825 + int state; /* state of grant or error if -ve */ 826 + } afs; 823 827 } fl_u; 824 828 }; 825 829