xfs: remove duplicate buffer flags
[deliverable/linux.git] / fs / xfs / linux-2.6 / xfs_buf.c
index 77b8be81c76900559d8e382ee9e7a42710ae86e5..730eff1e71a3d262f8ba66b18aececd5ac23c0db 100644 (file)
@@ -1050,6 +1050,33 @@ xfs_buf_ioerror(
        trace_xfs_buf_ioerror(bp, error, _RET_IP_);
 }
 
+int
+xfs_bwrite(
+       struct xfs_mount        *mp,
+       struct xfs_buf          *bp)
+{
+       int                     iowait = (bp->b_flags & XBF_ASYNC) == 0;
+       int                     error = 0;
+
+       bp->b_strat = xfs_bdstrat_cb;
+       bp->b_mount = mp;
+       bp->b_flags |= XBF_WRITE;
+       if (!iowait)
+               bp->b_flags |= _XBF_RUN_QUEUES;
+
+       xfs_buf_delwri_dequeue(bp);
+       xfs_buf_iostrategy(bp);
+
+       if (iowait) {
+               error = xfs_buf_iowait(bp);
+               if (error)
+                       xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
+               xfs_buf_relse(bp);
+       }
+
+       return error;
+}
+
 int
 xfs_bawrite(
        void                    *mp,
@@ -1085,6 +1112,126 @@ xfs_bdwrite(
        xfs_buf_delwri_queue(bp, 1);
 }
 
+/*
+ * Called when we want to stop a buffer from getting written or read.
+ * We attach the EIO error, muck with its flags, and call biodone
+ * so that the proper iodone callbacks get called.
+ */
+STATIC int
+xfs_bioerror(
+       xfs_buf_t *bp)
+{
+#ifdef XFSERRORDEBUG
+       ASSERT(XFS_BUF_ISREAD(bp) || bp->b_iodone);
+#endif
+
+       /*
+        * No need to wait until the buffer is unpinned, we aren't flushing it.
+        */
+       XFS_BUF_ERROR(bp, EIO);
+
+       /*
+        * We're calling biodone, so delete XBF_DONE flag.
+        */
+       XFS_BUF_UNREAD(bp);
+       XFS_BUF_UNDELAYWRITE(bp);
+       XFS_BUF_UNDONE(bp);
+       XFS_BUF_STALE(bp);
+
+       XFS_BUF_CLR_BDSTRAT_FUNC(bp);
+       xfs_biodone(bp);
+
+       return EIO;
+}
+
+/*
+ * Same as xfs_bioerror, except that we are releasing the buffer
+ * here ourselves, and avoiding the biodone call.
+ * This is meant for userdata errors; metadata bufs come with
+ * iodone functions attached, so that we can track down errors.
+ */
+STATIC int
+xfs_bioerror_relse(
+       struct xfs_buf  *bp)
+{
+       int64_t         fl = XFS_BUF_BFLAGS(bp);
+       /*
+        * No need to wait until the buffer is unpinned.
+        * We aren't flushing it.
+        *
+        * chunkhold expects B_DONE to be set, whether
+        * we actually finish the I/O or not. We don't want to
+        * change that interface.
+        */
+       XFS_BUF_UNREAD(bp);
+       XFS_BUF_UNDELAYWRITE(bp);
+       XFS_BUF_DONE(bp);
+       XFS_BUF_STALE(bp);
+       XFS_BUF_CLR_IODONE_FUNC(bp);
+       XFS_BUF_CLR_BDSTRAT_FUNC(bp);
+       if (!(fl & XBF_ASYNC)) {
+               /*
+                * Mark b_error and B_ERROR _both_.
+                * Lot's of chunkcache code assumes that.
+                * There's no reason to mark error for
+                * ASYNC buffers.
+                */
+               XFS_BUF_ERROR(bp, EIO);
+               XFS_BUF_FINISH_IOWAIT(bp);
+       } else {
+               xfs_buf_relse(bp);
+       }
+
+       return EIO;
+}
+
+
+/*
+ * All xfs metadata buffers except log state machine buffers
+ * get this attached as their b_bdstrat callback function.
+ * This is so that we can catch a buffer
+ * after prematurely unpinning it to forcibly shutdown the filesystem.
+ */
+int
+xfs_bdstrat_cb(
+       struct xfs_buf  *bp)
+{
+       if (XFS_FORCED_SHUTDOWN(bp->b_mount)) {
+               trace_xfs_bdstrat_shut(bp, _RET_IP_);
+               /*
+                * Metadata write that didn't get logged but
+                * written delayed anyway. These aren't associated
+                * with a transaction, and can be ignored.
+                */
+               if (!bp->b_iodone && !XFS_BUF_ISREAD(bp))
+                       return xfs_bioerror_relse(bp);
+               else
+                       return xfs_bioerror(bp);
+       }
+
+       xfs_buf_iorequest(bp);
+       return 0;
+}
+
+/*
+ * Wrapper around bdstrat so that we can stop data from going to disk in case
+ * we are shutting down the filesystem.  Typically user data goes thru this
+ * path; one of the exceptions is the superblock.
+ */
+void
+xfsbdstrat(
+       struct xfs_mount        *mp,
+       struct xfs_buf          *bp)
+{
+       if (XFS_FORCED_SHUTDOWN(mp)) {
+               trace_xfs_bdstrat_shut(bp, _RET_IP_);
+               xfs_bioerror_relse(bp);
+               return;
+       }
+
+       xfs_buf_iorequest(bp);
+}
+
 STATIC void
 _xfs_buf_ioend(
        xfs_buf_t               *bp,
@@ -1296,7 +1443,7 @@ xfs_buf_iomove(
        xfs_buf_t               *bp,    /* buffer to process            */
        size_t                  boff,   /* starting buffer offset       */
        size_t                  bsize,  /* length to copy               */
-       caddr_t                 data,   /* data address                 */
+       void                    *data,  /* data address                 */
        xfs_buf_rw_t            mode)   /* read/write/zero flag         */
 {
        size_t                  bend, cpoff, csize;
@@ -1595,6 +1742,11 @@ xfs_buf_delwri_queue(
                list_del(&bp->b_list);
        }
 
+       if (list_empty(dwq)) {
+               /* start xfsbufd as it is about to have something to do */
+               wake_up_process(bp->b_target->bt_task);
+       }
+
        bp->b_flags |= _XBF_DELWRI_Q;
        list_add_tail(&bp->b_list, dwq);
        bp->b_queuetime = jiffies;
@@ -1644,6 +1796,8 @@ xfsbufd_wakeup(
        list_for_each_entry(btp, &xfs_buftarg_list, bt_list) {
                if (test_bit(XBT_FORCE_SLEEP, &btp->bt_flags))
                        continue;
+               if (list_empty(&btp->bt_delwrite_queue))
+                       continue;
                set_bit(XBT_FORCE_FLUSH, &btp->bt_flags);
                wake_up_process(btp->bt_task);
        }
@@ -1708,6 +1862,9 @@ xfsbufd(
        set_freezable();
 
        do {
+               long    age = xfs_buf_age_centisecs * msecs_to_jiffies(10);
+               long    tout = xfs_buf_timer_centisecs * msecs_to_jiffies(10);
+
                if (unlikely(freezing(current))) {
                        set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
                        refrigerator();
@@ -1715,12 +1872,12 @@ xfsbufd(
                        clear_bit(XBT_FORCE_SLEEP, &target->bt_flags);
                }
 
-               schedule_timeout_interruptible(
-                       xfs_buf_timer_centisecs * msecs_to_jiffies(10));
-
-               xfs_buf_delwri_split(target, &tmp,
-                               xfs_buf_age_centisecs * msecs_to_jiffies(10));
+               /* sleep for a long time if there is nothing to do. */
+               if (list_empty(&target->bt_delwrite_queue))
+                       tout = MAX_SCHEDULE_TIMEOUT;
+               schedule_timeout_interruptible(tout);
 
+               xfs_buf_delwri_split(target, &tmp, age);
                count = 0;
                while (!list_empty(&tmp)) {
                        bp = list_entry(tmp.next, xfs_buf_t, b_list);
This page took 0.029676 seconds and 5 git commands to generate.