xfs: cleanup xfs_iunpin_wait/xfs_iunpin_nowait
[safe/jmp/linux-2.6] / fs / xfs / xfs_inode.c
index c1dc7ef..16c3968 100644 (file)
 #include "xfs_rw.h"
 #include "xfs_error.h"
 #include "xfs_utils.h"
-#include "xfs_dir2_trace.h"
 #include "xfs_quota.h"
 #include "xfs_filestream.h"
 #include "xfs_vnodeops.h"
+#include "xfs_trace.h"
 
 kmem_zone_t *xfs_ifork_zone;
 kmem_zone_t *xfs_inode_zone;
@@ -151,7 +151,7 @@ xfs_imap_to_bp(
                                "an error %d on %s.  Returning error.",
                                error, mp->m_fsname);
                } else {
-                       ASSERT(buf_flags & XFS_BUF_TRYLOCK);
+                       ASSERT(buf_flags & XBF_TRYLOCK);
                }
                return error;
        }
@@ -239,7 +239,7 @@ xfs_inotobp(
        if (error)
                return error;
 
-       error = xfs_imap_to_bp(mp, tp, &imap, &bp, XFS_BUF_LOCK, imap_flags);
+       error = xfs_imap_to_bp(mp, tp, &imap, &bp, XBF_LOCK, imap_flags);
        if (error)
                return error;
 
@@ -285,7 +285,7 @@ xfs_itobp(
                return error;
 
        if (!bp) {
-               ASSERT(buf_flags & XFS_BUF_TRYLOCK);
+               ASSERT(buf_flags & XBF_TRYLOCK);
                ASSERT(tp == NULL);
                *bpp = NULL;
                return EAGAIN;
@@ -807,7 +807,7 @@ xfs_iread(
         * Get pointers to the on-disk inode and the buffer containing it.
         */
        error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp,
-                              XFS_BUF_LOCK, iget_flags);
+                              XBF_LOCK, iget_flags);
        if (error)
                return error;
        dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
@@ -1291,42 +1291,6 @@ xfs_file_last_byte(
        return last_byte;
 }
 
-#if defined(XFS_RW_TRACE)
-STATIC void
-xfs_itrunc_trace(
-       int             tag,
-       xfs_inode_t     *ip,
-       int             flag,
-       xfs_fsize_t     new_size,
-       xfs_off_t       toss_start,
-       xfs_off_t       toss_finish)
-{
-       if (ip->i_rwtrace == NULL) {
-               return;
-       }
-
-       ktrace_enter(ip->i_rwtrace,
-                    (void*)((long)tag),
-                    (void*)ip,
-                    (void*)(unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff),
-                    (void*)(unsigned long)(ip->i_d.di_size & 0xffffffff),
-                    (void*)((long)flag),
-                    (void*)(unsigned long)((new_size >> 32) & 0xffffffff),
-                    (void*)(unsigned long)(new_size & 0xffffffff),
-                    (void*)(unsigned long)((toss_start >> 32) & 0xffffffff),
-                    (void*)(unsigned long)(toss_start & 0xffffffff),
-                    (void*)(unsigned long)((toss_finish >> 32) & 0xffffffff),
-                    (void*)(unsigned long)(toss_finish & 0xffffffff),
-                    (void*)(unsigned long)current_cpu(),
-                    (void*)(unsigned long)current_pid(),
-                    (void*)NULL,
-                    (void*)NULL,
-                    (void*)NULL);
-}
-#else
-#define        xfs_itrunc_trace(tag, ip, flag, new_size, toss_start, toss_finish)
-#endif
-
 /*
  * Start the truncation of the file to new_size.  The new size
  * must be smaller than the current size.  This routine will
@@ -1409,8 +1373,7 @@ xfs_itruncate_start(
                return 0;
        }
        last_byte = xfs_file_last_byte(ip);
-       xfs_itrunc_trace(XFS_ITRUNC_START, ip, flags, new_size, toss_start,
-                        last_byte);
+       trace_xfs_itruncate_start(ip, flags, new_size, toss_start, last_byte);
        if (last_byte > toss_start) {
                if (flags & XFS_ITRUNC_DEFINITE) {
                        xfs_tosspages(ip, toss_start,
@@ -1514,7 +1477,8 @@ xfs_itruncate_finish(
                new_size = 0LL;
        }
        first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
-       xfs_itrunc_trace(XFS_ITRUNC_FINISH1, ip, 0, new_size, 0, 0);
+       trace_xfs_itruncate_finish_start(ip, new_size);
+
        /*
         * The first thing we do is set the size to new_size permanently
         * on disk.  This way we don't have to worry about anyone ever
@@ -1731,7 +1695,7 @@ xfs_itruncate_finish(
        ASSERT((new_size != 0) ||
               (fork == XFS_ATTR_FORK) ||
               (ip->i_d.di_nextents == 0));
-       xfs_itrunc_trace(XFS_ITRUNC_FINISH2, ip, 0, new_size, 0, 0);
+       trace_xfs_itruncate_finish_end(ip, new_size);
        return 0;
 }
 
@@ -1787,7 +1751,7 @@ xfs_iunlink(
                 * Here we put the head pointer into our next pointer,
                 * and then we fall through to point the head at us.
                 */
-               error = xfs_itobp(mp, tp, ip, &dip, &ibp, XFS_BUF_LOCK);
+               error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);
                if (error)
                        return error;
 
@@ -1869,7 +1833,7 @@ xfs_iunlink_remove(
                 * of dealing with the buffer when there is no need to
                 * change it.
                 */
-               error = xfs_itobp(mp, tp, ip, &dip, &ibp, XFS_BUF_LOCK);
+               error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);
                if (error) {
                        cmn_err(CE_WARN,
                                "xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
@@ -1931,7 +1895,7 @@ xfs_iunlink_remove(
                 * Now last_ibp points to the buffer previous to us on
                 * the unlinked list.  Pull us from the list.
                 */
-               error = xfs_itobp(mp, tp, ip, &dip, &ibp, XFS_BUF_LOCK);
+               error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);
                if (error) {
                        cmn_err(CE_WARN,
                                "xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
@@ -1982,8 +1946,9 @@ xfs_ifree_cluster(
        xfs_inode_t             *ip, **ip_found;
        xfs_inode_log_item_t    *iip;
        xfs_log_item_t          *lip;
-       xfs_perag_t             *pag = xfs_get_perag(mp, inum);
+       struct xfs_perag        *pag;
 
+       pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, inum));
        if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
                blks_per_cluster = 1;
                ninodes = mp->m_sb.sb_inopblock;
@@ -2075,7 +2040,7 @@ xfs_ifree_cluster(
 
                bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno, 
                                        mp->m_bsize * blks_per_cluster,
-                                       XFS_BUF_LOCK);
+                                       XBF_LOCK);
 
                pre_flushed = 0;
                lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
@@ -2124,7 +2089,7 @@ xfs_ifree_cluster(
        }
 
        kmem_free(ip_found);
-       xfs_put_perag(mp, pag);
+       xfs_perag_put(pag);
 }
 
 /*
@@ -2186,7 +2151,7 @@ xfs_ifree(
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
-       error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, XFS_BUF_LOCK);
+       error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, XBF_LOCK);
        if (error)
                return error;
 
@@ -2502,44 +2467,31 @@ xfs_iunpin(
 }
 
 /*
- * This is called to unpin an inode. It can be directed to wait or to return
- * immediately without waiting for the inode to be unpinned.  The caller must
- * have the inode locked in at least shared mode so that the buffer cannot be
- * subsequently pinned once someone is waiting for it to be unpinned.
+ * This is called to unpin an inode.  The caller must have the inode locked
+ * in at least shared mode so that the buffer cannot be subsequently pinned
+ * once someone is waiting for it to be unpinned.
  */
-STATIC void
-__xfs_iunpin_wait(
-       xfs_inode_t     *ip,
-       int             wait)
+static void
+xfs_iunpin_nowait(
+       struct xfs_inode        *ip)
 {
-       xfs_inode_log_item_t    *iip = ip->i_itemp;
-
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
-       if (atomic_read(&ip->i_pincount) == 0)
-               return;
 
        /* Give the log a push to start the unpinning I/O */
-       xfs_log_force(ip->i_mount, (iip && iip->ili_last_lsn) ?
-                               iip->ili_last_lsn : 0, XFS_LOG_FORCE);
-       if (wait)
-               wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
-}
+       xfs_log_force_lsn(ip->i_mount, ip->i_itemp->ili_last_lsn, 0);
 
-static inline void
-xfs_iunpin_wait(
-       xfs_inode_t     *ip)
-{
-       __xfs_iunpin_wait(ip, 1);
 }
 
-static inline void
-xfs_iunpin_nowait(
-       xfs_inode_t     *ip)
+void
+xfs_iunpin_wait(
+       struct xfs_inode        *ip)
 {
-       __xfs_iunpin_wait(ip, 0);
+       if (xfs_ipincount(ip)) {
+               xfs_iunpin_nowait(ip);
+               wait_event(ip->i_ipin_wait, (xfs_ipincount(ip) == 0));
+       }
 }
 
-
 /*
  * xfs_iextents_copy()
  *
@@ -2711,7 +2663,7 @@ xfs_iflush_cluster(
        xfs_buf_t       *bp)
 {
        xfs_mount_t             *mp = ip->i_mount;
-       xfs_perag_t             *pag = xfs_get_perag(mp, ip->i_ino);
+       struct xfs_perag        *pag;
        unsigned long           first_index, mask;
        unsigned long           inodes_per_cluster;
        int                     ilist_size;
@@ -2722,6 +2674,7 @@ xfs_iflush_cluster(
        int                     bufwasdelwri;
        int                     i;
 
+       pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
        ASSERT(pag->pagi_inodeok);
        ASSERT(pag->pag_ici_init);
 
@@ -2729,7 +2682,7 @@ xfs_iflush_cluster(
        ilist_size = inodes_per_cluster * sizeof(xfs_inode_t *);
        ilist = kmem_alloc(ilist_size, KM_MAYFAIL|KM_NOFS);
        if (!ilist)
-               return 0;
+               goto out_put;
 
        mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
        first_index = XFS_INO_TO_AGINO(mp, ip->i_ino) & mask;
@@ -2798,6 +2751,8 @@ xfs_iflush_cluster(
 out_free:
        read_unlock(&pag->pag_ici_lock);
        kmem_free(ilist);
+out_put:
+       xfs_perag_put(pag);
        return 0;
 
 
@@ -2841,6 +2796,7 @@ cluster_corrupt_out:
         */
        xfs_iflush_abort(iq);
        kmem_free(ilist);
+       xfs_perag_put(pag);
        return XFS_ERROR(EFSCORRUPTED);
 }
 
@@ -2863,8 +2819,6 @@ xfs_iflush(
        xfs_dinode_t            *dip;
        xfs_mount_t             *mp;
        int                     error;
-       int                     noblock = (flags == XFS_IFLUSH_ASYNC_NOBLOCK);
-       enum { INT_DELWRI = (1 << 0), INT_ASYNC = (1 << 1) };
 
        XFS_STATS_INC(xs_iflush_count);
 
@@ -2877,15 +2831,6 @@ xfs_iflush(
        mp = ip->i_mount;
 
        /*
-        * If the inode isn't dirty, then just release the inode
-        * flush lock and do nothing.
-        */
-       if (xfs_inode_clean(ip)) {
-               xfs_ifunlock(ip);
-               return 0;
-       }
-
-       /*
         * We can't flush the inode until it is unpinned, so wait for it if we
         * are allowed to block.  We know noone new can pin it, because we are
         * holding the inode lock shared and you need to hold it exclusively to
@@ -2896,7 +2841,7 @@ xfs_iflush(
         * in the same cluster are dirty, they will probably write the inode
         * out for us if they occur after the log force completes.
         */
-       if (noblock && xfs_ipincount(ip)) {
+       if (!(flags & SYNC_WAIT) && xfs_ipincount(ip)) {
                xfs_iunpin_nowait(ip);
                xfs_ifunlock(ip);
                return EAGAIN;
@@ -2904,6 +2849,19 @@ xfs_iflush(
        xfs_iunpin_wait(ip);
 
        /*
+        * For stale inodes we cannot rely on the backing buffer remaining
+        * stale in cache for the remaining life of the stale inode and so
+        * xfs_itobp() below may give us a buffer that no longer contains
+        * inodes below. We have to check this after ensuring the inode is
+        * unpinned so that it is safe to reclaim the stale inode after the
+        * flush call.
+        */
+       if (xfs_iflags_test(ip, XFS_ISTALE)) {
+               xfs_ifunlock(ip);
+               return 0;
+       }
+
+       /*
         * This may have been unpinned because the filesystem is shutting
         * down forcibly. If that's the case we must not write this inode
         * to disk, because the log record didn't make it to disk!
@@ -2917,60 +2875,10 @@ xfs_iflush(
        }
 
        /*
-        * Decide how buffer will be flushed out.  This is done before
-        * the call to xfs_iflush_int because this field is zeroed by it.
-        */
-       if (iip != NULL && iip->ili_format.ilf_fields != 0) {
-               /*
-                * Flush out the inode buffer according to the directions
-                * of the caller.  In the cases where the caller has given
-                * us a choice choose the non-delwri case.  This is because
-                * the inode is in the AIL and we need to get it out soon.
-                */
-               switch (flags) {
-               case XFS_IFLUSH_SYNC:
-               case XFS_IFLUSH_DELWRI_ELSE_SYNC:
-                       flags = 0;
-                       break;
-               case XFS_IFLUSH_ASYNC_NOBLOCK:
-               case XFS_IFLUSH_ASYNC:
-               case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
-                       flags = INT_ASYNC;
-                       break;
-               case XFS_IFLUSH_DELWRI:
-                       flags = INT_DELWRI;
-                       break;
-               default:
-                       ASSERT(0);
-                       flags = 0;
-                       break;
-               }
-       } else {
-               switch (flags) {
-               case XFS_IFLUSH_DELWRI_ELSE_SYNC:
-               case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
-               case XFS_IFLUSH_DELWRI:
-                       flags = INT_DELWRI;
-                       break;
-               case XFS_IFLUSH_ASYNC_NOBLOCK:
-               case XFS_IFLUSH_ASYNC:
-                       flags = INT_ASYNC;
-                       break;
-               case XFS_IFLUSH_SYNC:
-                       flags = 0;
-                       break;
-               default:
-                       ASSERT(0);
-                       flags = 0;
-                       break;
-               }
-       }
-
-       /*
         * Get the buffer containing the on-disk inode.
         */
        error = xfs_itobp(mp, NULL, ip, &dip, &bp,
-                               noblock ? XFS_BUF_TRYLOCK : XFS_BUF_LOCK);
+                               (flags & SYNC_WAIT) ? XBF_LOCK : XBF_TRYLOCK);
        if (error || !bp) {
                xfs_ifunlock(ip);
                return error;
@@ -2988,7 +2896,7 @@ xfs_iflush(
         * get stuck waiting in the write for too long.
         */
        if (XFS_BUF_ISPINNED(bp))
-               xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
+               xfs_log_force(mp, 0);
 
        /*
         * inode clustering:
@@ -2998,13 +2906,10 @@ xfs_iflush(
        if (error)
                goto cluster_corrupt_out;
 
-       if (flags & INT_DELWRI) {
-               xfs_bdwrite(mp, bp);
-       } else if (flags & INT_ASYNC) {
-               error = xfs_bawrite(mp, bp);
-       } else {
+       if (flags & SYNC_WAIT)
                error = xfs_bwrite(mp, bp);
-       }
+       else
+               xfs_bdwrite(mp, bp);
        return error;
 
 corrupt_out:
@@ -3039,16 +2944,6 @@ xfs_iflush_int(
        iip = ip->i_itemp;
        mp = ip->i_mount;
 
-
-       /*
-        * If the inode isn't dirty, then just release the inode
-        * flush lock and do nothing.
-        */
-       if (xfs_inode_clean(ip)) {
-               xfs_ifunlock(ip);
-               return 0;
-       }
-
        /* set *dip = inode's place in the buffer */
        dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
 
@@ -3068,9 +2963,9 @@ xfs_iflush_int(
        SYNCHRONIZE();
 
        /*
-        * 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);
 
        if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC,
                               mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
@@ -3252,23 +3147,6 @@ corrupt_out:
        return XFS_ERROR(EFSCORRUPTED);
 }
 
-
-
-#ifdef XFS_ILOCK_TRACE
-void
-xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
-{
-       ktrace_enter(ip->i_lock_trace,
-                    (void *)ip,
-                    (void *)(unsigned long)lock, /* 1 = LOCK, 3=UNLOCK, etc */
-                    (void *)(unsigned long)lockflags, /* XFS_ILOCK_EXCL etc */
-                    (void *)ra,                /* caller of ilock */
-                    (void *)(unsigned long)current_cpu(),
-                    (void *)(unsigned long)current_pid(),
-                    NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
-}
-#endif
-
 /*
  * Return a pointer to the extent record at file index idx.
  */
@@ -3300,13 +3178,17 @@ xfs_iext_get_ext(
  */
 void
 xfs_iext_insert(
-       xfs_ifork_t     *ifp,           /* inode fork pointer */
+       xfs_inode_t     *ip,            /* incore inode pointer */
        xfs_extnum_t    idx,            /* starting index of new items */
        xfs_extnum_t    count,          /* number of inserted items */
-       xfs_bmbt_irec_t *new)           /* items to insert */
+       xfs_bmbt_irec_t *new,           /* items to insert */
+       int             state)          /* type of extent conversion */
 {
+       xfs_ifork_t     *ifp = (state & BMAP_ATTRFORK) ? ip->i_afp : &ip->i_df;
        xfs_extnum_t    i;              /* extent record index */
 
+       trace_xfs_iext_insert(ip, idx, new, state, _RET_IP_);
+
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
        xfs_iext_add(ifp, idx, count);
        for (i = idx; i < idx + count; i++, new++)
@@ -3549,13 +3431,17 @@ xfs_iext_add_indirect_multi(
  */
 void
 xfs_iext_remove(
-       xfs_ifork_t     *ifp,           /* inode fork pointer */
+       xfs_inode_t     *ip,            /* incore inode pointer */
        xfs_extnum_t    idx,            /* index to begin removing exts */
-       int             ext_diff)       /* number of extents to remove */
+       int             ext_diff,       /* number of extents to remove */
+       int             state)          /* type of extent conversion */
 {
+       xfs_ifork_t     *ifp = (state & BMAP_ATTRFORK) ? ip->i_afp : &ip->i_df;
        xfs_extnum_t    nextents;       /* number of extents in file */
        int             new_size;       /* size of extents after removal */
 
+       trace_xfs_iext_remove(ip, idx, state, _RET_IP_);
+
        ASSERT(ext_diff > 0);
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
        new_size = (nextents - ext_diff) * sizeof(xfs_bmbt_rec_t);