[patch 54/56] data send and packet allocation/free fix
Florian Delizy <[email protected]> Thu, 02 Nov 2006 22:57:39 +0100
| Newsgroups | gmane.linux.cluster.openmosix.devel |
|---|---|
| Message-ID | <[email protected]> |
This patch fix the data_send function, sending header and data at once it also fixes the pkt_create function to copy data always in a safe place before sending it ... ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ openMosix-devel mailing list openMosix-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/openmosix-devel
data_send-fix.patch
(text/x-patch, 6.6 KB)
Subject: [patch @num@/@total@] data send and packet allocation/free fix
This patch fix the data_send function, sending header and data at once
it also fixes the pkt_create function to copy data always in a safe place
before sending it ...
Index: linux/hpc/kcomd.c
===================================================================
--- linux.orig/hpc/kcomd.c 2006-11-02 22:53:01.000000000 +0100
+++ linux/hpc/kcomd.c 2006-11-02 22:53:08.000000000 +0100
@@ -160,79 +160,89 @@
* Description:
* Sends the kcom pkt header and the data, if any.
**/
-int data_send(struct socket *sock, void *data, int len)
+
+int data_send(struct socket *sock, struct kcom_pkt* pkt)
{
- struct iovec iov;
- int i=-1;
- struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0, MSG_WAITALL | MSG_NOSIGNAL };
- mm_segment_t oldfs;
- struct kcom_pkt *send_pkt;
- char buf[32];
- struct timeval start,stop;
-
- do_gettimeofday(&start);
- send_pkt=data;
-
-
- /* Send kcom_pkt header */
- iov.iov_base = send_pkt;
- iov.iov_len = sizeof(*send_pkt);
-
- oldfs = get_fs();
- set_fs(KERNEL_DS);
-
- while (iov.iov_len > 0) {
- i = sock_sendmsg(sock, &msg, iov.iov_len);
- if ((i == -ENOSPC) || (i == -EAGAIN)) {
- OMBUG("Retrying hdr...error %d\n", i);
- schedule_timeout(HZ/1000);
- continue;
- }
- if (i == -EFAULT) {
- OMBUG("Error %d sending data. Unable to access data.\n", i);
- OMBUG("Data may need to be copied into a temporary buffer to be sent.\n");
- }
- if (i < 0) {
- set_fs(oldfs);
- return -1;
+ struct msghdr msg;
+ struct kvec packet[2] = {{0}};
+ int nvec = 1;
+ int total_data = 0;
+ int first_vec = 0;
+ int sent = 0;
+ int i;
+
+ /* Sanity check */
+
+ if (!pkt) {
+ OMBUG("Can not send null packet\n");
+ return -EFAULT;
+ }
+
+ /* Prepare packets */
+
+ msg.msg_flags = MSG_WAITALL | MSG_NOSIGNAL;
+
+
+ packet[0].iov_base = pkt;
+ packet[0].iov_len = sizeof(struct kcom_pkt);
+
+ if (pkt->len) {
+ if(!pkt->data) {
+ OMBUG("Paket has data, but no data pointer");
+ return -EFAULT;
}
- iov.iov_base += i;
- iov.iov_len -= i;
- }
- set_fs(oldfs);
-
- /* Sending too small a data packet, delays. */
- if ((send_pkt->len > 0) && (send_pkt->len < 32)) {
- memset(&buf, 0, 32);
- memcpy(&buf, send_pkt->data, send_pkt->len);
- iov.iov_base = &buf;
- iov.iov_len = 32;
- } else {
- iov.iov_base = send_pkt->data;
- iov.iov_len = send_pkt->len;
+ packet[1].iov_base = pkt->data;
+ packet[1].iov_len = pkt->len;
+ nvec++;
+
}
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- while (iov.iov_len > 0) {
- i = sock_sendmsg(sock, &msg, iov.iov_len);
- if ((i == -ENOSPC) || (i == -EAGAIN)) {
+ total_data = packet[0].iov_len + packet[1].iov_len;
+
+ while (total_data > 0) {
+ sent = kernel_sendmsg(sock, &msg, &packet[first_vec], 2 - first_vec, total_data);
+
+ /* kernel_sendmsg can fail if no space left on skbuff, or interrupted ... */
+ if (-ENOSPC == sent || -EAGAIN == sent || 0 == sent) {
+ OMBUG("Can not send packet for now, retrying\n");
schedule_timeout(HZ/1000);
continue;
}
- if (i < 0) {
- OMBUG("openMosix: ERROR %d sending data\n", i);
- set_fs(oldfs);
- return -1;
+
+ /* if something wrong happened :*/
+ if (0 > sent) {
+ OMBUG("Can not send data : error %d\n", sent);
+ return sent;
+ }
+
+ /* check all is sent and retry to send in case not */
+
+ total_data -= sent;
+
+ if (!total_data) break;
+ /* Thanks to fs/cifs/transport.c !*/
+
+ for (i = first_vec; i < 2; i++) {
+
+ if (!packet[i].iov_len) continue;
+
+ if (sent > packet[i].iov_len) {
+ sent -= packet[i].iov_len;
+ packet[i].iov_len = 0;
+ } else {
+ packet[i].iov_base += sent;
+ packet[i].iov_len -= sent;
+ first_vec = i;
+ break;
+ }
+
}
- iov.iov_base += i;
- iov.iov_len -= i;
- }
- set_fs(oldfs);
- do_gettimeofday(&stop);
- return i;
+
+ }
+
+ return pkt->len;
}
@@ -429,12 +439,9 @@
,(unsigned)pkt->type, pkt->len);
OMDEBUG_KCOMD_DO(4, om_dump_packet(pkt));
- data_send(node->sock, (void *)pkt, pkt->len);
+ data_send(node->sock, pkt);
- list_del(&pkt->list);
- if (((pkt->type|PKT_ACK)==PKT_ACK) && (pkt->len > 0))
- kmem_cache_free(kcom_data_cachep, pkt->data);
- kmem_cache_free(kcom_pkt_cachep, pkt);
+ kcom_pkt_delete(pkt);
}
write_unlock(&task->out_packs_lock);
}
@@ -453,7 +460,6 @@
static void kcomd_thread_initialize(void)
{
- kcom_data_cachep=kmem_cache_create("kcom_data_cache", 1024, 0, 0, NULL, NULL); /* for now help chase down memory leaks*/
kcom_pkt_cachep =kmem_cache_create("kcom_pkt_cache", sizeof(struct kcom_pkt), 0, 0, NULL, NULL);
kcom_task_cachep=kmem_cache_create("kcom_task_cache", sizeof(struct kcom_task), 0, 0, NULL, NULL);
kcom_node_cachep=kmem_cache_create("kcom_node_cache", sizeof(struct kcom_node), 0, 0, NULL, NULL);
@@ -748,7 +754,6 @@
/* spin_unlock(&kcom_nodes_lock);*/
kfree(sockets_fds_bitmap);
- kmem_cache_destroy(kcom_data_cachep);
kmem_cache_destroy(kcom_pkt_cachep);
kmem_cache_destroy(kcom_task_cachep);
kmem_cache_destroy(kcom_node_cachep);
Index: linux/hpc/kcom.c
===================================================================
--- linux.orig/hpc/kcom.c 2006-11-02 22:53:06.000000000 +0100
+++ linux/hpc/kcom.c 2006-11-02 22:53:08.000000000 +0100
@@ -434,16 +434,18 @@
void kcom_pkt_delete(struct kcom_pkt *pkt)
{
- if (!pkt) {
- OMBUG("Can not delete Null packet\n");
- return;
- }
-
- if (!list_empty(&pkt->list)) {
- list_del(&pkt->list);
- }
+ if (!pkt) {
+ OMBUG("Can not delete Null packet\n");
+ return;
+ }
+
+ if (!list_empty(&pkt->list)) {
+ list_del(&pkt->list);
+ }
+
+ if (pkt->data) kfree(pkt->data);
- kmem_cache_free(kcom_pkt_cachep, pkt);
+ kmem_cache_free(kcom_pkt_cachep, pkt);
}
EXPORT_SYMBOL_GPL(kcom_pkt_delete);
@@ -509,17 +511,34 @@
, len, (unsigned)type, ack);
pkt=kmem_cache_alloc(kcom_pkt_cachep, SLAB_KERNEL);
if (pkt) {
- pkt->len = len;
+ pkt->len = 0;
pkt->type = type;
+ pkt->data = NULL;
- if (len > 0) pkt->data=data;
- else pkt->data=NULL;
+ if (len > 0) {
+ pkt->data = kmalloc(len, GFP_KERNEL);
+ if (! pkt->data)
+ {
+ OMBUG("Can't allocate temp space for storing packet !!\n");
+ kcom_pkt_delete(pkt);
+ }
+ pkt->len = len;
+
+ memcpy(pkt->data, data, len);
+ }
INIT_LIST_HEAD(&pkt->list);
- // acks and responses don't get new a msgid
- // FIXME: is this inc SMP safe?
+
+ /*
+ * SMP FIXME
+ * Florian Delizy:
+ * This is *NOT* the correct way to handle this in SMP !!
+ * we need to have a distinct msgid list or multiple processors
+ * may send packets with equal id => messup the stack
+ * SMP FIXME
+ */
if ((type & MSG_MASK) == PKT_NEW_MSG)
pkt->msgid = kcom_msgid++;