From ce9641d6c981aad0463b2d1455f0b60e5c8671c5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Dec 2013 11:00:43 +1100 Subject: xfs: refactor xfs_inode_item_size Split out two helpers to size the data and attribute to make the function more readable. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_inode_item.c | 62 ++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'fs/xfs/xfs_inode_item.c') diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 7c0d391f9a6e..050d2540f7b4 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -39,27 +39,14 @@ static inline struct xfs_inode_log_item *INODE_ITEM(struct xfs_log_item *lip) return container_of(lip, struct xfs_inode_log_item, ili_item); } - -/* - * This returns the number of iovecs needed to log the given inode item. - * - * We need one iovec for the inode log format structure, one for the - * inode core, and possibly one for the inode data/extents/b-tree root - * and one for the inode attribute data/extents/b-tree root. - */ STATIC void -xfs_inode_item_size( - struct xfs_log_item *lip, +xfs_inode_item_data_fork_size( + struct xfs_inode_log_item *iip, int *nvecs, int *nbytes) { - struct xfs_inode_log_item *iip = INODE_ITEM(lip); struct xfs_inode *ip = iip->ili_inode; - *nvecs += 2; - *nbytes += sizeof(struct xfs_inode_log_format) + - xfs_icdinode_size(ip->i_d.di_version); - switch (ip->i_d.di_format) { case XFS_DINODE_FMT_EXTENTS: if ((iip->ili_fields & XFS_ILOG_DEXT) && @@ -70,7 +57,6 @@ xfs_inode_item_size( *nvecs += 1; } break; - case XFS_DINODE_FMT_BTREE: if ((iip->ili_fields & XFS_ILOG_DBROOT) && ip->i_df.if_broot_bytes > 0) { @@ -78,7 +64,6 @@ xfs_inode_item_size( *nvecs += 1; } break; - case XFS_DINODE_FMT_LOCAL: if ((iip->ili_fields & XFS_ILOG_DDATA) && ip->i_df.if_bytes > 0) { @@ -90,19 +75,20 @@ xfs_inode_item_size( case XFS_DINODE_FMT_DEV: case XFS_DINODE_FMT_UUID: break; - default: ASSERT(0); break; } +} - if (!XFS_IFORK_Q(ip)) - return; - +STATIC void +xfs_inode_item_attr_fork_size( + struct xfs_inode_log_item *iip, + int *nvecs, + int *nbytes) +{ + struct xfs_inode *ip = iip->ili_inode; - /* - * Log any necessary attribute data. - */ switch (ip->i_d.di_aformat) { case XFS_DINODE_FMT_EXTENTS: if ((iip->ili_fields & XFS_ILOG_AEXT) && @@ -113,7 +99,6 @@ xfs_inode_item_size( *nvecs += 1; } break; - case XFS_DINODE_FMT_BTREE: if ((iip->ili_fields & XFS_ILOG_ABROOT) && ip->i_afp->if_broot_bytes > 0) { @@ -121,7 +106,6 @@ xfs_inode_item_size( *nvecs += 1; } break; - case XFS_DINODE_FMT_LOCAL: if ((iip->ili_fields & XFS_ILOG_ADATA) && ip->i_afp->if_bytes > 0) { @@ -129,13 +113,37 @@ xfs_inode_item_size( *nvecs += 1; } break; - default: ASSERT(0); break; } } +/* + * This returns the number of iovecs needed to log the given inode item. + * + * We need one iovec for the inode log format structure, one for the + * inode core, and possibly one for the inode data/extents/b-tree root + * and one for the inode attribute data/extents/b-tree root. + */ +STATIC void +xfs_inode_item_size( + struct xfs_log_item *lip, + int *nvecs, + int *nbytes) +{ + struct xfs_inode_log_item *iip = INODE_ITEM(lip); + struct xfs_inode *ip = iip->ili_inode; + + *nvecs += 2; + *nbytes += sizeof(struct xfs_inode_log_format) + + xfs_icdinode_size(ip->i_d.di_version); + + xfs_inode_item_data_fork_size(iip, nvecs, nbytes); + if (XFS_IFORK_Q(ip)) + xfs_inode_item_attr_fork_size(iip, nvecs, nbytes); +} + /* * xfs_inode_item_format_extents - convert in-core extents to on-disk form * -- cgit v1.2.2 From 3de559fbd04d67473b9be2bd183823c40c4b7557 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Dec 2013 11:00:43 +1100 Subject: xfs: refactor xfs_inode_item_format Split out a function to handle the data and attr fork, as well as a helper for the really old v1 inodes. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_inode_item.c | 165 ++++++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 76 deletions(-) (limited to 'fs/xfs/xfs_inode_item.c') diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 050d2540f7b4..2ad12dcf8311 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -180,63 +180,41 @@ xfs_inode_item_format_extents( } /* - * 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, - * and a possible third and/or fourth with the inode data/extents/b-tree - * root and inode attributes data/extents/b-tree root. + * If this is a v1 format inode, then we need to log it as such. This means + * that we have to copy the link count from the new field to the old. We + * don't have to worry about the new fields, because nothing trusts them as + * long as the old inode version number is there. */ STATIC void -xfs_inode_item_format( - struct xfs_log_item *lip, - struct xfs_log_iovec *vecp) +xfs_inode_item_format_v1_inode( + struct xfs_inode *ip) +{ + if (!xfs_sb_version_hasnlink(&ip->i_mount->m_sb)) { + /* + * Convert it back. + */ + ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1); + ip->i_d.di_onlink = ip->i_d.di_nlink; + } else { + /* + * The superblock version has already been bumped, + * so just make the conversion to the new inode + * format permanent. + */ + ip->i_d.di_version = 2; + ip->i_d.di_onlink = 0; + memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); + } +} + +STATIC struct xfs_log_iovec * +xfs_inode_item_format_data_fork( + struct xfs_inode_log_item *iip, + struct xfs_log_iovec *vecp, + int *nvecs) { - struct xfs_inode_log_item *iip = INODE_ITEM(lip); struct xfs_inode *ip = iip->ili_inode; - 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++; - nvecs++; - - /* - * If this is really an old format inode, then we need to - * log it as such. This means that we have to copy the link - * count from the new field to the old. We don't have to worry - * about the new fields, because nothing trusts them as long as - * the old inode version number is there. If the superblock already - * 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)); - if (ip->i_d.di_version == 1) { - if (!xfs_sb_version_hasnlink(&mp->m_sb)) { - /* - * Convert it back. - */ - ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1); - ip->i_d.di_onlink = ip->i_d.di_nlink; - } else { - /* - * The superblock version has already been bumped, - * so just make the conversion to the new inode - * format permanent. - */ - ip->i_d.di_version = 2; - ip->i_d.di_onlink = 0; - memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); - } - } switch (ip->i_d.di_format) { case XFS_DINODE_FMT_EXTENTS: @@ -271,12 +249,11 @@ xfs_inode_item_format( ASSERT(vecp->i_len <= ip->i_df.if_bytes); iip->ili_format.ilf_dsize = vecp->i_len; vecp++; - nvecs++; + (*nvecs)++; } else { iip->ili_fields &= ~XFS_ILOG_DEXT; } break; - case XFS_DINODE_FMT_BTREE: iip->ili_fields &= ~(XFS_ILOG_DDATA | XFS_ILOG_DEXT | @@ -289,7 +266,7 @@ xfs_inode_item_format( vecp->i_len = ip->i_df.if_broot_bytes; vecp->i_type = XLOG_REG_TYPE_IBROOT; vecp++; - nvecs++; + (*nvecs)++; iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; } else { ASSERT(!(iip->ili_fields & @@ -297,7 +274,6 @@ xfs_inode_item_format( iip->ili_fields &= ~XFS_ILOG_DBROOT; } break; - case XFS_DINODE_FMT_LOCAL: iip->ili_fields &= ~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT | @@ -319,13 +295,12 @@ xfs_inode_item_format( vecp->i_len = (int)data_bytes; vecp->i_type = XLOG_REG_TYPE_ILOCAL; vecp++; - nvecs++; + (*nvecs)++; iip->ili_format.ilf_dsize = (unsigned)data_bytes; } else { iip->ili_fields &= ~XFS_ILOG_DDATA; } break; - case XFS_DINODE_FMT_DEV: iip->ili_fields &= ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | @@ -335,7 +310,6 @@ xfs_inode_item_format( ip->i_df.if_u2.if_rdev; } break; - case XFS_DINODE_FMT_UUID: iip->ili_fields &= ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | @@ -345,20 +319,22 @@ xfs_inode_item_format( ip->i_df.if_u2.if_uuid; } break; - default: ASSERT(0); break; } - /* - * If there are no attributes associated with the file, then we're done. - */ - if (!XFS_IFORK_Q(ip)) { - iip->ili_fields &= - ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); - goto out; - } + return vecp; +} + +STATIC struct xfs_log_iovec * +xfs_inode_item_format_attr_fork( + struct xfs_inode_log_item *iip, + struct xfs_log_iovec *vecp, + int *nvecs) +{ + struct xfs_inode *ip = iip->ili_inode; + size_t data_bytes; switch (ip->i_d.di_aformat) { case XFS_DINODE_FMT_EXTENTS: @@ -386,12 +362,11 @@ xfs_inode_item_format( #endif iip->ili_format.ilf_asize = vecp->i_len; vecp++; - nvecs++; + (*nvecs)++; } else { iip->ili_fields &= ~XFS_ILOG_AEXT; } break; - case XFS_DINODE_FMT_BTREE: iip->ili_fields &= ~(XFS_ILOG_ADATA | XFS_ILOG_AEXT); @@ -404,13 +379,12 @@ xfs_inode_item_format( vecp->i_len = ip->i_afp->if_broot_bytes; vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT; vecp++; - nvecs++; + (*nvecs)++; iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; } else { iip->ili_fields &= ~XFS_ILOG_ABROOT; } break; - case XFS_DINODE_FMT_LOCAL: iip->ili_fields &= ~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT); @@ -431,19 +405,59 @@ xfs_inode_item_format( vecp->i_len = (int)data_bytes; vecp->i_type = XLOG_REG_TYPE_IATTR_LOCAL; vecp++; - nvecs++; + (*nvecs)++; iip->ili_format.ilf_asize = (unsigned)data_bytes; } else { iip->ili_fields &= ~XFS_ILOG_ADATA; } break; - default: ASSERT(0); break; } -out: + return vecp; +} + +/* + * 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, and a possible third and/or + * fourth with the inode data/extents/b-tree root and inode attributes + * data/extents/b-tree root. + */ +STATIC void +xfs_inode_item_format( + struct xfs_log_item *lip, + struct xfs_log_iovec *vecp) +{ + struct xfs_inode_log_item *iip = INODE_ITEM(lip); + struct xfs_inode *ip = iip->ili_inode; + uint nvecs; + + 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++; + nvecs++; + + if (ip->i_d.di_version == 1) + xfs_inode_item_format_v1_inode(ip); + + vecp = xfs_inode_item_format_data_fork(iip, vecp, &nvecs); + if (XFS_IFORK_Q(ip)) { + vecp = xfs_inode_item_format_attr_fork(iip, vecp, &nvecs); + } else { + iip->ili_fields &= + ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); + } + /* * 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 @@ -455,7 +469,6 @@ out: iip->ili_format.ilf_size = nvecs; } - /* * This is called to pin the inode associated with the inode log * item in memory so it cannot be written out. -- cgit v1.2.2 From 1234351cba958cd5d4338172ccfc869a687cd736 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Dec 2013 11:00:43 +1100 Subject: xfs: introduce xlog_copy_iovec Add a helper to abstract out filling the log iovecs in the log item format handlers. This will allow us to change the way we do the log item formatting more easily. The copy in the name is a bit confusing for now as it just assigns a pointer and lets the CIL code perform the copy, but that will change soon. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_inode_item.c | 115 ++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 63 deletions(-) (limited to 'fs/xfs/xfs_inode_item.c') diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 2ad12dcf8311..c75e14beff06 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 */ @@ -159,14 +160,15 @@ xfs_inode_item_size( * here, so always use the physical fork size to determine the size of the * buffer we need to allocate. */ -STATIC void +STATIC int xfs_inode_item_format_extents( struct xfs_inode *ip, - struct xfs_log_iovec *vecp, + struct xfs_log_iovec **vecp, int whichfork, int type) { xfs_bmbt_rec_t *ext_buffer; + int len; ext_buffer = kmem_alloc(XFS_IFORK_SIZE(ip, whichfork), KM_SLEEP); if (whichfork == XFS_DATA_FORK) @@ -174,9 +176,9 @@ xfs_inode_item_format_extents( 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; + len = xfs_iextents_copy(ip, ext_buffer, whichfork); + xlog_copy_iovec(vecp, type, ext_buffer, len); + return len; } /* @@ -207,10 +209,10 @@ xfs_inode_item_format_v1_inode( } } -STATIC struct xfs_log_iovec * +STATIC void xfs_inode_item_format_data_fork( struct xfs_inode_log_item *iip, - struct xfs_log_iovec *vecp, + struct xfs_log_iovec **vecp, int *nvecs) { struct xfs_inode *ip = iip->ili_inode; @@ -237,18 +239,18 @@ xfs_inode_item_format_data_fork( * 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; + xlog_copy_iovec(vecp, XLOG_REG_TYPE_IEXT, + ip->i_df.if_u1.if_extents, + ip->i_df.if_bytes); + iip->ili_format.ilf_dsize = ip->i_df.if_bytes; } else #endif { - xfs_inode_item_format_extents(ip, vecp, - XFS_DATA_FORK, XLOG_REG_TYPE_IEXT); + iip->ili_format.ilf_dsize = + xfs_inode_item_format_extents(ip, vecp, + XFS_DATA_FORK, XLOG_REG_TYPE_IEXT); + ASSERT(iip->ili_format.ilf_dsize <= ip->i_df.if_bytes); } - ASSERT(vecp->i_len <= ip->i_df.if_bytes); - iip->ili_format.ilf_dsize = vecp->i_len; - vecp++; (*nvecs)++; } else { iip->ili_fields &= ~XFS_ILOG_DEXT; @@ -262,10 +264,9 @@ xfs_inode_item_format_data_fork( 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++; + xlog_copy_iovec(vecp, XLOG_REG_TYPE_IBROOT, + ip->i_df.if_broot, + ip->i_df.if_broot_bytes); (*nvecs)++; iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; } else { @@ -280,21 +281,18 @@ xfs_inode_item_format_data_fork( XFS_ILOG_DEV | XFS_ILOG_UUID); if ((iip->ili_fields & XFS_ILOG_DDATA) && ip->i_df.if_bytes > 0) { - 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 * to be there by xfs_idata_realloc(). */ 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++; + ASSERT(ip->i_df.if_real_bytes == 0 || + ip->i_df.if_real_bytes == data_bytes); + ASSERT(ip->i_df.if_u1.if_data != NULL); + ASSERT(ip->i_d.di_size > 0); + xlog_copy_iovec(vecp, XLOG_REG_TYPE_ILOCAL, + ip->i_df.if_u1.if_data, data_bytes); (*nvecs)++; iip->ili_format.ilf_dsize = (unsigned)data_bytes; } else { @@ -323,14 +321,12 @@ xfs_inode_item_format_data_fork( ASSERT(0); break; } - - return vecp; } -STATIC struct xfs_log_iovec * +STATIC void xfs_inode_item_format_attr_fork( struct xfs_inode_log_item *iip, - struct xfs_log_iovec *vecp, + struct xfs_log_iovec **vecp, int *nvecs) { struct xfs_inode *ip = iip->ili_inode; @@ -352,16 +348,16 @@ xfs_inode_item_format_attr_fork( * 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; + xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_EXT, + ip->i_afp->if_u1.if_extents, + ip->i_afp->if_bytes); + iip->ili_format.ilf_asize = ip->i_afp->if_bytes; #else ASSERT(iip->ili_aextents_buf == NULL); - xfs_inode_item_format_extents(ip, vecp, + iip->ili_format.ilf_asize = + 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++; (*nvecs)++; } else { iip->ili_fields &= ~XFS_ILOG_AEXT; @@ -375,10 +371,9 @@ xfs_inode_item_format_attr_fork( 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++; + xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_BROOT, + ip->i_afp->if_broot, + ip->i_afp->if_broot_bytes); (*nvecs)++; iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; } else { @@ -391,20 +386,18 @@ xfs_inode_item_format_attr_fork( if ((iip->ili_fields & XFS_ILOG_ADATA) && 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 * to be there by xfs_idata_realloc(). */ 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++; + ASSERT(ip->i_afp->if_real_bytes == 0 || + ip->i_afp->if_real_bytes == data_bytes); + ASSERT(ip->i_afp->if_u1.if_data != NULL); + xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_LOCAL, + ip->i_afp->if_u1.if_data, + data_bytes); (*nvecs)++; iip->ili_format.ilf_asize = (unsigned)data_bytes; } else { @@ -415,8 +408,6 @@ xfs_inode_item_format_attr_fork( ASSERT(0); break; } - - return vecp; } /* @@ -435,24 +426,22 @@ xfs_inode_item_format( struct xfs_inode *ip = iip->ili_inode; uint nvecs; - 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; + xlog_copy_iovec(&vecp, XLOG_REG_TYPE_IFORMAT, + &iip->ili_format, + sizeof(struct xfs_inode_log_format)); + 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++; + xlog_copy_iovec(&vecp, XLOG_REG_TYPE_ICORE, + &ip->i_d, + xfs_icdinode_size(ip->i_d.di_version)); nvecs++; if (ip->i_d.di_version == 1) xfs_inode_item_format_v1_inode(ip); - vecp = xfs_inode_item_format_data_fork(iip, vecp, &nvecs); + xfs_inode_item_format_data_fork(iip, &vecp, &nvecs); if (XFS_IFORK_Q(ip)) { - vecp = xfs_inode_item_format_attr_fork(iip, vecp, &nvecs); + xfs_inode_item_format_attr_fork(iip, &vecp, &nvecs); } else { iip->ili_fields &= ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); -- cgit v1.2.2 From bde7cff67c39227c6ad503394e19e58debdbc5e3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Dec 2013 11:34:02 +1100 Subject: 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 Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_inode_item.c | 92 ++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 47 deletions(-) (limited to 'fs/xfs/xfs_inode_item.c') 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( STATIC int xfs_inode_item_format_extents( struct xfs_inode *ip, + struct xfs_log_vec *lv, struct xfs_log_iovec **vecp, int whichfork, int type) @@ -177,7 +178,7 @@ xfs_inode_item_format_extents( ip->i_itemp->ili_aextents_buf = ext_buffer; len = xfs_iextents_copy(ip, ext_buffer, whichfork); - xlog_copy_iovec(vecp, type, ext_buffer, len); + xlog_copy_iovec(lv, vecp, type, ext_buffer, len); return len; } @@ -212,8 +213,9 @@ xfs_inode_item_format_v1_inode( STATIC void xfs_inode_item_format_data_fork( struct xfs_inode_log_item *iip, - struct xfs_log_iovec **vecp, - int *nvecs) + struct xfs_inode_log_format *ilf, + struct xfs_log_vec *lv, + struct xfs_log_iovec **vecp) { struct xfs_inode *ip = iip->ili_inode; size_t data_bytes; @@ -239,19 +241,19 @@ xfs_inode_item_format_data_fork( * extents, so just point to the * real extents array. */ - xlog_copy_iovec(vecp, XLOG_REG_TYPE_IEXT, + xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IEXT, ip->i_df.if_u1.if_extents, ip->i_df.if_bytes); - iip->ili_format.ilf_dsize = ip->i_df.if_bytes; + ilf->ilf_dsize = ip->i_df.if_bytes; } else #endif { - iip->ili_format.ilf_dsize = - xfs_inode_item_format_extents(ip, vecp, + ilf->ilf_dsize = + xfs_inode_item_format_extents(ip, lv, vecp, XFS_DATA_FORK, XLOG_REG_TYPE_IEXT); ASSERT(iip->ili_format.ilf_dsize <= ip->i_df.if_bytes); } - (*nvecs)++; + ilf->ilf_size++; } else { iip->ili_fields &= ~XFS_ILOG_DEXT; } @@ -264,11 +266,11 @@ xfs_inode_item_format_data_fork( if ((iip->ili_fields & XFS_ILOG_DBROOT) && ip->i_df.if_broot_bytes > 0) { ASSERT(ip->i_df.if_broot != NULL); - xlog_copy_iovec(vecp, XLOG_REG_TYPE_IBROOT, + xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IBROOT, ip->i_df.if_broot, ip->i_df.if_broot_bytes); - (*nvecs)++; - iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; + ilf->ilf_dsize = ip->i_df.if_broot_bytes; + ilf->ilf_size++; } else { ASSERT(!(iip->ili_fields & XFS_ILOG_DBROOT)); @@ -291,10 +293,10 @@ xfs_inode_item_format_data_fork( ip->i_df.if_real_bytes == data_bytes); ASSERT(ip->i_df.if_u1.if_data != NULL); ASSERT(ip->i_d.di_size > 0); - xlog_copy_iovec(vecp, XLOG_REG_TYPE_ILOCAL, + xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_ILOCAL, ip->i_df.if_u1.if_data, data_bytes); - (*nvecs)++; - iip->ili_format.ilf_dsize = (unsigned)data_bytes; + ilf->ilf_dsize = (unsigned)data_bytes; + ilf->ilf_size++; } else { iip->ili_fields &= ~XFS_ILOG_DDATA; } @@ -303,19 +305,15 @@ xfs_inode_item_format_data_fork( 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: ASSERT(0); @@ -326,8 +324,9 @@ xfs_inode_item_format_data_fork( STATIC void xfs_inode_item_format_attr_fork( struct xfs_inode_log_item *iip, - struct xfs_log_iovec **vecp, - int *nvecs) + struct xfs_inode_log_format *ilf, + struct xfs_log_vec *lv, + struct xfs_log_iovec **vecp) { struct xfs_inode *ip = iip->ili_inode; size_t data_bytes; @@ -348,17 +347,17 @@ xfs_inode_item_format_attr_fork( * There are not delayed allocation extents * for attributes, so just point at the array. */ - xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_EXT, + xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT, ip->i_afp->if_u1.if_extents, ip->i_afp->if_bytes); - iip->ili_format.ilf_asize = ip->i_afp->if_bytes; + ilf->ilf_asize = ip->i_afp->if_bytes; #else ASSERT(iip->ili_aextents_buf == NULL); - iip->ili_format.ilf_asize = - xfs_inode_item_format_extents(ip, vecp, + ilf->ilf_asize = + xfs_inode_item_format_extents(ip, lv, vecp, XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT); #endif - (*nvecs)++; + ilf->ilf_size++; } else { iip->ili_fields &= ~XFS_ILOG_AEXT; } @@ -371,11 +370,11 @@ xfs_inode_item_format_attr_fork( ip->i_afp->if_broot_bytes > 0) { ASSERT(ip->i_afp->if_broot != NULL); - xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_BROOT, + xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_BROOT, ip->i_afp->if_broot, ip->i_afp->if_broot_bytes); - (*nvecs)++; - iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; + ilf->ilf_asize = ip->i_afp->if_broot_bytes; + ilf->ilf_size++; } else { iip->ili_fields &= ~XFS_ILOG_ABROOT; } @@ -395,11 +394,11 @@ xfs_inode_item_format_attr_fork( ASSERT(ip->i_afp->if_real_bytes == 0 || ip->i_afp->if_real_bytes == data_bytes); ASSERT(ip->i_afp->if_u1.if_data != NULL); - xlog_copy_iovec(vecp, XLOG_REG_TYPE_IATTR_LOCAL, + xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_LOCAL, ip->i_afp->if_u1.if_data, data_bytes); - (*nvecs)++; - iip->ili_format.ilf_asize = (unsigned)data_bytes; + ilf->ilf_asize = (unsigned)data_bytes; + ilf->ilf_size++; } else { iip->ili_fields &= ~XFS_ILOG_ADATA; } @@ -420,28 +419,28 @@ xfs_inode_item_format_attr_fork( 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; - uint nvecs; + struct xfs_inode_log_format *ilf; + struct xfs_log_iovec *vecp = NULL; - xlog_copy_iovec(&vecp, XLOG_REG_TYPE_IFORMAT, + ilf = xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT, &iip->ili_format, sizeof(struct xfs_inode_log_format)); - nvecs = 1; - - xlog_copy_iovec(&vecp, XLOG_REG_TYPE_ICORE, - &ip->i_d, - xfs_icdinode_size(ip->i_d.di_version)); - nvecs++; + ilf->ilf_size = 1; if (ip->i_d.di_version == 1) xfs_inode_item_format_v1_inode(ip); + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE, + &ip->i_d, + xfs_icdinode_size(ip->i_d.di_version)); + ilf->ilf_size++; - xfs_inode_item_format_data_fork(iip, &vecp, &nvecs); + xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp); if (XFS_IFORK_Q(ip)) { - xfs_inode_item_format_attr_fork(iip, &vecp, &nvecs); + xfs_inode_item_format_attr_fork(iip, ilf, lv, &vecp); } else { iip->ili_fields &= ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); @@ -455,7 +454,6 @@ xfs_inode_item_format( */ iip->ili_format.ilf_fields = XFS_ILOG_CORE | (iip->ili_fields & ~XFS_ILOG_TIMESTAMP); - iip->ili_format.ilf_size = nvecs; } /* -- cgit v1.2.2 From da7765031de15273d370d18a5354e1d8001ce2a9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Dec 2013 11:34:04 +1100 Subject: xfs: format logged extents directly into the CIL With the new iop_format scheme there is no need to have a temporary buffer to format logged extents into, we can do so directly into the CIL. This also allows to remove the shortcut for big endian systems that probably hasn't gotten a lot of test coverage for a long time. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_inode_item.c | 113 ++++++++---------------------------------------- 1 file changed, 18 insertions(+), 95 deletions(-) (limited to 'fs/xfs/xfs_inode_item.c') diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 6ab318f80c96..45224d28049e 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -145,43 +145,6 @@ xfs_inode_item_size( xfs_inode_item_attr_fork_size(iip, nvecs, nbytes); } -/* - * 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 int -xfs_inode_item_format_extents( - struct xfs_inode *ip, - struct xfs_log_vec *lv, - struct xfs_log_iovec **vecp, - int whichfork, - int type) -{ - xfs_bmbt_rec_t *ext_buffer; - int len; - - 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; - - len = xfs_iextents_copy(ip, ext_buffer, whichfork); - xlog_copy_iovec(lv, vecp, type, ext_buffer, len); - return len; -} - /* * If this is a v1 format inode, then we need to log it as such. This means * that we have to copy the link count from the new field to the old. We @@ -229,30 +192,18 @@ xfs_inode_item_format_data_fork( if ((iip->ili_fields & XFS_ILOG_DEXT) && ip->i_d.di_nextents > 0 && ip->i_df.if_bytes > 0) { + struct xfs_bmbt_rec *p; + 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. - */ - xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IEXT, - ip->i_df.if_u1.if_extents, - ip->i_df.if_bytes); - ilf->ilf_dsize = ip->i_df.if_bytes; - } else -#endif - { - ilf->ilf_dsize = - xfs_inode_item_format_extents(ip, lv, vecp, - XFS_DATA_FORK, XLOG_REG_TYPE_IEXT); - ASSERT(iip->ili_format.ilf_dsize <= ip->i_df.if_bytes); - } + + p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IEXT); + data_bytes = xfs_iextents_copy(ip, p, XFS_DATA_FORK); + xlog_finish_iovec(lv, *vecp, data_bytes); + + ASSERT(data_bytes <= ip->i_df.if_bytes); + + ilf->ilf_dsize = data_bytes; ilf->ilf_size++; } else { iip->ili_fields &= ~XFS_ILOG_DEXT; @@ -339,24 +290,17 @@ xfs_inode_item_format_attr_fork( if ((iip->ili_fields & XFS_ILOG_AEXT) && ip->i_d.di_anextents > 0 && ip->i_afp->if_bytes > 0) { + struct xfs_bmbt_rec *p; + 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. - */ - xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT, - ip->i_afp->if_u1.if_extents, - ip->i_afp->if_bytes); - ilf->ilf_asize = ip->i_afp->if_bytes; -#else - ASSERT(iip->ili_aextents_buf == NULL); - ilf->ilf_asize = - xfs_inode_item_format_extents(ip, lv, vecp, - XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT); -#endif + + p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT); + data_bytes = xfs_iextents_copy(ip, p, XFS_ATTR_FORK); + xlog_finish_iovec(lv, *vecp, data_bytes); + + ilf->ilf_asize = data_bytes; ilf->ilf_size++; } else { iip->ili_fields &= ~XFS_ILOG_AEXT; @@ -571,27 +515,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) -- cgit v1.2.2 From 2f251293b09065118d78ae4e883e5639cc22f94e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Dec 2013 11:34:05 +1100 Subject: xfs: remove the inode log format from the inode log item No need to keep the inode log format around all the time, we can easily generate it at iop_format time. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_inode_item.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'fs/xfs/xfs_inode_item.c') diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 45224d28049e..686889b4a1e5 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -370,17 +370,21 @@ xfs_inode_item_format( struct xfs_inode_log_format *ilf; struct xfs_log_iovec *vecp = NULL; - ilf = xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT, - &iip->ili_format, - sizeof(struct xfs_inode_log_format)); - ilf->ilf_size = 1; + ilf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT); + ilf->ilf_type = XFS_LI_INODE; + ilf->ilf_ino = ip->i_ino; + ilf->ilf_blkno = ip->i_imap.im_blkno; + ilf->ilf_len = ip->i_imap.im_len; + ilf->ilf_boffset = ip->i_imap.im_boffset; + ilf->ilf_fields = XFS_ILOG_CORE; + ilf->ilf_size = 2; /* format + core */ + xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format)); if (ip->i_d.di_version == 1) xfs_inode_item_format_v1_inode(ip); xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE, &ip->i_d, xfs_icdinode_size(ip->i_d.di_version)); - ilf->ilf_size++; xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp); if (XFS_IFORK_Q(ip)) { @@ -390,14 +394,8 @@ xfs_inode_item_format( ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); } - /* - * 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 | - (iip->ili_fields & ~XFS_ILOG_TIMESTAMP); + /* update the format with the exact fields we actually logged */ + ilf->ilf_fields |= (iip->ili_fields & ~XFS_ILOG_TIMESTAMP); } /* @@ -601,11 +599,6 @@ xfs_inode_item_init( iip->ili_inode = ip; xfs_log_item_init(mp, &iip->ili_item, XFS_LI_INODE, &xfs_inode_item_ops); - iip->ili_format.ilf_type = XFS_LI_INODE; - iip->ili_format.ilf_ino = ip->i_ino; - iip->ili_format.ilf_blkno = ip->i_imap.im_blkno; - iip->ili_format.ilf_len = ip->i_imap.im_len; - iip->ili_format.ilf_boffset = ip->i_imap.im_boffset; } /* -- cgit v1.2.2