<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 28, 2019 at 2:50 AM Anna Fuchs &lt;<a href="mailto:anna.fuchs@informatik.uni-hamburg.de">anna.fuchs@informatik.uni-hamburg.de</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Hello Matt,<br>
<br>
thanks for your reply.<br>
<br>
&gt; <br>
&gt; You can set the block size (of the first and only block) using <br>
&gt; dmu_object_set_blocksize().  FYI, I think that this comment is <br>
&gt; incorrect:<br>
&gt;  * If the first block is allocated already, the new size must be <br>
&gt; greater<br>
&gt;  * than the current block size.<br>
&gt; <br>
&gt; You can increase or decrease the block size with this routine.<br>
<br>
This is a deeper call of Lustre&#39;s osd_grow_blocksize I mentioned <br>
before. If I understand it correctly, they are called in the context of <br>
transactions, right?<br></blockquote><div><br></div><div>It is not possible to change the block size of a ZFS object outside of a transaction.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
If so, I can not use it - I need the blocksize to be set in the buffer <br>
preparation stage, before comitting in a transaction.<br>
Lustre&#39;s original routine looks simplified as follows:<br>
<br>
osd_bufs_get_write<br>
        bs = dn-&gt;dn_datablksz<br>
        while (len &gt; 0)<br>
                if (sz_in_block == bs)          /* full block, try zerocopy */<br>
                        abuf = osd_request_arcbuf(dn, bs);<br>
                else                            /* can&#39;t use zerocopy, allocate temp. buffers */<br>
                        ... alloc_page ...<br>
                        here going later on the dmu_write path (pagewise!)<br>
<br>
Currently, in the very first iteration this blocksize (bs) is taken <br>
from the dnode and is e.g. 4K.<br>
When writing a chunk of 16K, I get 4 arcbufs 4K each. For the next <br>
chunk the block size might be grown up to x (recordsize?).<br>
Here I need the blocksize to be set to 16K (or 128K or later some <br>
generic value defined by the Lustre client) before the first arcbuf is <br>
requested,<br>
because the compressed chunk sent from client is logically this size.<br>
At this point I don&#39;t have any dmu_tx yet to grow the blocksize saved <br>
in dn-&gt;dn_datablksz before the while loop.<br>
So I am not sure how deep to go? This min size is set on dnode creation <br>
by ZFS, how can I &quot;reset&quot; it?<br></blockquote><div><br></div><div>I think that you are saying that you want to be loaned an ARC buffer of the size provided by the client, which may be different from the object&#39;s current blocksize.  You will later (within a transaction) change the object&#39;s blocksize to the size specified by the client, and write the data (using the loaned ARC buffer).  You can do exactly that using the routines I mentioned.</div><div><br></div><div>In your example code above, you are providing the dnode when requesting the arc buf, which leads to the problem you described (needing that dnode&#39;s block size to match the size provided by the client before you change the blocksize of the object).  However, this is an unnecessary restriction, because arc_loan_compressed_buf() does not need to know the dnode, or its current block size.</div><div><br></div><div>--matt</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
&gt; <br>
&gt; I&#39;d recommend that you hand the compressed data to ZFS similarly to <br>
&gt; how &quot;zfs receive&quot; does (for compressed send streams).  It sounds like <br>
&gt; the is the direction you&#39;re going, which is great.  FYI, here are <br>
&gt; some of the routines you&#39;d want to use (copied from dmu_recv.c):<br>
&gt; <br>
&gt;                       abuf = arc_loan_compressed_buf(<br>
&gt; <br>
&gt;                          dmu_objset_spa(drc-&gt;drc_os),<br>
&gt; <br>
&gt;                          drrw-&gt;drr_compressed_size, drrw-&gt;drr_logical_size,<br>
&gt; <br>
&gt;                          drrw-&gt;drr_compressiontype);<br>
&gt; <br>
&gt; <br>
&gt;       dmu_assign_arcbuf(bonus, drrw-&gt;drr_offset, abuf, tx);<br>
&gt; <br>
&gt;  (or dmu_assign_arcbuf_dnode())<br>
&gt; <br>
&gt; <br>
&gt;                       dmu_return_arcbuf(rrd-&gt;write_buf);<br>
&gt; <br>
<br>
Yes, thanks for that. We have two paths how Lustre interacts with ZFS - <br>
requesting arc buffers or dmu_write.<br>
The common dmu_request_arcbuf goes over arc_loan_buf, so we introduced <br>
dmu_request_compressed_arcbuf to go over arc_loan_compressed_buf to <br>
reuse the receive functionality.<br>
We try to make as few changes as possible on Lustre&#39;s interface since <br>
we want mix compressed and uncompressed data chunks (and be at the same <br>
time compatible with ZFS&#39; on disk format..)<br>
The dmu_write path will be tricky, though.<br>
<br>
Any comments are welcome.<br>
<br>
Best regards<br>
Anna<br>
<br>
--<br>
<br>
Anna Fuchs<br>
Universität Hamburg<br>
<br>
<br>
</blockquote></div></div></div></div>