OSDN Git Service

xfs: fix up quotacheck buffer list error handling
authorBrian Foster <bfoster@redhat.com>
Fri, 21 Apr 2017 19:40:44 +0000 (12:40 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Jun 2017 10:06:02 +0000 (12:06 +0200)
commit 20e8a063786050083fe05b4f45be338c60b49126 upstream.

The quotacheck error handling of the delwri buffer list assumes the
resident buffers are locked and doesn't clear the _XBF_DELWRI_Q flag
on the buffers that are dequeued. This can lead to assert failures
on buffer release and possibly other locking problems.

Move this code to a delwri queue cancel helper function to
encapsulate the logic required to properly release buffers from a
delwri queue. Update the helper to clear the delwri queue flag and
call it from quotacheck.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_qm.c

index 8146b0c..dcb7096 100644 (file)
@@ -979,6 +979,8 @@ void
 xfs_buf_unlock(
        struct xfs_buf          *bp)
 {
+       ASSERT(xfs_buf_islocked(bp));
+
        XB_CLEAR_OWNER(bp);
        up(&bp->b_sema);
 
@@ -1713,6 +1715,28 @@ error:
 }
 
 /*
+ * Cancel a delayed write list.
+ *
+ * Remove each buffer from the list, clear the delwri queue flag and drop the
+ * associated buffer reference.
+ */
+void
+xfs_buf_delwri_cancel(
+       struct list_head        *list)
+{
+       struct xfs_buf          *bp;
+
+       while (!list_empty(list)) {
+               bp = list_first_entry(list, struct xfs_buf, b_list);
+
+               xfs_buf_lock(bp);
+               bp->b_flags &= ~_XBF_DELWRI_Q;
+               list_del_init(&bp->b_list);
+               xfs_buf_relse(bp);
+       }
+}
+
+/*
  * Add a buffer to the delayed write list.
  *
  * This queues a buffer for writeout if it hasn't already been.  Note that
index c75721a..149bbd4 100644 (file)
@@ -304,6 +304,7 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
 extern void *xfs_buf_offset(struct xfs_buf *, size_t);
 
 /* Delayed Write Buffer Routines */
+extern void xfs_buf_delwri_cancel(struct list_head *);
 extern bool xfs_buf_delwri_queue(struct xfs_buf *, struct list_head *);
 extern int xfs_buf_delwri_submit(struct list_head *);
 extern int xfs_buf_delwri_submit_nowait(struct list_head *);
index 532ab79..572b64a 100644 (file)
@@ -1355,12 +1355,7 @@ xfs_qm_quotacheck(
        mp->m_qflags |= flags;
 
  error_return:
-       while (!list_empty(&buffer_list)) {
-               struct xfs_buf *bp =
-                       list_first_entry(&buffer_list, struct xfs_buf, b_list);
-               list_del_init(&bp->b_list);
-               xfs_buf_relse(bp);
-       }
+       xfs_buf_delwri_cancel(&buffer_list);
 
        if (error) {
                xfs_warn(mp,