[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v8 05/36] raw-posix: Add image locking support
From: |
Max Reitz |
Subject: |
Re: [Qemu-devel] [PATCH v8 05/36] raw-posix: Add image locking support |
Date: |
Wed, 26 Oct 2016 16:56:26 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 |
On 25.10.2016 15:43, Fam Zheng wrote:
> On Tue, 10/25 15:28, Max Reitz wrote:
>> On 25.10.2016 08:31, Fam Zheng wrote:
>>> On Sat, 10/22 01:40, Max Reitz wrote:
>>>> On 30.09.2016 14:09, Fam Zheng wrote:
>>
>> [...]
>>
>>>>> +static int
>>>>> +raw_reopen_upgrade(BDRVReopenState *state,
>>>>> + RawReopenOperation op,
>>>>> + ImageLockMode old_lock,
>>>>> + ImageLockMode new_lock,
>>>>> + Error **errp)
>>>>> +{
>>>>> + BDRVRawReopenState *raw_s = state->opaque;
>>>>> + BDRVRawState *s = state->bs->opaque;
>>>>> + int ret = 0, ret2;
>>>>> +
>>>>> + assert(old_lock == IMAGE_LOCK_MODE_SHARED);
>>>>> + assert(new_lock == IMAGE_LOCK_MODE_EXCLUSIVE);
>>>>> + switch (op) {
>>>>> + case RAW_REOPEN_PREPARE:
>>>>> + ret = raw_lock_fd(raw_s->lock_fd, IMAGE_LOCK_MODE_SHARED);
>>>
>>> [1]
>>>
>>>>> + if (ret) {
>>>>> + error_setg_errno(errp, -ret, "Failed to lock new fd
>>>>> (shared)");
>>>>> + break;
>>>>> + }
>>>>> + ret = raw_lock_fd(s->lock_fd, IMAGE_LOCK_MODE_NOLOCK);
>>>
>>> [2]
>>>
>>>>> + if (ret) {
>>>>> + error_setg_errno(errp, -ret, "Failed to unlock old fd");
>>>>> + goto restore;
>>>>> + }
>>>>> + ret = raw_lock_fd(raw_s->lock_fd, IMAGE_LOCK_MODE_EXCLUSIVE);
>>>
>>> [3]
>>>
>>>>> + if (ret) {
>>>>> + error_setg_errno(errp, -ret, "Failed to lock new fd
>>>>> (exclusive)");
>>>>> + goto restore;
>>>>> + }
>>>>> + break;
>>>>> + case RAW_REOPEN_COMMIT:
>>>>> + break;
>>>>> + case RAW_REOPEN_ABORT:
>>>>> + raw_lock_fd(raw_s->lock_fd, IMAGE_LOCK_MODE_SHARED);
>>>>> + ret = raw_lock_fd(s->lock_fd, IMAGE_LOCK_MODE_SHARED);
>>>
>>> [4]
>>>
>>>>> + if (ret) {
>>>>> + error_report("Failed to restore lock on old fd");
>>>>
>>>> If we get here, s->lock_fd is still locked exclusively. The following is
>>>> a very personal opinion, but anyway: I think it would be be better for
>>>> it to be unlocked. If it's locked too strictly, this can really break
>>>> something; but if it's just not locked (while it should be locked in
>>>> shared mode), everything's going to be fine unless the user makes a
>>>> mistake. I think the latter is less bad.
>>>
>>> There are four lock states when we land on this "abort" branch:
>>>
>>> a) Lock "prepare" was not run, some other error happened earlier, so the
>>> lock
>>> aren't changed compared to before the transaction starts:
>>> raw_s->lock_fd is
>>> unlocked, s->lock_fd is shared locked. In this case raw_lock_fd [4]
>>> cannot
>>> fail, and even if it does, s->lock_fd is in the correct state.
>>>
>>> b) The raw_lock_fd [1] failed. This is similar to 1), s->lock_fd is
>>> intact, so
>>> we are good.
>>>
>>> c) The raw_lock_fd [2] failed. Again, similar to above.
>>>
>>> d) The raw_lock_fd [3] failed. Here raw_s->lock_fd is shared locked, and
>>> s->lock_fd is unlocked. The correct "abort" sequence is downgrade
>>> raw_s->lock_fd and "shared lock" s->lock_fd again. If the "abort"
>>> sequence
>>> failed, s->lock_fd is unlocked.
>>
>> OK, you're right, I somehow forgot about the cases where our prepare
>> sequence was either not run at all or failed. But I was thinking about
>> the case where our preparation was successful, but some later
>> preparation in the reopen transaction failed. Then, s->lock_fd should be
>> locked exclusively, no?
>
> Oh I missed to reason about that branch. Here we go:
>
> If our preparation succeeded, raw_s->lock_fd is exclusively locked, s->lock_fd
> is unlocked. In abort we should try to return to the old state (raw_s->lock_fd
> is _not_ exclusively locked and s->lock_fd is shared locked), hence the two
> raw_lock_fd() calls at [4]. In this case, if the second raw_lock_fd() at [4]
> doesn't work, s->lock_fd is unlocked, and raw_s->lock_fd will be closed
> anyway,
> which again matches what you suggested.
Oh, right, it's raw_s->lock_fd that's exclusively locked, not s->lock_fd...
See? I really can't tell the difference between raw_s and s. :-/
So you're right, but that makes me just all the more skeptical about
raw_s...
Max
signature.asc
Description: OpenPGP digital signature