aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_log.h19
-rw-r--r--fs/xfs/xfs_log_cil.c7
2 files changed, 17 insertions, 9 deletions
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 2c4004475e71..84e0deb95abd 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -24,7 +24,8 @@ struct xfs_log_vec {
24 struct xfs_log_iovec *lv_iovecp; /* iovec array */ 24 struct xfs_log_iovec *lv_iovecp; /* iovec array */
25 struct xfs_log_item *lv_item; /* owner */ 25 struct xfs_log_item *lv_item; /* owner */
26 char *lv_buf; /* formatted buffer */ 26 char *lv_buf; /* formatted buffer */
27 int lv_buf_len; /* size of formatted buffer */ 27 int lv_bytes; /* accounted space in buffer */
28 int lv_buf_len; /* aligned size of buffer */
28 int lv_size; /* size of allocated lv */ 29 int lv_size; /* size of allocated lv */
29}; 30};
30 31
@@ -52,15 +53,21 @@ xlog_prepare_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp,
52 return vec->i_addr; 53 return vec->i_addr;
53} 54}
54 55
56/*
57 * We need to make sure the next buffer is naturally aligned for the biggest
58 * basic data type we put into it. We already accounted for this padding when
59 * sizing the buffer.
60 *
61 * However, this padding does not get written into the log, and hence we have to
62 * track the space used by the log vectors separately to prevent log space hangs
63 * due to inaccurate accounting (i.e. a leak) of the used log space through the
64 * CIL context ticket.
65 */
55static inline void 66static inline void
56xlog_finish_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *vec, int len) 67xlog_finish_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *vec, int len)
57{ 68{
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)); 69 lv->lv_buf_len += round_up(len, sizeof(uint64_t));
70 lv->lv_bytes += len;
64 vec->i_len = len; 71 vec->i_len = len;
65} 72}
66 73
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 7e5455391176..de835da6764d 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -97,7 +97,7 @@ xfs_cil_prepare_item(
97{ 97{
98 /* Account for the new LV being passed in */ 98 /* Account for the new LV being passed in */
99 if (lv->lv_buf_len != XFS_LOG_VEC_ORDERED) { 99 if (lv->lv_buf_len != XFS_LOG_VEC_ORDERED) {
100 *diff_len += lv->lv_buf_len; 100 *diff_len += lv->lv_bytes;
101 *diff_iovecs += lv->lv_niovecs; 101 *diff_iovecs += lv->lv_niovecs;
102 } 102 }
103 103
@@ -111,7 +111,7 @@ xfs_cil_prepare_item(
111 else if (old_lv != lv) { 111 else if (old_lv != lv) {
112 ASSERT(lv->lv_buf_len != XFS_LOG_VEC_ORDERED); 112 ASSERT(lv->lv_buf_len != XFS_LOG_VEC_ORDERED);
113 113
114 *diff_len -= old_lv->lv_buf_len; 114 *diff_len -= old_lv->lv_bytes;
115 *diff_iovecs -= old_lv->lv_niovecs; 115 *diff_iovecs -= old_lv->lv_niovecs;
116 kmem_free(old_lv); 116 kmem_free(old_lv);
117 } 117 }
@@ -239,7 +239,7 @@ xlog_cil_insert_format_items(
239 * that the space reservation accounting is correct. 239 * that the space reservation accounting is correct.
240 */ 240 */
241 *diff_iovecs -= lv->lv_niovecs; 241 *diff_iovecs -= lv->lv_niovecs;
242 *diff_len -= lv->lv_buf_len; 242 *diff_len -= lv->lv_bytes;
243 } else { 243 } else {
244 /* allocate new data chunk */ 244 /* allocate new data chunk */
245 lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS); 245 lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS);
@@ -259,6 +259,7 @@ xlog_cil_insert_format_items(
259 259
260 /* 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; 261 lv->lv_buf_len = 0;
262 lv->lv_bytes = 0;
262 lv->lv_buf = (char *)lv + buf_size - nbytes; 263 lv->lv_buf = (char *)lv + buf_size - nbytes;
263 ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t))); 264 ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t)));
264 265