<div dir="ltr"><div dir="ltr">On Tue, Mar 2, 2021 at 8:25 PM Eric Blake <<a href="mailto:eblake@redhat.com">eblake@redhat.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 3/2/21 11:21 AM, Nir Soffer wrote:<br>
> On Tue, Mar 2, 2021 at 4:45 PM Eric Blake <<a href="mailto:eblake@redhat.com" target="_blank">eblake@redhat.com</a>> wrote:<br>
>><br>
>> Previously, attempts to use nbdkit without -r in order to visit a<br>
>> read-only image failed to open the image (in fact, a single read-only<br>
>> file in an otherwise usable directory makes "nbdkit file dir=. --run<br>
>> 'nbdinfo --list'" fail to print anything in libnbd 1.6).  But a saner<br>
>> approach is to try a fallback to a readonly fd if a read-write fd<br>
>> fails.<br>
> <br>
> So this is mainly a convenience if the user forgot -r, right?<br>
<br>
Not just that.  Right now, the NBD protocol has no way for the client to<br>
advertise its intent to the server.  I'd love to add an extension where<br>
a client can hint that it intends to be read-only, or that it wants<br>
write access, to allow a server to further fine-tune which files it<br>
advertises as available.  But without that extension, the choice of<br>
whether to be read-only resides solely on the server, prior to the<br>
client even being started.  Advertising something, then being unable to<br>
expose it after all, is annoying.<br>
<br>
Perhaps we could _also_ patch file dir=... mode to not even advertise<br>
read-only files if nbdkit was started without -r, but the graceful<br>
fallback to readonly seems nicer than requiring the user to remember to<br>
start nbdkit with -r.<br>
<br>
And for reference, I hit it while doing:<br>
<br>
nbdkit file dir=path/to/nbdkit --run 'nbdinfo --list'<br>
<br>
which failed to show anything at all (until my companion patch to libnbd<br>
earlier today, which I already pushed as it was not as challenging as<br>
this one), all because the nbdkit build process creates a readonly<br>
<a href="http://podwrapper.pl" rel="noreferrer" target="_blank">podwrapper.pl</a> in that directory from the <a href="http://podwrapper.pl.in" rel="noreferrer" target="_blank">podwrapper.pl.in</a> file.<br>
<br>
>>    h->fd = openat (dfd, file, flags);<br>
>> +  if (h->fd == -1 && !readonly) {<br>
>> +    int saved_errno = errno;<br>
>> +    flags = (flags & ~O_ACCMODE) | O_RDONLY;<br>
>> +    h->fd = openat (dfd, file, flags);<br>
>> +    if (h->fd == -1)<br>
>> +      errno = saved_errno;<br>
>> +    else<br>
>> +      h->can_write = false;<br>
>> +  }<br>
>>    if (h->fd == -1) {<br>
>>      nbdkit_error ("open: %s: %m", file);<br>
> <br>
> This will always report the error that failed open when using O_RDWR.<br>
> But if open(O_RDWR) fail with EPERM, and open(O_RDONLY) fails<br>
> with another error, the other error will be hidden.<br>
<br>
Generally, the first error is the one that matters most.  POSIX says<br>
that when more than one error condition applies, it is up to the<br>
implementation which one it wants to return.  But in practice, something<br>
like ENOENT will take precedence, and both the O_RDWR and O_RDONLY<br>
attempts will fail with the same ENOENT, and not the O_RDWR failing due<br>
to EPERM.<br>
<br>
> <br>
> Maybe it is better to log the first error so we don't need to save errno<br>
> when trying to open in read only mode?<br>
<br>
I didn't see it as that much added value.  I also considered checking<br>
for specific values of errno (EPERM, EROFS, others?) but figured I'd<br>
probably miss something.  I also tried to avoid the TOCTTOU race of<br>
checking stat() before open() (avoiding a second open if the stat says<br>
no read permissions, but then being potentially stale data if the file<br>
changed between the two calls).<br>
<br>
> <br>
> This can make it easier to use, but on the other hand it complicates<br>
> the code and error handling when a user could use --readdonly, so<br>
> I'm not sure about this.<br>
<br>
Requiring the server user to pass -r before even starting nbdkit is not<br>
as nice as if the client could request -r, but that NBD extension<br>
doesn't exist yet.<br></blockquote><div><br></div><div>Agree, it looks useful, and simplifies usage.</div><div> </div></div></div>