Re: [PATCH 11/14] nfsd: add user xattr RPC XDR encoding/decoding logic

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

 




> On Mar 20, 2020, at 12:47 PM, Frank van der Linden <fllinden@xxxxxxxxxx> wrote:
> 
> Hi Chuck,
> 
> On Thu, Mar 12, 2020 at 03:16:37PM -0400, Chuck Lever wrote:
>>> +static __be32
>>> +nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp,
>>> +                   struct nfsd4_setxattr *setxattr)
>>> +{
>>> +     DECODE_HEAD;
>>> +     u32 flags, maxcount, size;
>>> +     struct kvec head;
>>> +     struct page **pagelist;
>>> +
>>> +     READ_BUF(4);
>>> +     flags = be32_to_cpup(p++);
>>> +
>>> +     if (flags > SETXATTR4_REPLACE)
>>> +             return nfserr_inval;
>>> +     setxattr->setxa_flags = flags;
>>> +
>>> +     status = nfsd4_decode_xattr_name(argp, &setxattr->setxa_name);
>>> +     if (status)
>>> +             return status;
>>> +
>>> +     maxcount = svc_max_payload(argp->rqstp);
>>> +     maxcount = min_t(u32, XATTR_SIZE_MAX, maxcount);
>>> +
>>> +     READ_BUF(4);
>>> +     size = be32_to_cpup(p++);
>>> +     if (size > maxcount)
>>> +             return nfserr_xattr2big;
>>> +
>>> +     setxattr->setxa_len = size;
>>> +     if (size > 0) {
>>> +             status = svcxdr_construct_vector(argp, &head, &pagelist, size);
>>> +             if (status)
>>> +                     return status;
>>> +
>>> +             status = nfsd4_vbuf_from_stream(argp, &head, pagelist,
>>> +                 &setxattr->setxa_buf, size);
>>> +     }
>> 
>> Now I'm wondering if read_bytes_from_xdr_buf() might be adequate
>> for this purpose, so you can avoid open-coding all of this logic.
> 
> This took a little longer, I had to check my notes,

Thanks for checking!

> but basically the reasons for doing it this way are:
> 
> * The nfsd decode path uses nfsd4_compoundargs, which doesn't have an
>  xdr_stream (it has a page array). So read_bytes_from_xdr_buf isn't
>  a natural fit.
> * READ_BUF/read_buf don't deal with > PAGE_SIZE chunks, but xattrs may
>  be larger than that.
> 
> The other code that deals with > PAGE_SIZE chunks is the write code. So,
> I factored out some code from the write code, used that, and added a function
> to process the resulting kvec / pagelist (nfs4_vbuf_from_stream).

Yes, I only recently discovered that the xdr_stream helpers do not
work for decoding data items that are page size or larger.

For the record, my IMA prototype takes this approach for decode_fattr:

+       if (bmval[2] & FATTR4_WORD2_IMA) {
+               READ_BUF(4);
+               len += 4;
+               dummy32 = be32_to_cpup(p++);
+               READ_BUF(dummy32);
+               if (dummy32 > NFS4_MAXIMALEN)
+                       return nfserr_badlabel;
+               *ima = svcxdr_tmpalloc(argp, sizeof(**ima));
+               if (*ima == NULL)
+                       return nfserr_jukebox;
+
+               len += (XDR_QUADLEN(dummy32) << 2);
+               READMEM(buf, dummy32);
+               (*ima)->len = dummy32;
+               (*ima)->data = svcxdr_dupstr(argp, buf, dummy32);
+               if ((*ima)->data == NULL)
+                       return nfserr_jukebox;
+       } else
+               ima = NULL;

Although, an IMA blob is never larger than a page, IIRC.

> There definitely seem to be several copy functions in both the client
> and server code that basically do the same, but in slightly different ways,
> depending on whether they use an XDR buf or not, whether the pages are
> mapped or not, etc. Seems like a good candidate for a cleanup, but I
> considered it to be out of scope for these patches.

"out of scope" - probably so. Depending on Bruce's thinking, we can
add this to the list of janitorial tasks.

For my peace of mind, "from_stream" implies there _is_ an xdr_stream
in use, even though the function does not have a struct xdr_stream
parameter. Perhaps a different naming scheme would be wise.


--
Chuck Lever







[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