aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_cil.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-08-12 06:50:05 -0400
committerBen Myers <bpm@sgi.com>2013-08-13 17:12:30 -0400
commit7492c5b42de857c13d8b7e0dafb2a5e331598e00 (patch)
tree95a073b09c3ec9105bb33d1ee0cbbe28f2f78f9c /fs/xfs/xfs_log_cil.c
parent166d13688a0e2d0aa379e259af8e2ee6a401de9a (diff)
xfs: Reduce allocations during CIL insertion
Now that we have the size of the object before the formatting pass is called, we can allocation the log vector and it's buffer in a single allocation rather than two separate allocations. Store the size of the allocated buffer in the log vector so that we potentially avoid allocation for future modifications of the object. While touching this code, remove the IOP_FORMAT definition. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_log_cil.c')
-rw-r--r--fs/xfs/xfs_log_cil.c95
1 files changed, 56 insertions, 39 deletions
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 4e108720a789..423ceaf0aeb0 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -80,6 +80,36 @@ xlog_cil_init_post_recovery(
80 log->l_curr_block); 80 log->l_curr_block);
81} 81}
82 82
83STATIC int
84xlog_cil_lv_item_format(
85 struct xfs_log_item *lip,
86 struct xfs_log_vec *lv)
87{
88 int index;
89 char *ptr;
90
91 /* format new vectors into array */
92 lip->li_ops->iop_format(lip, lv->lv_iovecp);
93
94 /* copy data into existing array */
95 ptr = lv->lv_buf;
96 for (index = 0; index < lv->lv_niovecs; index++) {
97 struct xfs_log_iovec *vec = &lv->lv_iovecp[index];
98
99 memcpy(ptr, vec->i_addr, vec->i_len);
100 vec->i_addr = ptr;
101 ptr += vec->i_len;
102 }
103
104 /*
105 * some size calculations for log vectors over-estimate, so the caller
106 * doesn't know the amount of space actually used by the item. Return
107 * the byte count to the caller so they can check and store it
108 * appropriately.
109 */
110 return ptr - lv->lv_buf;
111}
112
83/* 113/*
84 * Format log item into a flat buffers 114 * Format log item into a flat buffers
85 * 115 *
@@ -111,7 +141,7 @@ xlog_cil_prepare_log_vecs(
111 struct xfs_trans *tp) 141 struct xfs_trans *tp)
112{ 142{
113 struct xfs_log_item_desc *lidp; 143 struct xfs_log_item_desc *lidp;
114 struct xfs_log_vec *lv = NULL; 144 struct xfs_log_vec *prev_lv = NULL;
115 struct xfs_log_vec *ret_lv = NULL; 145 struct xfs_log_vec *ret_lv = NULL;
116 146
117 147
@@ -123,12 +153,10 @@ xlog_cil_prepare_log_vecs(
123 153
124 list_for_each_entry(lidp, &tp->t_items, lid_trans) { 154 list_for_each_entry(lidp, &tp->t_items, lid_trans) {
125 struct xfs_log_item *lip = lidp->lid_item; 155 struct xfs_log_item *lip = lidp->lid_item;
126 struct xfs_log_vec *new_lv; 156 struct xfs_log_vec *lv;
127 void *ptr; 157 int niovecs = 0;
128 int index; 158 int nbytes = 0;
129 int len = 0; 159 int buf_size;
130 uint niovecs = 0;
131 uint nbytes = 0;
132 bool ordered = false; 160 bool ordered = false;
133 161
134 /* Skip items which aren't dirty in this transaction. */ 162 /* Skip items which aren't dirty in this transaction. */
@@ -150,48 +178,39 @@ xlog_cil_prepare_log_vecs(
150 if (niovecs == XFS_LOG_VEC_ORDERED) { 178 if (niovecs == XFS_LOG_VEC_ORDERED) {
151 ordered = true; 179 ordered = true;
152 niovecs = 0; 180 niovecs = 0;
181 nbytes = 0;
153 } 182 }
154 183
155 new_lv = kmem_zalloc(sizeof(*new_lv) + 184 /* calc buffer size */
156 niovecs * sizeof(struct xfs_log_iovec), 185 buf_size = sizeof(struct xfs_log_vec) + nbytes +
157 KM_SLEEP|KM_NOFS); 186 niovecs * sizeof(struct xfs_log_iovec);
158 187
159 new_lv->lv_item = lip; 188 /* allocate new data chunk */
160 new_lv->lv_niovecs = niovecs; 189 lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS);
190 lv->lv_item = lip;
191 lv->lv_size = buf_size;
192 lv->lv_niovecs = niovecs;
161 if (ordered) { 193 if (ordered) {
162 /* track as an ordered logvec */ 194 /* track as an ordered logvec */
163 new_lv->lv_buf_len = XFS_LOG_VEC_ORDERED; 195 ASSERT(lip->li_lv == NULL);
164 goto next; 196 lv->lv_buf_len = XFS_LOG_VEC_ORDERED;
197 goto insert;
165 } 198 }
166 199
167 /* The allocated iovec region lies beyond the log vector. */ 200 /* The allocated iovec region lies beyond the log vector. */
168 new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1]; 201 lv->lv_iovecp = (struct xfs_log_iovec *)&lv[1];
169
170 /* build the vector array and calculate it's length */
171 IOP_FORMAT(new_lv->lv_item, new_lv->lv_iovecp);
172 for (index = 0; index < new_lv->lv_niovecs; index++)
173 len += new_lv->lv_iovecp[index].i_len;
174 202
175 new_lv->lv_buf_len = len; 203 /* The allocated data region lies beyond the iovec region */
176 new_lv->lv_buf = kmem_alloc(new_lv->lv_buf_len, 204 lv->lv_buf = (char *)lv + buf_size - nbytes;
177 KM_SLEEP|KM_NOFS);
178 ptr = new_lv->lv_buf;
179
180 for (index = 0; index < new_lv->lv_niovecs; index++) {
181 struct xfs_log_iovec *vec = &new_lv->lv_iovecp[index];
182
183 memcpy(ptr, vec->i_addr, vec->i_len);
184 vec->i_addr = ptr;
185 ptr += vec->i_len;
186 }
187 ASSERT(ptr == new_lv->lv_buf + new_lv->lv_buf_len);
188 205
189next: 206 lv->lv_buf_len = xlog_cil_lv_item_format(lip, lv);
207 ASSERT(lv->lv_buf_len <= nbytes);
208insert:
190 if (!ret_lv) 209 if (!ret_lv)
191 ret_lv = new_lv; 210 ret_lv = lv;
192 else 211 else
193 lv->lv_next = new_lv; 212 prev_lv->lv_next = lv;
194 lv = new_lv; 213 prev_lv = lv;
195 } 214 }
196 215
197 return ret_lv; 216 return ret_lv;
@@ -228,7 +247,6 @@ xfs_cil_prepare_item(
228 247
229 *len += lv->lv_buf_len - old->lv_buf_len; 248 *len += lv->lv_buf_len - old->lv_buf_len;
230 *diff_iovecs += lv->lv_niovecs - old->lv_niovecs; 249 *diff_iovecs += lv->lv_niovecs - old->lv_niovecs;
231 kmem_free(old->lv_buf);
232 kmem_free(old); 250 kmem_free(old);
233 } else { 251 } else {
234 /* new lv, must pin the log item */ 252 /* new lv, must pin the log item */
@@ -354,7 +372,6 @@ xlog_cil_free_logvec(
354 372
355 for (lv = log_vector; lv; ) { 373 for (lv = log_vector; lv; ) {
356 struct xfs_log_vec *next = lv->lv_next; 374 struct xfs_log_vec *next = lv->lv_next;
357 kmem_free(lv->lv_buf);
358 kmem_free(lv); 375 kmem_free(lv);
359 lv = next; 376 lv = next;
360 } 377 }