aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_cil.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_log_cil.c')
-rw-r--r--fs/xfs/xfs_log_cil.c89
1 files changed, 35 insertions, 54 deletions
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 5eb51fc5eb84..4ef6fdbced78 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -82,36 +82,6 @@ xlog_cil_init_post_recovery(
82 log->l_curr_block); 82 log->l_curr_block);
83} 83}
84 84
85STATIC int
86xlog_cil_lv_item_format(
87 struct xfs_log_item *lip,
88 struct xfs_log_vec *lv)
89{
90 int index;
91 char *ptr;
92
93 /* format new vectors into array */
94 lip->li_ops->iop_format(lip, lv->lv_iovecp);
95
96 /* copy data into existing array */
97 ptr = lv->lv_buf;
98 for (index = 0; index < lv->lv_niovecs; index++) {
99 struct xfs_log_iovec *vec = &lv->lv_iovecp[index];
100
101 memcpy(ptr, vec->i_addr, vec->i_len);
102 vec->i_addr = ptr;
103 ptr += vec->i_len;
104 }
105
106 /*
107 * some size calculations for log vectors over-estimate, so the caller
108 * doesn't know the amount of space actually used by the item. Return
109 * the byte count to the caller so they can check and store it
110 * appropriately.
111 */
112 return ptr - lv->lv_buf;
113}
114
115/* 85/*
116 * Prepare the log item for insertion into the CIL. Calculate the difference in 86 * Prepare the log item for insertion into the CIL. Calculate the difference in
117 * log space and vectors it will consume, and if it is a new item pin it as 87 * log space and vectors it will consume, and if it is a new item pin it as
@@ -232,12 +202,28 @@ xlog_cil_insert_format_items(
232 nbytes = 0; 202 nbytes = 0;
233 } 203 }
234 204
205 /*
206 * We 64-bit align the length of each iovec so that the start
207 * of the next one is naturally aligned. We'll need to
208 * account for that slack space here. Then round nbytes up
209 * to 64-bit alignment so that the initial buffer alignment is
210 * easy to calculate and verify.
211 */
212 nbytes += niovecs * sizeof(uint64_t);
213 nbytes = round_up(nbytes, sizeof(uint64_t));
214
235 /* grab the old item if it exists for reservation accounting */ 215 /* grab the old item if it exists for reservation accounting */
236 old_lv = lip->li_lv; 216 old_lv = lip->li_lv;
237 217
238 /* calc buffer size */ 218 /*
239 buf_size = sizeof(struct xfs_log_vec) + nbytes + 219 * The data buffer needs to start 64-bit aligned, so round up
240 niovecs * sizeof(struct xfs_log_iovec); 220 * that space to ensure we can align it appropriately and not
221 * overrun the buffer.
222 */
223 buf_size = nbytes +
224 round_up((sizeof(struct xfs_log_vec) +
225 niovecs * sizeof(struct xfs_log_iovec)),
226 sizeof(uint64_t));
241 227
242 /* compare to existing item size */ 228 /* compare to existing item size */
243 if (lip->li_lv && buf_size <= lip->li_lv->lv_size) { 229 if (lip->li_lv && buf_size <= lip->li_lv->lv_size) {
@@ -254,34 +240,29 @@ xlog_cil_insert_format_items(
254 */ 240 */
255 *diff_iovecs -= lv->lv_niovecs; 241 *diff_iovecs -= lv->lv_niovecs;
256 *diff_len -= lv->lv_buf_len; 242 *diff_len -= lv->lv_buf_len;
257 243 } else {
258 /* Ensure the lv is set up according to ->iop_size */ 244 /* allocate new data chunk */
259 lv->lv_niovecs = niovecs; 245 lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS);
260 lv->lv_buf = (char *)lv + buf_size - nbytes; 246 lv->lv_item = lip;
261 247 lv->lv_size = buf_size;
262 lv->lv_buf_len = xlog_cil_lv_item_format(lip, lv); 248 if (ordered) {
263 goto insert; 249 /* track as an ordered logvec */
250 ASSERT(lip->li_lv == NULL);
251 lv->lv_buf_len = XFS_LOG_VEC_ORDERED;
252 goto insert;
253 }
254 lv->lv_iovecp = (struct xfs_log_iovec *)&lv[1];
264 } 255 }
265 256
266 /* allocate new data chunk */ 257 /* Ensure the lv is set up according to ->iop_size */
267 lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS);
268 lv->lv_item = lip;
269 lv->lv_size = buf_size;
270 lv->lv_niovecs = niovecs; 258 lv->lv_niovecs = niovecs;
271 if (ordered) {
272 /* track as an ordered logvec */
273 ASSERT(lip->li_lv == NULL);
274 lv->lv_buf_len = XFS_LOG_VEC_ORDERED;
275 goto insert;
276 }
277
278 /* The allocated iovec region lies beyond the log vector. */
279 lv->lv_iovecp = (struct xfs_log_iovec *)&lv[1];
280 259
281 /* The allocated data region lies beyond the iovec region */ 260 /* The allocated data region lies beyond the iovec region */
261 lv->lv_buf_len = 0;
282 lv->lv_buf = (char *)lv + buf_size - nbytes; 262 lv->lv_buf = (char *)lv + buf_size - nbytes;
263 ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t)));
283 264
284 lv->lv_buf_len = xlog_cil_lv_item_format(lip, lv); 265 lip->li_ops->iop_format(lip, lv);
285insert: 266insert:
286 ASSERT(lv->lv_buf_len <= nbytes); 267 ASSERT(lv->lv_buf_len <= nbytes);
287 xfs_cil_prepare_item(log, lv, old_lv, diff_len, diff_iovecs); 268 xfs_cil_prepare_item(log, lv, old_lv, diff_len, diff_iovecs);