diff options
author | Christoph Hellwig <hch@lst.de> | 2014-08-21 12:09:25 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-09-10 15:47:01 -0400 |
commit | 5f919c9f10c1cf821ee5f414683214a361a1b98c (patch) | |
tree | 401fab5447d465efa72b750905ea31868a7d4a5b /fs/nfs/nfs4xdr.c | |
parent | 47abadefad213bb7de9592d2e09a8bd282ddc3de (diff) |
pnfs: allow splicing pre-encoded pages into the layoutcommit args
Currently there is no XDR buffer space allocated for the per-layout driver
layoutcommit payload, which leads to server buffer overflows in the
blocklayout driver even under simple workloads. As we can't do per-layout
sizes for XDR operations we'll have to splice a previously encoded list
of pages into the XDR stream, similar to how we handle ACL buffers.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index e13b59d8d9aa..f2cd957adb90 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -395,7 +395,10 @@ static int nfs4_stat_to_errno(int); | |||
395 | 2 /* last byte written */ + \ | 395 | 2 /* last byte written */ + \ |
396 | 1 /* nt_timechanged (false) */ + \ | 396 | 1 /* nt_timechanged (false) */ + \ |
397 | 1 /* layoutupdate4 layout type */ + \ | 397 | 1 /* layoutupdate4 layout type */ + \ |
398 | 1 /* NULL filelayout layoutupdate4 payload */) | 398 | 1 /* layoutupdate4 opaqueue len */) |
399 | /* the actual content of layoutupdate4 should | ||
400 | be allocated by drivers and spliced in | ||
401 | using xdr_write_pages */ | ||
399 | #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) | 402 | #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) |
400 | #define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ | 403 | #define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \ |
401 | encode_stateid_maxsz + \ | 404 | encode_stateid_maxsz + \ |
@@ -1990,7 +1993,7 @@ encode_layoutget(struct xdr_stream *xdr, | |||
1990 | static int | 1993 | static int |
1991 | encode_layoutcommit(struct xdr_stream *xdr, | 1994 | encode_layoutcommit(struct xdr_stream *xdr, |
1992 | struct inode *inode, | 1995 | struct inode *inode, |
1993 | const struct nfs4_layoutcommit_args *args, | 1996 | struct nfs4_layoutcommit_args *args, |
1994 | struct compound_hdr *hdr) | 1997 | struct compound_hdr *hdr) |
1995 | { | 1998 | { |
1996 | __be32 *p; | 1999 | __be32 *p; |
@@ -2011,11 +2014,16 @@ encode_layoutcommit(struct xdr_stream *xdr, | |||
2011 | *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ | 2014 | *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ |
2012 | *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ | 2015 | *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ |
2013 | 2016 | ||
2014 | if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) | 2017 | if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) { |
2015 | NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit( | 2018 | NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit( |
2016 | NFS_I(inode)->layout, xdr, args); | 2019 | NFS_I(inode)->layout, xdr, args); |
2017 | else | 2020 | } else { |
2018 | encode_uint32(xdr, 0); /* no layout-type payload */ | 2021 | encode_uint32(xdr, args->layoutupdate_len); |
2022 | if (args->layoutupdate_pages) { | ||
2023 | xdr_write_pages(xdr, args->layoutupdate_pages, 0, | ||
2024 | args->layoutupdate_len); | ||
2025 | } | ||
2026 | } | ||
2019 | 2027 | ||
2020 | return 0; | 2028 | return 0; |
2021 | } | 2029 | } |