Commit 4ea62143 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

crtools: add ability to create and close a service fd (v3)

A service fd should be created, otherwise get_service_fd returns -1.

This patch removes this functionality from other subsystems and
allows to clone service descriptors.

v2: rename open_service_fd to install_service_fd
v3: two patches were merged for bisecting
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent e6106956
...@@ -228,10 +228,9 @@ struct cr_fdset *cr_glob_fdset_open(int mode) ...@@ -228,10 +228,9 @@ struct cr_fdset *cr_glob_fdset_open(int mode)
return cr_fdset_open(-1 /* ignored */, _CR_FD_GLOB_FROM, _CR_FD_GLOB_TO, mode); return cr_fdset_open(-1 /* ignored */, _CR_FD_GLOB_FROM, _CR_FD_GLOB_TO, mode);
} }
static int image_dir_fd = -1;
int open_image(int type, unsigned long flags, ...) int open_image(int type, unsigned long flags, ...)
{ {
int dfd = get_service_fd(IMG_FD_OFF);
char path[PATH_MAX]; char path[PATH_MAX];
va_list args; va_list args;
int ret; int ret;
...@@ -241,14 +240,14 @@ int open_image(int type, unsigned long flags, ...) ...@@ -241,14 +240,14 @@ int open_image(int type, unsigned long flags, ...)
va_end(args); va_end(args);
if (flags & O_EXCL) { if (flags & O_EXCL) {
ret = unlinkat(image_dir_fd, path, 0); ret = unlinkat(dfd, path, 0);
if (ret && errno != ENOENT) { if (ret && errno != ENOENT) {
pr_perror("Unable to unlink %s", path); pr_perror("Unable to unlink %s", path);
goto err; goto err;
} }
} }
ret = openat(image_dir_fd, path, flags, CR_FD_PERM); ret = openat(dfd, path, flags, CR_FD_PERM);
if (ret < 0) { if (ret < 0) {
pr_perror("Unable to open %s", path); pr_perror("Unable to open %s", path);
goto err; goto err;
...@@ -279,13 +278,7 @@ err: ...@@ -279,13 +278,7 @@ err:
int open_image_dir(void) int open_image_dir(void)
{ {
int fd; int fd, ret;
image_dir_fd = get_service_fd(IMG_FD_OFF);
if (image_dir_fd < 0) {
pr_perror("Can't get image fd");
return -1;
}
fd = open(".", O_RDONLY); fd = open(".", O_RDONLY);
if (fd < 0) { if (fd < 0) {
...@@ -293,13 +286,14 @@ int open_image_dir(void) ...@@ -293,13 +286,14 @@ int open_image_dir(void)
return -1; return -1;
} }
pr_info("Image dir fd is %d\n", image_dir_fd); ret = install_service_fd(IMG_FD_OFF, fd);
close(fd);
return reopen_fd_as(image_dir_fd, fd); return ret;
} }
void close_image_dir(void) void close_image_dir(void)
{ {
close(image_dir_fd); close_service_fd(IMG_FD_OFF);
image_dir_fd = -1;
} }
...@@ -125,6 +125,8 @@ enum sfd_type { ...@@ -125,6 +125,8 @@ enum sfd_type {
extern int clone_service_fd(int id); extern int clone_service_fd(int id);
extern int init_service_fd(void); extern int init_service_fd(void);
extern int get_service_fd(enum sfd_type type); extern int get_service_fd(enum sfd_type type);
extern int install_service_fd(enum sfd_type type, int fd);
extern int close_service_fd(enum sfd_type type);
extern bool is_service_fd(int fd, enum sfd_type type); extern bool is_service_fd(int fd, enum sfd_type type);
extern bool is_any_service_fd(int fd); extern bool is_any_service_fd(int fd);
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#define DEFAULT_LOGFD STDERR_FILENO #define DEFAULT_LOGFD STDERR_FILENO
static unsigned int current_loglevel = DEFAULT_LOGLEVEL; static unsigned int current_loglevel = DEFAULT_LOGLEVEL;
static int current_logfd = DEFAULT_LOGFD;
static int logdir = -1;
static char buffer[PAGE_SIZE]; static char buffer[PAGE_SIZE];
static char buf_off = 0; static char buf_off = 0;
...@@ -55,27 +53,22 @@ static void print_ts(void) ...@@ -55,27 +53,22 @@ static void print_ts(void)
buffer[TS_BUF_OFF - 1] = ' '; /* kill the '\0' produced by snprintf */ buffer[TS_BUF_OFF - 1] = ' '; /* kill the '\0' produced by snprintf */
} }
int log_get_fd(void) int log_get_fd(void)
{ {
return current_logfd; int fd = get_service_fd(LOG_FD_OFF);
return fd < 0 ? DEFAULT_LOGFD : fd;
} }
int log_init(const char *output) int log_init(const char *output)
{ {
int new_logfd, sfd, dfd; int new_logfd, dfd, fd;
gettimeofday(&start, NULL); gettimeofday(&start, NULL);
buf_off = TS_BUF_OFF; buf_off = TS_BUF_OFF;
dfd = get_service_fd(LOG_DIR_FD_OFF); dfd = get_service_fd(LOG_DIR_FD_OFF);
if (dfd < 0) { if (dfd < 0) {
pr_msg("Can't obtain logfd");
goto err;
}
if (logdir < 0) {
int tmp; int tmp;
tmp = open(".", O_RDONLY); tmp = open(".", O_RDONLY);
if (tmp == -1) { if (tmp == -1) {
...@@ -83,40 +76,26 @@ int log_init(const char *output) ...@@ -83,40 +76,26 @@ int log_init(const char *output)
return -1; return -1;
} }
if (reopen_fd_as(dfd, tmp) < 0) dfd = install_service_fd(LOG_DIR_FD_OFF, tmp);
close(tmp);
if (dfd < 0)
return -1; return -1;
logdir = dfd;
}
sfd = get_service_fd(LOG_FD_OFF);
if (sfd < 0) {
pr_msg("Can't obtain logfd");
goto err;
} }
if (output) { if (output) {
new_logfd = openat(logdir, output, new_logfd = openat(dfd, output,
O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0600); O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0600);
if (new_logfd < 0) { if (new_logfd < 0) {
pr_perror("Can't create log file %s", output); pr_perror("Can't create log file %s", output);
return -1; return -1;
} }
} else
new_logfd = dup(DEFAULT_LOGFD);
if (sfd == current_logfd) fd = install_service_fd(LOG_FD_OFF, new_logfd);
close(sfd); close(new_logfd);
if (fd < 0)
if (reopen_fd_as(sfd, new_logfd) < 0)
goto err;
} else {
new_logfd = dup2(DEFAULT_LOGFD, sfd);
if (new_logfd < 0) {
pr_perror("Dup %d -> %d failed", DEFAULT_LOGFD, sfd);
goto err; goto err;
}
}
current_logfd = sfd;
return 0; return 0;
...@@ -151,15 +130,13 @@ int log_init_by_pid(void) ...@@ -151,15 +130,13 @@ int log_init_by_pid(void)
void log_fini(void) void log_fini(void)
{ {
if (current_logfd > 2) close_service_fd(LOG_FD_OFF);
close_safe(&current_logfd); log_closedir();
current_logfd = DEFAULT_LOGFD;
} }
void log_closedir(void) void log_closedir(void)
{ {
close_safe(&logdir); close_service_fd(LOG_DIR_FD_OFF);
} }
void log_set_loglevel(unsigned int level) void log_set_loglevel(unsigned int level)
...@@ -186,7 +163,7 @@ void print_on_level(unsigned int loglevel, const char *format, ...) ...@@ -186,7 +163,7 @@ void print_on_level(unsigned int loglevel, const char *format, ...)
} else { } else {
if (loglevel > current_loglevel) if (loglevel > current_loglevel)
return; return;
fd = current_logfd; fd = log_get_fd();
print_ts(); print_ts();
off = 0; off = 0;
} }
......
...@@ -94,7 +94,6 @@ struct tty_dump_info { ...@@ -94,7 +94,6 @@ struct tty_dump_info {
static LIST_HEAD(all_tty_info_entries); static LIST_HEAD(all_tty_info_entries);
static LIST_HEAD(all_ttys); static LIST_HEAD(all_ttys);
static int self_stdin = -1;
#define INHERIT_SID (-1) #define INHERIT_SID (-1)
...@@ -1196,15 +1195,12 @@ int dump_tty(struct fd_parms *p, int lfd, const int fdinfo) ...@@ -1196,15 +1195,12 @@ int dump_tty(struct fd_parms *p, int lfd, const int fdinfo)
int tty_prep_fds(void) int tty_prep_fds(void)
{ {
self_stdin = get_service_fd(SELF_STDIN_OFF);
if (!isatty(STDIN_FILENO)) { if (!isatty(STDIN_FILENO)) {
pr_err("Standart stream is not a terminal, aborting\n"); pr_err("Standart stream is not a terminal, aborting\n");
return -1; return -1;
} }
if (dup2(STDIN_FILENO, self_stdin) < 0) { if (install_service_fd(SELF_STDIN_OFF, STDIN_FILENO) < 0) {
self_stdin = -1;
pr_perror("Can't dup stdin to SELF_STDIN_OFF"); pr_perror("Can't dup stdin to SELF_STDIN_OFF");
return -1; return -1;
} }
...@@ -1214,5 +1210,5 @@ int tty_prep_fds(void) ...@@ -1214,5 +1210,5 @@ int tty_prep_fds(void)
void tty_fini_fds(void) void tty_fini_fds(void)
{ {
close_safe(&self_stdin); close_service_fd(SELF_STDIN_OFF);
} }
...@@ -173,7 +173,6 @@ int move_img_fd(int *img_fd, int want_fd) ...@@ -173,7 +173,6 @@ int move_img_fd(int *img_fd, int want_fd)
static pid_t open_proc_pid = 0; static pid_t open_proc_pid = 0;
static int open_proc_fd = -1; static int open_proc_fd = -1;
static int proc_dir_fd = -1;
int close_pid_proc(void) int close_pid_proc(void)
{ {
...@@ -191,30 +190,18 @@ int close_pid_proc(void) ...@@ -191,30 +190,18 @@ int close_pid_proc(void)
void close_proc() void close_proc()
{ {
close_pid_proc(); close_pid_proc();
if (proc_dir_fd > 0)
close(proc_dir_fd); close_service_fd(PROC_FD_OFF);
proc_dir_fd = -1;
} }
int set_proc_fd(int fd) int set_proc_fd(int fd)
{ {
int sfd = get_service_fd(PROC_FD_OFF); return install_service_fd(PROC_FD_OFF, fd);
sfd = dup2(fd, sfd);
if (sfd < 0) {
pr_perror("Can't set proc fd\n");
return -1;
}
proc_dir_fd = sfd;
return 0;
} }
int set_proc_mountpoint(char *path) int set_proc_mountpoint(char *path)
{ {
int sfd = get_service_fd(PROC_FD_OFF), fd; int fd, ret;
close_proc(); close_proc();
fd = open(path, O_DIRECTORY | O_RDONLY); fd = open(path, O_DIRECTORY | O_RDONLY);
...@@ -223,14 +210,10 @@ int set_proc_mountpoint(char *path) ...@@ -223,14 +210,10 @@ int set_proc_mountpoint(char *path)
return -1; return -1;
} }
sfd = dup2(fd, sfd); ret = install_service_fd(PROC_FD_OFF, fd);
close(fd); close(fd);
if (sfd < 0) { if (ret < 0)
pr_err("Can't set proc fd\n");
return -1; return -1;
}
proc_dir_fd = sfd;
return 0; return 0;
} }
...@@ -239,20 +222,23 @@ inline int open_pid_proc(pid_t pid) ...@@ -239,20 +222,23 @@ inline int open_pid_proc(pid_t pid)
{ {
char path[18]; char path[18];
int fd; int fd;
int dfd;
if (pid == open_proc_pid) if (pid == open_proc_pid)
return open_proc_fd; return open_proc_fd;
close_pid_proc(); close_pid_proc();
if (proc_dir_fd == -1) { dfd = get_service_fd(PROC_FD_OFF);
fd = set_proc_mountpoint("/proc"); if (dfd < 0) {
if (fd < 0) if (set_proc_mountpoint("/proc") < 0)
return fd; return -1;
dfd = get_service_fd(PROC_FD_OFF);
} }
snprintf(path, sizeof(path), "%d", pid); snprintf(path, sizeof(path), "%d", pid);
fd = openat(proc_dir_fd, path, O_RDONLY); fd = openat(dfd, path, O_RDONLY);
if (fd < 0) if (fd < 0)
pr_perror("Can't open %s", path); pr_perror("Can't open %s", path);
else { else {
...@@ -307,12 +293,48 @@ static int __get_service_fd(enum sfd_type type, int service_fd_id) ...@@ -307,12 +293,48 @@ static int __get_service_fd(enum sfd_type type, int service_fd_id)
return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id; return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id;
} }
static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX);
int install_service_fd(enum sfd_type type, int fd)
{
int sfd = __get_service_fd(type, service_fd_id);
BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
if (dup2(fd, sfd) != sfd) {
pr_perror("Dup %d -> %d failed", fd, sfd);
return -1;
}
set_bit(type, sfd_map);
return sfd;
}
int get_service_fd(enum sfd_type type) int get_service_fd(enum sfd_type type)
{ {
BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX); BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
if (!test_bit(type, sfd_map))
return -1;
return __get_service_fd(type, service_fd_id); return __get_service_fd(type, service_fd_id);
} }
int close_service_fd(enum sfd_type type)
{
int fd;
fd = get_service_fd(type);
if (fd < 0)
return 0;
if (close_safe(&fd))
return -1;
clear_bit(type, sfd_map);
return 0;
}
int clone_service_fd(int id) int clone_service_fd(int id)
{ {
int ret = -1, i; int ret = -1, i;
......
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