summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-04-25 14:26:50 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-27 14:50:41 +0100
commit49862ce901e6bf98f5f5a264f90082bebceba5ca (patch)
tree157eb75b99f621c0acf9243ddbab4829dfce1228 /fs
parentadf1983a4f633d71c5245bb69c7e3cfd81da8e45 (diff)
afs: Fix AFS file locking to allow fine grained locks
[ Upstream commit 68ce801ffd82e72d5005ab5458e8b9e59f24d9cc ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs')
-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 1bb300ef362b..dffbb456629c 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -432,10 +432,6 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl)
_enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
- /* only whole-file locks are supported */
- if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
- return -EINVAL;
-
fl->fl_ops = &afs_lock_ops;
INIT_LIST_HEAD(&fl->fl_u.afs.link);
fl->fl_u.afs.state = AFS_LOCK_PENDING;
@@ -587,10 +583,6 @@ static int afs_do_unlk(struct file *file, struct file_lock *fl)
/* Flush all pending writes before doing anything with locks. */
vfs_fsync(file, 0);
- /* only whole-file unlocks are supported */
- if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
- return -EINVAL;
-
ret = posix_lock_file(file, fl, NULL);
_leave(" = %d [%u]", ret, vnode->lock_state);
return ret;
@@ -618,12 +610,15 @@ static int afs_do_getlk(struct file *file, struct file_lock *fl)
goto error;
lock_count = READ_ONCE(vnode->status.lock_count);
- if (lock_count > 0)
- fl->fl_type = F_RDLCK;
- else
- fl->fl_type = F_WRLCK;
- fl->fl_start = 0;
- fl->fl_end = OFFSET_MAX;
+ if (lock_count != 0) {
+ if (lock_count > 0)
+ fl->fl_type = F_RDLCK;
+ else
+ fl->fl_type = F_WRLCK;
+ fl->fl_start = 0;
+ fl->fl_end = OFFSET_MAX;
+ fl->fl_pid = 0;
+ }
}
ret = 0;