mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-04 08:15:37 +00:00
locks: Add leases c/r for kernels v4.0 and older
Information about locks in /proc/<pid>/fdinfo is presented only since kernel v4.1. This patch adds logic to *note_file_lock* to match leases and OFDs. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
committed by
Andrei Vagin
parent
b6dd25e939
commit
1fb5a051f7
@@ -270,6 +270,80 @@ static int lock_ofd_check_fd(int lfd, struct file_lock *fl)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lease_check_fd(int fd, int file_flags, struct file_lock *fl)
|
||||||
|
{
|
||||||
|
int file_lease_type, err;
|
||||||
|
int lease_type = fl->fl_ltype & (~LEASE_BREAKING);
|
||||||
|
|
||||||
|
if ((file_flags & O_ACCMODE) != O_RDONLY) {
|
||||||
|
/*
|
||||||
|
* Write OFD conflicts with any lease not associated
|
||||||
|
* with it, therefore there is can't be other lease
|
||||||
|
* or OFD for this file.
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_lease_type = fcntl(fd, F_GETLEASE);
|
||||||
|
if (file_lease_type < 0) {
|
||||||
|
pr_err("Can't get lease type\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only read OFDs can be present for the file. If
|
||||||
|
* read and write OFDs with at least one lease had
|
||||||
|
* presented, it would have conflicted.
|
||||||
|
*/
|
||||||
|
if (fl->fl_ltype & LEASE_BREAKING) {
|
||||||
|
/*
|
||||||
|
* Only read leases are possible for read OFDs
|
||||||
|
* and they all should be in breaking state,
|
||||||
|
* because the current one is.
|
||||||
|
*/
|
||||||
|
int compatible_type = file_lease_type;
|
||||||
|
|
||||||
|
if (compatible_type != F_UNLCK) {
|
||||||
|
pr_err("Lease doesn't conflicts but breaks\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Due to activated breaking sequence we can't
|
||||||
|
* get actual lease type with F_GETLEASE.
|
||||||
|
* The err == 0 after lease upgrade means, that
|
||||||
|
* there is already read lease on OFD. Otherwise
|
||||||
|
* it would fail, because current read lease is
|
||||||
|
* still set and breaking.
|
||||||
|
*/
|
||||||
|
err = fcntl(fd, F_SETLEASE, F_RDLCK);
|
||||||
|
if (err < 0) {
|
||||||
|
if (errno != EAGAIN) {
|
||||||
|
pr_perror("Can't set lease (fd %i)", fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* The file can have only non-breaking read
|
||||||
|
* leases, because otherwise the current one
|
||||||
|
* also would have broke.
|
||||||
|
*/
|
||||||
|
if (lease_type != F_RDLCK) {
|
||||||
|
pr_err("Incorrect lease type\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_lease_type == F_UNLCK)
|
||||||
|
return 0;
|
||||||
|
if (file_lease_type == F_RDLCK)
|
||||||
|
return 1;
|
||||||
|
pr_err("Invalid file lease type\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
|
int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
|
||||||
{
|
{
|
||||||
struct file_lock *fl;
|
struct file_lock *fl;
|
||||||
@@ -299,8 +373,17 @@ int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
|
|||||||
if (fl->fl_owner != pid->real)
|
if (fl->fl_owner != pid->real)
|
||||||
continue;
|
continue;
|
||||||
} else if (fl->fl_kind == FL_LEASE) {
|
} else if (fl->fl_kind == FL_LEASE) {
|
||||||
pr_err("Leases are not supported for kernel <= v4.0");
|
if (fl->owners_fd >= 0)
|
||||||
return -1;
|
continue;
|
||||||
|
if (fl->fl_owner != pid->real &&
|
||||||
|
fl->real_owner != -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = lease_check_fd(lfd, p->flags, fl);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret == 0)
|
||||||
|
continue;
|
||||||
} else /* fl->fl_kind == FL_FLOCK || fl->fl_kind == FL_OFD */ {
|
} else /* fl->fl_kind == FL_FLOCK || fl->fl_kind == FL_OFD */ {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user