From b1abc3b21c19f8b326e0eaff50df9c6e12cbb3a7 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Mon, 14 Jan 2013 18:47:19 +0400 Subject: [PATCH] restore: don't desable tcp repair mode twice TCP repair mode should be disabled after unlocking connections. Disabling of repair mode drops SO_REUSEADDR, so it should be restored. Signed-off-by: Andrey Vagin Signed-off-by: Pavel Emelyanov --- include/restorer.h | 2 +- include/sk-inet.h | 5 +++++ pie/restorer.c | 17 ++++++++++++++--- sk-inet.c | 13 ++++++++----- sk-tcp.c | 14 ++++++++------ 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/include/restorer.h b/include/restorer.h index c3f2e838f..172d64257 100644 --- a/include/restorer.h +++ b/include/restorer.h @@ -122,7 +122,7 @@ struct task_restore_core_args { int nr_rlim; struct rlimit rlims[RLIM_NLIMITS]; - int *rst_tcp_socks; + struct rst_tcp_sock *rst_tcp_socks; int rst_tcp_socks_size; } __aligned(sizeof(long)); diff --git a/include/sk-inet.h b/include/sk-inet.h index 522f54926..6aa1b70da 100644 --- a/include/sk-inet.h +++ b/include/sk-inet.h @@ -45,6 +45,11 @@ struct inet_sk_info { int inet_bind(int sk, struct inet_sk_info *); int inet_connect(int sk, struct inet_sk_info *); +struct rst_tcp_sock { + int sk; + bool reuseaddr; +}; + static inline void tcp_repair_off(int fd) { int aux = 0; diff --git a/pie/restorer.c b/pie/restorer.c index 4320f2729..c01fce15a 100644 --- a/pie/restorer.c +++ b/pie/restorer.c @@ -274,15 +274,26 @@ static u64 restore_mapping(const VmaEntry *vma_entry) return addr; } -static void rst_tcp_socks_all(int *arr, int size) +static void rst_tcp_repair_off(struct rst_tcp_sock *rts) +{ + int aux; + + tcp_repair_off(rts->sk); + + aux = rts->reuseaddr; + if (sys_setsockopt(rts->sk, SOL_SOCKET, SO_REUSEADDR, &aux, sizeof(aux)) < 0) + pr_perror("Failed to restore of SO_REUSEADDR on socket"); +} + +static void rst_tcp_socks_all(struct rst_tcp_sock *arr, int size) { int i; if (size == 0) return; - for (i =0; arr[i] >= 0; i++) - tcp_repair_off(arr[i]); + for (i =0; arr[i].sk >= 0; i++) + rst_tcp_repair_off(arr + i); sys_munmap(arr, size); } diff --git a/sk-inet.c b/sk-inet.c index b411c28e3..f8b47c0f2 100644 --- a/sk-inet.c +++ b/sk-inet.c @@ -439,16 +439,19 @@ static int post_open_inet_sk(struct file_desc *d, int sk) ii = container_of(d, struct inet_sk_info, d); + /* + * TCP sockets are handled at the last moment + * after unlocking connections. + */ + if (tcp_connection(ii->ie)) + return 0; + /* SO_REUSEADDR is set for all sockets */ - if (!tcp_connection(ii->ie) && ii->ie->opts->reuseaddr) + if (ii->ie->opts->reuseaddr) return 0; futex_wait_until(&ii->port->users, 0); - /* Disabling repair mode drops SO_REUSEADDR */ - if (tcp_connection(ii->ie)) - tcp_repair_off(sk); - val = ii->ie->opts->reuseaddr; if (restore_opt(sk, SOL_SOCKET, SO_REUSEADDR, &val)) return -1; diff --git a/sk-tcp.c b/sk-tcp.c index ebf98154c..825f8b8a8 100644 --- a/sk-tcp.c +++ b/sk-tcp.c @@ -520,7 +520,7 @@ err: * rst_tcp_socks contains sockets in repair mode, * which will be off in restorer before resuming. */ -static int *rst_tcp_socks = NULL; +static struct rst_tcp_sock *rst_tcp_socks = NULL; static int rst_tcp_socks_num = 0; int rst_tcp_socks_size = 0; @@ -532,7 +532,7 @@ int rst_tcp_socks_remap(void *addr) return 0; } - rst_tcp_socks[rst_tcp_socks_num] = -1; + rst_tcp_socks[rst_tcp_socks_num].sk = -1; ret = mmap(addr, rst_tcp_socks_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); @@ -547,17 +547,19 @@ int rst_tcp_socks_remap(void *addr) return 0; } -static int rst_tcp_socks_add(int fd) +static int rst_tcp_socks_add(int fd, bool reuseaddr) { /* + 2 = ( new one + guard (-1) ) */ - if ((rst_tcp_socks_num + 2) * sizeof(int) > rst_tcp_socks_size) { + if ((rst_tcp_socks_num + 2) * sizeof(struct rst_tcp_sock) > rst_tcp_socks_size) { rst_tcp_socks_size += PAGE_SIZE; rst_tcp_socks = xrealloc(rst_tcp_socks, rst_tcp_socks_size); if (rst_tcp_socks == NULL) return -1; } - rst_tcp_socks[rst_tcp_socks_num++] = fd; + rst_tcp_socks[rst_tcp_socks_num].sk = fd; + rst_tcp_socks[rst_tcp_socks_num].reuseaddr = reuseaddr; + rst_tcp_socks_num++; return 0; } @@ -568,7 +570,7 @@ int restore_one_tcp(int fd, struct inet_sk_info *ii) if (tcp_repair_on(fd)) return -1; - if (rst_tcp_socks_add(fd)) + if (rst_tcp_socks_add(fd, ii->ie->opts->reuseaddr)) return -1; if (restore_tcp_conn_state(fd, ii))