Patchwork [v7,3/6] char: Let writers know how much data was written in case of errors

login
register
mail settings
Submitter Amit Shah
Date May 4, 2010, 9:39 p.m.
Message ID <1273009170-17530-4-git-send-email-amit.shah@redhat.com>
Download mbox | patch
Permalink /patch/51692/
State New
Headers show

Comments

Amit Shah - May 4, 2010, 9:39 p.m.
On writing errors, we just returned -1 even if some bytes were already
written out. Ensure we return the number of bytes written before we
return the error (on a subsequent call to qemu_chr_write()).

Signed-off-by: Amit Shah <amit.shah@redhat.com>
---
 qemu-char.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)
Anthony Liguori - May 5, 2010, 1:15 p.m.
On 05/04/2010 04:39 PM, Amit Shah wrote:
> On writing errors, we just returned -1 even if some bytes were already
> written out. Ensure we return the number of bytes written before we
> return the error (on a subsequent call to qemu_chr_write()).
>
> Signed-off-by: Amit Shah<amit.shah@redhat.com>
> ---
>   qemu-char.c |   12 +++++++++++-
>   1 files changed, 11 insertions(+), 1 deletions(-)
>
> diff --git a/qemu-char.c b/qemu-char.c
> index 76ad12c..decf687 100644
> --- a/qemu-char.c
> +++ b/qemu-char.c
> @@ -507,6 +507,9 @@ int send_all(int fd, const void *buf, int len1)
>       while (len>  0) {
>           ret = send(fd, buf, len, 0);
>           if (ret<  0) {
> +            if (len1 - len) {
> +                return len1 - len;
> +            }
>               errno = WSAGetLastError();
>               if (errno != WSAEWOULDBLOCK) {
>                   return -1;
> @@ -531,8 +534,15 @@ static int unix_write(int fd, const uint8_t *buf, int len1)
>       while (len>  0) {
>           ret = write(fd, buf, len);
>           if (ret<  0) {
> -            if (errno != EINTR&&  errno != EAGAIN)
> +            if (errno == EINTR) {
> +                continue;
> +            }
> +            if (len1 - len) {
> +                return len1 - len;
> +            }
> +            if (errno != EAGAIN) {
>                   return -1;
> +            }
>           } else if (ret == 0) {
>               break;
>           } else {
>    

This will break lots of things.  The contract for send_all and 
unix_write is that the transmit all data.

Regards,

Anthony Liguori
Amit Shah - May 5, 2010, 1:23 p.m.
On (Wed) May 05 2010 [08:15:19], Anthony Liguori wrote:
> On 05/04/2010 04:39 PM, Amit Shah wrote:
>> On writing errors, we just returned -1 even if some bytes were already
>> written out. Ensure we return the number of bytes written before we
>> return the error (on a subsequent call to qemu_chr_write()).
>>
>> Signed-off-by: Amit Shah<amit.shah@redhat.com>
>> ---
>>   qemu-char.c |   12 +++++++++++-
>>   1 files changed, 11 insertions(+), 1 deletions(-)
>>
>> diff --git a/qemu-char.c b/qemu-char.c
>> index 76ad12c..decf687 100644
>> --- a/qemu-char.c
>> +++ b/qemu-char.c
>> @@ -507,6 +507,9 @@ int send_all(int fd, const void *buf, int len1)
>>       while (len>  0) {
>>           ret = send(fd, buf, len, 0);
>>           if (ret<  0) {
>> +            if (len1 - len) {
>> +                return len1 - len;
>> +            }
>>               errno = WSAGetLastError();
>>               if (errno != WSAEWOULDBLOCK) {
>>                   return -1;
>> @@ -531,8 +534,15 @@ static int unix_write(int fd, const uint8_t *buf, int len1)
>>       while (len>  0) {
>>           ret = write(fd, buf, len);
>>           if (ret<  0) {
>> -            if (errno != EINTR&&  errno != EAGAIN)
>> +            if (errno == EINTR) {
>> +                continue;
>> +            }
>> +            if (len1 - len) {
>> +                return len1 - len;
>> +            }
>> +            if (errno != EAGAIN) {
>>                   return -1;
>> +            }
>>           } else if (ret == 0) {
>>               break;
>>           } else {
>>    
>
> This will break lots of things.  The contract for send_all and  
> unix_write is that the transmit all data.

The current behaviour remains unchanged for all the users. Only callers
of qemu_chr_write_nb() will get an -EAGAIN return.

		Amit
Anthony Liguori - May 5, 2010, 1:54 p.m.
On 05/05/2010 08:23 AM, Amit Shah wrote:
> On (Wed) May 05 2010 [08:15:19], Anthony Liguori wrote:
>    
>> On 05/04/2010 04:39 PM, Amit Shah wrote:
>>      
>>> On writing errors, we just returned -1 even if some bytes were already
>>> written out. Ensure we return the number of bytes written before we
>>> return the error (on a subsequent call to qemu_chr_write()).
>>>
>>> Signed-off-by: Amit Shah<amit.shah@redhat.com>
>>> ---
>>>    qemu-char.c |   12 +++++++++++-
>>>    1 files changed, 11 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/qemu-char.c b/qemu-char.c
>>> index 76ad12c..decf687 100644
>>> --- a/qemu-char.c
>>> +++ b/qemu-char.c
>>> @@ -507,6 +507,9 @@ int send_all(int fd, const void *buf, int len1)
>>>        while (len>   0) {
>>>            ret = send(fd, buf, len, 0);
>>>            if (ret<   0) {
>>> +            if (len1 - len) {
>>> +                return len1 - len;
>>> +            }
>>>                errno = WSAGetLastError();
>>>                if (errno != WSAEWOULDBLOCK) {
>>>                    return -1;
>>> @@ -531,8 +534,15 @@ static int unix_write(int fd, const uint8_t *buf, int len1)
>>>        while (len>   0) {
>>>            ret = write(fd, buf, len);
>>>            if (ret<   0) {
>>> -            if (errno != EINTR&&   errno != EAGAIN)
>>> +            if (errno == EINTR) {
>>> +                continue;
>>> +            }
>>> +            if (len1 - len) {
>>> +                return len1 - len;
>>> +            }
>>> +            if (errno != EAGAIN) {
>>>                    return -1;
>>> +            }
>>>            } else if (ret == 0) {
>>>                break;
>>>            } else {
>>>
>>>        
>> This will break lots of things.  The contract for send_all and
>> unix_write is that the transmit all data.
>>      
> The current behaviour remains unchanged for all the users. Only callers
> of qemu_chr_write_nb() will get an -EAGAIN return.
>    

No, send_all used to send all data.  After your change, it only sends 
what it can the first time.  The same with unix_write.

Regards,

Anthony Liguori

> 		Amit
>
Amit Shah - May 5, 2010, 2:06 p.m.
On (Wed) May 05 2010 [08:54:48], Anthony Liguori wrote:
> On 05/05/2010 08:23 AM, Amit Shah wrote:
>> On (Wed) May 05 2010 [08:15:19], Anthony Liguori wrote:
>>    
>>> On 05/04/2010 04:39 PM, Amit Shah wrote:
>>>      
>>>> On writing errors, we just returned -1 even if some bytes were already
>>>> written out. Ensure we return the number of bytes written before we
>>>> return the error (on a subsequent call to qemu_chr_write()).
>>>>
>>>> Signed-off-by: Amit Shah<amit.shah@redhat.com>
>>>> ---
>>>>    qemu-char.c |   12 +++++++++++-
>>>>    1 files changed, 11 insertions(+), 1 deletions(-)
>>>>
>>>> diff --git a/qemu-char.c b/qemu-char.c
>>>> index 76ad12c..decf687 100644
>>>> --- a/qemu-char.c
>>>> +++ b/qemu-char.c
>>>> @@ -507,6 +507,9 @@ int send_all(int fd, const void *buf, int len1)
>>>>        while (len>   0) {
>>>>            ret = send(fd, buf, len, 0);
>>>>            if (ret<   0) {
>>>> +            if (len1 - len) {
>>>> +                return len1 - len;
>>>> +            }
>>>>                errno = WSAGetLastError();
>>>>                if (errno != WSAEWOULDBLOCK) {
>>>>                    return -1;
>>>> @@ -531,8 +534,15 @@ static int unix_write(int fd, const uint8_t *buf, int len1)
>>>>        while (len>   0) {
>>>>            ret = write(fd, buf, len);
>>>>            if (ret<   0) {
>>>> -            if (errno != EINTR&&   errno != EAGAIN)
>>>> +            if (errno == EINTR) {
>>>> +                continue;
>>>> +            }
>>>> +            if (len1 - len) {
>>>> +                return len1 - len;
>>>> +            }
>>>> +            if (errno != EAGAIN) {
>>>>                    return -1;
>>>> +            }
>>>>            } else if (ret == 0) {
>>>>                break;
>>>>            } else {
>>>>
>>>>        
>>> This will break lots of things.  The contract for send_all and
>>> unix_write is that the transmit all data.
>>>      
>> The current behaviour remains unchanged for all the users. Only callers
>> of qemu_chr_write_nb() will get an -EAGAIN return.
>>    
>
> No, send_all used to send all data.  After your change, it only sends  
> what it can the first time.  The same with unix_write.

Where do you see this?

		Amit

Patch

diff --git a/qemu-char.c b/qemu-char.c
index 76ad12c..decf687 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -507,6 +507,9 @@  int send_all(int fd, const void *buf, int len1)
     while (len > 0) {
         ret = send(fd, buf, len, 0);
         if (ret < 0) {
+            if (len1 - len) {
+                return len1 - len;
+            }
             errno = WSAGetLastError();
             if (errno != WSAEWOULDBLOCK) {
                 return -1;
@@ -531,8 +534,15 @@  static int unix_write(int fd, const uint8_t *buf, int len1)
     while (len > 0) {
         ret = write(fd, buf, len);
         if (ret < 0) {
-            if (errno != EINTR && errno != EAGAIN)
+            if (errno == EINTR) {
+                continue;
+            }
+            if (len1 - len) {
+                return len1 - len;
+            }
+            if (errno != EAGAIN) {
                 return -1;
+            }
         } else if (ret == 0) {
             break;
         } else {