diff options
Diffstat (limited to 'fs/xfs/xfs_log.h')
-rw-r--r-- | fs/xfs/xfs_log.h | 41 |
1 files changed, 37 insertions, 4 deletions
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 { #define XFS_LOG_VEC_ORDERED (-1) static inline void * -xlog_copy_iovec(struct xfs_log_iovec **vecp, uint type, void *data, int len) +xlog_prepare_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp, + uint type) { struct xfs_log_iovec *vec = *vecp; + if (vec) { + ASSERT(vec - lv->lv_iovecp < lv->lv_niovecs); + vec++; + } else { + vec = &lv->lv_iovecp[0]; + } + vec->i_type = type; - vec->i_addr = data; - vec->i_len = len; + vec->i_addr = lv->lv_buf + lv->lv_buf_len; + + ASSERT(IS_ALIGNED((unsigned long)vec->i_addr, sizeof(uint64_t))); - *vecp = vec + 1; + *vecp = vec; return vec->i_addr; } +static inline void +xlog_finish_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *vec, int len) +{ + /* + * We need to make sure the next buffer is naturally aligned for the + * biggest basic data type we put into it. We already accounted for + * this when sizing the buffer. + */ + lv->lv_buf_len += round_up(len, sizeof(uint64_t)); + vec->i_len = len; +} + +static inline void * +xlog_copy_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp, + uint type, void *data, int len) +{ + void *buf; + + buf = xlog_prepare_iovec(lv, vecp, type); + memcpy(buf, data, len); + xlog_finish_iovec(lv, *vecp, len); + return buf; +} + /* * Structure used to pass callback function and the function's argument * to the log manager. |