aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-04-25 09:26:50 -0400
committerDavid Howells <dhowells@redhat.com>2019-04-25 09:26:50 -0400
commit68ce801ffd82e72d5005ab5458e8b9e59f24d9cc (patch)
treef4de322f7e3b40b0a250858a0d9153339eb3b521 /fs/afs
parenta690f60a2ba3125a2f08cdde176376f5ec1d8a84 (diff)
afs: Fix AFS file locking to allow fine grained locks
Fix AFS file locking to allow fine grained locks as some applications, such as firefox, won't work if they can't take such locks on certain state files - thereby preventing the use of kAFS to distribute a home directory. Note that this cannot be made completely functional as the protocol only has provision for whole-file locks, so there exists the possibility of a process deadlocking itself by getting a partial read-lock on a file first and then trying to get a non-overlapping write-lock - but we got the server's read lock with the first lock, so we're now stuck. OpenAFS solves this by just granting any partial-range lock directly without consulting the server - and hoping there's no remote collision. I want to implement that in a separate patch and it requires a bit more thought. Fixes: 8d6c554126b8 ("AFS: implement file locking") Reported-by: Jonathan Billings <jsbillings@jsbillings.org> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs')
-rw-r--r--fs/afs/flock.c23
1 files changed, 9 insertions, 14 deletions
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
index 8b02f0056d54..6919f53ed4ad 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -458,10 +458,6 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl)
458 458
459 _enter("{%llx:%llu},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type); 459 _enter("{%llx:%llu},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
460 460
461 /* only whole-file locks are supported */
462 if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
463 return -EINVAL;
464
465 fl->fl_ops = &afs_lock_ops; 461 fl->fl_ops = &afs_lock_ops;
466 INIT_LIST_HEAD(&fl->fl_u.afs.link); 462 INIT_LIST_HEAD(&fl->fl_u.afs.link);
467 fl->fl_u.afs.state = AFS_LOCK_PENDING; 463 fl->fl_u.afs.state = AFS_LOCK_PENDING;
@@ -613,10 +609,6 @@ static int afs_do_unlk(struct file *file, struct file_lock *fl)
613 /* Flush all pending writes before doing anything with locks. */ 609 /* Flush all pending writes before doing anything with locks. */
614 vfs_fsync(file, 0); 610 vfs_fsync(file, 0);
615 611
616 /* only whole-file unlocks are supported */
617 if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
618 return -EINVAL;
619
620 ret = posix_lock_file(file, fl, NULL); 612 ret = posix_lock_file(file, fl, NULL);
621 _leave(" = %d [%u]", ret, vnode->lock_state); 613 _leave(" = %d [%u]", ret, vnode->lock_state);
622 return ret; 614 return ret;
@@ -644,12 +636,15 @@ static int afs_do_getlk(struct file *file, struct file_lock *fl)
644 goto error; 636 goto error;
645 637
646 lock_count = READ_ONCE(vnode->status.lock_count); 638 lock_count = READ_ONCE(vnode->status.lock_count);
647 if (lock_count > 0) 639 if (lock_count != 0) {
648 fl->fl_type = F_RDLCK; 640 if (lock_count > 0)
649 else 641 fl->fl_type = F_RDLCK;
650 fl->fl_type = F_WRLCK; 642 else
651 fl->fl_start = 0; 643 fl->fl_type = F_WRLCK;
652 fl->fl_end = OFFSET_MAX; 644 fl->fl_start = 0;
645 fl->fl_end = OFFSET_MAX;
646 fl->fl_pid = 0;
647 }
653 } 648 }
654 649
655 ret = 0; 650 ret = 0;