Re: Any idea how best to handle potentially large POSIX ACLs for getfacl?

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

 



On Thu, Aug 29, 2024 at 6:41 PM Trond Myklebust <trondmy@xxxxxxxxxxxxxxx> wrote:
>
> On Thu, 2024-08-29 at 18:32 -0700, Rick Macklem wrote:
> > On Thu, Aug 29, 2024 at 5:33 PM Trond Myklebust
> > <trondmy@xxxxxxxxxxxxxxx> wrote:
> > >
> > > On Thu, 2024-08-29 at 17:19 -0700, Rick Macklem wrote:
> > > > Hi,
> > > >
> > > > I have a rather crude patch that does the POSIX draft ACL
> > > > attributes
> > > > that my draft is suggesting for NFSv4.2 for the Linux client.
> > > > - It is working ok for small ACLs, but...
> > > >
> > > > The hassle is that the on-the-wire ACEs have a "who" field that
> > > > can
> > > > be up to 128bytes (IDMAP_NAMESZ).
> > > >
> > > > I think I have figured out the SETATTR side, which isn't too bad
> > > > because
> > > > it knows how many ACEs. (It does roughly what the NFSv3 NFSACL
> > > > code
> > > > did, which is allocate some pages for the large ones.)
> > > >
> > > > However, the getfacl side doesn't know how bug the ACL will be in
> > > > the reply. The NFSACL code allocates pages (7 of them) to handle
> > > > the
> > > > largest possible ACL. Unfortunately, for these NFSv4 attributes,
> > > > they
> > > > could be roughly 140Kbytes (140bytes assuming the largest "who"
> > > > times
> > > > 1024 ACEs).
> > > > --> Anyone have a better suggestion than just allocating 35pages
> > > > each
> > > > time
> > > >     (when 99.99% of them will fit in a fraction of a page)?
> > > >
> > > > Thanks for any suggestions, rick
> > > >
> > >
> > > See the NFSv3 posix acl client code.
> > >
> > > It allocates the 'pages[]' array of pointers to the page buffers to
> > > be
> > > of length NFSACL_MAXPAGES, but only allocates the first entry, and
> > > leaves the rest NULL.
> > > Then in the XDR encoder "nfs3_xdr_enc_getacl3args()" where it
> > > declares
> > > the length of that array, it sets the flag XDRBUF_SPARSE_PAGES on
> > > the
> > > reply buffer.
> > >
> > > That tells the RPC layer that if the incoming RPC reply needs to
> > > fill
> > > in more data than will fit into that single page, then it should
> > > allocate extra pages and add them to the 'pages' array.
> > Oh, ok thanks for the explanation.
> > It doesn't sound like a problem then.
> >
> > I'll just code things the same way.
> >
> > Maybe I can ask one more question??
> > There are a large # of XXX_decode_XXX functions. Are there any that
> > should/should not be used for the above case?
> > For example, there are:
> > - Ones that take a "struct xdr_stream *xdr" (usually with _stream_ in
> > the name)
> > vs
> > - Ones that take a "struct xdr_buf *buf" argument.
> >   (I ended up using these for the encode side and this looks like
> > what
> >    nfsacl_decode() uses, as well.)
> >
> > (I'll admit I have been wading around in the code, but haven't really
> > gotten to the point of understanding which ones should be used.)
> >
>
> The "struct xdr_stream' based code is the 'newer' way of doing things,
> and allows you to write code that abstracts away some of the ugliness
> in the RPC layer, particularly when you need to mix regular buffers and
> page data.
> That said, there is definitely legacy code out there that works quite
> well and is not worth a lot of effort to convert.
>
> I'd recommend trying to use the xdr_stream if possible, just because of
> the better abstraction, but if you have to fall back to manipulating
> the xdr_buf directly, then that API is there, and is still supported.
I haven't been able to figure out how to use the xdr_stream... stuff
when the attributes get large enough that they need pages.

What I currently have (that seems to work) is...
For GETATTR, XDRBUF_SPARSE_PAGES is set, and then, once it
gets to the actual ACL (which can be pretty big), I use
   xdr_decode_word() and read_bytes_from_xdr_buf() to decode it
   (The stream calls worked until the ACL got too big for the non-page
    part, which I think is 2Kbytes?)
   - Maybe there is some trick I don't know to get the big ones to work
     with the xdr_stream_XXX() decode calls?

For SETATTR, it seemed to be similar. I actually have two ways that
seem to work:
(A) - Allocates the max # of pages (assuming 128byte who fields) and
        then in the enc function specified in PROC(xxx), it does a
         - xdr_write_pages()
         - fills the data in with xdr_encode_word() and write_bytes_to_xdr_buf()
         - trims the size to the correct (not maximum) length by setting
           xdr->buf->len and xdr->buf->page_len
         --> I don't like this one because it typically allocates more pages
               than needed and requires the len to be trimmed.
(B) - I wrote a couple of simple functions (I couldn't find ones that already
         did this) which encode the ACLs before the RPC call
(nfs4_do_call_sync())
         allocating page(s) as required. Then all the enc function in PROC(...)
         does is a xdr_write_pages().
I prefer (B), but they both seem to work. Small ACLs don't do (A) or (B) and
are just encoded with the xdr_stream_XXX() functions.

Anyhow, if there are better ways to handle the big (up to 2 * 140Kbytes) ACLs,
please let me know.
In the meantime, the above seems to be working.

Thanks for your comments, rick

>
> --
> Trond Myklebust
> Linux NFS client maintainer, Hammerspace
> trond.myklebust@xxxxxxxxxxxxxxx
>
>





[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux