|
@@ -54,6 +54,7 @@ static void iucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
|
|
|
static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8],
|
|
|
u8 ipuser[16]);
|
|
|
static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
|
|
|
+static void iucv_callback_shutdown(struct iucv_path *, u8 ipuser[16]);
|
|
|
|
|
|
static struct iucv_sock_list iucv_sk_list = {
|
|
|
.lock = __RW_LOCK_UNLOCKED(iucv_sk_list.lock),
|
|
@@ -65,7 +66,8 @@ static struct iucv_handler af_iucv_handler = {
|
|
|
.path_complete = iucv_callback_connack,
|
|
|
.path_severed = iucv_callback_connrej,
|
|
|
.message_pending = iucv_callback_rx,
|
|
|
- .message_complete = iucv_callback_txdone
|
|
|
+ .message_complete = iucv_callback_txdone,
|
|
|
+ .path_quiesced = iucv_callback_shutdown,
|
|
|
};
|
|
|
|
|
|
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])
|
|
|
sk->sk_state_change(sk);
|
|
|
}
|
|
|
|
|
|
+/* called if the other communication side shuts down its RECV direction;
|
|
|
+ * in turn, the callback sets SEND_SHUTDOWN to disable sending of data.
|
|
|
+ */
|
|
|
+static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16])
|
|
|
+{
|
|
|
+ struct sock *sk = path->private;
|
|
|
+
|
|
|
+ bh_lock_sock(sk);
|
|
|
+ if (sk->sk_state != IUCV_CLOSED) {
|
|
|
+ sk->sk_shutdown |= SEND_SHUTDOWN;
|
|
|
+ sk->sk_state_change(sk);
|
|
|
+ }
|
|
|
+ bh_unlock_sock(sk);
|
|
|
+}
|
|
|
+
|
|
|
static struct proto_ops iucv_sock_ops = {
|
|
|
.family = PF_IUCV,
|
|
|
.owner = THIS_MODULE,
|