Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu
[safe/jmp/linux-2.6] / fs / xfs / xfs_inode_item.c
index 2caa91b..9794b87 100644 (file)
@@ -25,7 +25,6 @@
 #include "xfs_buf_item.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -33,7 +32,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -42,6 +40,7 @@
 #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 */
@@ -233,6 +232,15 @@ xfs_inode_item_format(
        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.
@@ -264,20 +272,12 @@ xfs_inode_item_format(
        }
 
        /*
-        * 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.
-        */
-       if (ip->i_update_size)
-               ip->i_update_size = 0;
-
-       /*
-        * Make sure to get the latest atime from the Linux inode.
+        * Make sure to get the latest timestamps 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++;
@@ -292,10 +292,9 @@ 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 == 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.
                         */
@@ -307,7 +306,7 @@ xfs_inode_item_format(
                         * 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));
                }
@@ -543,7 +542,7 @@ STATIC void
 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);
 }
 
@@ -617,7 +616,7 @@ xfs_inode_item_trylock(
                        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);
@@ -660,13 +659,13 @@ xfs_inode_item_unlock(
 
        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.
         */
@@ -682,7 +681,7 @@ xfs_inode_item_unlock(
                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) {
@@ -690,7 +689,7 @@ xfs_inode_item_unlock(
                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;
        }
 
@@ -709,8 +708,6 @@ xfs_inode_item_unlock(
         * 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;
 
        /*
@@ -745,28 +742,13 @@ xfs_inode_item_committed(
 }
 
 /*
- * The transaction with the inode locked has aborted.  The inode
- * must not be dirty within the transaction (unless we're forcibly
- * shutting down).  We simply unlock just as if the transaction
- * had been cancelled.
- */
-STATIC void
-xfs_inode_item_abort(
-       xfs_inode_log_item_t    *iip)
-{
-       xfs_inode_item_unlock(iip);
-       return;
-}
-
-
-/*
  * This gets called by xfs_trans_push_ail(), when IOP_TRYLOCK
  * failed to get the inode flush lock but did get the inode locked SHARED.
  * Here we're trying to see if the inode buffer is incore, and if so whether it's
  * 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
@@ -780,7 +762,7 @@ xfs_inode_item_pushbuf(
 
        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
@@ -790,11 +772,10 @@ xfs_inode_item_pushbuf(
        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);
@@ -809,14 +790,14 @@ xfs_inode_item_pushbuf(
                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);
@@ -825,7 +806,12 @@ xfs_inode_item_pushbuf(
                                              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);
                        }
@@ -863,8 +849,8 @@ xfs_inode_item_push(
 
        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
@@ -904,7 +890,7 @@ xfs_inode_item_committing(
 /*
  * This is the ops vector shared by all buf log items.
  */
-STATIC struct xfs_item_ops xfs_inode_item_ops = {
+static struct xfs_item_ops xfs_inode_item_ops = {
        .iop_size       = (uint(*)(xfs_log_item_t*))xfs_inode_item_size,
        .iop_format     = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
                                        xfs_inode_item_format,
@@ -917,7 +903,6 @@ STATIC struct xfs_item_ops xfs_inode_item_ops = {
        .iop_committed  = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_inode_item_committed,
        .iop_push       = (void(*)(xfs_log_item_t*))xfs_inode_item_push,
-       .iop_abort      = (void(*)(xfs_log_item_t*))xfs_inode_item_abort,
        .iop_pushbuf    = (void(*)(xfs_log_item_t*))xfs_inode_item_pushbuf,
        .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_inode_item_committing
@@ -940,6 +925,7 @@ xfs_inode_item_init(
        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;
 
        /*
@@ -950,9 +936,9 @@ xfs_inode_item_init(
 
        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;
 }
 
 /*
@@ -964,8 +950,7 @@ xfs_inode_item_destroy(
 {
 #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);
@@ -985,10 +970,8 @@ xfs_iflush_done(
        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
@@ -1001,15 +984,12 @@ xfs_iflush_done(
         */
        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);
                }
        }
 
@@ -1041,23 +1021,20 @@ void
 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;
                /*