Skip to content

Commit

Permalink
afs: Fix AFS file locking to allow fine grained locks
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Howells committed Apr 25, 2019
1 parent a690f60 commit 68ce801
Showing 1 changed file with 9 additions and 14 deletions.
23 changes: 9 additions & 14 deletions fs/afs/flock.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,10 +458,6 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl)

_enter("{%llx:%llu},%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;
Expand Down Expand Up @@ -613,10 +609,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;
Expand Down Expand Up @@ -644,12 +636,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;
Expand Down

0 comments on commit 68ce801

Please sign in to comment.