Commit bbb480ab authored by Yan, Zheng's avatar Yan, Zheng Committed by Ilya Dryomov
Browse files

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: default avatar"Yan, Zheng" <zyan@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent cb63483a
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -210,6 +210,21 @@ static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
	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.
 * 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
		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);
	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");
			err = posix_lock_file(file, fl, NULL);
			if (err) {
@@ -311,9 +332,15 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
	else
		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,
				inode, lock_cmd, wait, fl);
	if (!err) {
	if (!err && F_UNLCK != fl->fl_type) {
		err = locks_lock_file_wait(file, fl);
		if (err) {
			ceph_lock_message(CEPH_LOCK_FLOCK,