mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 15:18:19 +00:00
ceph: check if file lock exists before sending unlock request
When a process exits, kernel closes its files. locks_remove_file() is called to remove file locks on these files. locks_remove_file() tries unlocking files even there is no file lock. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
cb63483ad0
commit
bbb480ab05
1 changed files with 29 additions and 2 deletions
|
@ -210,6 +210,21 @@ static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int try_unlock_file(struct file *file, struct file_lock *fl)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int orig_flags = fl->fl_flags;
|
||||||
|
fl->fl_flags |= FL_EXISTS;
|
||||||
|
err = locks_lock_file_wait(file, fl);
|
||||||
|
fl->fl_flags = orig_flags;
|
||||||
|
if (err == -ENOENT) {
|
||||||
|
if (!(orig_flags & FL_EXISTS))
|
||||||
|
err = 0;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to set an fcntl lock.
|
* Attempt to set an fcntl lock.
|
||||||
* For now, this just goes away to the server. Later it may be more awesome.
|
* For now, this just goes away to the server. Later it may be more awesome.
|
||||||
|
@ -255,9 +270,15 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
|
||||||
else
|
else
|
||||||
lock_cmd = CEPH_LOCK_UNLOCK;
|
lock_cmd = CEPH_LOCK_UNLOCK;
|
||||||
|
|
||||||
|
if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK == fl->fl_type) {
|
||||||
|
err = try_unlock_file(file, fl);
|
||||||
|
if (err <= 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = ceph_lock_message(CEPH_LOCK_FCNTL, op, inode, lock_cmd, wait, fl);
|
err = ceph_lock_message(CEPH_LOCK_FCNTL, op, inode, lock_cmd, wait, fl);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (op == CEPH_MDS_OP_SETFILELOCK) {
|
if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK != fl->fl_type) {
|
||||||
dout("mds locked, locking locally\n");
|
dout("mds locked, locking locally\n");
|
||||||
err = posix_lock_file(file, fl, NULL);
|
err = posix_lock_file(file, fl, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -311,9 +332,15 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
|
||||||
else
|
else
|
||||||
lock_cmd = CEPH_LOCK_UNLOCK;
|
lock_cmd = CEPH_LOCK_UNLOCK;
|
||||||
|
|
||||||
|
if (F_UNLCK == fl->fl_type) {
|
||||||
|
err = try_unlock_file(file, fl);
|
||||||
|
if (err <= 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
|
err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
|
||||||
inode, lock_cmd, wait, fl);
|
inode, lock_cmd, wait, fl);
|
||||||
if (!err) {
|
if (!err && F_UNLCK != fl->fl_type) {
|
||||||
err = locks_lock_file_wait(file, fl);
|
err = locks_lock_file_wait(file, fl);
|
||||||
if (err) {
|
if (err) {
|
||||||
ceph_lock_message(CEPH_LOCK_FLOCK,
|
ceph_lock_message(CEPH_LOCK_FLOCK,
|
||||||
|
|
Loading…
Reference in a new issue