Re: [PATCH v2 4/4] refs/files: handle D/F conflicts during locking

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

 



Patrick Steinhardt <ps@xxxxxx> writes:

> On Mon, Sep 08, 2025 at 02:37:38PM +0200, Karthik Nayak wrote:
>> The previous commit, added the necessary validation and checks for F/D
>
> s/commit,/commit/
>

Thanks, will change.

>> diff --git a/refs.c b/refs.c
>> index 4c1c339ed9..ec4f0e9502 100644
>> --- a/refs.c
>> +++ b/refs.c
>> @@ -1232,6 +1232,12 @@ int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction,
>>  	if (err == REF_TRANSACTION_ERROR_GENERIC)
>>  		return 0;
>>
>> +	/*
>> +	 * Remove this refname from the list of refnames used for validation
>> +	 */
>
> Nit: it's obvious that we remove the refname from that list, so the
> comment is not helping much. It's much more important to explain _why_
> we do that though to give readers the necessary context.
>

Indeed, I'll add this instead

  Rejected refnames shouldn't be considered in the availability checks,
  so remove them from the list.

>> +	string_list_remove(&transaction->refnames,
>> +			   transaction->updates[update_idx]->refname, 0);
>> +
>>  	transaction->updates[update_idx]->rejection_err = err;
>>  	ALLOC_GROW(transaction->rejections->update_indices,
>>  		   transaction->rejections->nr + 1,
>> diff --git a/refs/files-backend.c b/refs/files-backend.c
>> index 85f2e14e93..ceeec272ff 100644
>> --- a/refs/files-backend.c
>> +++ b/refs/files-backend.c
>> @@ -852,6 +852,7 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs,
>>  				goto error_return;
>>  			} else if (remove_dir_recursively(&ref_file,
>>  							  REMOVE_DIR_EMPTY_ONLY)) {
>> +				ret = REF_TRANSACTION_ERROR_NAME_CONFLICT;
>>  				if (refs_verify_refname_available(
>>  						    &refs->base, refname,
>>  						    extras, NULL, 0, err)) {
>> @@ -859,7 +860,6 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs,
>>  					 * The error message set by
>>  					 * verify_refname_available() is OK.
>>  					 */
>> -					ret = REF_TRANSACTION_ERROR_NAME_CONFLICT;
>>  					goto error_return;
>>  				} else {
>>  					/*
>
> Hm, interesting. Previously we'd have returned a generic error in the
> `else` branch, which reads like this:
>
> 	} else {
> 		/*
> 		 * We can't delete the directory,
> 		 * but we also don't know of any
> 		 * references that it should
> 		 * contain.
> 		 */
> 		strbuf_addf(err, "there is a non-empty directory '%s' "
> 			    "blocking reference '%s'",
> 			    ref_file.buf, refname);
> 		goto error_return;
> 	}
>
> So that directory contains something, even though we've previously
> verified that it shouldn't, if I understand correctly. The test case you
> add does seem to indicate that there are valid cases though where this
> can happen on a case insensitive filesystem?
>
> If so, the comment definitely needs to be updated to explain this
> additional error case.
>

Yeah I think that comment needs to be rewritten.

> One more question is whether it's the correct thing to unconditionally
> return REF_TRANSACTION_ERROR_NAME_CONFLICT in that case now. Could it be
> that the directory exists but contains some garbage?
>
> Patrick

This does affect case-sensitive systems too. I should've added a test
there as well to showcase this.

Basically if there is a lock file in a directory
'refs/heads/foo/bar.lock' while fetching 'refs/heads/foo', this would
reach this section of the code. Pre batched-updates, we would skip this
ref and update other refs. So it makes sense to retain this behavior.
I'll add in a test and amend the commit message to reflect this
behavior.

- Karthik

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux