Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: xfs: revert to using a kthread for AIL pushing xfs: force the log if we encounter pinned buffers in .iop_pushbuf xfs: do not update xa_last_pushed_lsn for locked items
This commit is contained in:
commit
480082968a
|
@ -629,7 +629,7 @@ xfs_buf_item_push(
|
||||||
* the xfsbufd to get this buffer written. We have to unlock the buffer
|
* the xfsbufd to get this buffer written. We have to unlock the buffer
|
||||||
* to allow the xfsbufd to write it, too.
|
* to allow the xfsbufd to write it, too.
|
||||||
*/
|
*/
|
||||||
STATIC void
|
STATIC bool
|
||||||
xfs_buf_item_pushbuf(
|
xfs_buf_item_pushbuf(
|
||||||
struct xfs_log_item *lip)
|
struct xfs_log_item *lip)
|
||||||
{
|
{
|
||||||
|
@ -643,6 +643,7 @@ xfs_buf_item_pushbuf(
|
||||||
|
|
||||||
xfs_buf_delwri_promote(bp);
|
xfs_buf_delwri_promote(bp);
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
|
|
|
@ -183,13 +183,14 @@ xfs_qm_dqunpin_wait(
|
||||||
* search the buffer cache can be a time consuming thing, and AIL lock is a
|
* search the buffer cache can be a time consuming thing, and AIL lock is a
|
||||||
* spinlock.
|
* spinlock.
|
||||||
*/
|
*/
|
||||||
STATIC void
|
STATIC bool
|
||||||
xfs_qm_dquot_logitem_pushbuf(
|
xfs_qm_dquot_logitem_pushbuf(
|
||||||
struct xfs_log_item *lip)
|
struct xfs_log_item *lip)
|
||||||
{
|
{
|
||||||
struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip);
|
struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip);
|
||||||
struct xfs_dquot *dqp = qlip->qli_dquot;
|
struct xfs_dquot *dqp = qlip->qli_dquot;
|
||||||
struct xfs_buf *bp;
|
struct xfs_buf *bp;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
ASSERT(XFS_DQ_IS_LOCKED(dqp));
|
ASSERT(XFS_DQ_IS_LOCKED(dqp));
|
||||||
|
|
||||||
|
@ -201,17 +202,20 @@ xfs_qm_dquot_logitem_pushbuf(
|
||||||
if (completion_done(&dqp->q_flush) ||
|
if (completion_done(&dqp->q_flush) ||
|
||||||
!(lip->li_flags & XFS_LI_IN_AIL)) {
|
!(lip->li_flags & XFS_LI_IN_AIL)) {
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bp = xfs_incore(dqp->q_mount->m_ddev_targp, qlip->qli_format.qlf_blkno,
|
bp = xfs_incore(dqp->q_mount->m_ddev_targp, qlip->qli_format.qlf_blkno,
|
||||||
dqp->q_mount->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK);
|
dqp->q_mount->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK);
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
if (!bp)
|
if (!bp)
|
||||||
return;
|
return true;
|
||||||
if (XFS_BUF_ISDELAYWRITE(bp))
|
if (XFS_BUF_ISDELAYWRITE(bp))
|
||||||
xfs_buf_delwri_promote(bp);
|
xfs_buf_delwri_promote(bp);
|
||||||
|
if (xfs_buf_ispinned(bp))
|
||||||
|
ret = false;
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -708,13 +708,14 @@ xfs_inode_item_committed(
|
||||||
* marked delayed write. If that's the case, we'll promote it and that will
|
* marked delayed write. If that's the case, we'll promote it and that will
|
||||||
* allow the caller to write the buffer by triggering the xfsbufd to run.
|
* allow the caller to write the buffer by triggering the xfsbufd to run.
|
||||||
*/
|
*/
|
||||||
STATIC void
|
STATIC bool
|
||||||
xfs_inode_item_pushbuf(
|
xfs_inode_item_pushbuf(
|
||||||
struct xfs_log_item *lip)
|
struct xfs_log_item *lip)
|
||||||
{
|
{
|
||||||
struct xfs_inode_log_item *iip = INODE_ITEM(lip);
|
struct xfs_inode_log_item *iip = INODE_ITEM(lip);
|
||||||
struct xfs_inode *ip = iip->ili_inode;
|
struct xfs_inode *ip = iip->ili_inode;
|
||||||
struct xfs_buf *bp;
|
struct xfs_buf *bp;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
|
ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
|
||||||
|
|
||||||
|
@ -725,7 +726,7 @@ xfs_inode_item_pushbuf(
|
||||||
if (completion_done(&ip->i_flush) ||
|
if (completion_done(&ip->i_flush) ||
|
||||||
!(lip->li_flags & XFS_LI_IN_AIL)) {
|
!(lip->li_flags & XFS_LI_IN_AIL)) {
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bp = xfs_incore(ip->i_mount->m_ddev_targp, iip->ili_format.ilf_blkno,
|
bp = xfs_incore(ip->i_mount->m_ddev_targp, iip->ili_format.ilf_blkno,
|
||||||
|
@ -733,10 +734,13 @@ xfs_inode_item_pushbuf(
|
||||||
|
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
if (!bp)
|
if (!bp)
|
||||||
return;
|
return true;
|
||||||
if (XFS_BUF_ISDELAYWRITE(bp))
|
if (XFS_BUF_ISDELAYWRITE(bp))
|
||||||
xfs_buf_delwri_promote(bp);
|
xfs_buf_delwri_promote(bp);
|
||||||
|
if (xfs_buf_ispinned(bp))
|
||||||
|
ret = false;
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -68,6 +68,8 @@
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/freezer.h>
|
||||||
#include <linux/list_sort.h>
|
#include <linux/list_sort.h>
|
||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
|
@ -1652,24 +1652,13 @@ xfs_init_workqueues(void)
|
||||||
*/
|
*/
|
||||||
xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8);
|
xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8);
|
||||||
if (!xfs_syncd_wq)
|
if (!xfs_syncd_wq)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
xfs_ail_wq = alloc_workqueue("xfsail", WQ_CPU_INTENSIVE, 8);
|
|
||||||
if (!xfs_ail_wq)
|
|
||||||
goto out_destroy_syncd;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_destroy_syncd:
|
|
||||||
destroy_workqueue(xfs_syncd_wq);
|
|
||||||
out:
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
xfs_destroy_workqueues(void)
|
xfs_destroy_workqueues(void)
|
||||||
{
|
{
|
||||||
destroy_workqueue(xfs_ail_wq);
|
|
||||||
destroy_workqueue(xfs_syncd_wq);
|
destroy_workqueue(xfs_syncd_wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ typedef struct xfs_item_ops {
|
||||||
void (*iop_unlock)(xfs_log_item_t *);
|
void (*iop_unlock)(xfs_log_item_t *);
|
||||||
xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t);
|
xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t);
|
||||||
void (*iop_push)(xfs_log_item_t *);
|
void (*iop_push)(xfs_log_item_t *);
|
||||||
void (*iop_pushbuf)(xfs_log_item_t *);
|
bool (*iop_pushbuf)(xfs_log_item_t *);
|
||||||
void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
|
void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
|
||||||
} xfs_item_ops_t;
|
} xfs_item_ops_t;
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
#include "xfs_trans_priv.h"
|
#include "xfs_trans_priv.h"
|
||||||
#include "xfs_error.h"
|
#include "xfs_error.h"
|
||||||
|
|
||||||
struct workqueue_struct *xfs_ail_wq; /* AIL workqueue */
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/*
|
/*
|
||||||
* Check that the list is sorted as it should be.
|
* Check that the list is sorted as it should be.
|
||||||
|
@ -356,16 +354,10 @@ xfs_ail_delete(
|
||||||
xfs_trans_ail_cursor_clear(ailp, lip);
|
xfs_trans_ail_cursor_clear(ailp, lip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static long
|
||||||
* xfs_ail_worker does the work of pushing on the AIL. It will requeue itself
|
xfsaild_push(
|
||||||
* to run at a later time if there is more work to do to complete the push.
|
struct xfs_ail *ailp)
|
||||||
*/
|
|
||||||
STATIC void
|
|
||||||
xfs_ail_worker(
|
|
||||||
struct work_struct *work)
|
|
||||||
{
|
{
|
||||||
struct xfs_ail *ailp = container_of(to_delayed_work(work),
|
|
||||||
struct xfs_ail, xa_work);
|
|
||||||
xfs_mount_t *mp = ailp->xa_mount;
|
xfs_mount_t *mp = ailp->xa_mount;
|
||||||
struct xfs_ail_cursor cur;
|
struct xfs_ail_cursor cur;
|
||||||
xfs_log_item_t *lip;
|
xfs_log_item_t *lip;
|
||||||
|
@ -427,8 +419,13 @@ xfs_ail_worker(
|
||||||
|
|
||||||
case XFS_ITEM_PUSHBUF:
|
case XFS_ITEM_PUSHBUF:
|
||||||
XFS_STATS_INC(xs_push_ail_pushbuf);
|
XFS_STATS_INC(xs_push_ail_pushbuf);
|
||||||
IOP_PUSHBUF(lip);
|
|
||||||
ailp->xa_last_pushed_lsn = lsn;
|
if (!IOP_PUSHBUF(lip)) {
|
||||||
|
stuck++;
|
||||||
|
flush_log = 1;
|
||||||
|
} else {
|
||||||
|
ailp->xa_last_pushed_lsn = lsn;
|
||||||
|
}
|
||||||
push_xfsbufd = 1;
|
push_xfsbufd = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -440,7 +437,6 @@ xfs_ail_worker(
|
||||||
|
|
||||||
case XFS_ITEM_LOCKED:
|
case XFS_ITEM_LOCKED:
|
||||||
XFS_STATS_INC(xs_push_ail_locked);
|
XFS_STATS_INC(xs_push_ail_locked);
|
||||||
ailp->xa_last_pushed_lsn = lsn;
|
|
||||||
stuck++;
|
stuck++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -501,20 +497,6 @@ out_done:
|
||||||
/* We're past our target or empty, so idle */
|
/* We're past our target or empty, so idle */
|
||||||
ailp->xa_last_pushed_lsn = 0;
|
ailp->xa_last_pushed_lsn = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* We clear the XFS_AIL_PUSHING_BIT first before checking
|
|
||||||
* whether the target has changed. If the target has changed,
|
|
||||||
* this pushes the requeue race directly onto the result of the
|
|
||||||
* atomic test/set bit, so we are guaranteed that either the
|
|
||||||
* the pusher that changed the target or ourselves will requeue
|
|
||||||
* the work (but not both).
|
|
||||||
*/
|
|
||||||
clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags);
|
|
||||||
smp_rmb();
|
|
||||||
if (XFS_LSN_CMP(ailp->xa_target, target) == 0 ||
|
|
||||||
test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
|
|
||||||
return;
|
|
||||||
|
|
||||||
tout = 50;
|
tout = 50;
|
||||||
} else if (XFS_LSN_CMP(lsn, target) >= 0) {
|
} else if (XFS_LSN_CMP(lsn, target) >= 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -537,9 +519,30 @@ out_done:
|
||||||
tout = 20;
|
tout = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There is more to do, requeue us. */
|
return tout;
|
||||||
queue_delayed_work(xfs_syncd_wq, &ailp->xa_work,
|
}
|
||||||
msecs_to_jiffies(tout));
|
|
||||||
|
static int
|
||||||
|
xfsaild(
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct xfs_ail *ailp = data;
|
||||||
|
long tout = 0; /* milliseconds */
|
||||||
|
|
||||||
|
while (!kthread_should_stop()) {
|
||||||
|
if (tout && tout <= 20)
|
||||||
|
__set_current_state(TASK_KILLABLE);
|
||||||
|
else
|
||||||
|
__set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
schedule_timeout(tout ?
|
||||||
|
msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT);
|
||||||
|
|
||||||
|
try_to_freeze();
|
||||||
|
|
||||||
|
tout = xfsaild_push(ailp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -574,8 +577,9 @@ xfs_ail_push(
|
||||||
*/
|
*/
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn);
|
xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn);
|
||||||
if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
|
smp_wmb();
|
||||||
queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0);
|
|
||||||
|
wake_up_process(ailp->xa_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -813,9 +817,18 @@ xfs_trans_ail_init(
|
||||||
INIT_LIST_HEAD(&ailp->xa_ail);
|
INIT_LIST_HEAD(&ailp->xa_ail);
|
||||||
INIT_LIST_HEAD(&ailp->xa_cursors);
|
INIT_LIST_HEAD(&ailp->xa_cursors);
|
||||||
spin_lock_init(&ailp->xa_lock);
|
spin_lock_init(&ailp->xa_lock);
|
||||||
INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker);
|
|
||||||
|
ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild/%s",
|
||||||
|
ailp->xa_mount->m_fsname);
|
||||||
|
if (IS_ERR(ailp->xa_task))
|
||||||
|
goto out_free_ailp;
|
||||||
|
|
||||||
mp->m_ail = ailp;
|
mp->m_ail = ailp;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_free_ailp:
|
||||||
|
kmem_free(ailp);
|
||||||
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -824,6 +837,6 @@ xfs_trans_ail_destroy(
|
||||||
{
|
{
|
||||||
struct xfs_ail *ailp = mp->m_ail;
|
struct xfs_ail *ailp = mp->m_ail;
|
||||||
|
|
||||||
cancel_delayed_work_sync(&ailp->xa_work);
|
kthread_stop(ailp->xa_task);
|
||||||
kmem_free(ailp);
|
kmem_free(ailp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,23 +64,17 @@ struct xfs_ail_cursor {
|
||||||
*/
|
*/
|
||||||
struct xfs_ail {
|
struct xfs_ail {
|
||||||
struct xfs_mount *xa_mount;
|
struct xfs_mount *xa_mount;
|
||||||
|
struct task_struct *xa_task;
|
||||||
struct list_head xa_ail;
|
struct list_head xa_ail;
|
||||||
xfs_lsn_t xa_target;
|
xfs_lsn_t xa_target;
|
||||||
struct list_head xa_cursors;
|
struct list_head xa_cursors;
|
||||||
spinlock_t xa_lock;
|
spinlock_t xa_lock;
|
||||||
struct delayed_work xa_work;
|
|
||||||
xfs_lsn_t xa_last_pushed_lsn;
|
xfs_lsn_t xa_last_pushed_lsn;
|
||||||
unsigned long xa_flags;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define XFS_AIL_PUSHING_BIT 0
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From xfs_trans_ail.c
|
* From xfs_trans_ail.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern struct workqueue_struct *xfs_ail_wq; /* AIL workqueue */
|
|
||||||
|
|
||||||
void xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
|
void xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
|
||||||
struct xfs_ail_cursor *cur,
|
struct xfs_ail_cursor *cur,
|
||||||
struct xfs_log_item **log_items, int nr_items,
|
struct xfs_log_item **log_items, int nr_items,
|
||||||
|
|
Loading…
Reference in New Issue