#include "xfs_btree.h"
#include "xfs_ialloc.h"
#include "xfs_rw.h"
+#include "xfs_error.h"
kmem_zone_t *xfs_ili_zone; /* inode log item zone */
nvecs = 1;
/*
+ * Make sure the linux inode is dirty. We do this before
+ * clearing i_update_core as the VFS will call back into
+ * XFS here and set i_update_core, so we need to dirty the
+ * inode first so that the ordering of i_update_core and
+ * unlogged modifications still works as described below.
+ */
+ xfs_mark_inode_dirty_sync(ip);
+
+ /*
* Clear i_update_core if the timestamps (or any other
* non-transactional modification) need flushing/logging
* and we're about to log them with the rest of the core.
}
/*
- * We don't have to worry about re-ordering here because
- * the update_size field is protected by the inode lock
- * and we have that held in exclusive mode.
+ * Make sure to get the latest timestamps from the Linux inode.
*/
- if (ip->i_update_size)
- ip->i_update_size = 0;
-
- /*
- * Make sure to get the latest atime from the Linux inode.
- */
- xfs_synchronize_atime(ip);
+ xfs_synchronize_times(ip);
vecp->i_addr = (xfs_caddr_t)&ip->i_d;
- vecp->i_len = sizeof(xfs_dinode_core_t);
+ vecp->i_len = sizeof(struct xfs_icdinode);
XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE);
vecp++;
nvecs++;
* has a new version number, then we don't bother converting back.
*/
mp = ip->i_mount;
- ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1 ||
- XFS_SB_VERSION_HASNLINK(&mp->m_sb));
- if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {
- if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
+ 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.
*/
* so just make the conversion to the new inode
* format permanent.
*/
- ip->i_d.di_version = XFS_DINODE_VERSION_2;
+ 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));
}
xfs_inode_item_pin(
xfs_inode_log_item_t *iip)
{
- ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE));
+ ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
xfs_ipin(iip->ili_inode);
}
return XFS_ITEM_PUSHBUF;
} else {
/*
- * We hold the AIL_LOCK, so we must specify the
+ * We hold the AIL lock, so we must specify the
* NONOTIFY flag so that we won't double trip.
*/
xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY);
ASSERT(iip != NULL);
ASSERT(iip->ili_inode->i_itemp != NULL);
- ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE));
+ ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
ASSERT((!(iip->ili_inode->i_itemp->ili_flags &
XFS_ILI_IOLOCKED_EXCL)) ||
- ismrlocked(&(iip->ili_inode->i_iolock), MR_UPDATE));
+ xfs_isilocked(iip->ili_inode, XFS_IOLOCK_EXCL));
ASSERT((!(iip->ili_inode->i_itemp->ili_flags &
XFS_ILI_IOLOCKED_SHARED)) ||
- ismrlocked(&(iip->ili_inode->i_iolock), MR_ACCESS));
+ xfs_isilocked(iip->ili_inode, XFS_IOLOCK_SHARED));
/*
* Clear the transaction pointer in the inode.
*/
ASSERT(ip->i_d.di_nextents > 0);
ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_DEXT);
ASSERT(ip->i_df.if_bytes > 0);
- kmem_free(iip->ili_extents_buf, ip->i_df.if_bytes);
+ kmem_free(iip->ili_extents_buf);
iip->ili_extents_buf = NULL;
}
if (iip->ili_aextents_buf != NULL) {
ASSERT(ip->i_d.di_anextents > 0);
ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_AEXT);
ASSERT(ip->i_afp->if_bytes > 0);
- kmem_free(iip->ili_aextents_buf, ip->i_afp->if_bytes);
+ kmem_free(iip->ili_aextents_buf);
iip->ili_aextents_buf = NULL;
}
* Clear out the fields of the inode log item particular
* to the current transaction.
*/
- iip->ili_ilock_recur = 0;
- iip->ili_iolock_recur = 0;
iip->ili_flags = 0;
/*
* marked delayed write. If that's the case, we'll initiate a bawrite on that
* buffer to expedite the process.
*
- * We aren't holding the AIL_LOCK (or the flush lock) when this gets called,
+ * We aren't holding the AIL lock (or the flush lock) when this gets called,
* so it is inherently race-y.
*/
STATIC void
ip = iip->ili_inode;
- ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
/*
* The ili_pushbuf_flag keeps others from
ASSERT(iip->ili_push_owner == current_pid());
/*
- * If flushlock isn't locked anymore, chances are that the
- * inode flush completed and the inode was taken off the AIL.
- * So, just get out.
+ * If a flush is not in progress anymore, chances are that the
+ * inode was taken off the AIL. So, just get out.
*/
- if (!issemalocked(&(ip->i_flock)) ||
+ if (completion_done(&ip->i_flush) ||
((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) {
iip->ili_pushbuf_flag = 0;
xfs_iunlock(ip, XFS_ILOCK_SHARED);
if (XFS_BUF_ISDELAYWRITE(bp)) {
/*
* We were racing with iflush because we don't hold
- * the AIL_LOCK or the flush lock. However, at this point,
+ * the AIL lock or the flush lock. However, at this point,
* we have the buffer, and we know that it's dirty.
* So, it's possible that iflush raced with us, and
* this item is already taken off the AIL.
* If not, we can flush it async.
*/
dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) &&
- issemalocked(&(ip->i_flock)));
+ !completion_done(&ip->i_flush));
iip->ili_pushbuf_flag = 0;
xfs_iunlock(ip, XFS_ILOCK_SHARED);
xfs_buftrace("INODE ITEM PUSH", bp);
XFS_LOG_FORCE);
}
if (dopush) {
- xfs_bawrite(mp, bp);
+ int error;
+ error = xfs_bawrite(mp, bp);
+ if (error)
+ xfs_fs_cmn_err(CE_WARN, mp,
+ "xfs_inode_item_pushbuf: pushbuf error %d on iip %p, bp %p",
+ error, iip, bp);
} else {
xfs_buf_relse(bp);
}
ip = iip->ili_inode;
- ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
- ASSERT(issemalocked(&(ip->i_flock)));
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
+ ASSERT(!completion_done(&ip->i_flush));
/*
* Since we were able to lock the inode's flush lock and
* we found it on the AIL, the inode must be dirty. This
iip->ili_item.li_type = XFS_LI_INODE;
iip->ili_item.li_ops = &xfs_inode_item_ops;
iip->ili_item.li_mountp = mp;
+ iip->ili_item.li_ailp = mp->m_ail;
iip->ili_inode = ip;
/*
iip->ili_format.ilf_type = XFS_LI_INODE;
iip->ili_format.ilf_ino = ip->i_ino;
- iip->ili_format.ilf_blkno = ip->i_blkno;
- iip->ili_format.ilf_len = ip->i_len;
- iip->ili_format.ilf_boffset = ip->i_boffset;
+ 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;
}
/*
{
#ifdef XFS_TRANS_DEBUG
if (ip->i_itemp->ili_root_size != 0) {
- kmem_free(ip->i_itemp->ili_orig_root,
- ip->i_itemp->ili_root_size);
+ kmem_free(ip->i_itemp->ili_orig_root);
}
#endif
kmem_zone_free(xfs_ili_zone, ip->i_itemp);
xfs_buf_t *bp,
xfs_inode_log_item_t *iip)
{
- xfs_inode_t *ip;
- SPLDECL(s);
-
- ip = iip->ili_inode;
+ xfs_inode_t *ip = iip->ili_inode;
+ struct xfs_ail *ailp = iip->ili_item.li_ailp;
/*
* We only want to pull the item from the AIL if it is
*/
if (iip->ili_logged &&
(iip->ili_item.li_lsn == iip->ili_flush_lsn)) {
- AIL_LOCK(ip->i_mount, s);
+ spin_lock(&ailp->xa_lock);
if (iip->ili_item.li_lsn == iip->ili_flush_lsn) {
- /*
- * xfs_trans_delete_ail() drops the AIL lock.
- */
- xfs_trans_delete_ail(ip->i_mount,
- (xfs_log_item_t*)iip, s);
+ /* xfs_trans_ail_delete() drops the AIL lock. */
+ xfs_trans_ail_delete(ailp, (xfs_log_item_t*)iip);
} else {
- AIL_UNLOCK(ip->i_mount, s);
+ spin_unlock(&ailp->xa_lock);
}
}
xfs_iflush_abort(
xfs_inode_t *ip)
{
- xfs_inode_log_item_t *iip;
+ xfs_inode_log_item_t *iip = ip->i_itemp;
xfs_mount_t *mp;
- SPLDECL(s);
iip = ip->i_itemp;
mp = ip->i_mount;
if (iip) {
+ struct xfs_ail *ailp = iip->ili_item.li_ailp;
if (iip->ili_item.li_flags & XFS_LI_IN_AIL) {
- AIL_LOCK(mp, s);
+ spin_lock(&ailp->xa_lock);
if (iip->ili_item.li_flags & XFS_LI_IN_AIL) {
- /*
- * xfs_trans_delete_ail() drops the AIL lock.
- */
- xfs_trans_delete_ail(mp, (xfs_log_item_t *)iip,
- s);
+ /* xfs_trans_ail_delete() drops the AIL lock. */
+ xfs_trans_ail_delete(ailp, (xfs_log_item_t *)iip);
} else
- AIL_UNLOCK(mp, s);
+ spin_unlock(&ailp->xa_lock);
}
iip->ili_logged = 0;
/*