qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v4] block: report errno when flock fcntl fails


From: David Edmondson
Subject: Re: [PATCH v4] block: report errno when flock fcntl fails
Date: Wed, 13 Jan 2021 10:41:28 +0000

On Wednesday, 2021-01-13 at 13:26:48 +03, Vladimir Sementsov-Ogievskiy wrote:

> 12.01.2021 18:27, David Edmondson wrote:
>> When a call to fcntl(2) for the purpose of manipulating file locks
>> fails with an error other than EAGAIN or EACCES, report the error
>> returned by fcntl.
>> 
>> EAGAIN or EACCES are elided as they are considered to be common
>> failures, indicating that a conflicting lock is held by another
>> process.
>> 
>> Signed-off-by: David Edmondson <david.edmondson@oracle.com>
>> ---
>> v3:
>> - Remove the now unnecessary updates to the test framework (Max).
>> - Elide the error detail for EAGAIN or EACCES when locking (Kevin,
>>    sort-of Max).
>> - Philippe and Vladimir sent Reviewed-by, but things have changed
>>    noticeably, so I didn't add them (dme).
>> 
>> v4:
>> - Really, really remove the unnecessary updates to the test framework.
>> 
>>   block/file-posix.c | 52 +++++++++++++++++++++++++++++++++++++---------
>>   1 file changed, 42 insertions(+), 10 deletions(-)
>> 
>> diff --git a/block/file-posix.c b/block/file-posix.c
>> index 00cdaaa2d4..c5142f7ffa 100644
>
> Hmm, not it looks like too much code duplication. Maybe, we can add a helper 
> macro, like
>
> #define raw_lock_error_setg_errno(errp, os_error, fmt, ...) \
>    do {
>      if (err == EAGAIN || err == EACCES) {
>        error_setg((errp), (fmt), ## __VA_ARGS__);
>      } else {
>        error_setg_errno((errp), (os_error), (fmt), ## __VA_ARGS__);
>      }
>    } while (0)
>
> We can't make a helper function instead, as error_setg_errno is already a 
> macro and it wants to use __LINE__..
>
> But I think that macro is better than duplication anyway.

Okay.

>> --- a/block/file-posix.c
>> +++ b/block/file-posix.c
>> @@ -836,7 +836,13 @@ static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
>>           if ((perm_lock_bits & bit) && !(locked_perm & bit)) {
>>               ret = qemu_lock_fd(fd, off, 1, false);
>>               if (ret) {
>> -                error_setg(errp, "Failed to lock byte %d", off);
>> +                int err = -ret;
>> +
>> +                if (err == EAGAIN || err == EACCES) {
>> +                    error_setg(errp, "Failed to lock byte %d", off);
>> +                } else {
>> +                    error_setg_errno(errp, err, "Failed to lock byte %d", 
>> off);
>> +                }
>>                   return ret;
>>               } else if (s) {
>>                   s->locked_perm |= bit;
>> @@ -844,7 +850,13 @@ static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
>>           } else if (unlock && (locked_perm & bit) && !(perm_lock_bits & 
>> bit)) {
>>               ret = qemu_unlock_fd(fd, off, 1);
>>               if (ret) {
>> -                error_setg(errp, "Failed to unlock byte %d", off);
>> +                int err = -ret;
>> +
>> +                if (err == EAGAIN || err == EACCES) {
>> +                    error_setg(errp, "Failed to lock byte %d", off);
>
> s/lock/unlock
>
>> +                } else {
>> +                    error_setg_errno(errp, err, "Failed to lock byte %d", 
>> off);
>
> and here.
>
> Which proves, that code duplication is a bad idea in general :)

Ouch. Will fix.

>
>> +                }
>>                   return ret;
>>               } else if (s) {
>>                   s->locked_perm &= ~bit;
>> @@ -857,7 +869,13 @@ static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
>>           if ((shared_perm_lock_bits & bit) && !(locked_shared_perm & bit)) {
>>               ret = qemu_lock_fd(fd, off, 1, false);
>>               if (ret) {
>> -                error_setg(errp, "Failed to lock byte %d", off);
>> +                int err = -ret;
>> +
>> +                if (err == EAGAIN || err == EACCES) {
>> +                    error_setg(errp, "Failed to lock byte %d", off);
>> +                } else {
>> +                    error_setg_errno(errp, err, "Failed to lock byte %d", 
>> off);
>> +                }
>>                   return ret;
>>               } else if (s) {
>>                   s->locked_shared_perm |= bit;
>> @@ -866,7 +884,7 @@ static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
>>                      !(shared_perm_lock_bits & bit)) {
>>               ret = qemu_unlock_fd(fd, off, 1);
>>               if (ret) {
>> -                error_setg(errp, "Failed to unlock byte %d", off);
>> +                error_setg_errno(errp, -ret, "Failed to unlock byte %d", 
>> off);
>
> Don't know, why same logic is not applied here.. Probably I've missed from 
> the previous discussion. Anyway, if it is intentional exclusion, not bad to 
> mention it in commit message.

>From the documentation, it didn't seem to make sense that the unlock
case would generate EAGAIN or EACCES for "someone is already holding the
lock", so neither should be elided.

I can add a note in the commit message.

>>                   return ret;
>>               } else if (s) {
>>                   s->locked_shared_perm &= ~bit;
>> @@ -890,9 +908,16 @@ static int raw_check_lock_bytes(int fd, uint64_t perm, 
>> uint64_t shared_perm,
>>               ret = qemu_lock_fd_test(fd, off, 1, true);
>>               if (ret) {
>>                   char *perm_name = bdrv_perm_names(p);
>> -                error_setg(errp,
>> -                           "Failed to get \"%s\" lock",
>> -                           perm_name);
>> +                int err = -ret;
>> +
>> +                if (err == EAGAIN || err == EACCES) {
>> +                    error_setg(errp, "Failed to get \"%s\" lock",
>> +                               perm_name);
>
> fit in one line
>
>> +                } else {
>> +                    error_setg_errno(errp, err,
>> +                                     "Failed to get \"%s\" lock",
>> +                                     perm_name);
>
> fit in two lines..
>
>> +                }
>>                   g_free(perm_name);
>>                   return ret;
>>               }
>> @@ -905,9 +930,16 @@ static int raw_check_lock_bytes(int fd, uint64_t perm, 
>> uint64_t shared_perm,
>>               ret = qemu_lock_fd_test(fd, off, 1, true);
>>               if (ret) {
>>                   char *perm_name = bdrv_perm_names(p);
>> -                error_setg(errp,
>> -                           "Failed to get shared \"%s\" lock",
>> -                           perm_name);
>> +                int err = -ret;
>> +
>> +                if (err == EAGAIN || err == EACCES) {
>> +                    error_setg(errp, "Failed to get shared \"%s\" lock",
>> +                               perm_name);
>> +                } else {
>> +                    error_setg_errno(errp, err,
>> +                                     "Failed to get shared \"%s\" lock",
>> +                                     perm_name);
>> +                }
>>                   g_free(perm_name);
>>                   return ret;
>>               }
>> 
>
> also, I don't see much benefit in creating additional "err" variable instead 
> of just use ret, but it's a kind of taste..

Okay.

dme.
-- 
Tonight I'm gonna bury that horse in the ground.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]