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.
Signed-off-by: Christoph Hellwig <hch@xxxxxx>
---
fs/xfs/xfs_buf_item.c | 89 ++++++++++++-------
fs/xfs/xfs_dquot_item.c | 35 +++++---
fs/xfs/xfs_extfree_item.c | 33 ++++---
fs/xfs/xfs_icreate_item.c | 12 ++-
fs/xfs/xfs_inode_fork.c | 15 ++--
fs/xfs/xfs_inode_item.c | 209 ++++++++++++++++-----------------------------
fs/xfs/xfs_inode_item.h | 4 -
fs/xfs/xfs_log.h | 30 +++++++
fs/xfs/xfs_log_cil.c | 35 +-------
fs/xfs/xfs_trans.h | 2 +-
10 files changed, 222 insertions(+), 242 deletions(-)
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index a64f67b..067a840 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -182,10 +182,44 @@ xfs_buf_item_size(
trace_xfs_buf_item_size(bip);
}
+static inline struct xfs_log_iovec *
+xfs_buf_item_set_iovec(
+ struct xfs_log_vec *lv,
+ struct xfs_log_iovec *vec,
+ struct xfs_buf *bp,
+ uint offset,
+ int first_bit,
+ uint len)
+{
+ vec = xlog_next_iovec(lv, vec);
+
+ offset += first_bit * XFS_BLF_CHUNK;
+ len *= XFS_BLF_CHUNK;
+
+ memcpy(vec->i_addr, xfs_buf_offset(bp, offset), len);
+ vec->i_len = len;
+ vec->i_type = XLOG_REG_TYPE_BCHUNK;
+
+ return vec;
+}
+
+static inline bool
+xfs_buf_item_straddle(
+ struct xfs_buf *bp,
+ uint offset,
+ int next_bit,
+ int last_bit)
+{
+ return xfs_buf_offset(bp, offset + (next_bit << XFS_BLF_SHIFT)) !=
+ (xfs_buf_offset(bp, offset + (last_bit << XFS_BLF_SHIFT)) +
+ XFS_BLF_CHUNK);
+}
+
static struct xfs_log_iovec *
xfs_buf_item_format_segment(
struct xfs_buf_log_item *bip,
- struct xfs_log_iovec *vecp,
+ struct xfs_log_vec *lv,
+ struct xfs_log_iovec *vec,
uint offset,
struct xfs_buf_log_format *blfp)
{
@@ -196,7 +230,6 @@ xfs_buf_item_format_segment(
int last_bit;
int next_bit;
uint nbits;
- uint buffer_offset;
/* copy the flags across from the base format item */
blfp->blf_flags = bip->__bli_format.blf_flags;
@@ -218,10 +251,14 @@ xfs_buf_item_format_segment(
goto out;
}
- vecp->i_addr = blfp;
- vecp->i_len = base_size;
- vecp->i_type = XLOG_REG_TYPE_BFORMAT;
- vecp++;
+ if (vec)
+ vec = xlog_next_iovec(lv, vec);
+ else
+ vec = xlog_first_iovec(lv);
+
+ blfp = memcpy(vec->i_addr, blfp, base_size);
+ vec->i_len = base_size;
+ vec->i_type = XLOG_REG_TYPE_BFORMAT;
nvecs = 1;
if (bip->bli_flags & XFS_BLI_STALE) {
@@ -261,33 +298,16 @@ xfs_buf_item_format_segment(
* keep counting and scanning.
*/
if (next_bit == -1) {
- buffer_offset = offset + first_bit * XFS_BLF_CHUNK;
- vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
- vecp->i_len = nbits * XFS_BLF_CHUNK;
- vecp->i_type = XLOG_REG_TYPE_BCHUNK;
+ vec = xfs_buf_item_set_iovec(lv, vec, bp, offset,
+ first_bit, nbits);
nvecs++;
break;
- } else if (next_bit != last_bit + 1) {
- buffer_offset = offset + first_bit * XFS_BLF_CHUNK;
- vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
- vecp->i_len = nbits * XFS_BLF_CHUNK;
- vecp->i_type = XLOG_REG_TYPE_BCHUNK;
+ } else if (next_bit != last_bit + 1 ||
+ xfs_buf_item_straddle(bp, offset, next_bit,
last_bit)) {
+ vec = xfs_buf_item_set_iovec(lv, vec, bp, offset,
+ first_bit, nbits);
nvecs++;
- vecp++;
- first_bit = next_bit;
- last_bit = next_bit;
- nbits = 1;
- } else if (xfs_buf_offset(bp, offset +
- (next_bit << XFS_BLF_SHIFT)) !=
- (xfs_buf_offset(bp, offset +
- (last_bit << XFS_BLF_SHIFT)) +
- XFS_BLF_CHUNK)) {
- buffer_offset = offset + first_bit * XFS_BLF_CHUNK;
- vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
- vecp->i_len = nbits * XFS_BLF_CHUNK;
- vecp->i_type = XLOG_REG_TYPE_BCHUNK;
- nvecs++;
- vecp++;
+
first_bit = next_bit;
last_bit = next_bit;
nbits = 1;
@@ -298,7 +318,7 @@ xfs_buf_item_format_segment(
}
out:
blfp->blf_size = nvecs;
- return vecp;
+ return vec;
}
/*
@@ -310,10 +330,11 @@ out:
STATIC void
xfs_buf_item_format(
struct xfs_log_item *lip,
- struct xfs_log_iovec *vecp)
+ struct xfs_log_vec *lv)
{
struct xfs_buf_log_item *bip = BUF_ITEM(lip);
struct xfs_buf *bp = bip->bli_buf;
+ struct xfs_log_iovec *vec = NULL;
uint offset = 0;
int i;
@@ -354,11 +375,13 @@ xfs_buf_item_format(
}
for (i = 0; i < bip->bli_format_count; i++) {
- vecp = xfs_buf_item_format_segment(bip, vecp, offset,
+ vec = xfs_buf_item_format_segment(bip, lv, vec, offset,
&bip->bli_formats[i]);
offset += bp->b_maps[i].bm_len;
}
+ xlog_last_iovec(lv, vec);
+
/*
* Check to make sure everything is consistent.
*/
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
index 92e5f62..5f446a7 100644
--- a/fs/xfs/xfs_dquot_item.c
+++ b/fs/xfs/xfs_dquot_item.c
@@ -57,20 +57,24 @@ xfs_qm_dquot_logitem_size(
STATIC void
xfs_qm_dquot_logitem_format(
struct xfs_log_item *lip,
- struct xfs_log_iovec *logvec)
+ struct xfs_log_vec *lv)
{
struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip);
-
- logvec->i_addr = &qlip->qli_format;
- logvec->i_len = sizeof(xfs_dq_logformat_t);
- logvec->i_type = XLOG_REG_TYPE_QFORMAT;
- logvec++;
- logvec->i_addr = &qlip->qli_dquot->q_core;
- logvec->i_len = sizeof(xfs_disk_dquot_t);
- logvec->i_type = XLOG_REG_TYPE_DQUOT;
+ struct xfs_log_iovec *vec;
qlip->qli_format.qlf_size = 2;
+ vec = xlog_first_iovec(lv);
+ memcpy(vec->i_addr, &qlip->qli_format, sizeof(xfs_dq_logformat_t));
+ vec->i_len = sizeof(xfs_dq_logformat_t);
+ vec->i_type = XLOG_REG_TYPE_QFORMAT;
+
+ vec = xlog_next_iovec(lv, vec);
+ memcpy(vec->i_addr, &qlip->qli_dquot->q_core, sizeof(xfs_disk_dquot_t));
+ vec->i_len = sizeof(xfs_disk_dquot_t);
+ vec->i_type = XLOG_REG_TYPE_DQUOT;
+
+ xlog_last_iovec(lv, vec);
}
/*
@@ -304,16 +308,21 @@ xfs_qm_qoff_logitem_size(
STATIC void
xfs_qm_qoff_logitem_format(
struct xfs_log_item *lip,
- struct xfs_log_iovec *log_vector)
+ struct xfs_log_vec *lv)
{
struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip);
+ struct xfs_log_iovec *vec;
ASSERT(qflip->qql_format.qf_type == XFS_LI_QUOTAOFF);
- log_vector->i_addr = &qflip->qql_format;
- log_vector->i_len = sizeof(xfs_qoff_logitem_t);
- log_vector->i_type = XLOG_REG_TYPE_QUOTAOFF;
qflip->qql_format.qf_size = 1;
+
+ vec = xlog_first_iovec(lv);
+ memcpy(vec->i_addr, &qflip->qql_format, sizeof(xfs_qoff_logitem_t));
+ vec->i_len = sizeof(xfs_qoff_logitem_t);
+ vec->i_type = XLOG_REG_TYPE_QUOTAOFF;
+
+ xlog_last_iovec(lv, vec);
}
/*
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 3680d04..94bf5e7 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -26,6 +26,7 @@
#include "xfs_trans_priv.h"
#include "xfs_buf_item.h"
#include "xfs_extfree_item.h"
+#include "xfs_log.h"
kmem_zone_t *xfs_efi_zone;
@@ -101,9 +102,11 @@ xfs_efi_item_size(
STATIC void
xfs_efi_item_format(
struct xfs_log_item *lip,
- struct xfs_log_iovec *log_vector)
+ struct xfs_log_vec *lv)
{
struct xfs_efi_log_item *efip = EFI_ITEM(lip);
+ struct xfs_log_iovec *vec;
+ int size;
ASSERT(atomic_read(&efip->efi_next_extent) ==
efip->efi_format.efi_nextents);
@@ -111,12 +114,16 @@ xfs_efi_item_format(
efip->efi_format.efi_type = XFS_LI_EFI;
efip->efi_format.efi_size = 1;
- log_vector->i_addr = &efip->efi_format;
- log_vector->i_len = xfs_efi_item_sizeof(efip);
- log_vector->i_type = XLOG_REG_TYPE_EFI_FORMAT;
- ASSERT(log_vector->i_len >= sizeof(xfs_efi_log_format_t));
-}
+ size = xfs_efi_item_sizeof(efip);
+ ASSERT(size >= sizeof(xfs_efi_log_format_t));
+
+ vec = xlog_first_iovec(lv);
+ memcpy(vec->i_addr, &efip->efi_format, size);
+ vec->i_len = size;
+ vec->i_type = XLOG_REG_TYPE_EFI_FORMAT;
+ xlog_last_iovec(lv, vec);
+}
/*
* Pinning has no meaning for an efi item, so just return.
@@ -368,19 +375,23 @@ xfs_efd_item_size(
STATIC void
xfs_efd_item_format(
struct xfs_log_item *lip,
- struct xfs_log_iovec *log_vector)
+ struct xfs_log_vec *lv)
{
struct xfs_efd_log_item *efdp = EFD_ITEM(lip);
+ struct xfs_log_iovec *vec;
ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents);
efdp->efd_format.efd_type = XFS_LI_EFD;
efdp->efd_format.efd_size = 1;
- log_vector->i_addr = &efdp->efd_format;
- log_vector->i_len = xfs_efd_item_sizeof(efdp);
- log_vector->i_type = XLOG_REG_TYPE_EFD_FORMAT;
- ASSERT(log_vector->i_len >= sizeof(xfs_efd_log_format_t));
+ vec = xlog_first_iovec(lv);
+ memcpy(vec->i_addr, &efdp->efd_format, xfs_efd_item_sizeof(efdp));
+ vec->i_len = xfs_efd_item_sizeof(efdp);
+ vec->i_type = XLOG_REG_TYPE_EFD_FORMAT;
+ ASSERT(vec->i_len >= sizeof(xfs_efd_log_format_t));
+
+ xlog_last_iovec(lv, vec);
}
/*
diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c
index d2eaccf..f6115c3 100644
--- a/fs/xfs/xfs_icreate_item.c
+++ b/fs/xfs/xfs_icreate_item.c
@@ -28,6 +28,7 @@
#include "xfs_trans_priv.h"
#include "xfs_error.h"
#include "xfs_icreate_item.h"
+#include "xfs_log.h"
kmem_zone_t *xfs_icreate_zone; /* inode create item zone */
@@ -58,13 +59,16 @@ xfs_icreate_item_size(
STATIC void
xfs_icreate_item_format(
struct xfs_log_item *lip,
- struct xfs_log_iovec *log_vector)
+ struct xfs_log_vec *lv)
{
struct xfs_icreate_item *icp = ICR_ITEM(lip);
+ struct xfs_log_iovec *vec;
- log_vector->i_addr = (xfs_caddr_t)&icp->ic_format;
- log_vector->i_len = sizeof(struct xfs_icreate_log);
- log_vector->i_type = XLOG_REG_TYPE_ICREATE;
+ vec = xlog_first_iovec(lv);
+ memcpy(vec->i_addr, &icp->ic_format, sizeof(struct xfs_icreate_log));
+ vec->i_len = sizeof(struct xfs_icreate_log);
+ vec->i_type = XLOG_REG_TYPE_ICREATE;
+ xlog_last_iovec(lv, vec);
}
diff --git a/fs/xfs/xfs_inode_fork.c b/fs/xfs/xfs_inode_fork.c
index cfee14a..06abaee 100644
--- a/fs/xfs/xfs_inode_fork.c
+++ b/fs/xfs/xfs_inode_fork.c
@@ -721,15 +721,16 @@ xfs_idestroy_fork(
}
/*
- * xfs_iextents_copy()
+ * Convert in-core extents to on-disk form
*
- * This is called to copy the REAL extents (as opposed to the delayed
- * allocation extents) from the inode into the given buffer. It
- * returns the number of bytes copied into the buffer.
+ * For either the data or attr fork in extent format, we need to endian convert
+ * the in-core extent as we place them into the on-disk inode.
*
- * If there are no delayed allocation extents, then we can just
- * memcpy() the extents into the buffer. Otherwise, we need to
- * examine each extent in turn and skip those which are delayed.
+ * In the case of the data fork, the in-core and on-disk fork sizes can be
+ * different due to delayed allocation extents. We only copy on-disk extents
+ * here, so callers must always use the physical fork size to determine the
+ * size of the buffer passed to this routine. We will return the size actually
+ * used.
*/
int
xfs_iextents_copy(
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 7c0d391f..fbdcde1 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -30,6 +30,7 @@
#include "xfs_trace.h"
#include "xfs_trans_priv.h"
#include "xfs_dinode.h"
+#include "xfs_log.h"
kmem_zone_t *xfs_ili_zone; /* inode log item zone */
@@ -137,41 +138,6 @@ xfs_inode_item_size(
}
/*
- * xfs_inode_item_format_extents - convert in-core extents to on-disk form
- *
- * For either the data or attr fork in extent format, we need to endian convert
- * the in-core extent as we place them into the on-disk inode. In this case, we
- * need to do this conversion before we write the extents into the log. Because
- * we don't have the disk inode to write into here, we allocate a buffer and
- * format the extents into it via xfs_iextents_copy(). We free the buffer in
- * the unlock routine after the copy for the log has been made.
- *
- * In the case of the data fork, the in-core and on-disk fork sizes can be
- * different due to delayed allocation extents. We only log on-disk extents
- * here, so always use the physical fork size to determine the size of the
- * buffer we need to allocate.
- */
-STATIC void
-xfs_inode_item_format_extents(
- struct xfs_inode *ip,
- struct xfs_log_iovec *vecp,
- int whichfork,
- int type)
-{
- xfs_bmbt_rec_t *ext_buffer;
-
- ext_buffer = kmem_alloc(XFS_IFORK_SIZE(ip, whichfork), KM_SLEEP);
- if (whichfork == XFS_DATA_FORK)
- ip->i_itemp->ili_extents_buf = ext_buffer;
- else
- ip->i_itemp->ili_aextents_buf = ext_buffer;
-
- vecp->i_addr = ext_buffer;
- vecp->i_len = xfs_iextents_copy(ip, ext_buffer, whichfork);
- vecp->i_type = type;
-}
-
-/*
* This is called to fill in the vector of log iovecs for the
* given inode log item. It fills the first item with an inode
* log format structure, the second with the on-disk inode structure,
@@ -181,24 +147,29 @@ xfs_inode_item_format_extents(
STATIC void
xfs_inode_item_format(
struct xfs_log_item *lip,
- struct xfs_log_iovec *vecp)
+ struct xfs_log_vec *lv)
{
struct xfs_inode_log_item *iip = INODE_ITEM(lip);
struct xfs_inode *ip = iip->ili_inode;
+ struct xfs_log_iovec *vec;
+ struct xfs_inode_log_format *ilf;
+ uint size;
uint nvecs;
size_t data_bytes;
xfs_mount_t *mp;
- vecp->i_addr = &iip->ili_format;
- vecp->i_len = sizeof(xfs_inode_log_format_t);
- vecp->i_type = XLOG_REG_TYPE_IFORMAT;
- vecp++;
- nvecs = 1;
-
- vecp->i_addr = &ip->i_d;
- vecp->i_len = xfs_icdinode_size(ip->i_d.di_version);
- vecp->i_type = XLOG_REG_TYPE_ICORE;
- vecp++;
+ vec = xlog_first_iovec(lv);
+ ilf = memcpy(vec->i_addr, &iip->ili_format,
+ sizeof(struct xfs_inode_log_format));
+ vec->i_len = sizeof(struct xfs_inode_log_format);
+ vec->i_type = XLOG_REG_TYPE_IFORMAT;
+ nvecs = 1;
+
+ vec = xlog_next_iovec(lv, vec);
+ size = xfs_icdinode_size(ip->i_d.di_version);
+ memcpy(vec->i_addr, &ip->i_d, size);
+ vec->i_len = size;
+ vec->i_type = XLOG_REG_TYPE_ICORE;
nvecs++;
/*
@@ -210,9 +181,10 @@ xfs_inode_item_format(
* has a new version number, then we don't bother converting back.
*/
mp = ip->i_mount;
- ASSERT(ip->i_d.di_version == 1 || xfs_sb_version_hasnlink(&mp->m_sb));
+ ASSERT(ip->i_d.di_version == 1 ||
+ xfs_sb_version_hasnlink(&ip->i_mount->m_sb));
if (ip->i_d.di_version == 1) {
- if (!xfs_sb_version_hasnlink(&mp->m_sb)) {
+ if (!xfs_sb_version_hasnlink(&ip->i_mount->m_sb)) {
/*
* Convert it back.
*/
@@ -241,29 +213,15 @@ xfs_inode_item_format(
ip->i_df.if_bytes > 0) {
ASSERT(ip->i_df.if_u1.if_extents != NULL);
ASSERT(ip->i_df.if_bytes / sizeof(xfs_bmbt_rec_t) > 0);
- ASSERT(iip->ili_extents_buf == NULL);
-
-#ifdef XFS_NATIVE_HOST
- if (ip->i_d.di_nextents == ip->i_df.if_bytes /
- (uint)sizeof(xfs_bmbt_rec_t)) {
- /*
- * There are no delayed allocation
- * extents, so just point to the
- * real extents array.
- */
- vecp->i_addr = ip->i_df.if_u1.if_extents;
- vecp->i_len = ip->i_df.if_bytes;
- vecp->i_type = XLOG_REG_TYPE_IEXT;
- } else
-#endif
- {
- xfs_inode_item_format_extents(ip, vecp,
- XFS_DATA_FORK, XLOG_REG_TYPE_IEXT);
- }
- ASSERT(vecp->i_len <= ip->i_df.if_bytes);
- iip->ili_format.ilf_dsize = vecp->i_len;
- vecp++;
+
+ vec = xlog_next_iovec(lv, vec);
+ vec->i_len = xfs_iextents_copy(ip, vec->i_addr,
+ XFS_DATA_FORK);
+ vec->i_type = XLOG_REG_TYPE_IEXT;
nvecs++;
+
+ ASSERT(vec->i_len <= ip->i_df.if_bytes);
+ ilf->ilf_dsize = vec->i_len;
} else {
iip->ili_fields &= ~XFS_ILOG_DEXT;
}
@@ -277,12 +235,15 @@ xfs_inode_item_format(
if ((iip->ili_fields & XFS_ILOG_DBROOT) &&
ip->i_df.if_broot_bytes > 0) {
ASSERT(ip->i_df.if_broot != NULL);
- vecp->i_addr = ip->i_df.if_broot;
- vecp->i_len = ip->i_df.if_broot_bytes;
- vecp->i_type = XLOG_REG_TYPE_IBROOT;
- vecp++;
+
+ vec = xlog_next_iovec(lv, vec);
+ memcpy(vec->i_addr, ip->i_df.if_broot,
+ ip->i_df.if_broot_bytes);
+ vec->i_len = ip->i_df.if_broot_bytes;
+ vec->i_type = XLOG_REG_TYPE_IBROOT;
nvecs++;
- iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes;
+
+ ilf->ilf_dsize = ip->i_df.if_broot_bytes;
} else {
ASSERT(!(iip->ili_fields &
XFS_ILOG_DBROOT));
@@ -299,7 +260,6 @@ xfs_inode_item_format(
ASSERT(ip->i_df.if_u1.if_data != NULL);
ASSERT(ip->i_d.di_size > 0);
- vecp->i_addr = ip->i_df.if_u1.if_data;
/*
* Round i_bytes up to a word boundary.
* The underlying memory is guaranteed to
@@ -308,11 +268,14 @@ xfs_inode_item_format(
data_bytes = roundup(ip->i_df.if_bytes, 4);
ASSERT((ip->i_df.if_real_bytes == 0) ||
(ip->i_df.if_real_bytes == data_bytes));
- vecp->i_len = (int)data_bytes;
- vecp->i_type = XLOG_REG_TYPE_ILOCAL;
- vecp++;
+
+ vec = xlog_next_iovec(lv, vec);
+ memcpy(vec->i_addr, ip->i_df.if_u1.if_data, data_bytes);
+ vec->i_len = data_bytes;
+ vec->i_type = XLOG_REG_TYPE_ILOCAL;
nvecs++;
- iip->ili_format.ilf_dsize = (unsigned)data_bytes;
+
+ ilf->ilf_dsize = (unsigned)data_bytes;
} else {
iip->ili_fields &= ~XFS_ILOG_DDATA;
}
@@ -322,20 +285,16 @@ xfs_inode_item_format(
iip->ili_fields &=
~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
XFS_ILOG_DEXT | XFS_ILOG_UUID);
- if (iip->ili_fields & XFS_ILOG_DEV) {
- iip->ili_format.ilf_u.ilfu_rdev =
- ip->i_df.if_u2.if_rdev;
- }
+ if (iip->ili_fields & XFS_ILOG_DEV)
+ ilf->ilf_u.ilfu_rdev = ip->i_df.if_u2.if_rdev;
break;
case XFS_DINODE_FMT_UUID:
iip->ili_fields &=
~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
XFS_ILOG_DEXT | XFS_ILOG_DEV);
- if (iip->ili_fields & XFS_ILOG_UUID) {
- iip->ili_format.ilf_u.ilfu_uuid =
- ip->i_df.if_u2.if_uuid;
- }
+ if (iip->ili_fields & XFS_ILOG_UUID)
+ ilf->ilf_u.ilfu_uuid = ip->i_df.if_u2.if_uuid;
break;
default:
@@ -363,22 +322,14 @@ xfs_inode_item_format(
ASSERT(ip->i_afp->if_bytes / sizeof(xfs_bmbt_rec_t) ==
ip->i_d.di_anextents);
ASSERT(ip->i_afp->if_u1.if_extents != NULL);
-#ifdef XFS_NATIVE_HOST
- /*
- * There are not delayed allocation extents
- * for attributes, so just point at the array.
- */
- vecp->i_addr = ip->i_afp->if_u1.if_extents;
- vecp->i_len = ip->i_afp->if_bytes;
- vecp->i_type = XLOG_REG_TYPE_IATTR_EXT;
-#else
- ASSERT(iip->ili_aextents_buf == NULL);
- xfs_inode_item_format_extents(ip, vecp,
- XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT);
-#endif
- iip->ili_format.ilf_asize = vecp->i_len;
- vecp++;
+
+ vec = xlog_next_iovec(lv, vec);
+ vec->i_len = xfs_iextents_copy(ip, vec->i_addr,
+ XFS_ATTR_FORK);
+ vec->i_type = XLOG_REG_TYPE_IATTR_EXT;
nvecs++;
+
+ ilf->ilf_asize = vec->i_len;
} else {
iip->ili_fields &= ~XFS_ILOG_AEXT;
}
@@ -392,12 +343,14 @@ xfs_inode_item_format(
ip->i_afp->if_broot_bytes > 0) {
ASSERT(ip->i_afp->if_broot != NULL);
- vecp->i_addr = ip->i_afp->if_broot;
- vecp->i_len = ip->i_afp->if_broot_bytes;
- vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT;
- vecp++;
+ vec = xlog_next_iovec(lv, vec);
+ memcpy(vec->i_addr, ip->i_afp->if_broot,
+ ip->i_afp->if_broot_bytes);
+ vec->i_len = ip->i_afp->if_broot_bytes;
+ vec->i_type = XLOG_REG_TYPE_IATTR_BROOT;
nvecs++;
- iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes;
+
+ ilf->ilf_asize = ip->i_afp->if_broot_bytes;
} else {
iip->ili_fields &= ~XFS_ILOG_ABROOT;
}
@@ -411,7 +364,6 @@ xfs_inode_item_format(
ip->i_afp->if_bytes > 0) {
ASSERT(ip->i_afp->if_u1.if_data != NULL);
- vecp->i_addr = ip->i_afp->if_u1.if_data;
/*
* Round i_bytes up to a word boundary.
* The underlying memory is guaranteed to
@@ -420,11 +372,15 @@ xfs_inode_item_format(
data_bytes = roundup(ip->i_afp->if_bytes, 4);
ASSERT((ip->i_afp->if_real_bytes == 0) ||
(ip->i_afp->if_real_bytes == data_bytes));
- vecp->i_len = (int)data_bytes;
- vecp->i_type = XLOG_REG_TYPE_IATTR_LOCAL;
- vecp++;
+
+ vec = xlog_next_iovec(lv, vec);
+ memcpy(vec->i_addr, ip->i_afp->if_u1.if_data,
+ data_bytes);
+ vec->i_len = data_bytes;
+ vec->i_type = XLOG_REG_TYPE_IATTR_LOCAL;
nvecs++;
- iip->ili_format.ilf_asize = (unsigned)data_bytes;
+
+ ilf->ilf_asize = (unsigned)data_bytes;
} else {
iip->ili_fields &= ~XFS_ILOG_ADATA;
}
@@ -436,18 +392,18 @@ xfs_inode_item_format(
}
out:
+ xlog_last_iovec(lv, vec);
/*
* Now update the log format that goes out to disk from the in-core
* values. We always write the inode core to make the arithmetic
* games in recovery easier, which isn't a big deal as just about any
* transaction would dirty it anyway.
*/
- iip->ili_format.ilf_fields = XFS_ILOG_CORE |
+ ilf->ilf_fields = XFS_ILOG_CORE |
(iip->ili_fields & ~XFS_ILOG_TIMESTAMP);
- iip->ili_format.ilf_size = nvecs;
+ ilf->ilf_size = nvecs;
}
-
/*
* This is called to pin the inode associated with the inode log
* item in memory so it cannot be written out.
@@ -563,27 +519,6 @@ xfs_inode_item_unlock(
ASSERT(ip->i_itemp != NULL);
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
- /*
- * If the inode needed a separate buffer with which to log
- * its extents, then free it now.
- */
- if (iip->ili_extents_buf != NULL) {
- ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS);
- ASSERT(ip->i_d.di_nextents > 0);
- ASSERT(iip->ili_fields & XFS_ILOG_DEXT);
- ASSERT(ip->i_df.if_bytes > 0);
- kmem_free(iip->ili_extents_buf);
- iip->ili_extents_buf = NULL;
- }
- if (iip->ili_aextents_buf != NULL) {
- ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS);
- ASSERT(ip->i_d.di_anextents > 0);
- ASSERT(iip->ili_fields & XFS_ILOG_AEXT);
- ASSERT(ip->i_afp->if_bytes > 0);
- kmem_free(iip->ili_aextents_buf);
- iip->ili_aextents_buf = NULL;
- }
-
lock_flags = iip->ili_lock_flags;
iip->ili_lock_flags = 0;
if (lock_flags)
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index dce4d65..29b5f2b 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -34,10 +34,6 @@ typedef struct xfs_inode_log_item {
unsigned short ili_logged; /* flushed logged data */
unsigned int ili_last_fields; /* fields when flushed */
unsigned int ili_fields; /* fields to be logged */
- struct xfs_bmbt_rec *ili_extents_buf; /* array of logged
- data exts */
- struct xfs_bmbt_rec *ili_aextents_buf; /* array of logged
- attr exts */
xfs_inode_log_format_t ili_format; /* logged structure */
} xfs_inode_log_item_t;
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index e148719..3769830 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -30,6 +30,36 @@ struct xfs_log_vec {
#define XFS_LOG_VEC_ORDERED (-1)
+static inline struct xfs_log_iovec *
+xlog_first_iovec(struct xfs_log_vec *lv)
+{
+ struct xfs_log_iovec *vec = &lv->lv_iovecp[0];
+
+ vec->i_addr = lv->lv_buf;
+ lv->lv_buf_len = 0;
+ return vec;
+}
+
+static inline struct xfs_log_iovec *
+xlog_next_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *prev)
+{
+ struct xfs_log_iovec *vec;
+
+ ASSERT(prev - lv->lv_iovecp < lv->lv_niovecs);
+
+ vec = prev + 1;
+ vec->i_addr = prev->i_addr + prev->i_len;
+ lv->lv_buf_len += prev->i_len;
+ return vec;
+}
+
+static inline void
+xlog_last_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *prev)
+{
+ ASSERT(prev - lv->lv_iovecp < lv->lv_niovecs);
+ lv->lv_buf_len += prev->i_len;
+}
+
/*
* Structure used to pass callback function and the function's argument
* to the log manager.
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 5eb51fc..8d5f2ea 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -82,36 +82,6 @@ xlog_cil_init_post_recovery(
log->l_curr_block);
}
-STATIC int
-xlog_cil_lv_item_format(
- struct xfs_log_item *lip,
- struct xfs_log_vec *lv)
-{
- int index;
- char *ptr;
-
- /* format new vectors into array */
- lip->li_ops->iop_format(lip, lv->lv_iovecp);
-
- /* copy data into existing array */
- ptr = lv->lv_buf;
- for (index = 0; index < lv->lv_niovecs; index++) {
- struct xfs_log_iovec *vec = &lv->lv_iovecp[index];
-
- memcpy(ptr, vec->i_addr, vec->i_len);
- vec->i_addr = ptr;
- ptr += vec->i_len;
- }
-
- /*
- * some size calculations for log vectors over-estimate, so the caller
- * doesn't know the amount of space actually used by the item. Return
- * the byte count to the caller so they can check and store it
- * appropriately.
- */
- return ptr - lv->lv_buf;
-}
-
/*
* Prepare the log item for insertion into the CIL. Calculate the difference in
* log space and vectors it will consume, and if it is a new item pin it as
@@ -259,7 +229,7 @@ xlog_cil_insert_format_items(
lv->lv_niovecs = niovecs;
lv->lv_buf = (char *)lv + buf_size - nbytes;
- lv->lv_buf_len = xlog_cil_lv_item_format(lip, lv);
+ lip->li_ops->iop_format(lip, lv);
goto insert;
}
@@ -281,7 +251,8 @@ xlog_cil_insert_format_items(
/* The allocated data region lies beyond the iovec region */
lv->lv_buf = (char *)lv + buf_size - nbytes;
- lv->lv_buf_len = xlog_cil_lv_item_format(lip, lv);
+ /* Format new vectors into array */
+ lip->li_ops->iop_format(lip, lv);
insert:
ASSERT(lv->lv_buf_len <= nbytes);
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 9b96d35..b5bc1ab 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -64,7 +64,7 @@ typedef struct xfs_log_item {
struct xfs_item_ops {
void (*iop_size)(xfs_log_item_t *, int *, int *);
- void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *);
+ void (*iop_format)(xfs_log_item_t *, struct xfs_log_vec *);
void (*iop_pin)(xfs_log_item_t *);
void (*iop_unpin)(xfs_log_item_t *, int remove);
uint (*iop_push)(struct xfs_log_item *, struct list_head *);
--
1.7.10.4
|