Skip to content

Commit

Permalink
xfs: split in-core and on-disk inode log item fields
Browse files Browse the repository at this point in the history
Add a new ili_fields member to the inode log item to isolate the in-memory
flags from the ones that actually go to the log.  This will allow tracking
timestamp-only updates for fdatasync and O_DSYNC in the next patch and
prepares for divorcing the on-disk log format from the in-memory log item
a little further down the road.

Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
  • Loading branch information
Christoph Hellwig authored and Ben Myers committed Mar 13, 2012
1 parent 339a5f5 commit f5d8d5c
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 92 deletions.
24 changes: 11 additions & 13 deletions fs/xfs/xfs_dfrag.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ xfs_swap_extents(
xfs_trans_t *tp;
xfs_bstat_t *sbp = &sxp->sx_stat;
xfs_ifork_t *tempifp, *ifp, *tifp;
int ilf_fields, tilf_fields;
int src_log_flags, target_log_flags;
int error = 0;
int aforkblks = 0;
int taforkblks = 0;
Expand Down Expand Up @@ -385,9 +385,8 @@ xfs_swap_extents(
tip->i_delayed_blks = ip->i_delayed_blks;
ip->i_delayed_blks = 0;

ilf_fields = XFS_ILOG_CORE;

switch(ip->i_d.di_format) {
src_log_flags = XFS_ILOG_CORE;
switch (ip->i_d.di_format) {
case XFS_DINODE_FMT_EXTENTS:
/* If the extents fit in the inode, fix the
* pointer. Otherwise it's already NULL or
Expand All @@ -397,16 +396,15 @@ xfs_swap_extents(
ifp->if_u1.if_extents =
ifp->if_u2.if_inline_ext;
}
ilf_fields |= XFS_ILOG_DEXT;
src_log_flags |= XFS_ILOG_DEXT;
break;
case XFS_DINODE_FMT_BTREE:
ilf_fields |= XFS_ILOG_DBROOT;
src_log_flags |= XFS_ILOG_DBROOT;
break;
}

tilf_fields = XFS_ILOG_CORE;

switch(tip->i_d.di_format) {
target_log_flags = XFS_ILOG_CORE;
switch (tip->i_d.di_format) {
case XFS_DINODE_FMT_EXTENTS:
/* If the extents fit in the inode, fix the
* pointer. Otherwise it's already NULL or
Expand All @@ -416,19 +414,19 @@ xfs_swap_extents(
tifp->if_u1.if_extents =
tifp->if_u2.if_inline_ext;
}
tilf_fields |= XFS_ILOG_DEXT;
target_log_flags |= XFS_ILOG_DEXT;
break;
case XFS_DINODE_FMT_BTREE:
tilf_fields |= XFS_ILOG_DBROOT;
target_log_flags |= XFS_ILOG_DBROOT;
break;
}


xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);

xfs_trans_log_inode(tp, ip, ilf_fields);
xfs_trans_log_inode(tp, tip, tilf_fields);
xfs_trans_log_inode(tp, ip, src_log_flags);
xfs_trans_log_inode(tp, tip, target_log_flags);

/*
* If this is a synchronous mount, make sure that the
Expand Down
69 changes: 33 additions & 36 deletions fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1661,8 +1661,8 @@ xfs_ifree_cluster(
continue;
}

iip->ili_last_fields = iip->ili_format.ilf_fields;
iip->ili_format.ilf_fields = 0;
iip->ili_last_fields = iip->ili_fields;
iip->ili_fields = 0;
iip->ili_logged = 1;
xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn,
&iip->ili_item.li_lsn);
Expand Down Expand Up @@ -2176,7 +2176,7 @@ xfs_iflush_fork(
mp = ip->i_mount;
switch (XFS_IFORK_FORMAT(ip, whichfork)) {
case XFS_DINODE_FMT_LOCAL:
if ((iip->ili_format.ilf_fields & dataflag[whichfork]) &&
if ((iip->ili_fields & dataflag[whichfork]) &&
(ifp->if_bytes > 0)) {
ASSERT(ifp->if_u1.if_data != NULL);
ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
Expand All @@ -2186,8 +2186,8 @@ xfs_iflush_fork(

case XFS_DINODE_FMT_EXTENTS:
ASSERT((ifp->if_flags & XFS_IFEXTENTS) ||
!(iip->ili_format.ilf_fields & extflag[whichfork]));
if ((iip->ili_format.ilf_fields & extflag[whichfork]) &&
!(iip->ili_fields & extflag[whichfork]));
if ((iip->ili_fields & extflag[whichfork]) &&
(ifp->if_bytes > 0)) {
ASSERT(xfs_iext_get_ext(ifp, 0));
ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
Expand All @@ -2197,7 +2197,7 @@ xfs_iflush_fork(
break;

case XFS_DINODE_FMT_BTREE:
if ((iip->ili_format.ilf_fields & brootflag[whichfork]) &&
if ((iip->ili_fields & brootflag[whichfork]) &&
(ifp->if_broot_bytes > 0)) {
ASSERT(ifp->if_broot != NULL);
ASSERT(ifp->if_broot_bytes <=
Expand All @@ -2210,14 +2210,14 @@ xfs_iflush_fork(
break;

case XFS_DINODE_FMT_DEV:
if (iip->ili_format.ilf_fields & XFS_ILOG_DEV) {
if (iip->ili_fields & XFS_ILOG_DEV) {
ASSERT(whichfork == XFS_DATA_FORK);
xfs_dinode_put_rdev(dip, ip->i_df.if_u2.if_rdev);
}
break;

case XFS_DINODE_FMT_UUID:
if (iip->ili_format.ilf_fields & XFS_ILOG_UUID) {
if (iip->ili_fields & XFS_ILOG_UUID) {
ASSERT(whichfork == XFS_DATA_FORK);
memcpy(XFS_DFORK_DPTR(dip),
&ip->i_df.if_u2.if_uuid,
Expand Down Expand Up @@ -2451,7 +2451,7 @@ xfs_iflush(
*/
if (XFS_FORCED_SHUTDOWN(mp)) {
if (iip)
iip->ili_format.ilf_fields = 0;
iip->ili_fields = 0;
xfs_ifunlock(ip);
return XFS_ERROR(EIO);
}
Expand Down Expand Up @@ -2641,36 +2641,33 @@ xfs_iflush_int(
xfs_inobp_check(mp, bp);

/*
* We've recorded everything logged in the inode, so we'd
* like to clear the ilf_fields bits so we don't log and
* flush things unnecessarily. However, we can't stop
* logging all this information until the data we've copied
* into the disk buffer is written to disk. If we did we might
* overwrite the copy of the inode in the log with all the
* data after re-logging only part of it, and in the face of
* a crash we wouldn't have all the data we need to recover.
* We've recorded everything logged in the inode, so we'd like to clear
* the ili_fields bits so we don't log and flush things unnecessarily.
* However, we can't stop logging all this information until the data
* we've copied into the disk buffer is written to disk. If we did we
* might overwrite the copy of the inode in the log with all the data
* after re-logging only part of it, and in the face of a crash we
* wouldn't have all the data we need to recover.
*
* What we do is move the bits to the ili_last_fields field.
* When logging the inode, these bits are moved back to the
* ilf_fields field. In the xfs_iflush_done() routine we
* clear ili_last_fields, since we know that the information
* those bits represent is permanently on disk. As long as
* the flush completes before the inode is logged again, then
* both ilf_fields and ili_last_fields will be cleared.
* What we do is move the bits to the ili_last_fields field. When
* logging the inode, these bits are moved back to the ili_fields field.
* In the xfs_iflush_done() routine we clear ili_last_fields, since we
* know that the information those bits represent is permanently on
* disk. As long as the flush completes before the inode is logged
* again, then both ili_fields and ili_last_fields will be cleared.
*
* We can play with the ilf_fields bits here, because the inode
* lock must be held exclusively in order to set bits there
* and the flush lock protects the ili_last_fields bits.
* Set ili_logged so the flush done
* routine can tell whether or not to look in the AIL.
* Also, store the current LSN of the inode so that we can tell
* whether the item has moved in the AIL from xfs_iflush_done().
* In order to read the lsn we need the AIL lock, because
* it is a 64 bit value that cannot be read atomically.
* We can play with the ili_fields bits here, because the inode lock
* must be held exclusively in order to set bits there and the flush
* lock protects the ili_last_fields bits. Set ili_logged so the flush
* done routine can tell whether or not to look in the AIL. Also, store
* the current LSN of the inode so that we can tell whether the item has
* moved in the AIL from xfs_iflush_done(). In order to read the lsn we
* need the AIL lock, because it is a 64 bit value that cannot be read
* atomically.
*/
if (iip != NULL && iip->ili_format.ilf_fields != 0) {
iip->ili_last_fields = iip->ili_format.ilf_fields;
iip->ili_format.ilf_fields = 0;
if (iip != NULL && iip->ili_fields != 0) {
iip->ili_last_fields = iip->ili_fields;
iip->ili_fields = 0;
iip->ili_logged = 1;

xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn,
Expand Down
Loading

0 comments on commit f5d8d5c

Please sign in to comment.