diff options
author | Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 2009-04-21 19:26:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-04-23 07:04:30 -0400 |
commit | af88b52def76679c8c5bcdbed199fbe62b6a16d4 (patch) | |
tree | a53c8d8f27a5b19cf10e5ca97abcad48261f7c1e /net/iucv | |
parent | 42e1b4c2c6c823ae26e64c557addf5329a7735b7 (diff) |
af_iucv: sync sk shutdown flag if iucv path is quiesced
If the af_iucv communication partner quiesces the path to shutdown its
receive direction, provide a quiesce callback implementation to shutdown
the (local) send direction. This ensures that both sides are synchronized.
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.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 49e786535dc8..6cf02b41ef95 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -54,6 +54,7 @@ static void iucv_callback_connack(struct iucv_path *, u8 ipuser[16]); | |||
54 | static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8], | 54 | static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8], |
55 | u8 ipuser[16]); | 55 | u8 ipuser[16]); |
56 | static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]); | 56 | static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]); |
57 | static void iucv_callback_shutdown(struct iucv_path *, u8 ipuser[16]); | ||
57 | 58 | ||
58 | static struct iucv_sock_list iucv_sk_list = { | 59 | static struct iucv_sock_list iucv_sk_list = { |
59 | .lock = __RW_LOCK_UNLOCKED(iucv_sk_list.lock), | 60 | .lock = __RW_LOCK_UNLOCKED(iucv_sk_list.lock), |
@@ -65,7 +66,8 @@ static struct iucv_handler af_iucv_handler = { | |||
65 | .path_complete = iucv_callback_connack, | 66 | .path_complete = iucv_callback_connack, |
66 | .path_severed = iucv_callback_connrej, | 67 | .path_severed = iucv_callback_connrej, |
67 | .message_pending = iucv_callback_rx, | 68 | .message_pending = iucv_callback_rx, |
68 | .message_complete = iucv_callback_txdone | 69 | .message_complete = iucv_callback_txdone, |
70 | .path_quiesced = iucv_callback_shutdown, | ||
69 | }; | 71 | }; |
70 | 72 | ||
71 | static inline void high_nmcpy(unsigned char *dst, char *src) | 73 | static inline void high_nmcpy(unsigned char *dst, char *src) |
@@ -1196,6 +1198,21 @@ static void iucv_callback_connrej(struct iucv_path *path, u8 ipuser[16]) | |||
1196 | sk->sk_state_change(sk); | 1198 | sk->sk_state_change(sk); |
1197 | } | 1199 | } |
1198 | 1200 | ||
1201 | /* called if the other communication side shuts down its RECV direction; | ||
1202 | * in turn, the callback sets SEND_SHUTDOWN to disable sending of data. | ||
1203 | */ | ||
1204 | static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16]) | ||
1205 | { | ||
1206 | struct sock *sk = path->private; | ||
1207 | |||
1208 | bh_lock_sock(sk); | ||
1209 | if (sk->sk_state != IUCV_CLOSED) { | ||
1210 | sk->sk_shutdown |= SEND_SHUTDOWN; | ||
1211 | sk->sk_state_change(sk); | ||
1212 | } | ||
1213 | bh_unlock_sock(sk); | ||
1214 | } | ||
1215 | |||
1199 | static struct proto_ops iucv_sock_ops = { | 1216 | static struct proto_ops iucv_sock_ops = { |
1200 | .family = PF_IUCV, | 1217 | .family = PF_IUCV, |
1201 | .owner = THIS_MODULE, | 1218 | .owner = THIS_MODULE, |