aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-12 19:34:02 -0500
committerDave Chinner <david@fromorbit.com>2013-12-12 19:34:02 -0500
commitbde7cff67c39227c6ad503394e19e58debdbc5e3 (patch)
tree4325938342c4dece835e387e323106db53fe137d /fs/xfs
parent1234351cba958cd5d4338172ccfc869a687cd736 (diff)
xfs: format log items write directly into the linear CIL buffer
Instead of setting up pointers to memory locations in iop_format which then get copied into the CIL linear buffer after return move the copy into the individual inode items. This avoids the need to always have a memory block in the exact same layout that gets written into the log around, and allow the log items to be much more flexible in their in-memory layouts. The only caveat is that we need to properly align the data for each iovec so that don't have structures misaligned in subsequent iovecs. Note that all log item format routines now need to be careful to modify the copy of the item that was placed into the CIL after calls to xlog_copy_iovec instead of the in-memory copy. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_buf_item.c29
-rw-r--r--fs/xfs/xfs_dquot_item.c19
-rw-r--r--fs/xfs/xfs_extfree_item.c10
-rw-r--r--fs/xfs/xfs_icreate_item.c5
-rw-r--r--fs/xfs/xfs_inode_item.c92
-rw-r--r--fs/xfs/xfs_log.h41
-rw-r--r--fs/xfs/xfs_log_cil.c41
-rw-r--r--fs/xfs/xfs_trans.h2
8 files changed, 125 insertions, 114 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index d49419d4bb46..764117305438 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -184,6 +184,7 @@ xfs_buf_item_size(
184 184
185static inline void 185static inline void
186xfs_buf_item_copy_iovec( 186xfs_buf_item_copy_iovec(
187 struct xfs_log_vec *lv,
187 struct xfs_log_iovec **vecp, 188 struct xfs_log_iovec **vecp,
188 struct xfs_buf *bp, 189 struct xfs_buf *bp,
189 uint offset, 190 uint offset,
@@ -191,7 +192,7 @@ xfs_buf_item_copy_iovec(
191 uint nbits) 192 uint nbits)
192{ 193{
193 offset += first_bit * XFS_BLF_CHUNK; 194 offset += first_bit * XFS_BLF_CHUNK;
194 xlog_copy_iovec(vecp, XLOG_REG_TYPE_BCHUNK, 195 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_BCHUNK,
195 xfs_buf_offset(bp, offset), 196 xfs_buf_offset(bp, offset),
196 nbits * XFS_BLF_CHUNK); 197 nbits * XFS_BLF_CHUNK);
197} 198}
@@ -211,13 +212,13 @@ xfs_buf_item_straddle(
211static void 212static void
212xfs_buf_item_format_segment( 213xfs_buf_item_format_segment(
213 struct xfs_buf_log_item *bip, 214 struct xfs_buf_log_item *bip,
215 struct xfs_log_vec *lv,
214 struct xfs_log_iovec **vecp, 216 struct xfs_log_iovec **vecp,
215 uint offset, 217 uint offset,
216 struct xfs_buf_log_format *blfp) 218 struct xfs_buf_log_format *blfp)
217{ 219{
218 struct xfs_buf *bp = bip->bli_buf; 220 struct xfs_buf *bp = bip->bli_buf;
219 uint base_size; 221 uint base_size;
220 uint nvecs;
221 int first_bit; 222 int first_bit;
222 int last_bit; 223 int last_bit;
223 int next_bit; 224 int next_bit;
@@ -233,18 +234,17 @@ xfs_buf_item_format_segment(
233 */ 234 */
234 base_size = xfs_buf_log_format_size(blfp); 235 base_size = xfs_buf_log_format_size(blfp);
235 236
236 nvecs = 0;
237 first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); 237 first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0);
238 if (!(bip->bli_flags & XFS_BLI_STALE) && first_bit == -1) { 238 if (!(bip->bli_flags & XFS_BLI_STALE) && first_bit == -1) {
239 /* 239 /*
240 * If the map is not be dirty in the transaction, mark 240 * If the map is not be dirty in the transaction, mark
241 * the size as zero and do not advance the vector pointer. 241 * the size as zero and do not advance the vector pointer.
242 */ 242 */
243 goto out; 243 return;
244 } 244 }
245 245
246 xlog_copy_iovec(vecp, XLOG_REG_TYPE_BFORMAT, blfp, base_size); 246 blfp = xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_BFORMAT, blfp, base_size);
247 nvecs = 1; 247 blfp->blf_size = 1;
248 248
249 if (bip->bli_flags & XFS_BLI_STALE) { 249 if (bip->bli_flags & XFS_BLI_STALE) {
250 /* 250 /*
@@ -254,7 +254,7 @@ xfs_buf_item_format_segment(
254 */ 254 */
255 trace_xfs_buf_item_format_stale(bip); 255 trace_xfs_buf_item_format_stale(bip);
256 ASSERT(blfp->blf_flags & XFS_BLF_CANCEL); 256 ASSERT(blfp->blf_flags & XFS_BLF_CANCEL);
257 goto out; 257 return;
258 } 258 }
259 259
260 260
@@ -280,15 +280,15 @@ xfs_buf_item_format_segment(
280 * same set of bits so just keep counting and scanning. 280 * same set of bits so just keep counting and scanning.
281 */ 281 */
282 if (next_bit == -1) { 282 if (next_bit == -1) {
283 xfs_buf_item_copy_iovec(vecp, bp, offset, 283 xfs_buf_item_copy_iovec(lv, vecp, bp, offset,
284 first_bit, nbits); 284 first_bit, nbits);
285 nvecs++; 285 blfp->blf_size++;
286 break; 286 break;
287 } else if (next_bit != last_bit + 1 || 287 } else if (next_bit != last_bit + 1 ||
288 xfs_buf_item_straddle(bp, offset, next_bit, last_bit)) { 288 xfs_buf_item_straddle(bp, offset, next_bit, last_bit)) {
289 xfs_buf_item_copy_iovec(vecp, bp, offset, 289 xfs_buf_item_copy_iovec(lv, vecp, bp, offset,
290 first_bit, nbits); 290 first_bit, nbits);
291 nvecs++; 291 blfp->blf_size++;
292 first_bit = next_bit; 292 first_bit = next_bit;
293 last_bit = next_bit; 293 last_bit = next_bit;
294 nbits = 1; 294 nbits = 1;
@@ -297,8 +297,6 @@ xfs_buf_item_format_segment(
297 nbits++; 297 nbits++;
298 } 298 }
299 } 299 }
300out:
301 blfp->blf_size = nvecs;
302} 300}
303 301
304/* 302/*
@@ -310,10 +308,11 @@ out:
310STATIC void 308STATIC void
311xfs_buf_item_format( 309xfs_buf_item_format(
312 struct xfs_log_item *lip, 310 struct xfs_log_item *lip,
313 struct xfs_log_iovec *vecp) 311 struct xfs_log_vec *lv)
314{ 312{
315 struct xfs_buf_log_item *bip = BUF_ITEM(lip); 313 struct xfs_buf_log_item *bip = BUF_ITEM(lip);
316 struct xfs_buf *bp = bip->bli_buf; 314 struct xfs_buf *bp = bip->bli_buf;
315 struct xfs_log_iovec *vecp = NULL;
317 uint offset = 0; 316 uint offset = 0;
318 int i; 317 int i;
319 318
@@ -354,7 +353,7 @@ xfs_buf_item_format(
354 } 353 }
355 354
356 for (i = 0; i < bip->bli_format_count; i++) { 355 for (i = 0; i < bip->bli_format_count; i++) {
357 xfs_buf_item_format_segment(bip, &vecp, offset, 356 xfs_buf_item_format_segment(bip, lv, &vecp, offset,
358 &bip->bli_formats[i]); 357 &bip->bli_formats[i]);
359 offset += bp->b_maps[i].bm_len; 358 offset += bp->b_maps[i].bm_len;
360 } 359 }
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
index ca354a821838..946d588070b0 100644
--- a/fs/xfs/xfs_dquot_item.c
+++ b/fs/xfs/xfs_dquot_item.c
@@ -57,18 +57,19 @@ xfs_qm_dquot_logitem_size(
57STATIC void 57STATIC void
58xfs_qm_dquot_logitem_format( 58xfs_qm_dquot_logitem_format(
59 struct xfs_log_item *lip, 59 struct xfs_log_item *lip,
60 struct xfs_log_iovec *vecp) 60 struct xfs_log_vec *lv)
61{ 61{
62 struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip); 62 struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip);
63 struct xfs_log_iovec *vecp = NULL;
63 64
64 xlog_copy_iovec(&vecp, XLOG_REG_TYPE_QFORMAT, 65 qlip->qli_format.qlf_size = 2;
66
67 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_QFORMAT,
65 &qlip->qli_format, 68 &qlip->qli_format,
66 sizeof(struct xfs_dq_logformat)); 69 sizeof(struct xfs_dq_logformat));
67 xlog_copy_iovec(&vecp, XLOG_REG_TYPE_DQUOT, 70 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_DQUOT,
68 &qlip->qli_dquot->q_core, 71 &qlip->qli_dquot->q_core,
69 sizeof(struct xfs_disk_dquot)); 72 sizeof(struct xfs_disk_dquot));
70
71 qlip->qli_format.qlf_size = 2;
72} 73}
73 74
74/* 75/*
@@ -302,17 +303,17 @@ xfs_qm_qoff_logitem_size(
302STATIC void 303STATIC void
303xfs_qm_qoff_logitem_format( 304xfs_qm_qoff_logitem_format(
304 struct xfs_log_item *lip, 305 struct xfs_log_item *lip,
305 struct xfs_log_iovec *vecp) 306 struct xfs_log_vec *lv)
306{ 307{
307 struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip); 308 struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip);
309 struct xfs_log_iovec *vecp = NULL;
308 310
309 ASSERT(qflip->qql_format.qf_type == XFS_LI_QUOTAOFF); 311 ASSERT(qflip->qql_format.qf_type == XFS_LI_QUOTAOFF);
312 qflip->qql_format.qf_size = 1;
310 313
311 xlog_copy_iovec(&vecp, XLOG_REG_TYPE_QUOTAOFF, 314 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_QUOTAOFF,
312 &qflip->qql_format, 315 &qflip->qql_format,
313 sizeof(struct xfs_qoff_logitem)); 316 sizeof(struct xfs_qoff_logitem));
314
315 qflip->qql_format.qf_size = 1;
316} 317}
317 318
318/* 319/*
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 08823ecbcd82..fb7a4c1ce1c5 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -102,9 +102,10 @@ xfs_efi_item_size(
102STATIC void 102STATIC void
103xfs_efi_item_format( 103xfs_efi_item_format(
104 struct xfs_log_item *lip, 104 struct xfs_log_item *lip,
105 struct xfs_log_iovec *vecp) 105 struct xfs_log_vec *lv)
106{ 106{
107 struct xfs_efi_log_item *efip = EFI_ITEM(lip); 107 struct xfs_efi_log_item *efip = EFI_ITEM(lip);
108 struct xfs_log_iovec *vecp = NULL;
108 109
109 ASSERT(atomic_read(&efip->efi_next_extent) == 110 ASSERT(atomic_read(&efip->efi_next_extent) ==
110 efip->efi_format.efi_nextents); 111 efip->efi_format.efi_nextents);
@@ -112,7 +113,7 @@ xfs_efi_item_format(
112 efip->efi_format.efi_type = XFS_LI_EFI; 113 efip->efi_format.efi_type = XFS_LI_EFI;
113 efip->efi_format.efi_size = 1; 114 efip->efi_format.efi_size = 1;
114 115
115 xlog_copy_iovec(&vecp, XLOG_REG_TYPE_EFI_FORMAT, 116 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT,
116 &efip->efi_format, 117 &efip->efi_format,
117 xfs_efi_item_sizeof(efip)); 118 xfs_efi_item_sizeof(efip));
118} 119}
@@ -368,16 +369,17 @@ xfs_efd_item_size(
368STATIC void 369STATIC void
369xfs_efd_item_format( 370xfs_efd_item_format(
370 struct xfs_log_item *lip, 371 struct xfs_log_item *lip,
371 struct xfs_log_iovec *vecp) 372 struct xfs_log_vec *lv)
372{ 373{
373 struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 374 struct xfs_efd_log_item *efdp = EFD_ITEM(lip);
375 struct xfs_log_iovec *vecp = NULL;
374 376
375 ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); 377 ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents);
376 378
377 efdp->efd_format.efd_type = XFS_LI_EFD; 379 efdp->efd_format.efd_type = XFS_LI_EFD;
378 efdp->efd_format.efd_size = 1; 380 efdp->efd_format.efd_size = 1;
379 381
380 xlog_copy_iovec(&vecp, XLOG_REG_TYPE_EFD_FORMAT, 382 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT,
381 &efdp->efd_format, 383 &efdp->efd_format,
382 xfs_efd_item_sizeof(efdp)); 384 xfs_efd_item_sizeof(efdp));
383} 385}
diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c
index 5751fa8580ee..7e4549233251 100644
--- a/fs/xfs/xfs_icreate_item.c
+++ b/fs/xfs/xfs_icreate_item.c
@@ -59,11 +59,12 @@ xfs_icreate_item_size(
59STATIC void 59STATIC void
60xfs_icreate_item_format( 60xfs_icreate_item_format(
61 struct xfs_log_item *lip, 61 struct xfs_log_item *lip,
62 struct xfs_log_iovec *vecp) 62 struct xfs_log_vec *lv)
63{ 63{
64 struct xfs_icreate_item *icp = ICR_ITEM(lip); 64 struct xfs_icreate_item *icp = ICR_ITEM(lip);
65 struct xfs_log_iovec *vecp = NULL;
65 66
66 xlog_copy_iovec(&vecp, XLOG_REG_TYPE_ICREATE, 67 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICREATE,
67 &icp->ic_format, 68 &icp->ic_format,
68 sizeof(struct xfs_icreate_log)); 69 sizeof(struct xfs_icreate_log));
69} 70}
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index c75e14beff06..6ab318f80c96 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -163,6 +163,7 @@ xfs_inode_item_size(
163STATIC int 163STATIC int
164xfs_inode_item_format_extents( 164xfs_inode_item_format_extents(
165 struct xfs_inode *ip, 165 struct xfs_inode *ip,
166 struct xfs_log_vec *lv,
166 struct xfs_log_iovec **vecp, 167 struct xfs_log_iovec **vecp,
167 int whichfork, 168 int whichfork,
168 int type) 169 int type)
@@ -177,7 +178,7 @@ xfs_inode_item_format_extents(
177 ip->i_itemp->ili_aextents_buf = ext_buffer; 178 ip->i_itemp->ili_aextents_buf = ext_buffer;
178 179
179 len = xfs_iextents_copy(ip, ext_buffer, whichfork); 180 len = xfs_iextents_copy(ip, ext_buffer, whichfork);
180 xlog_copy_iovec(vecp, type, ext_buffer, len); 181 xlog_copy_iovec(lv, vecp, type, ext_buffer, len);
181 return len; 182 return len;
182} 183}
183 184
@@ -212,8 +213,9 @@ xfs_inode_item_format_v1_inode(
212STATIC void 213STATIC void
213xfs_inode_item_format_data_fork( 214xfs_inode_item_format_data_fork(
214 struct xfs_inode_log_item *iip, 215 struct xfs_inode_log_item *iip,
215 struct xfs_log_iovec **vecp, 216 struct xfs_inode_log_format *ilf,
216 int *nvecs) 217 struct xfs_log_vec *lv,
218 struct xfs_log_iovec **vecp)
217{ 219{
218 struct xfs_inode *ip = iip->ili_inode; 220 struct xfs_inode *ip = iip->ili_inode;
219 size_t data_bytes; 221 size_t data_bytes;
@@ -239,19 +241,19 @@ xfs_inode_item_format_data_fork(
239 * extents, so just point to the 241 * extents, so just point to the
240 * real extents array. 242 * real extents array.
241 */ 243 */
242 xlog_copy_iovec(vecp, XLOG_REG_TYPE_IEXT, 244 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IEXT,
243 ip->i_df.if_u1.if_extents, 245 ip->i_df.if_u1.if_extents,
244 ip->i_df.if_bytes); 246 ip->i_df.if_bytes);
245 iip->ili_format.ilf_dsize = ip->i_df.if_bytes; 247 ilf->ilf_dsize = ip->i_df.if_bytes;
246 } else 248 } else
247#endif 249#endif
248 { 250 {
249 iip->ili_format.ilf_dsize = 251 ilf->ilf_dsize =
250 xfs_inode_item_format_extents(ip, vecp, 252 xfs_inode_item_format_extents(ip, lv, vecp,
251 XFS_DATA_FORK, XLOG_REG_TYPE_IEXT); 253 XFS_DATA_FORK, XLOG_REG_TYPE_IEXT);
252 ASSERT(iip->ili_format.ilf_dsize <= ip->i_df.if_bytes); 254 ASSERT(iip->ili_format.ilf_dsize <= ip->i_df.if_bytes);
253 } 255 }
254 (*nvecs)++; 256 ilf->ilf_size++;
255 } else { 257 } else {
256 iip->ili_fields &= ~XFS_ILOG_DEXT; 258 iip->ili_fields &= ~XFS_ILOG_DEXT;
257 } 259 }
@@ -264,11 +266,11 @@ xfs_inode_item_format_data_fork(
264 if ((iip->ili_fields & XFS_ILOG_DBROOT) && 266 if ((iip->ili_fields & XFS_ILOG_DBROOT) &&
265 ip->i_df.if_broot_bytes > 0) { 267 ip->i_df.if_broot_bytes > 0) {
266 ASSERT(ip->i_df.if_broot != NULL); 268 ASSERT(ip->i_df.if_broot != NULL);
267 xlog_copy_iovec(vecp, XLOG_REG_TYPE_IBROOT, 269 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IBROOT,
268 ip->i_df.if_broot, 270 ip->i_df.if_broot,
269 ip->i_df.if_broot_bytes); 271 ip->i_df.if_broot_bytes);
270 (*nvecs)++; 272 ilf->ilf_dsize = ip->i_df.if_broot_bytes;
271 iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; 273 ilf->ilf_size++;
272 } else { 274 } else {
273 ASSERT(!(iip->ili_fields & 275 ASSERT(!(iip->ili_fields &
274 XFS_ILOG_DBROOT)); 276 XFS_ILOG_DBROOT));
@@ -291,10 +293,10 @@ xfs_inode_item_format_data_fork(
291 ip->i_df.if_real_bytes == data_bytes); 293 ip->i_df.if_real_bytes == data_bytes);
292 ASSERT(ip->i_df.if_u1.if_data != NULL); 294 ASSERT(ip->i_df.if_u1.if_data != NULL);
293 ASSERT(ip->i_d.di_size > 0); 295 ASSERT(ip->i_d.di_size > 0);
294 xlog_copy_iovec(vecp, XLOG_REG_TYPE_ILOCAL, 296 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_ILOCAL,
295 ip->i_df.if_u1.if_data, data_bytes); 297 ip->i_df.if_u1.if_data, data_bytes);
296 (*nvecs)++; 298 ilf->ilf_dsize = (unsigned)data_bytes;
297 iip->ili_format.ilf_dsize = (unsigned)data_bytes; 299 ilf->ilf_size++;
298 } else { 300 } else {
299 iip->ili_fields &= ~XFS_ILOG_DDATA; 301 iip->ili_fields &= ~XFS_ILOG_DDATA;
300 } 302 }
@@ -303,19 +305,15 @@ xfs_inode_item_format_data_fork(
303 iip->ili_fields &= 305 iip->ili_fields &=
304 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | 306 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
305 XFS_ILOG_DEXT | XFS_ILOG_UUID); 307 XFS_ILOG_DEXT | XFS_ILOG_UUID);
306 if (iip->ili_fields & XFS_ILOG_DEV) { 308 if (iip->ili_fields & XFS_ILOG_DEV)
307 iip->ili_format.ilf_u.ilfu_rdev = 309 ilf->ilf_u.ilfu_rdev = ip->i_df.if_u2.if_rdev;
308 ip->i_df.if_u2.if_rdev;
309 }
310 break; 310 break;
311 case XFS_DINODE_FMT_UUID: 311 case XFS_DINODE_FMT_UUID:
312 iip->ili_fields &= 312 iip->ili_fields &=
313 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | 313 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
314 XFS_ILOG_DEXT | XFS_ILOG_DEV); 314 XFS_ILOG_DEXT | XFS_ILOG_DEV);
315 if (iip->ili_fields & XFS_ILOG_UUID) { 315 if (iip->ili_fields & XFS_ILOG_UUID)
316 iip->ili_format.ilf_u.ilfu_uuid = 316 ilf->ilf_u.ilfu_uuid = ip->i_df.if_u2.if_uuid;
317 ip->i_df.if_u2.if_uuid;
318 }
319 break; 317 break;
320 default: 318 default:
321 ASSERT(0); 319 ASSERT(0);
@@ -326,8 +324,9 @@ xfs_inode_item_format_data_fork(
326STATIC void 324STATIC void
327xfs_inode_item_format_attr_fork( 325xfs_inode_item_format_attr_fork(
328 struct xfs_inode_log_item *iip, 326 struct xfs_inode_log_item *iip,
329 struct xfs_log_iovec **vecp, 327 struct xfs_inode_log_format *ilf,
330 int *nvecs) 328 struct xfs_log_vec *lv,
329 struct xfs_log_iovec **vecp)
331{ 330{
332 struct xfs_inode *ip = iip->ili_inode; 331 struct xfs_inode *ip = iip->ili_inode;
333 size_t data_bytes; 332 size_t data_bytes;
@@ -348,17 +347,17 @@ xfs_inode_item_format_attr_fork(
348 * There are not delayed allocation extents 347 * There are not delayed allocation extents
349 * for attributes, so just point at the array. 348 * for attributes, so just point at the array.
350 */ 349 */
351 xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_EXT, 350 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT,
352 ip->i_afp->if_u1.if_extents, 351 ip->i_afp->if_u1.if_extents,
353 ip->i_afp->if_bytes); 352 ip->i_afp->if_bytes);
354 iip->ili_format.ilf_asize = ip->i_afp->if_bytes; 353 ilf->ilf_asize = ip->i_afp->if_bytes;
355#else 354#else
356 ASSERT(iip->ili_aextents_buf == NULL); 355 ASSERT(iip->ili_aextents_buf == NULL);
357 iip->ili_format.ilf_asize = 356 ilf->ilf_asize =
358 xfs_inode_item_format_extents(ip, vecp, 357 xfs_inode_item_format_extents(ip, lv, vecp,
359 XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT); 358 XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT);
360#endif 359#endif
361 (*nvecs)++; 360 ilf->ilf_size++;
362 } else { 361 } else {
363 iip->ili_fields &= ~XFS_ILOG_AEXT; 362 iip->ili_fields &= ~XFS_ILOG_AEXT;
364 } 363 }
@@ -371,11 +370,11 @@ xfs_inode_item_format_attr_fork(
371 ip->i_afp->if_broot_bytes > 0) { 370 ip->i_afp->if_broot_bytes > 0) {
372 ASSERT(ip->i_afp->if_broot != NULL); 371 ASSERT(ip->i_afp->if_broot != NULL);
373 372
374 xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_BROOT, 373 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_BROOT,
375 ip->i_afp->if_broot, 374 ip->i_afp->if_broot,
376 ip->i_afp->if_broot_bytes); 375 ip->i_afp->if_broot_bytes);
377 (*nvecs)++; 376 ilf->ilf_asize = ip->i_afp->if_broot_bytes;
378 iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; 377 ilf->ilf_size++;
379 } else { 378 } else {
380 iip->ili_fields &= ~XFS_ILOG_ABROOT; 379 iip->ili_fields &= ~XFS_ILOG_ABROOT;
381 } 380 }
@@ -395,11 +394,11 @@ xfs_inode_item_format_attr_fork(
395 ASSERT(ip->i_afp->if_real_bytes == 0 || 394 ASSERT(ip->i_afp->if_real_bytes == 0 ||
396 ip->i_afp->if_real_bytes == data_bytes); 395 ip->i_afp->if_real_bytes == data_bytes);
397 ASSERT(ip->i_afp->if_u1.if_data != NULL); 396 ASSERT(ip->i_afp->if_u1.if_data != NULL);
398 xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_LOCAL, 397 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_LOCAL,
399 ip->i_afp->if_u1.if_data, 398 ip->i_afp->if_u1.if_data,
400 data_bytes); 399 data_bytes);
401 (*nvecs)++; 400 ilf->ilf_asize = (unsigned)data_bytes;
402 iip->ili_format.ilf_asize = (unsigned)data_bytes; 401 ilf->ilf_size++;
403 } else { 402 } else {
404 iip->ili_fields &= ~XFS_ILOG_ADATA; 403 iip->ili_fields &= ~XFS_ILOG_ADATA;
405 } 404 }
@@ -420,28 +419,28 @@ xfs_inode_item_format_attr_fork(
420STATIC void 419STATIC void
421xfs_inode_item_format( 420xfs_inode_item_format(
422 struct xfs_log_item *lip, 421 struct xfs_log_item *lip,
423 struct xfs_log_iovec *vecp) 422 struct xfs_log_vec *lv)
424{ 423{
425 struct xfs_inode_log_item *iip = INODE_ITEM(lip); 424 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
426 struct xfs_inode *ip = iip->ili_inode; 425 struct xfs_inode *ip = iip->ili_inode;
427 uint nvecs; 426 struct xfs_inode_log_format *ilf;
427 struct xfs_log_iovec *vecp = NULL;
428 428
429 xlog_copy_iovec(&vecp, XLOG_REG_TYPE_IFORMAT, 429 ilf = xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT,
430 &iip->ili_format, 430 &iip->ili_format,
431 sizeof(struct xfs_inode_log_format)); 431 sizeof(struct xfs_inode_log_format));
432 nvecs = 1; 432 ilf->ilf_size = 1;
433
434 xlog_copy_iovec(&vecp, XLOG_REG_TYPE_ICORE,
435 &ip->i_d,
436 xfs_icdinode_size(ip->i_d.di_version));
437 nvecs++;
438 433
439 if (ip->i_d.di_version == 1) 434 if (ip->i_d.di_version == 1)
440 xfs_inode_item_format_v1_inode(ip); 435 xfs_inode_item_format_v1_inode(ip);
436 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE,
437 &ip->i_d,
438 xfs_icdinode_size(ip->i_d.di_version));
439 ilf->ilf_size++;
441 440
442 xfs_inode_item_format_data_fork(iip, &vecp, &nvecs); 441 xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp);
443 if (XFS_IFORK_Q(ip)) { 442 if (XFS_IFORK_Q(ip)) {
444 xfs_inode_item_format_attr_fork(iip, &vecp, &nvecs); 443 xfs_inode_item_format_attr_fork(iip, ilf, lv, &vecp);
445 } else { 444 } else {
446 iip->ili_fields &= 445 iip->ili_fields &=
447 ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); 446 ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT);
@@ -455,7 +454,6 @@ xfs_inode_item_format(
455 */ 454 */
456 iip->ili_format.ilf_fields = XFS_ILOG_CORE | 455 iip->ili_format.ilf_fields = XFS_ILOG_CORE |
457 (iip->ili_fields & ~XFS_ILOG_TIMESTAMP); 456 (iip->ili_fields & ~XFS_ILOG_TIMESTAMP);
458 iip->ili_format.ilf_size = nvecs;
459} 457}
460 458
461/* 459/*
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 384c6c469661..b0f4ef77fa70 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -31,18 +31,51 @@ struct xfs_log_vec {
31#define XFS_LOG_VEC_ORDERED (-1) 31#define XFS_LOG_VEC_ORDERED (-1)
32 32
33static inline void * 33static inline void *
34xlog_copy_iovec(struct xfs_log_iovec **vecp, uint type, void *data, int len) 34xlog_prepare_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp,
35 uint type)
35{ 36{
36 struct xfs_log_iovec *vec = *vecp; 37 struct xfs_log_iovec *vec = *vecp;
37 38
39 if (vec) {
40 ASSERT(vec - lv->lv_iovecp < lv->lv_niovecs);
41 vec++;
42 } else {
43 vec = &lv->lv_iovecp[0];
44 }
45
38 vec->i_type = type; 46 vec->i_type = type;
39 vec->i_addr = data; 47 vec->i_addr = lv->lv_buf + lv->lv_buf_len;
40 vec->i_len = len; 48
49 ASSERT(IS_ALIGNED((unsigned long)vec->i_addr, sizeof(uint64_t)));
41 50
42 *vecp = vec + 1; 51 *vecp = vec;
43 return vec->i_addr; 52 return vec->i_addr;
44} 53}
45 54
55static inline void
56xlog_finish_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *vec, int len)
57{
58 /*
59 * We need to make sure the next buffer is naturally aligned for the
60 * biggest basic data type we put into it. We already accounted for
61 * this when sizing the buffer.
62 */
63 lv->lv_buf_len += round_up(len, sizeof(uint64_t));
64 vec->i_len = len;
65}
66
67static inline void *
68xlog_copy_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp,
69 uint type, void *data, int len)
70{
71 void *buf;
72
73 buf = xlog_prepare_iovec(lv, vecp, type);
74 memcpy(buf, data, len);
75 xlog_finish_iovec(lv, *vecp, len);
76 return buf;
77}
78
46/* 79/*
47 * Structure used to pass callback function and the function's argument 80 * Structure used to pass callback function and the function's argument
48 * to the log manager. 81 * to the log manager.
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 0a7a8cef6019..cdebd832c3db 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,6 +202,13 @@ 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.
209 */
210 nbytes += niovecs * sizeof(uint64_t);
211
235 /* grab the old item if it exists for reservation accounting */ 212 /* grab the old item if it exists for reservation accounting */
236 old_lv = lip->li_lv; 213 old_lv = lip->li_lv;
237 214
@@ -272,9 +249,9 @@ xlog_cil_insert_format_items(
272 lv->lv_niovecs = niovecs; 249 lv->lv_niovecs = niovecs;
273 250
274 /* The allocated data region lies beyond the iovec region */ 251 /* The allocated data region lies beyond the iovec region */
252 lv->lv_buf_len = 0;
275 lv->lv_buf = (char *)lv + buf_size - nbytes; 253 lv->lv_buf = (char *)lv + buf_size - nbytes;
276 254 lip->li_ops->iop_format(lip, lv);
277 lv->lv_buf_len = xlog_cil_lv_item_format(lip, lv);
278insert: 255insert:
279 ASSERT(lv->lv_buf_len <= nbytes); 256 ASSERT(lv->lv_buf_len <= nbytes);
280 xfs_cil_prepare_item(log, lv, old_lv, diff_len, diff_iovecs); 257 xfs_cil_prepare_item(log, lv, old_lv, diff_len, diff_iovecs);
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 9b96d35e483d..b5bc1ab3c4da 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -64,7 +64,7 @@ typedef struct xfs_log_item {
64 64
65struct xfs_item_ops { 65struct xfs_item_ops {
66 void (*iop_size)(xfs_log_item_t *, int *, int *); 66 void (*iop_size)(xfs_log_item_t *, int *, int *);
67 void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *); 67 void (*iop_format)(xfs_log_item_t *, struct xfs_log_vec *);
68 void (*iop_pin)(xfs_log_item_t *); 68 void (*iop_pin)(xfs_log_item_t *);
69 void (*iop_unpin)(xfs_log_item_t *, int remove); 69 void (*iop_unpin)(xfs_log_item_t *, int remove);
70 uint (*iop_push)(struct xfs_log_item *, struct list_head *); 70 uint (*iop_push)(struct xfs_log_item *, struct list_head *);