diff options
Diffstat (limited to 'fs/xfs/xfs_log_cil.c')
| -rw-r--r-- | fs/xfs/xfs_log_cil.c | 75 |
1 files changed, 51 insertions, 24 deletions
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index d0833b54e55d..02b9cf3f8252 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
| @@ -127,6 +127,7 @@ xlog_cil_prepare_log_vecs( | |||
| 127 | int index; | 127 | int index; |
| 128 | int len = 0; | 128 | int len = 0; |
| 129 | uint niovecs; | 129 | uint niovecs; |
| 130 | bool ordered = false; | ||
| 130 | 131 | ||
| 131 | /* Skip items which aren't dirty in this transaction. */ | 132 | /* Skip items which aren't dirty in this transaction. */ |
| 132 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) | 133 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) |
| @@ -137,14 +138,30 @@ xlog_cil_prepare_log_vecs( | |||
| 137 | if (!niovecs) | 138 | if (!niovecs) |
| 138 | continue; | 139 | continue; |
| 139 | 140 | ||
| 141 | /* | ||
| 142 | * Ordered items need to be tracked but we do not wish to write | ||
| 143 | * them. We need a logvec to track the object, but we do not | ||
| 144 | * need an iovec or buffer to be allocated for copying data. | ||
| 145 | */ | ||
| 146 | if (niovecs == XFS_LOG_VEC_ORDERED) { | ||
| 147 | ordered = true; | ||
| 148 | niovecs = 0; | ||
| 149 | } | ||
| 150 | |||
| 140 | new_lv = kmem_zalloc(sizeof(*new_lv) + | 151 | new_lv = kmem_zalloc(sizeof(*new_lv) + |
| 141 | niovecs * sizeof(struct xfs_log_iovec), | 152 | niovecs * sizeof(struct xfs_log_iovec), |
| 142 | KM_SLEEP|KM_NOFS); | 153 | KM_SLEEP|KM_NOFS); |
| 143 | 154 | ||
| 155 | new_lv->lv_item = lidp->lid_item; | ||
| 156 | new_lv->lv_niovecs = niovecs; | ||
| 157 | if (ordered) { | ||
| 158 | /* track as an ordered logvec */ | ||
| 159 | new_lv->lv_buf_len = XFS_LOG_VEC_ORDERED; | ||
| 160 | goto next; | ||
| 161 | } | ||
| 162 | |||
| 144 | /* The allocated iovec region lies beyond the log vector. */ | 163 | /* The allocated iovec region lies beyond the log vector. */ |
| 145 | new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1]; | 164 | new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1]; |
| 146 | new_lv->lv_niovecs = niovecs; | ||
| 147 | new_lv->lv_item = lidp->lid_item; | ||
| 148 | 165 | ||
| 149 | /* build the vector array and calculate it's length */ | 166 | /* build the vector array and calculate it's length */ |
| 150 | IOP_FORMAT(new_lv->lv_item, new_lv->lv_iovecp); | 167 | IOP_FORMAT(new_lv->lv_item, new_lv->lv_iovecp); |
| @@ -165,6 +182,7 @@ xlog_cil_prepare_log_vecs( | |||
| 165 | } | 182 | } |
| 166 | ASSERT(ptr == new_lv->lv_buf + new_lv->lv_buf_len); | 183 | ASSERT(ptr == new_lv->lv_buf + new_lv->lv_buf_len); |
| 167 | 184 | ||
| 185 | next: | ||
| 168 | if (!ret_lv) | 186 | if (!ret_lv) |
| 169 | ret_lv = new_lv; | 187 | ret_lv = new_lv; |
| 170 | else | 188 | else |
| @@ -191,8 +209,18 @@ xfs_cil_prepare_item( | |||
| 191 | 209 | ||
| 192 | if (old) { | 210 | if (old) { |
| 193 | /* existing lv on log item, space used is a delta */ | 211 | /* existing lv on log item, space used is a delta */ |
| 194 | ASSERT(!list_empty(&lv->lv_item->li_cil)); | 212 | ASSERT((old->lv_buf && old->lv_buf_len && old->lv_niovecs) || |
| 195 | ASSERT(old->lv_buf && old->lv_buf_len && old->lv_niovecs); | 213 | old->lv_buf_len == XFS_LOG_VEC_ORDERED); |
| 214 | |||
| 215 | /* | ||
| 216 | * If the new item is ordered, keep the old one that is already | ||
| 217 | * tracking dirty or ordered regions | ||
| 218 | */ | ||
| 219 | if (lv->lv_buf_len == XFS_LOG_VEC_ORDERED) { | ||
| 220 | ASSERT(!lv->lv_buf); | ||
| 221 | kmem_free(lv); | ||
| 222 | return; | ||
| 223 | } | ||
| 196 | 224 | ||
| 197 | *len += lv->lv_buf_len - old->lv_buf_len; | 225 | *len += lv->lv_buf_len - old->lv_buf_len; |
| 198 | *diff_iovecs += lv->lv_niovecs - old->lv_niovecs; | 226 | *diff_iovecs += lv->lv_niovecs - old->lv_niovecs; |
| @@ -201,10 +229,11 @@ xfs_cil_prepare_item( | |||
| 201 | } else { | 229 | } else { |
| 202 | /* new lv, must pin the log item */ | 230 | /* new lv, must pin the log item */ |
| 203 | ASSERT(!lv->lv_item->li_lv); | 231 | ASSERT(!lv->lv_item->li_lv); |
| 204 | ASSERT(list_empty(&lv->lv_item->li_cil)); | ||
| 205 | 232 | ||
| 206 | *len += lv->lv_buf_len; | 233 | if (lv->lv_buf_len != XFS_LOG_VEC_ORDERED) { |
| 207 | *diff_iovecs += lv->lv_niovecs; | 234 | *len += lv->lv_buf_len; |
| 235 | *diff_iovecs += lv->lv_niovecs; | ||
| 236 | } | ||
| 208 | IOP_PIN(lv->lv_item); | 237 | IOP_PIN(lv->lv_item); |
| 209 | 238 | ||
| 210 | } | 239 | } |
| @@ -259,18 +288,24 @@ xlog_cil_insert_items( | |||
| 259 | * We can do this safely because the context can't checkpoint until we | 288 | * We can do this safely because the context can't checkpoint until we |
| 260 | * are done so it doesn't matter exactly how we update the CIL. | 289 | * are done so it doesn't matter exactly how we update the CIL. |
| 261 | */ | 290 | */ |
| 262 | for (lv = log_vector; lv; lv = lv->lv_next) | ||
| 263 | xfs_cil_prepare_item(log, lv, &len, &diff_iovecs); | ||
| 264 | |||
| 265 | /* account for space used by new iovec headers */ | ||
| 266 | len += diff_iovecs * sizeof(xlog_op_header_t); | ||
| 267 | |||
| 268 | spin_lock(&cil->xc_cil_lock); | 291 | spin_lock(&cil->xc_cil_lock); |
| 292 | for (lv = log_vector; lv; ) { | ||
| 293 | struct xfs_log_vec *next = lv->lv_next; | ||
| 269 | 294 | ||
| 270 | /* move the items to the tail of the CIL */ | 295 | ASSERT(lv->lv_item->li_lv || list_empty(&lv->lv_item->li_cil)); |
| 271 | for (lv = log_vector; lv; lv = lv->lv_next) | 296 | lv->lv_next = NULL; |
| 297 | |||
| 298 | /* | ||
| 299 | * xfs_cil_prepare_item() may free the lv, so move the item on | ||
| 300 | * the CIL first. | ||
| 301 | */ | ||
| 272 | list_move_tail(&lv->lv_item->li_cil, &cil->xc_cil); | 302 | list_move_tail(&lv->lv_item->li_cil, &cil->xc_cil); |
| 303 | xfs_cil_prepare_item(log, lv, &len, &diff_iovecs); | ||
| 304 | lv = next; | ||
| 305 | } | ||
| 273 | 306 | ||
| 307 | /* account for space used by new iovec headers */ | ||
| 308 | len += diff_iovecs * sizeof(xlog_op_header_t); | ||
| 274 | ctx->nvecs += diff_iovecs; | 309 | ctx->nvecs += diff_iovecs; |
| 275 | 310 | ||
| 276 | /* | 311 | /* |
| @@ -381,9 +416,7 @@ xlog_cil_push( | |||
| 381 | struct xfs_cil_ctx *new_ctx; | 416 | struct xfs_cil_ctx *new_ctx; |
| 382 | struct xlog_in_core *commit_iclog; | 417 | struct xlog_in_core *commit_iclog; |
| 383 | struct xlog_ticket *tic; | 418 | struct xlog_ticket *tic; |
| 384 | int num_lv; | ||
| 385 | int num_iovecs; | 419 | int num_iovecs; |
| 386 | int len; | ||
| 387 | int error = 0; | 420 | int error = 0; |
| 388 | struct xfs_trans_header thdr; | 421 | struct xfs_trans_header thdr; |
| 389 | struct xfs_log_iovec lhdr; | 422 | struct xfs_log_iovec lhdr; |
| @@ -428,12 +461,9 @@ xlog_cil_push( | |||
| 428 | * side which is currently locked out by the flush lock. | 461 | * side which is currently locked out by the flush lock. |
| 429 | */ | 462 | */ |
| 430 | lv = NULL; | 463 | lv = NULL; |
| 431 | num_lv = 0; | ||
| 432 | num_iovecs = 0; | 464 | num_iovecs = 0; |
| 433 | len = 0; | ||
| 434 | while (!list_empty(&cil->xc_cil)) { | 465 | while (!list_empty(&cil->xc_cil)) { |
| 435 | struct xfs_log_item *item; | 466 | struct xfs_log_item *item; |
| 436 | int i; | ||
| 437 | 467 | ||
| 438 | item = list_first_entry(&cil->xc_cil, | 468 | item = list_first_entry(&cil->xc_cil, |
| 439 | struct xfs_log_item, li_cil); | 469 | struct xfs_log_item, li_cil); |
| @@ -444,11 +474,7 @@ xlog_cil_push( | |||
| 444 | lv->lv_next = item->li_lv; | 474 | lv->lv_next = item->li_lv; |
| 445 | lv = item->li_lv; | 475 | lv = item->li_lv; |
| 446 | item->li_lv = NULL; | 476 | item->li_lv = NULL; |
| 447 | |||
| 448 | num_lv++; | ||
| 449 | num_iovecs += lv->lv_niovecs; | 477 | num_iovecs += lv->lv_niovecs; |
| 450 | for (i = 0; i < lv->lv_niovecs; i++) | ||
| 451 | len += lv->lv_iovecp[i].i_len; | ||
| 452 | } | 478 | } |
| 453 | 479 | ||
| 454 | /* | 480 | /* |
| @@ -701,6 +727,7 @@ xfs_log_commit_cil( | |||
| 701 | if (commit_lsn) | 727 | if (commit_lsn) |
| 702 | *commit_lsn = log->l_cilp->xc_ctx->sequence; | 728 | *commit_lsn = log->l_cilp->xc_ctx->sequence; |
| 703 | 729 | ||
| 730 | /* xlog_cil_insert_items() destroys log_vector list */ | ||
| 704 | xlog_cil_insert_items(log, log_vector, tp->t_ticket); | 731 | xlog_cil_insert_items(log, log_vector, tp->t_ticket); |
| 705 | 732 | ||
| 706 | /* check we didn't blow the reservation */ | 733 | /* check we didn't blow the reservation */ |
