[Libguestfs] [PATCH nbdkit v2 7/7] New filter: nbdkit-block-size-constraint-filter

Richard W.M. Jones rjones at redhat.com
Thu Feb 17 20:55:43 UTC 2022


> > Subject: Re: [PATCH nbdkit v2 7/7] New filter: nbdkit-block-size-constraint-filter

Now also notice that I didn't change the commit message!  Fixed in my
local copy.

On Thu, Feb 17, 2022 at 12:40:23PM -0600, Eric Blake wrote:
> On Thu, Feb 17, 2022 at 02:36:48PM +0000, Richard W.M. Jones wrote:
...
> > +  nbdkit --filter=blocksize-policy \
> > +         --filter=blocksize \
> > +         PLUGIN ... \
> > +         blocksize-error-policy=allow \
> > +         blocksize-minimum=64K minblock=64K
> > +
> > +This says to advertise a minimum block size of 64K.  Well-behaved
> > +clients will obey this.  Badly behaved clients will send requests
> > +S<E<lt> 64K> which will be converted to slow 64K read-modify-write
> > +cycles to the underlying plugin.  In either case the plugin will only
> > +see requests on 64K (or multiples of 64K) boundaries.
> 
> Should the blocksize filter implement .block_size?  But that's a
> separate patch compared to this one adding a new filter.  The example
> looks good.

I think there's an argument for the blocksize filter returning minimum
the same as minblock (if set) and maximum the same as
MAX (maxlen, maxdata), but I think it is a separate patch.

...
> > +    if (config_maximum)
> > +      *maximum = config_maximum;
> > +    else
> > +      *maximum = 0xffffffff;
> 
> I'd be inclined to advertise 64*1024*1024 here instead of 0xffffffff,
> to match the actual buffer size that we know nbdkit is constrained by.
>
> Then again, doing that may cause clients to self-limit calls to .zero
> with at most 64M in a chunk, instead of calling it with 4G in a chunk.
> It's a toss-up.  (The NBD protocol really does need a fourth value, to
> distinguish between maximum buffer and maximum length)

Agreed.  Clients shouldn't set > 32M pread/pwrite requests regardless
of the limit, if I'm reading the spec correctly.

...
> > +/* This function checks the error policy for all request functions below. */
> > +static int
> > +check_policy (nbdkit_next *next, const char *type,
> > +              uint32_t count, uint64_t offset, int *err)
> 
> Ah, new code compared to the last draft ;)
> 
> > +{
> > +  uint32_t minimum, preferred, maximum;
> > +
> > +  if (error_policy == ALLOW)
> > +    return 0;
> > +
> > +  /* Get the current block size constraints.  Note these are cached in
> > +   * the backend so if they've already been computed then this simply
> > +   * returns the cached values.  The plugin is only asked once per
> > +   * connection.
> > +   */
> > +  errno = 0;
> > +  if (next->block_size (next, &minimum, &preferred, &maximum) == -1) {
> > +    *err = errno ? : EIO;
> > +    return -1;
> > +  }
> 
> Correct.
> 
> > +
> > +  /* If there are no constraints, allow. */
> > +  if (minimum == 0)
> > +    return 0;
> > +
> > +  /* Check constraints. */
> > +  if (count < minimum) {
> > +    *err = EIO;
> > +    nbdkit_error ("client %s request rejected: "
> > +                  "count %" PRIu32 " is smaller than minimum size %" PRIu32,
> > +                  type, count, minimum);
> > +    return -1;
> > +  }
> > +  if (count > maximum) {
> > +    *err = EIO;
> > +    nbdkit_error ("client %s request rejected: "
> > +                  "count %" PRIu32 " is larger than maximum size %" PRIu32,
> > +                  type, count, maximum);
> > +    return -1;
> > +  }
> 
> This is where I worry about size constraints on data (pread/pwrite)
> vs. length (zero/trim/cache).  Again, I'm happy to propose a patch on
> top of this, so we can use this as our starting point.

Hmm, this is a good point that I didn't think about.

Maybe make the maximum check here conditional on it not being
a non-data request?

> > +  if ((count % minimum) != 0) {
> > +    *err = EIO;
> > +    nbdkit_error ("client %s request rejected: "
> > +                  "count %" PRIu32 " is not a multiple "
> > +                  "of minimum size %" PRIu32,
> > +                  type, count, minimum);
> > +    return -1;
> > +  }
> > +  if ((offset % minimum) != 0) {
> > +    *err = EIO;
> > +    nbdkit_error ("client %s request rejected: "
> > +                  "offset %" PRIu64 " is not aligned to a multiple "
> > +                  "of minimum size %" PRIu32,
> > +                  type, offset, minimum);
> > +    return -1;
> > +  }
> 
> Do we also want to override .get_size, to flag (or round down) the
> case where the size reported by the plugin is not a multiple of the
> plugin's minsize, at which point those trailing bytes are inaccessbile
> to the client?  Could be done on top.
> 
> Overall the series looks good, I'll leave it up to you if you think it
> is ready to push now or if you want to adjust for one more round of
> reviews, and meanwhile I can start working on my proposed tweaks to
> compare on top to see how they look.

I've got a bit of thinking to do on it.

BTW I extended nbdkit-nbd-plugin proxy, OCaml and Python already, will
send those patches separately.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v




More information about the Libguestfs mailing list