* [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1
@ 2009-04-22 9:26 Ursula Braun
2009-04-22 9:26 ` [patch 1/8] [PATCH] iucv: provide second per-cpu IUCV command parameter block Ursula Braun
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390; +Cc: schwidefsky, heiko.carstens
Dave,
thanks for applying our critical af_iucv bug fixes to net-2.6.
Here is now the series of iucv / af_iucv patches for the current
development cycle.
The patches are based on top of the current net-next-2.6 kernel
(2.6.30-rc1).
Hendrik Brueckner (7)
af_iucv: sync sk shutdown flag if iucv path is quiesced
af_iucv: add sockopt() to enable/disable use of IPRM_DATA msgs
af_iucv: Support data in IUCV msg parameter lists (IPRMDATA)
af_iucv: Modify iucv msg target class using control msghdr
af_iucv: Provide new socket type SOCK_SEQPACKET
af_iucv: cleanup and refactor recvmsg() EFAULT handling
af_iucv: New socket option for setting IUCV MSGLIMITs
Ursula Braun (1):
iucv: provide second per-cpu IUCV command parameter block
Kind regards,
Ursula Braun
^ permalink raw reply [flat|nested] 10+ messages in thread
* [patch 1/8] [PATCH] iucv: provide second per-cpu IUCV command parameter block
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
@ 2009-04-22 9:26 ` Ursula Braun
2009-04-22 9:26 ` [patch 2/8] [PATCH] af_iucv: sync sk shutdown flag if iucv path is quiesced Ursula Braun
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390; +Cc: schwidefsky, heiko.carstens, Ursula Braun
[-- Attachment #1: 600-iucv-2ndparm.diff --]
[-- Type: text/plain, Size: 4740 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
Some of the IUCV commands can be invoked in interrupt context.
Those commands need a different per-cpu IUCV command parameter block,
otherwise they might overwrite an IUCV command parameter of a not yet
finished IUCV command invocation in process context.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
---
net/iucv/iucv.c | 41 +++++++++++++++++++++++++++++++----------
1 file changed, 31 insertions(+), 10 deletions(-)
diff -urpN linux-2.6/net/iucv/iucv.c linux-2.6-patched/net/iucv/iucv.c
--- linux-2.6/net/iucv/iucv.c 2009-03-04 15:58:05.000000000 +0100
+++ linux-2.6-patched/net/iucv/iucv.c 2009-03-04 15:58:26.000000000 +0100
@@ -280,6 +280,7 @@ union iucv_param {
* Anchor for per-cpu IUCV command parameter block.
*/
static union iucv_param *iucv_param[NR_CPUS];
+static union iucv_param *iucv_param_irq[NR_CPUS];
/**
* iucv_call_b2f0
@@ -358,7 +359,7 @@ static void iucv_allow_cpu(void *data)
* 0x10 - Flag to allow priority message completion interrupts
* 0x08 - Flag to allow IUCV control interrupts
*/
- parm = iucv_param[cpu];
+ parm = iucv_param_irq[cpu];
memset(parm, 0, sizeof(union iucv_param));
parm->set_mask.ipmask = 0xf8;
iucv_call_b2f0(IUCV_SETMASK, parm);
@@ -379,7 +380,7 @@ static void iucv_block_cpu(void *data)
union iucv_param *parm;
/* Disable all iucv interrupts. */
- parm = iucv_param[cpu];
+ parm = iucv_param_irq[cpu];
memset(parm, 0, sizeof(union iucv_param));
iucv_call_b2f0(IUCV_SETMASK, parm);
@@ -403,7 +404,7 @@ static void iucv_declare_cpu(void *data)
return;
/* Declare interrupt buffer. */
- parm = iucv_param[cpu];
+ parm = iucv_param_irq[cpu];
memset(parm, 0, sizeof(union iucv_param));
parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]);
rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
@@ -460,7 +461,7 @@ static void iucv_retrieve_cpu(void *data
iucv_block_cpu(NULL);
/* Retrieve interrupt buffer. */
- parm = iucv_param[cpu];
+ parm = iucv_param_irq[cpu];
iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm);
/* Clear indication that an iucv buffer exists for this cpu. */
@@ -574,11 +575,22 @@ static int __cpuinit iucv_cpu_notify(str
iucv_irq_data[cpu] = NULL;
return NOTIFY_BAD;
}
+ iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
+ GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+ if (!iucv_param_irq[cpu]) {
+ kfree(iucv_param[cpu]);
+ iucv_param[cpu] = NULL;
+ kfree(iucv_irq_data[cpu]);
+ iucv_irq_data[cpu] = NULL;
+ return NOTIFY_BAD;
+ }
break;
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
+ kfree(iucv_param_irq[cpu]);
+ iucv_param_irq[cpu] = NULL;
kfree(iucv_param[cpu]);
iucv_param[cpu] = NULL;
kfree(iucv_irq_data[cpu]);
@@ -625,7 +637,7 @@ static int iucv_sever_pathid(u16 pathid,
{
union iucv_param *parm;
- parm = iucv_param[smp_processor_id()];
+ parm = iucv_param_irq[smp_processor_id()];
memset(parm, 0, sizeof(union iucv_param));
if (userdata)
memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser));
@@ -918,10 +930,8 @@ int iucv_path_sever(struct iucv_path *pa
if (iucv_active_cpu != smp_processor_id())
spin_lock_bh(&iucv_table_lock);
rc = iucv_sever_pathid(path->pathid, userdata);
- if (!rc) {
- iucv_path_table[path->pathid] = NULL;
- list_del_init(&path->list);
- }
+ iucv_path_table[path->pathid] = NULL;
+ list_del_init(&path->list);
if (iucv_active_cpu != smp_processor_id())
spin_unlock_bh(&iucv_table_lock);
preempt_enable();
@@ -1413,7 +1423,7 @@ static void iucv_path_severed(struct iuc
else {
iucv_sever_pathid(path->pathid, NULL);
iucv_path_table[path->pathid] = NULL;
- list_del_init(&path->list);
+ list_del(&path->list);
iucv_path_free(path);
}
}
@@ -1717,6 +1727,13 @@ static int __init iucv_init(void)
rc = -ENOMEM;
goto out_free;
}
+ iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
+ GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+ if (!iucv_param_irq[cpu]) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+
}
rc = register_hotcpu_notifier(&iucv_cpu_notifier);
if (rc)
@@ -1734,6 +1751,8 @@ out_cpu:
unregister_hotcpu_notifier(&iucv_cpu_notifier);
out_free:
for_each_possible_cpu(cpu) {
+ kfree(iucv_param_irq[cpu]);
+ iucv_param_irq[cpu] = NULL;
kfree(iucv_param[cpu]);
iucv_param[cpu] = NULL;
kfree(iucv_irq_data[cpu]);
@@ -1764,6 +1783,8 @@ static void __exit iucv_exit(void)
spin_unlock_irq(&iucv_queue_lock);
unregister_hotcpu_notifier(&iucv_cpu_notifier);
for_each_possible_cpu(cpu) {
+ kfree(iucv_param_irq[cpu]);
+ iucv_param_irq[cpu] = NULL;
kfree(iucv_param[cpu]);
iucv_param[cpu] = NULL;
kfree(iucv_irq_data[cpu]);
^ permalink raw reply [flat|nested] 10+ messages in thread
* [patch 2/8] [PATCH] af_iucv: sync sk shutdown flag if iucv path is quiesced
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
2009-04-22 9:26 ` [patch 1/8] [PATCH] iucv: provide second per-cpu IUCV command parameter block Ursula Braun
@ 2009-04-22 9:26 ` Ursula Braun
2009-04-22 9:26 ` [patch 3/8] [PATCH] af_iucv: add sockopt() to enable/disable use of IPRM_DATA msgs Ursula Braun
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390
Cc: schwidefsky, heiko.carstens, Hendrik Brueckner, Ursula Braun
[-- Attachment #1: 605-af_iucv-sync-shutdown.diff --]
[-- Type: text/plain, Size: 2081 bytes --]
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
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>
---
net/iucv/af_iucv.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
Index: net-next-2.6-uschi/net/iucv/af_iucv.c
===================================================================
--- net-next-2.6-uschi.orig/net/iucv/af_iucv.c
+++ net-next-2.6-uschi/net/iucv/af_iucv.c
@@ -54,6 +54,7 @@ static void iucv_callback_connack(struct
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_handl
.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
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,
^ permalink raw reply [flat|nested] 10+ messages in thread
* [patch 3/8] [PATCH] af_iucv: add sockopt() to enable/disable use of IPRM_DATA msgs
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
2009-04-22 9:26 ` [patch 1/8] [PATCH] iucv: provide second per-cpu IUCV command parameter block Ursula Braun
2009-04-22 9:26 ` [patch 2/8] [PATCH] af_iucv: sync sk shutdown flag if iucv path is quiesced Ursula Braun
@ 2009-04-22 9:26 ` Ursula Braun
2009-04-22 9:26 ` [patch 4/8] [PATCH] af_iucv: Support data in IUCV msg parameter lists (IPRMDATA) Ursula Braun
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390
Cc: schwidefsky, heiko.carstens, Hendrik Brueckner, Ursula Braun
[-- Attachment #1: 607-af_iucv-iprm-sockopt.diff --]
[-- Type: text/plain, Size: 4096 bytes --]
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Provide the socket operations getsocktopt() and setsockopt() to enable/disable
sending of data in the parameter list of IUCV messages.
The patch sets respective flag only.
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
---
include/linux/socket.h | 1
include/net/iucv/af_iucv.h | 4 ++
net/iucv/af_iucv.c | 79 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 81 insertions(+), 3 deletions(-)
Index: net-next-2.6-uschi/include/linux/socket.h
===================================================================
--- net-next-2.6-uschi.orig/include/linux/socket.h
+++ net-next-2.6-uschi/include/linux/socket.h
@@ -303,6 +303,7 @@ struct ucred {
#define SOL_BLUETOOTH 274
#define SOL_PNPIPE 275
#define SOL_RDS 276
+#define SOL_IUCV 277
/* IPX options */
#define IPX_TYPE 1
Index: net-next-2.6-uschi/include/net/iucv/af_iucv.h
===================================================================
--- net-next-2.6-uschi.orig/include/net/iucv/af_iucv.h
+++ net-next-2.6-uschi/include/net/iucv/af_iucv.h
@@ -73,8 +73,12 @@ struct iucv_sock {
struct sk_buff_head backlog_skb_q;
struct sock_msg_q message_q;
unsigned int send_tag;
+ u8 flags;
};
+/* iucv socket options (SOL_IUCV) */
+#define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */
+
struct iucv_sock_list {
struct hlist_head head;
rwlock_t lock;
Index: net-next-2.6-uschi/net/iucv/af_iucv.c
===================================================================
--- net-next-2.6-uschi.orig/net/iucv/af_iucv.c
+++ net-next-2.6-uschi/net/iucv/af_iucv.c
@@ -32,7 +32,7 @@
#define CONFIG_IUCV_SOCK_DEBUG 1
#define IPRMDATA 0x80
-#define VERSION "1.0"
+#define VERSION "1.1"
static char iucv_userid[80];
@@ -226,6 +226,7 @@ static struct sock *iucv_sock_alloc(stru
spin_lock_init(&iucv_sk(sk)->message_q.lock);
skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q);
iucv_sk(sk)->send_tag = 0;
+ iucv_sk(sk)->flags = 0;
sk->sk_destruct = iucv_sock_destruct;
sk->sk_sndtimeo = IUCV_CONN_TIMEOUT;
@@ -1003,6 +1004,78 @@ static int iucv_sock_release(struct sock
return err;
}
+/* getsockopt and setsockopt */
+static int iucv_sock_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int optlen)
+{
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ int val;
+ int rc;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+
+ if (optlen < sizeof(int))
+ return -EINVAL;
+
+ if (get_user(val, (int __user *) optval))
+ return -EFAULT;
+
+ rc = 0;
+
+ lock_sock(sk);
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ if (val)
+ iucv->flags |= IUCV_IPRMDATA;
+ else
+ iucv->flags &= ~IUCV_IPRMDATA;
+ break;
+ default:
+ rc = -ENOPROTOOPT;
+ break;
+ }
+ release_sock(sk);
+
+ return rc;
+}
+
+static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ int val, len;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ if (len < 0)
+ return -EINVAL;
+
+ len = min_t(unsigned int, len, sizeof(int));
+
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
+ break;
+ default:
+ return -ENOPROTOOPT;
+ }
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &val, len))
+ return -EFAULT;
+
+ return 0;
+}
+
+
/* Callback wrappers - called from iucv base support */
static int iucv_callback_connreq(struct iucv_path *path,
u8 ipvmid[8], u8 ipuser[16])
@@ -1229,8 +1302,8 @@ static struct proto_ops iucv_sock_ops =
.mmap = sock_no_mmap,
.socketpair = sock_no_socketpair,
.shutdown = iucv_sock_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt
+ .setsockopt = iucv_sock_setsockopt,
+ .getsockopt = iucv_sock_getsockopt,
};
static struct net_proto_family iucv_sock_family_ops = {
^ permalink raw reply [flat|nested] 10+ messages in thread
* [patch 4/8] [PATCH] af_iucv: Support data in IUCV msg parameter lists (IPRMDATA)
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
` (2 preceding siblings ...)
2009-04-22 9:26 ` [patch 3/8] [PATCH] af_iucv: add sockopt() to enable/disable use of IPRM_DATA msgs Ursula Braun
@ 2009-04-22 9:26 ` Ursula Braun
2009-04-22 9:26 ` [patch 5/8] [PATCH] af_iucv: Modify iucv msg target class using control msghdr Ursula Braun
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390
Cc: schwidefsky, heiko.carstens, Hendrik Brueckner, Ursula Braun
[-- Attachment #1: 608-af_iucv-iprmdata.diff --]
[-- Type: text/plain, Size: 8927 bytes --]
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
The patch allows to send and receive data in the parameter list of an
iucv message.
The parameter list is an arry of 8 bytes that are used by af_iucv as
follows:
0..6 7 bytes for socket data and
7 1 byte to store the data length.
Instead of storing the data length directly, the difference
between 0xFF and the data length is used.
This convention does not interfere with the existing use of PRM
messages for shutting down the send direction of an AF_IUCV socket
(shutdown() operation). Data lenghts greater than 7 (or PRM message
byte 8 is less than 0xF8) denotes to special messages.
Currently, the special SEND_SHUTDOWN message is supported only.
To use IPRM messages, both communicators must set the IUCV_IPRMDATA
flag during path negotiation, i.e. in iucv_connect() and
path_pending().
To be compatible to older af_iucv implementations, sending PRM
messages is controlled by the socket option SO_IPRMDATA_MSG.
Receiving PRM messages does not depend on the socket option (but
requires the IUCV_IPRMDATA path flag to be set).
Sending/Receiving data in the parameter list improves performance for
small amounts of data by reducing message_completion() interrupts and
memory copy operations.
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
---
net/iucv/af_iucv.c | 121 ++++++++++++++++++++++++++++++++++++++++++++---------
net/iucv/iucv.c | 2
2 files changed, 103 insertions(+), 20 deletions(-)
Index: net-next-2.6-uschi/net/iucv/af_iucv.c
===================================================================
--- net-next-2.6-uschi.orig/net/iucv/af_iucv.c
+++ net-next-2.6-uschi/net/iucv/af_iucv.c
@@ -29,9 +29,6 @@
#include <net/iucv/iucv.h>
#include <net/iucv/af_iucv.h>
-#define CONFIG_IUCV_SOCK_DEBUG 1
-
-#define IPRMDATA 0x80
#define VERSION "1.1"
static char iucv_userid[80];
@@ -44,6 +41,10 @@ static struct proto iucv_proto = {
.obj_size = sizeof(struct iucv_sock),
};
+/* special AF_IUCV IPRM messages */
+static const u8 iprm_shutdown[8] =
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
+
static void iucv_sock_kill(struct sock *sk);
static void iucv_sock_close(struct sock *sk);
@@ -80,6 +81,37 @@ static inline void low_nmcpy(unsigned ch
memcpy(&dst[8], src, 8);
}
+/**
+ * iucv_msg_length() - Returns the length of an iucv message.
+ * @msg: Pointer to struct iucv_message, MUST NOT be NULL
+ *
+ * The function returns the length of the specified iucv message @msg of data
+ * stored in a buffer and of data stored in the parameter list (PRMDATA).
+ *
+ * For IUCV_IPRMDATA, AF_IUCV uses the following convention to transport socket
+ * data:
+ * PRMDATA[0..6] socket data (max 7 bytes);
+ * PRMDATA[7] socket data length value (len is 0xff - PRMDATA[7])
+ *
+ * The socket data length is computed by substracting the socket data length
+ * value from 0xFF.
+ * If the socket data len is greater 7, then PRMDATA can be used for special
+ * notifications (see iucv_sock_shutdown); and further,
+ * if the socket data len is > 7, the function returns 8.
+ *
+ * Use this function to allocate socket buffers to store iucv message data.
+ */
+static inline size_t iucv_msg_length(struct iucv_message *msg)
+{
+ size_t datalen;
+
+ if (msg->flags & IUCV_IPRMDATA) {
+ datalen = 0xff - msg->rmmsg[7];
+ return (datalen < 8) ? datalen : 8;
+ }
+ return msg->length;
+}
+
/* Timers */
static void iucv_sock_timeout(unsigned long arg)
{
@@ -487,7 +519,7 @@ static int iucv_sock_connect(struct sock
iucv = iucv_sk(sk);
/* Create path. */
iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT,
- IPRMDATA, GFP_KERNEL);
+ IUCV_IPRMDATA, GFP_KERNEL);
if (!iucv->path) {
err = -ENOMEM;
goto done;
@@ -521,8 +553,7 @@ static int iucv_sock_connect(struct sock
}
if (sk->sk_state == IUCV_DISCONN) {
- release_sock(sk);
- return -ECONNREFUSED;
+ err = -ECONNREFUSED;
}
if (err) {
@@ -636,6 +667,30 @@ static int iucv_sock_getname(struct sock
return 0;
}
+/**
+ * iucv_send_iprm() - Send socket data in parameter list of an iucv message.
+ * @path: IUCV path
+ * @msg: Pointer to a struct iucv_message
+ * @skb: The socket data to send, skb->len MUST BE <= 7
+ *
+ * Send the socket data in the parameter list in the iucv message
+ * (IUCV_IPRMDATA). The socket data is stored at index 0 to 6 in the parameter
+ * list and the socket data len at index 7 (last byte).
+ * See also iucv_msg_length().
+ *
+ * Returns the error code from the iucv_message_send() call.
+ */
+static int iucv_send_iprm(struct iucv_path *path, struct iucv_message *msg,
+ struct sk_buff *skb)
+{
+ u8 prmdata[8];
+
+ memcpy(prmdata, (void *) skb->data, skb->len);
+ prmdata[7] = 0xff - (u8) skb->len;
+ return iucv_message_send(path, msg, IUCV_IPRMDATA, 0,
+ (void *) prmdata, 8);
+}
+
static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
@@ -677,8 +732,29 @@ static int iucv_sock_sendmsg(struct kioc
txmsg.tag = iucv->send_tag++;
memcpy(skb->cb, &txmsg.tag, 4);
skb_queue_tail(&iucv->send_skb_q, skb);
- err = iucv_message_send(iucv->path, &txmsg, 0, 0,
- (void *) skb->data, skb->len);
+
+ if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags)
+ && skb->len <= 7) {
+ err = iucv_send_iprm(iucv->path, &txmsg, skb);
+
+ /* on success: there is no message_complete callback
+ * for an IPRMDATA msg; remove skb from send queue */
+ if (err == 0) {
+ skb_unlink(skb, &iucv->send_skb_q);
+ kfree_skb(skb);
+ }
+
+ /* this error should never happen since the
+ * IUCV_IPRMDATA path flag is set... sever path */
+ if (err == 0x15) {
+ iucv_path_sever(iucv->path, NULL);
+ skb_unlink(skb, &iucv->send_skb_q);
+ err = -EPIPE;
+ goto fail;
+ }
+ } else
+ err = iucv_message_send(iucv->path, &txmsg, 0, 0,
+ (void *) skb->data, skb->len);
if (err) {
if (err == 3) {
user_id[8] = 0;
@@ -744,19 +820,25 @@ static void iucv_process_message(struct
struct iucv_message *msg)
{
int rc;
+ unsigned int len;
- if (msg->flags & IPRMDATA) {
- skb->data = NULL;
- skb->len = 0;
+ len = iucv_msg_length(msg);
+
+ /* check for special IPRM messages (e.g. iucv_sock_shutdown) */
+ if ((msg->flags & IUCV_IPRMDATA) && len > 7) {
+ if (memcmp(msg->rmmsg, iprm_shutdown, 8) == 0) {
+ skb->data = NULL;
+ skb->len = 0;
+ }
} else {
- rc = iucv_message_receive(path, msg, 0, skb->data,
- msg->length, NULL);
+ rc = iucv_message_receive(path, msg, msg->flags & IUCV_IPRMDATA,
+ skb->data, len, NULL);
if (rc) {
kfree_skb(skb);
return;
}
if (skb->truesize >= sk->sk_rcvbuf / 4) {
- rc = iucv_fragment_skb(sk, skb, msg->length);
+ rc = iucv_fragment_skb(sk, skb, len);
kfree_skb(skb);
skb = NULL;
if (rc) {
@@ -767,7 +849,7 @@ static void iucv_process_message(struct
} else {
skb_reset_transport_header(skb);
skb_reset_network_header(skb);
- skb->len = msg->length;
+ skb->len = len;
}
}
@@ -782,7 +864,7 @@ static void iucv_process_message_q(struc
struct sock_msg_q *p, *n;
list_for_each_entry_safe(p, n, &iucv->message_q.list, list) {
- skb = alloc_skb(p->msg.length, GFP_ATOMIC | GFP_DMA);
+ skb = alloc_skb(iucv_msg_length(&p->msg), GFP_ATOMIC | GFP_DMA);
if (!skb)
break;
iucv_process_message(sk, skb, p->path, &p->msg);
@@ -928,7 +1010,6 @@ static int iucv_sock_shutdown(struct soc
struct iucv_sock *iucv = iucv_sk(sk);
struct iucv_message txmsg;
int err = 0;
- u8 prmmsg[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
how++;
@@ -950,7 +1031,7 @@ static int iucv_sock_shutdown(struct soc
txmsg.class = 0;
txmsg.tag = 0;
err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0,
- (void *) prmmsg, 8);
+ (void *) iprm_shutdown, 8);
if (err) {
switch (err) {
case 1:
@@ -1196,11 +1277,11 @@ static void iucv_callback_rx(struct iucv
goto save_message;
len = atomic_read(&sk->sk_rmem_alloc);
- len += msg->length + sizeof(struct sk_buff);
+ len += iucv_msg_length(msg) + sizeof(struct sk_buff);
if (len > sk->sk_rcvbuf)
goto save_message;
- skb = alloc_skb(msg->length, GFP_ATOMIC | GFP_DMA);
+ skb = alloc_skb(iucv_msg_length(msg), GFP_ATOMIC | GFP_DMA);
if (!skb)
goto save_message;
Index: net-next-2.6-uschi/net/iucv/iucv.c
===================================================================
--- net-next-2.6-uschi.orig/net/iucv/iucv.c
+++ net-next-2.6-uschi/net/iucv/iucv.c
@@ -1388,6 +1388,8 @@ static void iucv_path_complete(struct iu
struct iucv_path_complete *ipc = (void *) data;
struct iucv_path *path = iucv_path_table[ipc->ippathid];
+ if (path)
+ path->flags = ipc->ipflags1;
if (path && path->handler && path->handler->path_complete)
path->handler->path_complete(path, ipc->ipuser);
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* [patch 5/8] [PATCH] af_iucv: Modify iucv msg target class using control msghdr
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
` (3 preceding siblings ...)
2009-04-22 9:26 ` [patch 4/8] [PATCH] af_iucv: Support data in IUCV msg parameter lists (IPRMDATA) Ursula Braun
@ 2009-04-22 9:26 ` Ursula Braun
2009-04-22 9:26 ` [patch 6/8] [PATCH] af_iucv: Provide new socket type SOCK_SEQPACKET Ursula Braun
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390
Cc: schwidefsky, heiko.carstens, Hendrik Brueckner, Ursula Braun
[-- Attachment #1: 609-af_iucv-target-class.diff --]
[-- Type: text/plain, Size: 5463 bytes --]
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Allow 'classification' of socket data that is sent or received over
an af_iucv socket. For classification of data, the target class of an
(native) iucv message is used.
This patch provides the cmsg interface for iucv_sock_recvmsg() and
iucv_sock_sendmsg(). Applications can use the msg_control field of
struct msghdr to set or get the target class as a
"socket control message" (SCM/CMSG).
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
---
include/net/iucv/af_iucv.h | 3 +
net/iucv/af_iucv.c | 79 ++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 78 insertions(+), 4 deletions(-)
Index: net-next-2.6-uschi/include/net/iucv/af_iucv.h
===================================================================
--- net-next-2.6-uschi.orig/include/net/iucv/af_iucv.h
+++ net-next-2.6-uschi/include/net/iucv/af_iucv.h
@@ -79,6 +79,9 @@ struct iucv_sock {
/* iucv socket options (SOL_IUCV) */
#define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */
+/* iucv related control messages (scm) */
+#define SCM_IUCV_TRGCLS 0x0001 /* target class control message */
+
struct iucv_sock_list {
struct hlist_head head;
rwlock_t lock;
Index: net-next-2.6-uschi/net/iucv/af_iucv.c
===================================================================
--- net-next-2.6-uschi.orig/net/iucv/af_iucv.c
+++ net-next-2.6-uschi/net/iucv/af_iucv.c
@@ -45,6 +45,15 @@ static struct proto iucv_proto = {
static const u8 iprm_shutdown[8] =
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
+#define TRGCLS_SIZE (sizeof(((struct iucv_message *)0)->class))
+
+/* macros to set/get socket control buffer at correct offset */
+#define CB_TAG(skb) ((skb)->cb) /* iucv message tag */
+#define CB_TAG_LEN (sizeof(((struct iucv_message *) 0)->tag))
+#define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */
+#define CB_TRGCLS_LEN (TRGCLS_SIZE)
+
+
static void iucv_sock_kill(struct sock *sk);
static void iucv_sock_close(struct sock *sk);
@@ -698,6 +707,8 @@ static int iucv_sock_sendmsg(struct kioc
struct iucv_sock *iucv = iucv_sk(sk);
struct sk_buff *skb;
struct iucv_message txmsg;
+ struct cmsghdr *cmsg;
+ int cmsg_done;
char user_id[9];
char appl_id[9];
int err;
@@ -717,6 +728,48 @@ static int iucv_sock_sendmsg(struct kioc
}
if (sk->sk_state == IUCV_CONNECTED) {
+ /* initialize defaults */
+ cmsg_done = 0; /* check for duplicate headers */
+ txmsg.class = 0;
+
+ /* iterate over control messages */
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg;
+ cmsg = CMSG_NXTHDR(msg, cmsg)) {
+
+ if (!CMSG_OK(msg, cmsg)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (cmsg->cmsg_level != SOL_IUCV)
+ continue;
+
+ if (cmsg->cmsg_type & cmsg_done) {
+ err = -EINVAL;
+ goto out;
+ }
+ cmsg_done |= cmsg->cmsg_type;
+
+ switch (cmsg->cmsg_type) {
+ case SCM_IUCV_TRGCLS:
+ if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* set iucv message target class */
+ memcpy(&txmsg.class,
+ (void *) CMSG_DATA(cmsg), TRGCLS_SIZE);
+
+ break;
+
+ default:
+ err = -EINVAL;
+ goto out;
+ break;
+ }
+ }
+
if (!(skb = sock_alloc_send_skb(sk, len,
msg->msg_flags & MSG_DONTWAIT,
&err)))
@@ -727,10 +780,9 @@ static int iucv_sock_sendmsg(struct kioc
goto fail;
}
- txmsg.class = 0;
- memcpy(&txmsg.class, skb->data, skb->len >= 4 ? 4 : skb->len);
+ /* increment and save iucv message tag for msg_completion cbk */
txmsg.tag = iucv->send_tag++;
- memcpy(skb->cb, &txmsg.tag, 4);
+ memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN);
skb_queue_tail(&iucv->send_skb_q, skb);
if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags)
@@ -801,6 +853,10 @@ static int iucv_fragment_skb(struct sock
if (!nskb)
return -ENOMEM;
+ /* copy target class to control buffer of new skb */
+ memcpy(CB_TRGCLS(nskb), CB_TRGCLS(skb), CB_TRGCLS_LEN);
+
+ /* copy data fragment */
memcpy(nskb->data, skb->data + copied, size);
copied += size;
dataleft -= size;
@@ -824,6 +880,10 @@ static void iucv_process_message(struct
len = iucv_msg_length(msg);
+ /* store msg target class in the second 4 bytes of skb ctrl buffer */
+ /* Note: the first 4 bytes are reserved for msg tag */
+ memcpy(CB_TRGCLS(skb), &msg->class, CB_TRGCLS_LEN);
+
/* check for special IPRM messages (e.g. iucv_sock_shutdown) */
if ((msg->flags & IUCV_IPRMDATA) && len > 7) {
if (memcmp(msg->rmmsg, iprm_shutdown, 8) == 0) {
@@ -915,6 +975,17 @@ static int iucv_sock_recvmsg(struct kioc
len -= copied;
+ /* create control message to store iucv msg target class:
+ * get the trgcls from the control buffer of the skb due to
+ * fragmentation of original iucv message. */
+ err = put_cmsg(msg, SOL_IUCV, SCM_IUCV_TRGCLS,
+ CB_TRGCLS_LEN, CB_TRGCLS(skb));
+ if (err) {
+ if (!(flags & MSG_PEEK))
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ return err;
+ }
+
/* Mark read part of skb as used */
if (!(flags & MSG_PEEK)) {
skb_pull(skb, copied);
@@ -1316,7 +1387,7 @@ static void iucv_callback_txdone(struct
spin_lock_irqsave(&list->lock, flags);
while (list_skb != (struct sk_buff *)list) {
- if (!memcmp(&msg->tag, list_skb->cb, 4)) {
+ if (!memcmp(&msg->tag, CB_TAG(list_skb), CB_TAG_LEN)) {
this = list_skb;
break;
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* [patch 6/8] [PATCH] af_iucv: Provide new socket type SOCK_SEQPACKET
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
` (4 preceding siblings ...)
2009-04-22 9:26 ` [patch 5/8] [PATCH] af_iucv: Modify iucv msg target class using control msghdr Ursula Braun
@ 2009-04-22 9:26 ` Ursula Braun
2009-04-22 9:26 ` [patch 7/8] [PATCH] af_iucv: cleanup and refactor recvmsg() EFAULT handling Ursula Braun
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390
Cc: schwidefsky, heiko.carstens, Hendrik Brueckner, Ursula Braun
[-- Attachment #1: 610-af_iucv-seqpacket-socket.diff --]
[-- Type: text/plain, Size: 5717 bytes --]
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
This patch provides the socket type SOCK_SEQPACKET in addition to
SOCK_STREAM.
AF_IUCV sockets of type SOCK_SEQPACKET supports an 1:1 mapping of
socket read or write operations to complete IUCV messages.
Socket data or IUCV message data is not fragmented as this is the
case for SOCK_STREAM sockets.
The intention is to help application developers who write
applications or device drivers using native IUCV interfaces
(Linux kernel or z/VM IUCV interfaces).
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
---
net/iucv/af_iucv.c | 73 ++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 56 insertions(+), 17 deletions(-)
Index: net-next-2.6-uschi/net/iucv/af_iucv.c
===================================================================
--- net-next-2.6-uschi.orig/net/iucv/af_iucv.c
+++ net-next-2.6-uschi/net/iucv/af_iucv.c
@@ -289,11 +289,22 @@ static int iucv_sock_create(struct net *
{
struct sock *sk;
- if (sock->type != SOCK_STREAM)
- return -ESOCKTNOSUPPORT;
+ if (protocol && protocol != PF_IUCV)
+ return -EPROTONOSUPPORT;
sock->state = SS_UNCONNECTED;
- sock->ops = &iucv_sock_ops;
+
+ switch (sock->type) {
+ case SOCK_STREAM:
+ sock->ops = &iucv_sock_ops;
+ break;
+ case SOCK_SEQPACKET:
+ /* currently, proto ops can handle both sk types */
+ sock->ops = &iucv_sock_ops;
+ break;
+ default:
+ return -ESOCKTNOSUPPORT;
+ }
sk = iucv_sock_alloc(sock, protocol, GFP_KERNEL);
if (!sk)
@@ -504,11 +515,9 @@ static int iucv_sock_connect(struct sock
if (sk->sk_state != IUCV_OPEN && sk->sk_state != IUCV_BOUND)
return -EBADFD;
- if (sk->sk_type != SOCK_STREAM)
+ if (sk->sk_type != SOCK_STREAM && sk->sk_type != SOCK_SEQPACKET)
return -EINVAL;
- iucv = iucv_sk(sk);
-
if (sk->sk_state == IUCV_OPEN) {
err = iucv_sock_autobind(sk);
if (unlikely(err))
@@ -585,7 +594,10 @@ static int iucv_sock_listen(struct socke
lock_sock(sk);
err = -EINVAL;
- if (sk->sk_state != IUCV_BOUND || sock->type != SOCK_STREAM)
+ if (sk->sk_state != IUCV_BOUND)
+ goto done;
+
+ if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
goto done;
sk->sk_max_ack_backlog = backlog;
@@ -720,6 +732,10 @@ static int iucv_sock_sendmsg(struct kioc
if (msg->msg_flags & MSG_OOB)
return -EOPNOTSUPP;
+ /* SOCK_SEQPACKET: we do not support segmented records */
+ if (sk->sk_type == SOCK_SEQPACKET && !(msg->msg_flags & MSG_EOR))
+ return -EOPNOTSUPP;
+
lock_sock(sk);
if (sk->sk_shutdown & SEND_SHUTDOWN) {
@@ -770,6 +786,10 @@ static int iucv_sock_sendmsg(struct kioc
}
}
+ /* allocate one skb for each iucv message:
+ * this is fine for SOCK_SEQPACKET (unless we want to support
+ * segmented records using the MSG_EOR flag), but
+ * for SOCK_STREAM we might want to improve it in future */
if (!(skb = sock_alloc_send_skb(sk, len,
msg->msg_flags & MSG_DONTWAIT,
&err)))
@@ -897,7 +917,11 @@ static void iucv_process_message(struct
kfree_skb(skb);
return;
}
- if (skb->truesize >= sk->sk_rcvbuf / 4) {
+ /* we need to fragment iucv messages for SOCK_STREAM only;
+ * for SOCK_SEQPACKET, it is only relevant if we support
+ * record segmentation using MSG_EOR (see also recvmsg()) */
+ if (sk->sk_type == SOCK_STREAM &&
+ skb->truesize >= sk->sk_rcvbuf / 4) {
rc = iucv_fragment_skb(sk, skb, len);
kfree_skb(skb);
skb = NULL;
@@ -941,7 +965,8 @@ static int iucv_sock_recvmsg(struct kioc
int noblock = flags & MSG_DONTWAIT;
struct sock *sk = sock->sk;
struct iucv_sock *iucv = iucv_sk(sk);
- int target, copied = 0;
+ int target;
+ unsigned int copied, rlen;
struct sk_buff *skb, *rskb, *cskb;
int err = 0;
@@ -963,7 +988,8 @@ static int iucv_sock_recvmsg(struct kioc
return err;
}
- copied = min_t(unsigned int, skb->len, len);
+ rlen = skb->len; /* real length of skb */
+ copied = min_t(unsigned int, rlen, len);
cskb = skb;
if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) {
@@ -973,7 +999,13 @@ static int iucv_sock_recvmsg(struct kioc
goto done;
}
- len -= copied;
+ /* SOCK_SEQPACKET: set MSG_TRUNC if recv buf size is too small */
+ if (sk->sk_type == SOCK_SEQPACKET) {
+ if (copied < rlen)
+ msg->msg_flags |= MSG_TRUNC;
+ /* each iucv message contains a complete record */
+ msg->msg_flags |= MSG_EOR;
+ }
/* create control message to store iucv msg target class:
* get the trgcls from the control buffer of the skb due to
@@ -988,11 +1020,14 @@ static int iucv_sock_recvmsg(struct kioc
/* Mark read part of skb as used */
if (!(flags & MSG_PEEK)) {
- skb_pull(skb, copied);
- if (skb->len) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- goto done;
+ /* SOCK_STREAM: re-queue skb if it contains unreceived data */
+ if (sk->sk_type == SOCK_STREAM) {
+ skb_pull(skb, copied);
+ if (skb->len) {
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ goto done;
+ }
}
kfree_skb(skb);
@@ -1019,7 +1054,11 @@ static int iucv_sock_recvmsg(struct kioc
skb_queue_head(&sk->sk_receive_queue, skb);
done:
- return err ? : copied;
+ /* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */
+ if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC))
+ copied = rlen;
+
+ return copied;
}
static inline unsigned int iucv_accept_poll(struct sock *parent)
@@ -1281,7 +1320,7 @@ static int iucv_callback_connreq(struct
}
/* Create the new socket */
- nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC);
+ nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC);
if (!nsk) {
err = iucv_path_sever(path, user_data);
iucv_path_free(path);
^ permalink raw reply [flat|nested] 10+ messages in thread
* [patch 7/8] [PATCH] af_iucv: cleanup and refactor recvmsg() EFAULT handling
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
` (5 preceding siblings ...)
2009-04-22 9:26 ` [patch 6/8] [PATCH] af_iucv: Provide new socket type SOCK_SEQPACKET Ursula Braun
@ 2009-04-22 9:26 ` Ursula Braun
2009-04-22 9:26 ` [patch 8/8] [PATCH] af_iucv: New socket option for setting IUCV MSGLIMITs Ursula Braun
2009-04-22 9:48 ` [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 David Miller
8 siblings, 0 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390
Cc: schwidefsky, heiko.carstens, Hendrik Brueckner, Ursula Braun
[-- Attachment #1: 611-af_iucv-recvmsg.diff --]
[-- Type: text/plain, Size: 1601 bytes --]
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
If the skb cannot be copied to user iovec, always return -EFAULT.
The skb is enqueued again, except MSG_PEEK flag is set, to allow user space
applications to correct its iovec pointer.
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
---
net/iucv/af_iucv.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
Index: net-next-2.6-uschi/net/iucv/af_iucv.c
===================================================================
--- net-next-2.6-uschi.orig/net/iucv/af_iucv.c
+++ net-next-2.6-uschi/net/iucv/af_iucv.c
@@ -965,7 +965,6 @@ static int iucv_sock_recvmsg(struct kioc
int noblock = flags & MSG_DONTWAIT;
struct sock *sk = sock->sk;
struct iucv_sock *iucv = iucv_sk(sk);
- int target;
unsigned int copied, rlen;
struct sk_buff *skb, *rskb, *cskb;
int err = 0;
@@ -979,8 +978,6 @@ static int iucv_sock_recvmsg(struct kioc
if (flags & (MSG_OOB))
return -EOPNOTSUPP;
- target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
-
skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb) {
if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -993,10 +990,9 @@ static int iucv_sock_recvmsg(struct kioc
cskb = skb;
if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- if (copied == 0)
- return -EFAULT;
- goto done;
+ if (!(flags & MSG_PEEK))
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ return -EFAULT;
}
/* SOCK_SEQPACKET: set MSG_TRUNC if recv buf size is too small */
^ permalink raw reply [flat|nested] 10+ messages in thread
* [patch 8/8] [PATCH] af_iucv: New socket option for setting IUCV MSGLIMITs
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
` (6 preceding siblings ...)
2009-04-22 9:26 ` [patch 7/8] [PATCH] af_iucv: cleanup and refactor recvmsg() EFAULT handling Ursula Braun
@ 2009-04-22 9:26 ` Ursula Braun
2009-04-22 9:48 ` [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 David Miller
8 siblings, 0 replies; 10+ messages in thread
From: Ursula Braun @ 2009-04-22 9:26 UTC (permalink / raw)
To: davem, netdev, linux-s390
Cc: schwidefsky, heiko.carstens, Hendrik Brueckner, Ursula Braun
[-- Attachment #1: 612-af_iucv-msglimit.diff --]
[-- Type: text/plain, Size: 3829 bytes --]
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
The SO_MSGLIMIT socket option modifies the message limit for new
IUCV communication paths.
The message limit specifies the maximum number of outstanding messages
that are allowed for connections. This setting can be lowered by z/VM
when an IUCV connection is established.
Expects an integer value in the range of 1 to 65535.
The default value is 65535.
The message limit must be set before calling connect() or listen()
for sockets.
If sockets are already connected or in state listen, changing the message
limit is not supported.
For reading the message limit value, unconnected sockets return the limit
that has been set or the default limit. For connected sockets, the actual
message limit is returned. The actual message limit is assigned by z/VM
for each connection and it depends on IUCV MSGLIMIT authorizations
specified for the z/VM guest virtual machine.
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
---
include/net/iucv/af_iucv.h | 2 ++
net/iucv/af_iucv.c | 27 +++++++++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)
Index: net-next-2.6-uschi/include/net/iucv/af_iucv.h
===================================================================
--- net-next-2.6-uschi.orig/include/net/iucv/af_iucv.h
+++ net-next-2.6-uschi/include/net/iucv/af_iucv.h
@@ -74,10 +74,12 @@ struct iucv_sock {
struct sock_msg_q message_q;
unsigned int send_tag;
u8 flags;
+ u16 msglimit;
};
/* iucv socket options (SOL_IUCV) */
#define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */
+#define SO_MSGLIMIT 0x1000 /* get/set IUCV MSGLIMIT */
/* iucv related control messages (scm) */
#define SCM_IUCV_TRGCLS 0x0001 /* target class control message */
Index: net-next-2.6-uschi/net/iucv/af_iucv.c
===================================================================
--- net-next-2.6-uschi.orig/net/iucv/af_iucv.c
+++ net-next-2.6-uschi/net/iucv/af_iucv.c
@@ -268,6 +268,7 @@ static struct sock *iucv_sock_alloc(stru
skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q);
iucv_sk(sk)->send_tag = 0;
iucv_sk(sk)->flags = 0;
+ iucv_sk(sk)->msglimit = IUCV_QUEUELEN_DEFAULT;
sk->sk_destruct = iucv_sock_destruct;
sk->sk_sndtimeo = IUCV_CONN_TIMEOUT;
@@ -536,7 +537,7 @@ static int iucv_sock_connect(struct sock
iucv = iucv_sk(sk);
/* Create path. */
- iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT,
+ iucv->path = iucv_path_alloc(iucv->msglimit,
IUCV_IPRMDATA, GFP_KERNEL);
if (!iucv->path) {
err = -ENOMEM;
@@ -1219,6 +1220,20 @@ static int iucv_sock_setsockopt(struct s
else
iucv->flags &= ~IUCV_IPRMDATA;
break;
+ case SO_MSGLIMIT:
+ switch (sk->sk_state) {
+ case IUCV_OPEN:
+ case IUCV_BOUND:
+ if (val < 1 || val > (u16)(~0))
+ rc = -EINVAL;
+ else
+ iucv->msglimit = val;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ break;
default:
rc = -ENOPROTOOPT;
break;
@@ -1250,6 +1265,12 @@ static int iucv_sock_getsockopt(struct s
case SO_IPRMDATA_MSG:
val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
break;
+ case SO_MSGLIMIT:
+ lock_sock(sk);
+ val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
+ : iucv->msglimit; /* default */
+ release_sock(sk);
+ break;
default:
return -ENOPROTOOPT;
}
@@ -1339,7 +1360,9 @@ static int iucv_callback_connreq(struct
memcpy(nuser_data + 8, niucv->src_name, 8);
ASCEBC(nuser_data + 8, 8);
- path->msglim = IUCV_QUEUELEN_DEFAULT;
+ /* set message limit for path based on msglimit of accepting socket */
+ niucv->msglimit = iucv->msglimit;
+ path->msglim = iucv->msglimit;
err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk);
if (err) {
err = iucv_path_sever(path, user_data);
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
` (7 preceding siblings ...)
2009-04-22 9:26 ` [patch 8/8] [PATCH] af_iucv: New socket option for setting IUCV MSGLIMITs Ursula Braun
@ 2009-04-22 9:48 ` David Miller
8 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2009-04-22 9:48 UTC (permalink / raw)
To: ursula.braun; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens
From: Ursula Braun <ursula.braun@de.ibm.com>
Date: Wed, 22 Apr 2009 11:26:19 +0200
> thanks for applying our critical af_iucv bug fixes to net-2.6.
> Here is now the series of iucv / af_iucv patches for the current
> development cycle.
> The patches are based on top of the current net-next-2.6 kernel
> (2.6.30-rc1).
Do I need to pull net-2.6 into net-next-2.6 for this stuff
to apply properly?
Just checking.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-04-22 9:48 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-22 9:26 [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 Ursula Braun
2009-04-22 9:26 ` [patch 1/8] [PATCH] iucv: provide second per-cpu IUCV command parameter block Ursula Braun
2009-04-22 9:26 ` [patch 2/8] [PATCH] af_iucv: sync sk shutdown flag if iucv path is quiesced Ursula Braun
2009-04-22 9:26 ` [patch 3/8] [PATCH] af_iucv: add sockopt() to enable/disable use of IPRM_DATA msgs Ursula Braun
2009-04-22 9:26 ` [patch 4/8] [PATCH] af_iucv: Support data in IUCV msg parameter lists (IPRMDATA) Ursula Braun
2009-04-22 9:26 ` [patch 5/8] [PATCH] af_iucv: Modify iucv msg target class using control msghdr Ursula Braun
2009-04-22 9:26 ` [patch 6/8] [PATCH] af_iucv: Provide new socket type SOCK_SEQPACKET Ursula Braun
2009-04-22 9:26 ` [patch 7/8] [PATCH] af_iucv: cleanup and refactor recvmsg() EFAULT handling Ursula Braun
2009-04-22 9:26 ` [patch 8/8] [PATCH] af_iucv: New socket option for setting IUCV MSGLIMITs Ursula Braun
2009-04-22 9:48 ` [patch 0/8] iucv / af_iucv patches for net-next-2.6.30-rc1 David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).