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 <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
Christoph Hellwig 2013-12-13 11:00:43 +11:00 committed by Dave Chinner
parent ce9641d6c9
commit 3de559fbd0
1 changed files with 90 additions and 77 deletions

View File

@ -180,63 +180,41 @@ xfs_inode_item_format_extents(
} }
/* /*
* This is called to fill in the vector of log iovecs for the * If this is a v1 format inode, then we need to log it as such. This means
* given inode log item. It fills the first item with an inode * that we have to copy the link count from the new field to the old. We
* log format structure, the second with the on-disk inode structure, * don't have to worry about the new fields, because nothing trusts them as
* and a possible third and/or fourth with the inode data/extents/b-tree * long as the old inode version number is there.
* root and inode attributes data/extents/b-tree root.
*/ */
STATIC void STATIC void
xfs_inode_item_format( xfs_inode_item_format_v1_inode(
struct xfs_log_item *lip, struct xfs_inode *ip)
struct xfs_log_iovec *vecp)
{ {
struct xfs_inode_log_item *iip = INODE_ITEM(lip); if (!xfs_sb_version_hasnlink(&ip->i_mount->m_sb)) {
struct xfs_inode *ip = iip->ili_inode; /*
uint nvecs; * Convert it back.
size_t data_bytes; */
xfs_mount_t *mp; ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
ip->i_d.di_onlink = ip->i_d.di_nlink;
vecp->i_addr = &iip->ili_format; } else {
vecp->i_len = sizeof(xfs_inode_log_format_t); /*
vecp->i_type = XLOG_REG_TYPE_IFORMAT; * The superblock version has already been bumped,
vecp++; * so just make the conversion to the new inode
nvecs = 1; * format permanent.
*/
vecp->i_addr = &ip->i_d; ip->i_d.di_version = 2;
vecp->i_len = xfs_icdinode_size(ip->i_d.di_version); ip->i_d.di_onlink = 0;
vecp->i_type = XLOG_REG_TYPE_ICORE; memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
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));
}
} }
}
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 *ip = iip->ili_inode;
size_t data_bytes;
switch (ip->i_d.di_format) { switch (ip->i_d.di_format) {
case XFS_DINODE_FMT_EXTENTS: case XFS_DINODE_FMT_EXTENTS:
@ -271,12 +249,11 @@ xfs_inode_item_format(
ASSERT(vecp->i_len <= ip->i_df.if_bytes); ASSERT(vecp->i_len <= ip->i_df.if_bytes);
iip->ili_format.ilf_dsize = vecp->i_len; iip->ili_format.ilf_dsize = vecp->i_len;
vecp++; vecp++;
nvecs++; (*nvecs)++;
} else { } else {
iip->ili_fields &= ~XFS_ILOG_DEXT; iip->ili_fields &= ~XFS_ILOG_DEXT;
} }
break; break;
case XFS_DINODE_FMT_BTREE: case XFS_DINODE_FMT_BTREE:
iip->ili_fields &= iip->ili_fields &=
~(XFS_ILOG_DDATA | XFS_ILOG_DEXT | ~(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_len = ip->i_df.if_broot_bytes;
vecp->i_type = XLOG_REG_TYPE_IBROOT; vecp->i_type = XLOG_REG_TYPE_IBROOT;
vecp++; vecp++;
nvecs++; (*nvecs)++;
iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes;
} else { } else {
ASSERT(!(iip->ili_fields & ASSERT(!(iip->ili_fields &
@ -297,7 +274,6 @@ xfs_inode_item_format(
iip->ili_fields &= ~XFS_ILOG_DBROOT; iip->ili_fields &= ~XFS_ILOG_DBROOT;
} }
break; break;
case XFS_DINODE_FMT_LOCAL: case XFS_DINODE_FMT_LOCAL:
iip->ili_fields &= iip->ili_fields &=
~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT | ~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT |
@ -319,13 +295,12 @@ xfs_inode_item_format(
vecp->i_len = (int)data_bytes; vecp->i_len = (int)data_bytes;
vecp->i_type = XLOG_REG_TYPE_ILOCAL; vecp->i_type = XLOG_REG_TYPE_ILOCAL;
vecp++; vecp++;
nvecs++; (*nvecs)++;
iip->ili_format.ilf_dsize = (unsigned)data_bytes; iip->ili_format.ilf_dsize = (unsigned)data_bytes;
} else { } else {
iip->ili_fields &= ~XFS_ILOG_DDATA; iip->ili_fields &= ~XFS_ILOG_DDATA;
} }
break; break;
case XFS_DINODE_FMT_DEV: case XFS_DINODE_FMT_DEV:
iip->ili_fields &= iip->ili_fields &=
~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
@ -335,7 +310,6 @@ xfs_inode_item_format(
ip->i_df.if_u2.if_rdev; ip->i_df.if_u2.if_rdev;
} }
break; break;
case XFS_DINODE_FMT_UUID: case XFS_DINODE_FMT_UUID:
iip->ili_fields &= iip->ili_fields &=
~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
@ -345,20 +319,22 @@ xfs_inode_item_format(
ip->i_df.if_u2.if_uuid; ip->i_df.if_u2.if_uuid;
} }
break; break;
default: default:
ASSERT(0); ASSERT(0);
break; break;
} }
/* return vecp;
* If there are no attributes associated with the file, then we're done. }
*/
if (!XFS_IFORK_Q(ip)) { STATIC struct xfs_log_iovec *
iip->ili_fields &= xfs_inode_item_format_attr_fork(
~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); struct xfs_inode_log_item *iip,
goto out; struct xfs_log_iovec *vecp,
} int *nvecs)
{
struct xfs_inode *ip = iip->ili_inode;
size_t data_bytes;
switch (ip->i_d.di_aformat) { switch (ip->i_d.di_aformat) {
case XFS_DINODE_FMT_EXTENTS: case XFS_DINODE_FMT_EXTENTS:
@ -386,12 +362,11 @@ xfs_inode_item_format(
#endif #endif
iip->ili_format.ilf_asize = vecp->i_len; iip->ili_format.ilf_asize = vecp->i_len;
vecp++; vecp++;
nvecs++; (*nvecs)++;
} else { } else {
iip->ili_fields &= ~XFS_ILOG_AEXT; iip->ili_fields &= ~XFS_ILOG_AEXT;
} }
break; break;
case XFS_DINODE_FMT_BTREE: case XFS_DINODE_FMT_BTREE:
iip->ili_fields &= iip->ili_fields &=
~(XFS_ILOG_ADATA | XFS_ILOG_AEXT); ~(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_len = ip->i_afp->if_broot_bytes;
vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT; vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT;
vecp++; vecp++;
nvecs++; (*nvecs)++;
iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes;
} else { } else {
iip->ili_fields &= ~XFS_ILOG_ABROOT; iip->ili_fields &= ~XFS_ILOG_ABROOT;
} }
break; break;
case XFS_DINODE_FMT_LOCAL: case XFS_DINODE_FMT_LOCAL:
iip->ili_fields &= iip->ili_fields &=
~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT); ~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT);
@ -431,19 +405,59 @@ xfs_inode_item_format(
vecp->i_len = (int)data_bytes; vecp->i_len = (int)data_bytes;
vecp->i_type = XLOG_REG_TYPE_IATTR_LOCAL; vecp->i_type = XLOG_REG_TYPE_IATTR_LOCAL;
vecp++; vecp++;
nvecs++; (*nvecs)++;
iip->ili_format.ilf_asize = (unsigned)data_bytes; iip->ili_format.ilf_asize = (unsigned)data_bytes;
} else { } else {
iip->ili_fields &= ~XFS_ILOG_ADATA; iip->ili_fields &= ~XFS_ILOG_ADATA;
} }
break; break;
default: default:
ASSERT(0); ASSERT(0);
break; 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 * 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 * values. We always write the inode core to make the arithmetic
@ -455,7 +469,6 @@ out:
iip->ili_format.ilf_size = nvecs; iip->ili_format.ilf_size = nvecs;
} }
/* /*
* This is called to pin the inode associated with the inode log * This is called to pin the inode associated with the inode log
* item in memory so it cannot be written out. * item in memory so it cannot be written out.