aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorWu Fengguang <fengguang.wu@intel.com>2011-12-02 11:21:33 -0500
committerWu Fengguang <fengguang.wu@intel.com>2011-12-07 21:49:27 -0500
commitc5c6343c4d75f9d3226e05a72e7861e967fc8099 (patch)
treee31d6d748b347314d7ef64fac8f14acc36dfb701 /mm
parentaed21ad28b1323b2807faea019e5ac388a7bc837 (diff)
writeback: permit through good bdi even when global dirty exceeded
On a system with 1 local mount and 1 NFS mount, if the NFS server becomes not responding when dd to the NFS mount, the NFS dirty pages may exceed the global dirty limit and _every_ task involving writing will be blocked. The whole system appears unresponsive. The workaround is to permit through the bdi's that only has a small number of dirty pages. The number chosen (bdi_stat_error pages) is not enough to enable the local disk to run in optimal throughput, however is enough to make the system responsive on a broken NFS mount. The user can then kill the dirtiers on the NFS mount and increase the global dirty limit to bring up the local disk's throughput. It risks allowing dirty pages to grow much larger than the global dirty limit when there are 1000+ mounts, however that's very unlikely to happen, especially in low memory profiles. Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Diffstat (limited to 'mm')
-rw-r--r--mm/page-writeback.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 155efca4c123..17403e3a7c89 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1148,6 +1148,19 @@ pause:
1148 if (task_ratelimit) 1148 if (task_ratelimit)
1149 break; 1149 break;
1150 1150
1151 /*
1152 * In the case of an unresponding NFS server and the NFS dirty
1153 * pages exceeds dirty_thresh, give the other good bdi's a pipe
1154 * to go through, so that tasks on them still remain responsive.
1155 *
1156 * In theory 1 page is enough to keep the comsumer-producer
1157 * pipe going: the flusher cleans 1 page => the task dirties 1
1158 * more page. However bdi_dirty has accounting errors. So use
1159 * the larger and more IO friendly bdi_stat_error.
1160 */
1161 if (bdi_dirty <= bdi_stat_error(bdi))
1162 break;
1163
1151 if (fatal_signal_pending(current)) 1164 if (fatal_signal_pending(current))
1152 break; 1165 break;
1153 } 1166 }