Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / arch / um / drivers / net_user.c
index 098fa65..107c5e4 100644 (file)
@@ -22,13 +22,14 @@ int tap_open_common(void *dev, char *gate_addr)
 {
        int tap_addr[4];
 
-       if(gate_addr == NULL) return(0);
+       if(gate_addr == NULL)
+               return 0;
        if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], 
                  &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
                printk("Invalid tap IP address - '%s'\n", gate_addr);
-               return(-EINVAL);
+               return -EINVAL;
        }
-       return(0);
+       return 0;
 }
 
 void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
@@ -47,10 +48,12 @@ void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
        }
 }
 
+/* Do reliable error handling as this fails frequently enough. */
 void read_output(int fd, char *output, int len)
 {
-       int remain, n, actual;
+       int remain, ret, expected;
        char c;
+       char *str;
 
        if(output == NULL){
                output = &c;
@@ -58,23 +61,31 @@ void read_output(int fd, char *output, int len)
        }
                
        *output = '\0';
-       n = os_read_file(fd, &remain, sizeof(remain));
-       if(n != sizeof(remain)){
-               printk("read_output - read of length failed, err = %d\n", -n);
-               return;
+       ret = os_read_file(fd, &remain, sizeof(remain));
+
+       if (ret != sizeof(remain)) {
+               expected = sizeof(remain);
+               str = "length";
+               goto err;
        }
 
        while(remain != 0){
-               n = (remain < len) ? remain : len;
-               actual = os_read_file(fd, output, n);
-               if(actual != n){
-                       printk("read_output - read of data failed, "
-                              "err = %d\n", -actual);
-                       return;
+               expected = (remain < len) ? remain : len;
+               ret = os_read_file(fd, output, expected);
+               if (ret != expected) {
+                       str = "data";
+                       goto err;
                }
-               remain -= actual;
+               remain -= ret;
        }
+
        return;
+
+err:
+       if (ret < 0)
+               printk("read_output - read of %s failed, errno = %d\n", str, -ret);
+       else
+               printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected);
 }
 
 int net_read(int fd, void *buf, int len)
@@ -84,25 +95,25 @@ int net_read(int fd, void *buf, int len)
        n = os_read_file(fd,  buf,  len);
 
        if(n == -EAGAIN)
-               return(0);
+               return 0;
        else if(n == 0)
-               return(-ENOTCONN);
-       return(n);
+               return -ENOTCONN;
+       return n;
 }
 
 int net_recvfrom(int fd, void *buf, int len)
 {
        int n;
 
-       while(((n = recvfrom(fd,  buf,  len, 0, NULL, NULL)) < 0) && 
-             (errno == EINTR)) ;
-
+       CATCH_EINTR(n = recvfrom(fd,  buf,  len, 0, NULL, NULL));
        if(n < 0){
-               if(errno == EAGAIN) return(0);
-               return(-errno);
+               if(errno == EAGAIN)
+                       return 0;
+               return -errno;
        }
-       else if(n == 0) return(-ENOTCONN);
-       return(n);
+       else if(n == 0)
+               return -ENOTCONN;
+       return n;
 }
 
 int net_write(int fd, void *buf, int len)
@@ -112,37 +123,41 @@ int net_write(int fd, void *buf, int len)
        n = os_write_file(fd, buf, len);
 
        if(n == -EAGAIN)
-               return(0);
+               return 0;
        else if(n == 0)
-               return(-ENOTCONN);
-       return(n);
+               return -ENOTCONN;
+       return n;
 }
 
 int net_send(int fd, void *buf, int len)
 {
        int n;
 
-       while(((n = send(fd, buf, len, 0)) < 0) && (errno == EINTR)) ;
+       CATCH_EINTR(n = send(fd, buf, len, 0));
        if(n < 0){
-               if(errno == EAGAIN) return(0);
-               return(-errno);
+               if(errno == EAGAIN)
+                       return 0;
+               return -errno;
        }
-       else if(n == 0) return(-ENOTCONN);
-       return(n);      
+       else if(n == 0)
+               return -ENOTCONN;
+       return n;
 }
 
 int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
 {
        int n;
 
-       while(((n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
-                          sock_len)) < 0) && (errno == EINTR)) ;
+       CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
+                              sock_len));
        if(n < 0){
-               if(errno == EAGAIN) return(0);
-               return(-errno);
+               if(errno == EAGAIN)
+                       return 0;
+               return -errno;
        }
-       else if(n == 0) return(-ENOTCONN);
-       return(n);      
+       else if(n == 0)
+               return -ENOTCONN;
+       return n;
 }
 
 struct change_pre_exec_data {
@@ -166,19 +181,21 @@ static int change_tramp(char **argv, char *output, int output_len)
        err = os_pipe(fds, 1, 0);
        if(err < 0){
                printk("change_tramp - pipe failed, err = %d\n", -err);
-               return(err);
+               return err;
        }
        pe_data.close_me = fds[0];
        pe_data.stdout = fds[1];
        pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
 
-       read_output(fds[0], output, output_len);
+       if (pid > 0)    /* Avoid hang as we won't get data in failure case. */
+               read_output(fds[0], output, output_len);
+
        os_close_file(fds[0]);
        os_close_file(fds[1]);
 
        if (pid > 0)
                CATCH_EINTR(err = waitpid(pid, NULL, 0));
-       return(pid);
+       return pid;
 }
 
 static void change(char *dev, char *what, unsigned char *addr,
@@ -229,26 +246,15 @@ char *split_if_spec(char *str, ...)
        va_start(ap, str);
        while((arg = va_arg(ap, char **)) != NULL){
                if(*str == '\0')
-                       return(NULL);
+                       return NULL;
                end = strchr(str, ',');
                if(end != str)
                        *arg = str;
                if(end == NULL)
-                       return(NULL);
+                       return NULL;
                *end++ = '\0';
                str = end;
        }
        va_end(ap);
-       return(str);
+       return str;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */