From aa6f5ffbdba45aa8e19e5048648fc6c7b25376d3 Mon Sep 17 00:00:00 2001 From: merge Date: Thu, 22 Jan 2009 13:55:32 +0000 Subject: MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 / fdf777a63bcb59e0dfd78bfe2c6242e01f6d4eb9 ... parent commitmessage: From: merge MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 stable-tracking-hist top was MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 / 90463bfd2d5a3c8b52f6e6d71024a00e052b0ced ... parent commitmessage: From: merge MERGE-via-mokopatches-tracking-hist-fix-stray-endmenu-patch mokopatches-tracking-hist top was fix-stray-endmenu-patch / 3630e0be570de8057e7f8d2fe501ed353cdf34e6 ... parent commitmessage: From: Andy Green fix-stray-endmenu.patch Signed-off-by: Andy Green --- net/iucv/af_iucv.c | 47 ++++++++++++-- net/iucv/iucv.c | 186 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 179 insertions(+), 54 deletions(-) (limited to 'net/iucv') diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 29f7baa2511..eb8a2a0b6eb 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -8,6 +8,9 @@ * Author(s): Jennifer Hunt */ +#define KMSG_COMPONENT "af_iucv" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include #include #include @@ -491,7 +494,21 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, if (err) { iucv_path_free(iucv->path); iucv->path = NULL; - err = -ECONNREFUSED; + switch (err) { + case 0x0b: /* Target communicator is not logged on */ + err = -ENETUNREACH; + break; + case 0x0d: /* Max connections for this guest exceeded */ + case 0x0e: /* Max connections for target guest exceeded */ + err = -EAGAIN; + break; + case 0x0f: /* Missing IUCV authorization */ + err = -EACCES; + break; + default: + err = -ECONNREFUSED; + break; + } goto done; } @@ -504,6 +521,13 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, release_sock(sk); return -ECONNREFUSED; } + + if (err) { + iucv_path_sever(iucv->path, NULL); + iucv_path_free(iucv->path); + iucv->path = NULL; + } + done: release_sock(sk); return err; @@ -616,6 +640,8 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct iucv_sock *iucv = iucv_sk(sk); struct sk_buff *skb; struct iucv_message txmsg; + char user_id[9]; + char appl_id[9]; int err; err = sock_error(sk); @@ -651,8 +677,15 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, err = iucv_message_send(iucv->path, &txmsg, 0, 0, (void *) skb->data, skb->len); if (err) { - if (err == 3) - printk(KERN_ERR "AF_IUCV msg limit exceeded\n"); + if (err == 3) { + user_id[8] = 0; + memcpy(user_id, iucv->dst_user_id, 8); + appl_id[8] = 0; + memcpy(appl_id, iucv->dst_name, 8); + pr_err("Application %s on z/VM guest %s" + " exceeds message limit\n", + user_id, appl_id); + } skb_unlink(skb, &iucv->send_skb_q); err = -EPIPE; goto fail; @@ -1009,12 +1042,14 @@ static int iucv_callback_connreq(struct iucv_path *path, ASCEBC(user_data, sizeof(user_data)); if (sk->sk_state != IUCV_LISTEN) { err = iucv_path_sever(path, user_data); + iucv_path_free(path); goto fail; } /* Check for backlog size */ if (sk_acceptq_is_full(sk)) { err = iucv_path_sever(path, user_data); + iucv_path_free(path); goto fail; } @@ -1022,6 +1057,7 @@ static int iucv_callback_connreq(struct iucv_path *path, nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC); if (!nsk) { err = iucv_path_sever(path, user_data); + iucv_path_free(path); goto fail; } @@ -1045,6 +1081,8 @@ static int iucv_callback_connreq(struct iucv_path *path, err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk); if (err) { err = iucv_path_sever(path, user_data); + iucv_path_free(path); + iucv_sock_kill(nsk); goto fail; } @@ -1190,7 +1228,8 @@ static int __init afiucv_init(void) int err; if (!MACHINE_IS_VM) { - printk(KERN_ERR "AF_IUCV connection needs VM as base\n"); + pr_err("The af_iucv module cannot be loaded" + " without z/VM\n"); err = -EPROTONOSUPPORT; goto out; } diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index d7b54b5bfa6..a35240f61ec 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -30,6 +30,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define KMSG_COMPONENT "iucv" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include #include #include @@ -47,7 +50,6 @@ #include #include #include -#include #include /* @@ -424,8 +426,8 @@ static void iucv_declare_cpu(void *data) err = "Paging or storage error"; break; } - printk(KERN_WARNING "iucv_register: iucv_declare_buffer " - "on cpu %i returned error 0x%02x (%s)\n", cpu, rc, err); + pr_warning("Defining an interrupt buffer on CPU %i" + " failed with 0x%02x (%s)\n", cpu, rc, err); return; } @@ -514,6 +516,7 @@ static int iucv_enable(void) size_t alloc_size; int cpu, rc; + get_online_cpus(); rc = -ENOMEM; alloc_size = iucv_max_pathid * sizeof(struct iucv_path); iucv_path_table = kzalloc(alloc_size, GFP_KERNEL); @@ -521,19 +524,17 @@ static int iucv_enable(void) goto out; /* Declare per cpu buffers. */ rc = -EIO; - get_online_cpus(); for_each_online_cpu(cpu) smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); if (cpus_empty(iucv_buffer_cpumask)) /* No cpu could declare an iucv buffer. */ - goto out_path; + goto out; put_online_cpus(); return 0; - -out_path: - put_online_cpus(); - kfree(iucv_path_table); out: + kfree(iucv_path_table); + iucv_path_table = NULL; + put_online_cpus(); return rc; } @@ -548,8 +549,9 @@ static void iucv_disable(void) { get_online_cpus(); on_each_cpu(iucv_retrieve_cpu, NULL, 1); - put_online_cpus(); kfree(iucv_path_table); + iucv_path_table = NULL; + put_online_cpus(); } static int __cpuinit iucv_cpu_notify(struct notifier_block *self, @@ -586,10 +588,14 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, case CPU_ONLINE_FROZEN: case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: + if (!iucv_path_table) + break; smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: + if (!iucv_path_table) + break; cpumask = iucv_buffer_cpumask; cpu_clear(cpu, cpumask); if (cpus_empty(cpumask)) @@ -957,7 +963,52 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg, EXPORT_SYMBOL(iucv_message_purge); /** - * iucv_message_receive + * iucv_message_receive_iprmdata + * @path: address of iucv path structure + * @msg: address of iucv msg structure + * @flags: how the message is received (IUCV_IPBUFLST) + * @buffer: address of data buffer or address of struct iucv_array + * @size: length of data buffer + * @residual: + * + * Internal function used by iucv_message_receive and __iucv_message_receive + * to receive RMDATA data stored in struct iucv_message. + */ +static int iucv_message_receive_iprmdata(struct iucv_path *path, + struct iucv_message *msg, + u8 flags, void *buffer, + size_t size, size_t *residual) +{ + struct iucv_array *array; + u8 *rmmsg; + size_t copy; + + /* + * Message is 8 bytes long and has been stored to the + * message descriptor itself. + */ + if (residual) + *residual = abs(size - 8); + rmmsg = msg->rmmsg; + if (flags & IUCV_IPBUFLST) { + /* Copy to struct iucv_array. */ + size = (size < 8) ? size : 8; + for (array = buffer; size > 0; array++) { + copy = min_t(size_t, size, array->length); + memcpy((u8 *)(addr_t) array->address, + rmmsg, copy); + rmmsg += copy; + size -= copy; + } + } else { + /* Copy to direct buffer. */ + memcpy(buffer, rmmsg, min_t(size_t, size, 8)); + } + return 0; +} + +/** + * __iucv_message_receive * @path: address of iucv path structure * @msg: address of iucv msg structure * @flags: how the message is received (IUCV_IPBUFLST) @@ -969,44 +1020,19 @@ EXPORT_SYMBOL(iucv_message_purge); * established paths. This function will deal with RMDATA messages * embedded in struct iucv_message as well. * + * Locking: no locking + * * Returns the result from the CP IUCV call. */ -int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, - u8 flags, void *buffer, size_t size, size_t *residual) +int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, + u8 flags, void *buffer, size_t size, size_t *residual) { union iucv_param *parm; - struct iucv_array *array; - u8 *rmmsg; - size_t copy; int rc; - if (msg->flags & IUCV_IPRMDATA) { - /* - * Message is 8 bytes long and has been stored to the - * message descriptor itself. - */ - rc = (size < 8) ? 5 : 0; - if (residual) - *residual = abs(size - 8); - rmmsg = msg->rmmsg; - if (flags & IUCV_IPBUFLST) { - /* Copy to struct iucv_array. */ - size = (size < 8) ? size : 8; - for (array = buffer; size > 0; array++) { - copy = min_t(size_t, size, array->length); - memcpy((u8 *)(addr_t) array->address, - rmmsg, copy); - rmmsg += copy; - size -= copy; - } - } else { - /* Copy to direct buffer. */ - memcpy(buffer, rmmsg, min_t(size_t, size, 8)); - } - return 0; - } - - local_bh_disable(); + if (msg->flags & IUCV_IPRMDATA) + return iucv_message_receive_iprmdata(path, msg, flags, + buffer, size, residual); parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); parm->db.ipbfadr1 = (u32)(addr_t) buffer; @@ -1022,6 +1048,37 @@ int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, if (residual) *residual = parm->db.ipbfln1f; } + return rc; +} +EXPORT_SYMBOL(__iucv_message_receive); + +/** + * iucv_message_receive + * @path: address of iucv path structure + * @msg: address of iucv msg structure + * @flags: how the message is received (IUCV_IPBUFLST) + * @buffer: address of data buffer or address of struct iucv_array + * @size: length of data buffer + * @residual: + * + * This function receives messages that are being sent to you over + * established paths. This function will deal with RMDATA messages + * embedded in struct iucv_message as well. + * + * Locking: local_bh_enable/local_bh_disable + * + * Returns the result from the CP IUCV call. + */ +int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, + u8 flags, void *buffer, size_t size, size_t *residual) +{ + int rc; + + if (msg->flags & IUCV_IPRMDATA) + return iucv_message_receive_iprmdata(path, msg, flags, + buffer, size, residual); + local_bh_disable(); + rc = __iucv_message_receive(path, msg, flags, buffer, size, residual); local_bh_enable(); return rc; } @@ -1101,7 +1158,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg, EXPORT_SYMBOL(iucv_message_reply); /** - * iucv_message_send + * __iucv_message_send * @path: address of iucv path structure * @msg: address of iucv msg structure * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST) @@ -1113,15 +1170,16 @@ EXPORT_SYMBOL(iucv_message_reply); * transmitted is in a buffer and this is a one-way message and the * receiver will not reply to the message. * + * Locking: no locking + * * Returns the result from the CP IUCV call. */ -int iucv_message_send(struct iucv_path *path, struct iucv_message *msg, +int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg, u8 flags, u32 srccls, void *buffer, size_t size) { union iucv_param *parm; int rc; - local_bh_disable(); parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (flags & IUCV_IPRMDATA) { @@ -1144,6 +1202,34 @@ int iucv_message_send(struct iucv_path *path, struct iucv_message *msg, rc = iucv_call_b2f0(IUCV_SEND, parm); if (!rc) msg->id = parm->db.ipmsgid; + return rc; +} +EXPORT_SYMBOL(__iucv_message_send); + +/** + * iucv_message_send + * @path: address of iucv path structure + * @msg: address of iucv msg structure + * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST) + * @srccls: source class of message + * @buffer: address of send buffer or address of struct iucv_array + * @size: length of send buffer + * + * This function transmits data to another application. Data to be + * transmitted is in a buffer and this is a one-way message and the + * receiver will not reply to the message. + * + * Locking: local_bh_enable/local_bh_disable + * + * Returns the result from the CP IUCV call. + */ +int iucv_message_send(struct iucv_path *path, struct iucv_message *msg, + u8 flags, u32 srccls, void *buffer, size_t size) +{ + int rc; + + local_bh_disable(); + rc = __iucv_message_send(path, msg, flags, srccls, buffer, size); local_bh_enable(); return rc; } @@ -1572,7 +1658,7 @@ static void iucv_external_interrupt(u16 code) BUG_ON(p->iptype < 0x01 || p->iptype > 0x09); work = kmalloc(sizeof(struct iucv_irq_list), GFP_ATOMIC); if (!work) { - printk(KERN_WARNING "iucv_external_interrupt: out of memory\n"); + pr_warning("iucv_external_interrupt: out of memory\n"); return; } memcpy(&work->data, p, sizeof(work->data)); @@ -1609,7 +1695,7 @@ static int __init iucv_init(void) rc = register_external_interrupt(0x4000, iucv_external_interrupt); if (rc) goto out; - iucv_root = s390_root_dev_register("iucv"); + iucv_root = root_device_register("iucv"); if (IS_ERR(iucv_root)) { rc = PTR_ERR(iucv_root); goto out_int; @@ -1653,7 +1739,7 @@ out_free: kfree(iucv_irq_data[cpu]); iucv_irq_data[cpu] = NULL; } - s390_root_dev_unregister(iucv_root); + root_device_unregister(iucv_root); out_int: unregister_external_interrupt(0x4000, iucv_external_interrupt); out: @@ -1683,7 +1769,7 @@ static void __exit iucv_exit(void) kfree(iucv_irq_data[cpu]); iucv_irq_data[cpu] = NULL; } - s390_root_dev_unregister(iucv_root); + root_device_unregister(iucv_root); bus_unregister(&iucv_bus); unregister_external_interrupt(0x4000, iucv_external_interrupt); } -- cgit v1.2.3