소스 검색

SUNRPC: Add a label for RPC calls that require allocation on receive

If the RPC call relies on the receive call allocating pages as buffers,
then let's label it so that we
a) Don't leak memory by allocating pages for requests that do not expect
   this behaviour
b) Can optimise for the common case where calls do not require allocation.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Trond Myklebust 6 년 전
부모
커밋
431f6eb357
4개의 변경된 파일6개의 추가작업 그리고 2개의 파일을 삭제
  1. 3 1
      fs/nfs/nfs3xdr.c
  2. 1 0
      include/linux/sunrpc/xdr.h
  3. 1 0
      net/sunrpc/auth_gss/gss_rpc_xdr.c
  4. 1 1
      net/sunrpc/socklib.c

+ 3 - 1
fs/nfs/nfs3xdr.c

@@ -1364,10 +1364,12 @@ static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req,
 
 
 	encode_nfs_fh3(xdr, args->fh);
 	encode_nfs_fh3(xdr, args->fh);
 	encode_uint32(xdr, args->mask);
 	encode_uint32(xdr, args->mask);
-	if (args->mask & (NFS_ACL | NFS_DFACL))
+	if (args->mask & (NFS_ACL | NFS_DFACL)) {
 		prepare_reply_buffer(req, args->pages, 0,
 		prepare_reply_buffer(req, args->pages, 0,
 					NFSACL_MAXPAGES << PAGE_SHIFT,
 					NFSACL_MAXPAGES << PAGE_SHIFT,
 					ACL3_getaclres_sz);
 					ACL3_getaclres_sz);
+		req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
+	}
 }
 }
 
 
 static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
 static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,

+ 1 - 0
include/linux/sunrpc/xdr.h

@@ -58,6 +58,7 @@ struct xdr_buf {
 			flags;		/* Flags for data disposition */
 			flags;		/* Flags for data disposition */
 #define XDRBUF_READ		0x01		/* target of file read */
 #define XDRBUF_READ		0x01		/* target of file read */
 #define XDRBUF_WRITE		0x02		/* source of file write */
 #define XDRBUF_WRITE		0x02		/* source of file write */
+#define XDRBUF_SPARSE_PAGES	0x04		/* Page array is sparse */
 
 
 	unsigned int	buflen,		/* Total length of storage buffer */
 	unsigned int	buflen,		/* Total length of storage buffer */
 			len;		/* Length of XDR encoded message */
 			len;		/* Length of XDR encoded message */

+ 1 - 0
net/sunrpc/auth_gss/gss_rpc_xdr.c

@@ -784,6 +784,7 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req,
 	xdr_inline_pages(&req->rq_rcv_buf,
 	xdr_inline_pages(&req->rq_rcv_buf,
 		PAGE_SIZE/2 /* pretty arbitrary */,
 		PAGE_SIZE/2 /* pretty arbitrary */,
 		arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
 		arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
+	req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
 done:
 done:
 	if (err)
 	if (err)
 		dprintk("RPC:       gssx_enc_accept_sec_context: %d\n", err);
 		dprintk("RPC:       gssx_enc_accept_sec_context: %d\n", err);

+ 1 - 1
net/sunrpc/socklib.c

@@ -104,7 +104,7 @@ ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct
 
 
 		/* ACL likes to be lazy in allocating pages - ACLs
 		/* ACL likes to be lazy in allocating pages - ACLs
 		 * are small by default but can get huge. */
 		 * are small by default but can get huge. */
-		if (unlikely(*ppage == NULL)) {
+		if ((xdr->flags & XDRBUF_SPARSE_PAGES) && *ppage == NULL) {
 			*ppage = alloc_page(GFP_ATOMIC);
 			*ppage = alloc_page(GFP_ATOMIC);
 			if (unlikely(*ppage == NULL)) {
 			if (unlikely(*ppage == NULL)) {
 				if (copied == 0)
 				if (copied == 0)