From: VMware, Inc <> Date: Thu, 24 Feb 2011 22:04:22 +0000 (-0800) Subject: Hang in VMCISockets caused by uninitialized notification state. X-Git-Tag: 2011.02.23-368700~35 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=894b5dcf36b8025c145fa48c5966fb7e123dfd17;p=thirdparty%2Fopen-vm-tools.git Hang in VMCISockets caused by uninitialized notification state. It turns out that a recent unload/shutdown fix broke the notification code. We don't call the notification functions when the qpair is invalid, to guard against touching the qpair after the device has shutdown, but some of those functions need to be called *before* a qpair is actually attached. There are actually a few of them, so rather than introduce a new macro for notifications that don't need qpairs, I've removed the qpair check from the macros and embedded it as necessary in the notification code. We also uncovered a problem where if the notification write window is less than a page we can underflow. Fixed on all platforms. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/modules/linux/vsock/linux/notify.c b/open-vm-tools/modules/linux/vsock/linux/notify.c index a6e61bc3d..4fbe5b4c6 100644 --- a/open-vm-tools/modules/linux/vsock/linux/notify.c +++ b/open-vm-tools/modules/linux/vsock/linux/notify.c @@ -77,11 +77,16 @@ VSockVmciNotifyWaitingWrite(VSockVmciSock *vsk) // IN if (!PKT_FIELD(vsk, peerWaitingWriteDetected)) { PKT_FIELD(vsk, peerWaitingWriteDetected) = TRUE; - PKT_FIELD(vsk, writeNotifyWindow) -= PAGE_SIZE; - if (PKT_FIELD(vsk, writeNotifyWindow) < - PKT_FIELD(vsk, writeNotifyMinWindow)) { + if (PKT_FIELD(vsk, writeNotifyWindow) < PAGE_SIZE) { PKT_FIELD(vsk, writeNotifyWindow) = PKT_FIELD(vsk, writeNotifyMinWindow); + } else { + PKT_FIELD(vsk, writeNotifyWindow) -= PAGE_SIZE; + if (PKT_FIELD(vsk, writeNotifyWindow) < + PKT_FIELD(vsk, writeNotifyMinWindow)) { + PKT_FIELD(vsk, writeNotifyWindow) = + PKT_FIELD(vsk, writeNotifyMinWindow); + } } } notifyLimit = vsk->consumeSize - PKT_FIELD(vsk, writeNotifyWindow); @@ -538,7 +543,7 @@ VSockVmciNotifyPktSocketInit(struct sock *sk) // IN VSockVmciSock *vsk; vsk = vsock_sk(sk); - PKT_FIELD(vsk, writeNotifyWindow) = 0; + PKT_FIELD(vsk, writeNotifyWindow) = PAGE_SIZE; PKT_FIELD(vsk, writeNotifyMinWindow) = PAGE_SIZE; PKT_FIELD(vsk, peerWaitingRead) = FALSE; PKT_FIELD(vsk, peerWaitingWrite) = FALSE; @@ -1151,6 +1156,9 @@ VSockVmciNotifyPktProcessRequest(struct sock *sk) // IN vsk = vsock_sk(sk); PKT_FIELD(vsk, writeNotifyWindow) = vsk->consumeSize; + if (vsk->consumeSize < PKT_FIELD(vsk, writeNotifyMinWindow)) { + PKT_FIELD(vsk, writeNotifyMinWindow) = vsk->consumeSize; + } } @@ -1180,6 +1188,9 @@ VSockVmciNotifyPktProcessNegotiate(struct sock *sk) // IN vsk = vsock_sk(sk); PKT_FIELD(vsk, writeNotifyWindow) = vsk->consumeSize; + if (vsk->consumeSize < PKT_FIELD(vsk, writeNotifyMinWindow)) { + PKT_FIELD(vsk, writeNotifyMinWindow) = vsk->consumeSize; + } } diff --git a/open-vm-tools/modules/linux/vsock/linux/notifyQState.c b/open-vm-tools/modules/linux/vsock/linux/notifyQState.c index 59f2f760e..5b1cb6066 100644 --- a/open-vm-tools/modules/linux/vsock/linux/notifyQState.c +++ b/open-vm-tools/modules/linux/vsock/linux/notifyQState.c @@ -74,11 +74,16 @@ VSockVmciNotifyWaitingWrite(VSockVmciSock *vsk) // IN if (!PKT_FIELD(vsk, peerWaitingWriteDetected)) { PKT_FIELD(vsk, peerWaitingWriteDetected) = TRUE; - PKT_FIELD(vsk, writeNotifyWindow) -= PAGE_SIZE; - if (PKT_FIELD(vsk, writeNotifyWindow) < - PKT_FIELD(vsk, writeNotifyMinWindow)) { + if (PKT_FIELD(vsk, writeNotifyWindow) < PAGE_SIZE) { PKT_FIELD(vsk, writeNotifyWindow) = PKT_FIELD(vsk, writeNotifyMinWindow); + } else { + PKT_FIELD(vsk, writeNotifyWindow) -= PAGE_SIZE; + if (PKT_FIELD(vsk, writeNotifyWindow) < + PKT_FIELD(vsk, writeNotifyMinWindow)) { + PKT_FIELD(vsk, writeNotifyWindow) = + PKT_FIELD(vsk, writeNotifyMinWindow); + } } } notifyLimit = vsk->consumeSize - PKT_FIELD(vsk, writeNotifyWindow); @@ -278,7 +283,7 @@ VSockVmciNotifyPktSocketInit(struct sock *sk) // IN VSockVmciSock *vsk; vsk = vsock_sk(sk); - PKT_FIELD(vsk, writeNotifyWindow) = 0; + PKT_FIELD(vsk, writeNotifyWindow) = PAGE_SIZE; PKT_FIELD(vsk, writeNotifyMinWindow) = PAGE_SIZE; PKT_FIELD(vsk, peerWaitingWrite) = FALSE; PKT_FIELD(vsk, peerWaitingWriteDetected) = FALSE; @@ -307,11 +312,10 @@ VSockVmciNotifyPktSocketDestruct(struct sock *sk) // IN VSockVmciSock *vsk; vsk = vsock_sk(sk); - PKT_FIELD(vsk, writeNotifyWindow) = 0; + PKT_FIELD(vsk, writeNotifyWindow) = PAGE_SIZE; PKT_FIELD(vsk, writeNotifyMinWindow) = PAGE_SIZE; PKT_FIELD(vsk, peerWaitingWrite) = FALSE; PKT_FIELD(vsk, peerWaitingWriteDetected) = FALSE; - return; } @@ -731,6 +735,9 @@ VSockVmciNotifyPktProcessRequest(struct sock *sk) // IN vsk = vsock_sk(sk); PKT_FIELD(vsk, writeNotifyWindow) = vsk->consumeSize; + if (vsk->consumeSize < PKT_FIELD(vsk, writeNotifyMinWindow)) { + PKT_FIELD(vsk, writeNotifyMinWindow) = vsk->consumeSize; + } } @@ -760,6 +767,9 @@ VSockVmciNotifyPktProcessNegotiate(struct sock *sk) // IN vsk = vsock_sk(sk); PKT_FIELD(vsk, writeNotifyWindow) = vsk->consumeSize; + if (vsk->consumeSize < PKT_FIELD(vsk, writeNotifyMinWindow)) { + PKT_FIELD(vsk, writeNotifyMinWindow) = vsk->consumeSize; + } }