aboutsummaryrefslogtreecommitdiffstats
path: root/net/iucv
diff options
context:
space:
mode:
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>2009-04-21 02:04:24 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-22 02:43:15 -0400
commit3fa6b5adbe46b3d665267dee0f879858ab464f44 (patch)
tree4c526871b0195570f9844e6e586611c1fa4731e8 /net/iucv
parente14ad5fa8705fb354e72312479abbe420ebc3f8e (diff)
af_iucv: Fix race when queuing incoming iucv messages
AF_IUCV runs into a race when queuing incoming iucv messages and receiving the resulting backlog. If the Linux system is under pressure (high load or steal time), the message queue grows up, but messages are not received and queued onto the backlog queue. In that case, applications do not receive any data with recvmsg() even if AF_IUCV puts incoming messages onto the message queue. The race can be avoided if the message queue spinlock in the message_pending callback is spreaded across the entire callback function. Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/iucv')
-rw-r--r--net/iucv/af_iucv.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 9cfdaaddc5b2..b51c9187c347 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -1124,6 +1124,8 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
1124 return; 1124 return;
1125 } 1125 }
1126 1126
1127 spin_lock(&iucv->message_q.lock);
1128
1127 if (!list_empty(&iucv->message_q.list) || 1129 if (!list_empty(&iucv->message_q.list) ||
1128 !skb_queue_empty(&iucv->backlog_skb_q)) 1130 !skb_queue_empty(&iucv->backlog_skb_q))
1129 goto save_message; 1131 goto save_message;
@@ -1137,9 +1139,8 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
1137 if (!skb) 1139 if (!skb)
1138 goto save_message; 1140 goto save_message;
1139 1141
1140 spin_lock(&iucv->message_q.lock);
1141 iucv_process_message(sk, skb, path, msg); 1142 iucv_process_message(sk, skb, path, msg);
1142 spin_unlock(&iucv->message_q.lock); 1143 goto out_unlock;
1143 1144
1144 return; 1145 return;
1145 1146
@@ -1150,8 +1151,9 @@ save_message:
1150 save_msg->path = path; 1151 save_msg->path = path;
1151 save_msg->msg = *msg; 1152 save_msg->msg = *msg;
1152 1153
1153 spin_lock(&iucv->message_q.lock);
1154 list_add_tail(&save_msg->list, &iucv->message_q.list); 1154 list_add_tail(&save_msg->list, &iucv->message_q.list);
1155
1156out_unlock:
1155 spin_unlock(&iucv->message_q.lock); 1157 spin_unlock(&iucv->message_q.lock);
1156} 1158}
1157 1159