[RFC,1/2] sk-unix: ignore shutdown mismatch in unix sockets

Submitted by Andrey Ryabinin on May 19, 2016, 3:55 p.m.

Details

Message ID 1463673337-12026-2-git-send-email-aryabinin@virtuozzo.com
State Accepted
Series "Handle unix stream sockets with mismatch in shutdown state"
Commit e15f7766a4f468e1b514de3240607d87d7e3bc51
Headers show

Commit Message

Andrey Ryabinin May 19, 2016, 3:55 p.m.
Usually unix stream sockets have consistent shutdown state
(if one end shutdown for read than other end will be shut down for write).
However sometimes it's possible to have stream sockets with mismatched
shutdown state. This happens if we connect() already shut down socket
(see upcoming sockets03.c test for example).

On read()/write() kernel always checks shutdown state on both ends, so
from userspace POV sockets with mismatched shutdown state behave the same
way as with matched state. So I think that we can just ignore shutdown
mismatch during dump, and just restore sockets with matching shutdown
state. Process should not see the differences.

Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 criu/sk-unix.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index 1396d76..b21dd4b 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -371,12 +371,15 @@  static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 				((ue->shutdown == SK_SHUTDOWN__BOTH)  &&
 				 (peer->shutdown != SK_SHUTDOWN__BOTH)) )) {
 			/*
-			 * On restore we assume, that stream pairs must
-			 * be shut down from one end only
+			 * Usually this doesn't happen, however it's possible if
+			 * socket was shut down before connect() (see sockets03.c test).
+			 * On restore we will shutdown both end (iow socktes will be in
+			 * matched state). This shoudn't be a problem, since kernel seems
+			 * to check both ends on read()/write(). Thus mismatched sockets behave
+			 * the same way as matched.
 			 */
-			pr_err("Shutdown mismatch %u:%d -> %u:%d\n",
+			pr_warn("Shutdown mismatch %u:%d -> %u:%d\n",
 					ue->ino, ue->shutdown, peer->sd.ino, peer->shutdown);
-			goto err;
 		}
 	} else if (ue->state == TCP_ESTABLISHED) {
 		const struct unix_sk_listen_icon *e;
@@ -1066,13 +1069,8 @@  static int open_unixsk_pair_slave(struct unix_sk_info *ui)
 	if (restore_socket_opts(sk, ui->ue->opts))
 		return -1;
 
-	if (ui->ue->type == SOCK_DGRAM)
-		/*
-		 * Stream socket's "slave" end will be shut down
-		 * together with master
-		 */
-		if (shutdown_unix_sk(sk, ui))
-			return -1;
+	if (shutdown_unix_sk(sk, ui))
+		return -1;
 
 	return sk;
 }