diff options
author | Chuck Lever <cel@netapp.com> | 2006-05-25 01:40:53 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-09 09:34:07 -0400 |
commit | 0d0b5cb36faf7002a11736032313f06d6f3d881c (patch) | |
tree | d767ae12fde00b553546aab9f5aa3e23cd86069d | |
parent | bf3fcf89552f24657bcfb6a9d73cd167ebb496c6 (diff) |
NFS: Optimize allocation of nfs_read/write_data structures
Clean up use of page_array, and fix an off-by-one error noticed by Tom
Talpey which causes kmalloc calls in cases where using the page_array
is sufficient.
Test plan:
Normal client functional testing with r/wsize=32768.
Signed-off-by: Chuck Lever <cel@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/read.c | 11 | ||||
-rw-r--r-- | fs/nfs/write.c | 18 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 4 |
3 files changed, 13 insertions, 20 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 4b5f58da5650..fd9018c692bb 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -51,14 +51,11 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | |||
51 | if (p) { | 51 | if (p) { |
52 | memset(p, 0, sizeof(*p)); | 52 | memset(p, 0, sizeof(*p)); |
53 | INIT_LIST_HEAD(&p->pages); | 53 | INIT_LIST_HEAD(&p->pages); |
54 | if (pagecount < NFS_PAGEVEC_SIZE) | 54 | if (pagecount <= ARRAY_SIZE(p->page_array)) |
55 | p->pagevec = &p->page_array[0]; | 55 | p->pagevec = p->page_array; |
56 | else { | 56 | else { |
57 | size_t size = ++pagecount * sizeof(struct page *); | 57 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS); |
58 | p->pagevec = kmalloc(size, GFP_NOFS); | 58 | if (!p->pagevec) { |
59 | if (p->pagevec) { | ||
60 | memset(p->pagevec, 0, size); | ||
61 | } else { | ||
62 | mempool_free(p, nfs_rdata_mempool); | 59 | mempool_free(p, nfs_rdata_mempool); |
63 | p = NULL; | 60 | p = NULL; |
64 | } | 61 | } |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 4cfada2cc09f..a515ec714bb6 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -98,11 +98,10 @@ struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount) | |||
98 | if (p) { | 98 | if (p) { |
99 | memset(p, 0, sizeof(*p)); | 99 | memset(p, 0, sizeof(*p)); |
100 | INIT_LIST_HEAD(&p->pages); | 100 | INIT_LIST_HEAD(&p->pages); |
101 | if (pagecount < NFS_PAGEVEC_SIZE) | 101 | if (pagecount <= ARRAY_SIZE(p->page_array)) |
102 | p->pagevec = &p->page_array[0]; | 102 | p->pagevec = p->page_array; |
103 | else { | 103 | else { |
104 | size_t size = ++pagecount * sizeof(struct page *); | 104 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS); |
105 | p->pagevec = kzalloc(size, GFP_NOFS); | ||
106 | if (!p->pagevec) { | 105 | if (!p->pagevec) { |
107 | mempool_free(p, nfs_commit_mempool); | 106 | mempool_free(p, nfs_commit_mempool); |
108 | p = NULL; | 107 | p = NULL; |
@@ -126,14 +125,11 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | |||
126 | if (p) { | 125 | if (p) { |
127 | memset(p, 0, sizeof(*p)); | 126 | memset(p, 0, sizeof(*p)); |
128 | INIT_LIST_HEAD(&p->pages); | 127 | INIT_LIST_HEAD(&p->pages); |
129 | if (pagecount < NFS_PAGEVEC_SIZE) | 128 | if (pagecount <= ARRAY_SIZE(p->page_array)) |
130 | p->pagevec = &p->page_array[0]; | 129 | p->pagevec = p->page_array; |
131 | else { | 130 | else { |
132 | size_t size = ++pagecount * sizeof(struct page *); | 131 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS); |
133 | p->pagevec = kmalloc(size, GFP_NOFS); | 132 | if (!p->pagevec) { |
134 | if (p->pagevec) { | ||
135 | memset(p->pagevec, 0, size); | ||
136 | } else { | ||
137 | mempool_free(p, nfs_wdata_mempool); | 133 | mempool_free(p, nfs_wdata_mempool); |
138 | p = NULL; | 134 | p = NULL; |
139 | } | 135 | } |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index c483e239f993..e206c07080fe 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -694,7 +694,7 @@ struct nfs_read_data { | |||
694 | #ifdef CONFIG_NFS_V4 | 694 | #ifdef CONFIG_NFS_V4 |
695 | unsigned long timestamp; /* For lease renewal */ | 695 | unsigned long timestamp; /* For lease renewal */ |
696 | #endif | 696 | #endif |
697 | struct page *page_array[NFS_PAGEVEC_SIZE + 1]; | 697 | struct page *page_array[NFS_PAGEVEC_SIZE]; |
698 | }; | 698 | }; |
699 | 699 | ||
700 | struct nfs_write_data { | 700 | struct nfs_write_data { |
@@ -712,7 +712,7 @@ struct nfs_write_data { | |||
712 | #ifdef CONFIG_NFS_V4 | 712 | #ifdef CONFIG_NFS_V4 |
713 | unsigned long timestamp; /* For lease renewal */ | 713 | unsigned long timestamp; /* For lease renewal */ |
714 | #endif | 714 | #endif |
715 | struct page *page_array[NFS_PAGEVEC_SIZE + 1]; | 715 | struct page *page_array[NFS_PAGEVEC_SIZE]; |
716 | }; | 716 | }; |
717 | 717 | ||
718 | struct nfs_access_entry; | 718 | struct nfs_access_entry; |