Commit b9c14a09 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

kerndat: check the lock field in fdinfo (v2)

Starting with the 4.1 kernel, fdinfo contains information about file
locks.

v2: s/has_lock/has_fdinfo_lock/
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent a0497682
......@@ -671,6 +671,23 @@ static int check_aio_remap(void)
return 0;
}
static int check_fdinfo_lock(void)
{
if (kerndat_fdinfo_has_lock())
return -1;
if (!kdat.has_fdinfo_lock) {
if (!opts.check_ms_kernel) {
pr_err("fdinfo doesn't contain the lock field\n");
return -1;
} else {
pr_warn("fdinfo doesn't contain the lock field\n");
}
}
return 0;
}
static int (*chk_feature)(void);
int cr_check(void)
......@@ -723,6 +740,7 @@ int cr_check(void)
ret |= check_timerfd();
ret |= check_mnt_id();
ret |= check_aio_remap();
ret |= check_fdinfo_lock();
out:
if (!ret)
......@@ -774,6 +792,8 @@ int check_add_feature(char *feat)
chk_feature = check_tun;
else if (!strcmp(feat, "userns"))
chk_feature = check_userns;
else if (!strcmp(feat, "fdinfo_lock"))
chk_feature = check_fdinfo_lock;
else {
pr_err("Unknown feature %s\n", feat);
return -1;
......
......@@ -13,6 +13,7 @@ struct stat;
extern int kerndat_init(void);
extern int kerndat_init_rst(void);
extern int kerndat_get_dirty_track(void);
extern int kerndat_fdinfo_has_lock(void);
struct kerndat_s {
dev_t shmem_dev;
......@@ -21,6 +22,7 @@ struct kerndat_s {
u64 zero_page_pfn;
bool has_dirty_track;
bool has_memfd;
bool has_fdinfo_lock;
};
extern struct kerndat_s kdat;
......
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
......@@ -273,6 +274,42 @@ static bool kerndat_has_memfd_create(void)
return 0;
}
int kerndat_fdinfo_has_lock()
{
int fd, pfd = -1, exit_code = -1, len;
char buf[PAGE_SIZE];
fd = open("/proc/locks", O_RDONLY);
if (fd < 0) {
pr_perror("Unable to open /proc/locks");
return -1;
}
if (flock(fd, LOCK_SH)) {
pr_perror("Can't take a lock\n");
return -1;
}
pfd = open_proc(PROC_SELF, "fdinfo/%d", fd);
if (pfd < 0)
goto out;
len = read(pfd, buf, sizeof(buf));
if (len < 0) {
pr_perror("Unable to read");
goto out;
}
kdat.has_fdinfo_lock = (strstr(buf, "lock:") != NULL);
exit_code = 0;
out:
close(pfd);
close(fd);
return exit_code;
}
int kerndat_init(void)
{
int ret;
......@@ -284,6 +321,8 @@ int kerndat_init(void)
ret = init_zero_page_pfn();
if (!ret)
ret = get_last_cap();
if (!ret)
ret = kerndat_fdinfo_has_lock();
return ret;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment