Other 2.6.34 candidate patches
cover Other 2.6.34 candidate patches
Cleanup and on-demand wakeup patches that have been cleaned up after review.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 1/3 XFS: Use list_heads for log recovery item lists
Remove the roll-your-own linked list operations.
--- fs/xfs/xfs_log_recover.c | 205 ++++++++++++++++------------------------------ fs/xfs/xfs_log_recover.h | 23 +++--- 2 files changed, 81 insertions(+), 147 deletions(-)
fs/xfs/xfs_log_recover.c +70 -135
@@ -50,8 +50,6 @@ STATIC int xlog_find_zeroed(xlog_t *, xfs_daddr_t *); STATIC int xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t); -STATIC void xlog_recover_insert_item_backq(xlog_recover_item_t **q, -xlog_recover_item_t *item);#if defined(DEBUG ) STATIC void xlog_recover_check_summary(xlog_t *);#else
@@ -1367,36 +1365,45 @@ xlog_clear_stale_blocks( STATIC xlog_recover_t *xlog_recover_find_tid ( -xlog_recover_t *q, +struct hlist_head *head,xlog_tid_t tid) { -xlog_recover_t *p = q; +xlog_recover_t *trans; +struct hlist_node *n; -while (p !=NULL ) { -if (p->r_log_tid == tid) -break ; - p = p->r_next; +hlist_for_each_entry (trans, n, head, r_list) { +if (trans->r_log_tid == tid) +return trans; } -return p; +return NULL ; } STATIC void -xlog_recover_put_hashq ( -xlog_recover_t **q, -xlog_recover_t *trans) +xlog_recover_new_tid ( +struct hlist_head *head, +xlog_tid_t tid, +xfs_lsn_t lsn) { - trans->r_next = *q; - *q = trans; +xlog_recover_t *trans; + + trans =kmem_zalloc (sizeof (xlog_recover_t),KM_SLEEP ); + trans->r_log_tid = tid; + trans->r_lsn = lsn; +INIT_LIST_HEAD (&trans->r_itemq); + +INIT_HLIST_NODE (&trans->r_list); +hlist_add_head (&trans->r_list, head); } STATIC voidxlog_recover_add_item ( -xlog_recover_item_t **itemq) +struct list_head *head) {xlog_recover_item_t *item; item =kmem_zalloc (sizeof (xlog_recover_item_t),KM_SLEEP ); -xlog_recover_insert_item_backq (itemq, item); +INIT_LIST_HEAD (&item->ri_list); +list_add_tail (&item->ri_list, head); }STATIC int
@@ -1409,8 +1416,7 @@ xlog_recover_add_to_cont_trans(xfs_caddr_t ptr, old_ptr;int old_len; - item = trans->r_itemq; -if (item ==NULL ) { +if (list_empty (&trans->r_itemq)) {/* finish copying rest of trans header */ xlog_recover_add_item (&trans->r_itemq); ptr = (xfs_caddr_t) &trans->r_theader +
@@ -1418,7 +1424,8 @@ xlog_recover_add_to_cont_trans(memcpy (ptr, dp, len);/* d, s, l */ return 0 ; } - item = item->ri_prev; +/* take the tail entry */ + item =list_entry (trans->r_itemq.prev, xlog_recover_item_t, ri_list); old_ptr = item->ri_buf[item->ri_cnt-1 ].i_addr; old_len = item->ri_buf[item->ri_cnt-1 ].i_len;
@@ -1455,8 +1462,7 @@ xlog_recover_add_to_trans(if (!len)return 0 ; - item = trans->r_itemq; -if (item ==NULL ) { +if (list_empty (&trans->r_itemq)) {/* we need to catch log corruptions here */ if (*(uint *)dp !=XFS_TRANS_HEADER_MAGIC ) { xlog_warn("XFS: xlog_recover_add_to_trans: "
@@ -1474,12 +1480,15 @@ xlog_recover_add_to_trans(memcpy (ptr, dp, len); in_f = (xfs_inode_log_format_t *)ptr; -if (item->ri_prev->ri_total !=0 && - item->ri_prev->ri_total == item->ri_prev->ri_cnt) { +/* take the tail entry */ + item =list_entry (trans->r_itemq.prev, xlog_recover_item_t, ri_list); +if (item->ri_total !=0 && + item->ri_total == item->ri_cnt) { +/* tail item is in use, get a new one */ xlog_recover_add_item (&trans->r_itemq); + item =list_entry (trans->r_itemq.prev, + xlog_recover_item_t, ri_list); } - item = trans->r_itemq; - item = item->ri_prev;if (item->ri_total ==0 ) {/* first region to be added */ if (in_f->ilf_size == 0 ||
@@ -1504,96 +1513,29 @@ xlog_recover_add_to_trans(return 0 ; } -STATIC void -xlog_recover_new_tid ( -xlog_recover_t **q, -xlog_tid_t tid, -xfs_lsn_t lsn) -{ -xlog_recover_t *trans; - - trans =kmem_zalloc (sizeof (xlog_recover_t),KM_SLEEP ); - trans->r_log_tid = tid; - trans->r_lsn = lsn; -xlog_recover_put_hashq (q, trans); -} - -STATIC int -xlog_recover_unlink_tid ( -xlog_recover_t **q, -xlog_recover_t *trans) -{ -xlog_recover_t *tp; -int found =0 ; - -ASSERT (trans !=NULL ); -if (trans == *q) { - *q = (*q)->r_next; - }else { - tp = *q; -while (tp) { -if (tp->r_next == trans) { - found =1 ; -break ; - } - tp = tp->r_next; - } -if (!found) { -xlog_warn ( -"XFS: xlog_recover_unlink_tid: trans not found" ); -ASSERT (0 ); -return XFS_ERROR (EIO ); - } - tp->r_next = tp->r_next->r_next; - } -return 0 ; -} - -STATIC void -xlog_recover_insert_item_backq ( -xlog_recover_item_t **q, -xlog_recover_item_t *item) -{ -if (*q ==NULL ) { - item->ri_prev = item->ri_next = item; - *q = item; - }else { - item->ri_next = *q; - item->ri_prev = (*q)->ri_prev; - (*q)->ri_prev = item; - item->ri_prev->ri_next = item; - } -} - -STATIC void -xlog_recover_insert_item_frontq ( -xlog_recover_item_t **q, -xlog_recover_item_t *item) -{ -xlog_recover_insert_item_backq (q, item); - *q = item; -} - +/* +* Sort the log items in the transaction. Cancelled buffers need +* to be put first so they are processed before any items that might +* modify the buffers. If they are cancelled, then the modifications +* don't need to be replayed. +*/ STATIC intxlog_recover_reorder_trans (xlog_recover_t *trans) { -xlog_recover_item_t *first_item, *itemq, *itemq_next; -xfs_buf_log_format_t *buf_f; -ushort flags =0 ; +xlog_recover_item_t *item, *n; +LIST_HEAD (sort_list); + +list_splice_init (&trans->r_itemq, &sort_list); +list_for_each_entry_safe (item, n, &sort_list, ri_list) { +xfs_buf_log_format_t *buf_f; - first_item = itemq = trans->r_itemq; - trans->r_itemq =NULL ; - do { - itemq_next = itemq->ri_next; - buf_f = (xfs_buf_log_format_t *)itemq->ri_buf[0].i_addr; + buf_f = (xfs_buf_log_format_t *)item->ri_buf[0 ].i_addr; - switch (ITEM_TYPE(itemq)) { +switch (ITEM_TYPE (item)) {case XFS_LI_BUF : - flags = buf_f->blf_flags; - if (!(flags & XFS_BLI_CANCEL)) { - xlog_recover_insert_item_frontq(&trans->r_itemq, - itemq); +if (!(buf_f->blf_flags &XFS_BLI_CANCEL )) { +list_move (&item->ri_list, &trans->r_itemq);break ; }case XFS_LI_INODE :
@@ -1601,7 +1543,7 @@ xlog_recover_reorder_trans(case XFS_LI_QUOTAOFF :case XFS_LI_EFD :case XFS_LI_EFI : -xlog_recover_insert_item_backq (&trans->r_itemq, itemq); +list_move_tail (&item->ri_list, &trans->r_itemq);break ;default : xlog_warn(
@@ -1609,8 +1551,8 @@ xlog_recover_reorder_trans(ASSERT (0 );return XFS_ERROR (EIO ); } - itemq = itemq_next; - }while (first_item != itemq); + } +ASSERT (list_empty (&sort_list));return 0 ; }
@@ -2814,14 +2756,13 @@ xlog_recover_do_trans( int pass) {int error =0 ; -xlog_recover_item_t *item, *first_item; +xlog_recover_item_t *item; error =xlog_recover_reorder_trans (trans);if (error)return error; - first_item = item = trans->r_itemq; - do { +list_for_each_entry (item, &trans->r_itemq, ri_list) {switch (ITEM_TYPE (item)) {case XFS_LI_BUF : error =xlog_recover_do_buffer_trans (log, item, pass);
@@ -2854,8 +2795,7 @@ xlog_recover_do_trans(if (error)return error; - item = item->ri_next; - }while (first_item != item); + }return 0 ; }
@@ -2869,21 +2809,18 @@ STATIC voidxlog_recover_free_trans ( xlog_recover_t *trans) { -xlog_recover_item_t *first_item, *item, *free_item; +xlog_recover_item_t *item, *n;int i; - item = first_item = trans->r_itemq; -do { - free_item = item; - item = item->ri_next; -/* Free the regions in the item. */ -for (i =0 ; i < free_item->ri_cnt; i++) { -kmem_free (free_item->ri_buf[i].i_addr); - } +list_for_each_entry_safe (item, n, &trans->r_itemq, ri_list) { +/* Free the regions in the item. */ +list_del (&item->ri_list); +for (i =0 ; i < item->ri_cnt; i++) +kmem_free (item->ri_buf[i].i_addr);/* Free the item itself */ -kmem_free (free_item->ri_buf); -kmem_free (free_item); - }while (first_item != item); +kmem_free (item->ri_buf); +kmem_free (item); + }/* Free the transaction recover structure */ kmem_free (trans); }
@@ -2891,14 +2828,12 @@ xlog_recover_free_trans( STATIC intxlog_recover_commit_trans (xlog_t *log, -xlog_recover_t **q,xlog_recover_t *trans,int pass) {int error; -if ((error =xlog_recover_unlink_tid (q, trans))) -return error; +hlist_del (&trans->r_list);if ((error =xlog_recover_do_trans (log, trans, pass)))return error;xlog_recover_free_trans (trans);/* no error */
@@ -2926,7 +2861,7 @@ xlog_recover_unmount_trans( STATIC intxlog_recover_process_data (xlog_t *log, -xlog_recover_t *rhash[], +struct hlist_head rhash[],xlog_rec_header_t *rhead,xfs_caddr_t dp,int pass)
@@ -2960,7 +2895,7 @@ xlog_recover_process_data( } tid =be32_to_cpu (ohead->oh_tid); hash =XLOG_RHASH (tid); - trans =xlog_recover_find_tid (rhash[hash], tid); + trans =xlog_recover_find_tid (&rhash[hash], tid);if (trans ==NULL ) {/* not found; add new tid */ if (ohead->oh_flags &XLOG_START_TRANS ) xlog_recover_new_tid(&rhash[hash], tid,
@@ -2978,7 +2913,7 @@ xlog_recover_process_data(switch (flags) {case XLOG_COMMIT_TRANS : error =xlog_recover_commit_trans (log, - &rhash[hash], trans, pass); + trans, pass);break ;case XLOG_UNMOUNT_TRANS : error =xlog_recover_unmount_trans (trans);
@@ -3517,7 +3452,7 @@ xlog_do_recovery_pass(int error =0 , h_size;int bblks, split_bblks;int hblks, split_hblks, wrapped_hblks; -xlog_recover_t *rhash[XLOG_RHASH_SIZE ]; +struct hlist_head rhash[XLOG_RHASH_SIZE ];ASSERT (head_blk != tail_blk);
fs/xfs/xfs_log_recover.h +11 -12
@@ -35,22 +35,21 @@* item headers are in ri_buf[0]. Additional buffers follow. */ typedef struct xlog_recover_item { -struct xlog_recover_item *ri_next; -struct xlog_recover_item *ri_prev; -int ri_type; -int ri_cnt;/* count of regions found */ -int ri_total;/* total regions */ -xfs_log_iovec_t *ri_buf;/* ptr to regions buffer */ +struct list_head ri_list; +int ri_type; +int ri_cnt;/* count of regions found */ +int ri_total;/* total regions */ +xfs_log_iovec_t *ri_buf;/* ptr to regions buffer */ }xlog_recover_item_t ;struct xlog_tid ;typedef struct xlog_recover { -struct xlog_recover *r_next; -xlog_tid_t r_log_tid;/* log's transaction id */ -xfs_trans_header_t r_theader;/* trans header for partial */ -int r_state;/* not needed */ -xfs_lsn_t r_lsn;/* xact lsn */ -xlog_recover_item_t *r_itemq;/* q for items */ +struct hlist_node r_list; +xlog_tid_t r_log_tid;/* log's transaction id */ +xfs_trans_header_t r_theader;/* trans header for partial */ +int r_state;/* not needed */ +xfs_lsn_t r_lsn;/* xact lsn */ +struct list_head r_itemq;/* q for items */ }xlog_recover_t ;#define ITEM_TYPE (i) (*(ushort *)(i)->ri_buf[0].i_addr)
Signature · 6 lines
1.6.5 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 1/3] XFS: Use list_heads for log recovery item lists
Quoted 1 line · Dave Chinner
Remove the roll-your-own linked list operations.
I can't spot any changes since the version I reviewed a few days ago, so:
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 2/3 XFS: Don't wake the aild once per second
In reply to Dave ChinnerNow that the AIL push algorithm is traversal safe, we don't need a watchdog function in the xfsaild to catch pushes that fail to make progress. Remove the watchdog timeout and make pushes purely driven by demand. This will remove the once-per-second wakeup that is seen when the filesystem is idle and make laptop power misers happy.
--- fs/xfs/linux-2.6/xfs_super.c | 7 +++---- fs/xfs/xfs_trans_ail.c | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-)
fs/xfs/linux-2.6/xfs_super.c +3 -4
@@ -877,12 +877,11 @@ xfsaild( {struct xfs_ail *ailp = data;xfs_lsn_t last_pushed_lsn =0 ; -long tout =0 ; +long tout =0 ;/* milliseconds */ while (!kthread_should_stop ()) { -if (tout) -schedule_timeout_interruptible (msecs_to_jiffies (tout)); - tout =1000 ; +schedule_timeout_interruptible (tout ? +msecs_to_jiffies (tout) :MAX_SCHEDULE_TIMEOUT );/* swsusp */ try_to_freeze ();
fs/xfs/xfs_trans_ail.c +11 -8
@@ -237,14 +237,15 @@ out: }/* -* Function that does the work of pushing on the AIL +* xfsaild_push does the work of pushing on the AIL. Returning a timeout of +* zero indicates that the caller should sleep until woken. */ long xfsaild_push (struct xfs_ail *ailp,xfs_lsn_t *last_lsn) { -long tout =1000 ;/* milliseconds */ +long tout =0 ;xfs_lsn_t last_pushed_lsn = *last_lsn;xfs_lsn_t target = ailp->xa_target;xfs_lsn_t lsn;
@@ -262,7 +263,7 @@ xfsaild_push(*/ xfs_trans_ail_cursor_done (ailp, cur);spin_unlock (&ailp->xa_lock); - last_pushed_lsn =0 ; + *last_lsn =0 ;return tout; }
@@ -279,7 +280,6 @@ xfsaild_push(* prevents use from spinning when we can't do anything or there is * lots of contention on the AIL lists. */ - tout =10 ; lsn = lip->li_lsn; flush_log = stuck = count =0 ;while ((XFS_LSN_CMP (lip->li_lsn, target) <0 )) {
@@ -376,14 +376,14 @@ xfsaild_push(if (!count) {/* We're past our target or empty, so idle */ - tout =1000 ; + last_pushed_lsn =0 ; }else if (XFS_LSN_CMP (lsn, target) >=0 ) {/* * We reached the target so wait a bit longer for I/O to * complete and remove pushed items from the AIL before we * start the next scan from the start of the AIL. */ - tout +=20 ; + tout =50 ; last_pushed_lsn =0 ; }else if ((stuck *100 ) / count >90 ) {/*
@@ -395,11 +395,14 @@ xfsaild_push(* Backoff a bit more to allow some I/O to complete before * continuing from where we were. */ - tout +=10 ; + tout =20 ; + }else { +/* more to do, but wait a short while before continuing */ + tout =10 ; } *last_lsn = last_pushed_lsn;return tout; -}/* xfsaild_push */ +}/*
Signature · 6 lines
1.6.5 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 2/3] XFS: Don't wake the aild once per second
Quoted 7 lines · Dave Chinner
Now that the AIL push algorithm is traversal safe, we don't need a watchdog function in the xfsaild to catch pushes that fail to make progress. Remove the watchdog timeout and make pushes purely driven by demand. This will remove the once-per-second wakeup that is seen when the filesystem is idle and make laptop power misers happy.
Signed-off-by Dave Chinner <[email protected]>
Looks good,
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 3/3 XFS: Don't wake xfsbufd when idle
In reply to Dave ChinnerThe xfsbufd wakes every xfsbufd_centisecs (once per second by default) for each filesystem even when the filesystem is idle. If the xfsbufd has nothing to do, put it into a long term sleep and only wake it up when there is work pending (i.e. dirty buffers to flush soon). This will make laptop power misers happy.
--- fs/xfs/linux-2.6/xfs_buf.c | 20 +++++++++++++++----- 1 files changed, 15 insertions(+), 5 deletions(-)
fs/xfs/linux-2.6/xfs_buf.c +15 -5
@@ -1595,6 +1595,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 +1649,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 +1715,9 @@ xfsbufd(set_freezable (); do { + long age = xfs_buf_age_centisecs * msecs_to_jiffies(10); + long tout = age; + if (unlikely(freezing(current))) { set_bit(XBT_FORCE_SLEEP, &target->bt_flags); refrigerator();
@@ -1715,12 +1725,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);
Signature · 6 lines
1.6.5 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 3/3] XFS: Don't wake xfsbufd when idle
Quoted 7 lines · Dave Chinner
The xfsbufd wakes every
xfsbufd_centisecs(once per second by default) for each filesystem even when the filesystem is idle. If the xfsbufd has nothing to do, put it into a long term sleep and only wake it up when there is work pending (i.e. dirty buffers to flush soon). This will make laptop power misers happy.Signed-off-by Dave Chinner <[email protected]>
Looks good,
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
RE: [PATCH 3/3] XFS: Don't wake xfsbufd when idle
In reply to Dave ChinnerQuoted 5 lines · Dave Chinner
The xfsbufd wakes every
xfsbufd_centisecs(once per second by default) for each filesystem even when the filesystem is idle. If the xfsbufd has nothing to do, put it into a long term sleep and only wake it up when there is work pending (i.e. dirty buffers to flush soon). This will make laptop power misers happy.
Patch generally looks good but I have a question, below.
Quoted 31 lines
Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/linux-2.6/xfs_buf.c | 20 +++++++++++++++----- 1 files changed, 15 insertions(+), 5 deletions(-)fs/xfs/linux-2.6/xfs_buf.c +7
-0@@ -1595,6 +1595,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 +1649,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); }
fs/xfs/linux-2.6/xfs_buf.c xfsbufd( · line 1719
Quoted 5 lines
fs/xfs/linux-2.6/xfs_buf.c +2
-0@@ -1708,6 +1715,9 @@ xfsbufd(set_freezable (); do { + long age = xfs_buf_age_centisecs * msecs_to_jiffies(10); + long tout = age;
Why do you switch from using xfs_buf_timer_centisecs to using xfs_buf_age_centisecs for the timeout (in the non-empty delwrite queue case)?
fs/xfs/linux-2.6/xfs_buf.c xfsbufd( · line 1719
Quoted 10 lines
fs/xfs/linux-2.6/xfs_buf.c +1
-2+if (unlikely (freezing (current))) {set_bit (XBT_FORCE_SLEEP , &target->bt_flags);refrigerator ();@@ -1715,12 +1725,12 @@ xfsbufd(clear_bit (XBT_FORCE_SLEEP , &target->bt_flags); } -schedule_timeout_interruptible ( - xfs_buf_timer_centisecs *msecs_to_jiffies (10 ));
Here is where the timeout was computed previously.
fs/xfs/linux-2.6/xfs_buf.c xfsbufd( · line 1730
Quoted 6 lines
fs/xfs/linux-2.6/xfs_buf.c +3
-3- -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 ;
Effect of the timout change is here...
fs/xfs/linux-2.6/xfs_buf.c xfsbufd( · line 1736
Quoted 6 lines
fs/xfs/linux-2.6/xfs_buf.c +2
-0+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);
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH v2 1/1 XFS: Don't wake xfsbufd when idle
Quoted 9 lines · Alex Elder
Quoted 5 lines · Dave Chinner
The xfsbufd wakes every
xfsbufd_centisecs(once per second by default) for each filesystem even when the filesystem is idle. If the xfsbufd has nothing to do, put it into a long term sleep and only wake it up when there is work pending (i.e. dirty buffers to flush soon). This will make laptop power misers happy.Patch generally looks good but I have a question, below.
Quoted 7 lines
Review
Quoted 3 lines
(quoted diff) +2
-0do { + long age = xfs_buf_age_centisecs * msecs_to_jiffies(10); + long tout = age;Why do you switch from using
xfs_buf_timer_centisecsto usingxfs_buf_age_centisecsfor the timeout (in the non-empty delwrite queue case)?
Because it's a bug? It should be xfs_buf_timer_centisecs here. Good catch, Alex. :)
Updated patch below
Cheers,
Dave.
Signature · 16 lines
Dave Chinner [email protected] XFS: Don't wake xfsbufd when idle V2 The xfsbufd wakes every xfsbufd_centisecs (once per second by default) for each filesystem even when the filesystem is idle. If the xfsbufd has nothing to do, put it into a long term sleep and only wake it up when there is work pending (i.e. dirty buffers to flush soon). This will make laptop power misers happy. --- V2: fix xfsbufd timer interval fs/xfs/linux-2.6/xfs_buf.c | 20 +++++++++++++++----- 1 files changed, 15 insertions(+), 5 deletions(-)
fs/xfs/linux-2.6/xfs_buf.c +15 -5
@@ -1595,6 +1595,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 +1649,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 +1715,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 +1725,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);
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
RE: [PATCH V2] XFS: Don't wake xfsbufd when idle
Quoted 18 lines · Dave Chinner
Quoted 9 lines · Alex Elder
Quoted 5 lines · Dave Chinner
The xfsbufd wakes every
xfsbufd_centisecs(once per second by default) for each filesystem even when the filesystem is idle. If the xfsbufd has nothing to do, put it into a long term sleep and only wake it up when there is work pending (i.e. dirty buffers to flush soon). This will make laptop power misers happy.Patch generally looks good but I have a question, below.
Quoted 7 lines
fs/xfs/linux-2.6/xfs_buf.c xfsbufd(
Quoted 3 lines
fs/xfs/linux-2.6/xfs_buf.c +2
-0do { + long age = xfs_buf_age_centisecs * msecs_to_jiffies(10); + long tout = age;Why do you switch from using
xfs_buf_timer_centisecsto usingxfs_buf_age_centisecsfor the timeout (in the non-empty delwrite queue case)?
Quoted 8 lines
Because it's a bug? It should be
xfs_buf_timer_centisecshere. Good catch, Alex. :)Updated patch below
Cheers,
Dave.
Looks good.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs