|
@@ -68,6 +68,12 @@ static inline long sync_writeback_pages(void)
|
|
*/
|
|
*/
|
|
int dirty_background_ratio = 5;
|
|
int dirty_background_ratio = 5;
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * dirty_background_bytes starts at 0 (disabled) so that it is a function of
|
|
|
|
+ * dirty_background_ratio * the amount of dirtyable memory
|
|
|
|
+ */
|
|
|
|
+unsigned long dirty_background_bytes;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* free highmem will not be subtracted from the total free memory
|
|
* free highmem will not be subtracted from the total free memory
|
|
* for calculating free ratios if vm_highmem_is_dirtyable is true
|
|
* for calculating free ratios if vm_highmem_is_dirtyable is true
|
|
@@ -79,6 +85,12 @@ int vm_highmem_is_dirtyable;
|
|
*/
|
|
*/
|
|
int vm_dirty_ratio = 10;
|
|
int vm_dirty_ratio = 10;
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * vm_dirty_bytes starts at 0 (disabled) so that it is a function of
|
|
|
|
+ * vm_dirty_ratio * the amount of dirtyable memory
|
|
|
|
+ */
|
|
|
|
+unsigned long vm_dirty_bytes;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* The interval between `kupdate'-style writebacks, in jiffies
|
|
* The interval between `kupdate'-style writebacks, in jiffies
|
|
*/
|
|
*/
|
|
@@ -135,23 +147,75 @@ static int calc_period_shift(void)
|
|
{
|
|
{
|
|
unsigned long dirty_total;
|
|
unsigned long dirty_total;
|
|
|
|
|
|
- dirty_total = (vm_dirty_ratio * determine_dirtyable_memory()) / 100;
|
|
|
|
|
|
+ if (vm_dirty_bytes)
|
|
|
|
+ dirty_total = vm_dirty_bytes / PAGE_SIZE;
|
|
|
|
+ else
|
|
|
|
+ dirty_total = (vm_dirty_ratio * determine_dirtyable_memory()) /
|
|
|
|
+ 100;
|
|
return 2 + ilog2(dirty_total - 1);
|
|
return 2 + ilog2(dirty_total - 1);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * update the period when the dirty ratio changes.
|
|
|
|
|
|
+ * update the period when the dirty threshold changes.
|
|
*/
|
|
*/
|
|
|
|
+static void update_completion_period(void)
|
|
|
|
+{
|
|
|
|
+ int shift = calc_period_shift();
|
|
|
|
+ prop_change_shift(&vm_completions, shift);
|
|
|
|
+ prop_change_shift(&vm_dirties, shift);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int dirty_background_ratio_handler(struct ctl_table *table, int write,
|
|
|
|
+ struct file *filp, void __user *buffer, size_t *lenp,
|
|
|
|
+ loff_t *ppos)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = proc_dointvec_minmax(table, write, filp, buffer, lenp, ppos);
|
|
|
|
+ if (ret == 0 && write)
|
|
|
|
+ dirty_background_bytes = 0;
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int dirty_background_bytes_handler(struct ctl_table *table, int write,
|
|
|
|
+ struct file *filp, void __user *buffer, size_t *lenp,
|
|
|
|
+ loff_t *ppos)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos);
|
|
|
|
+ if (ret == 0 && write)
|
|
|
|
+ dirty_background_ratio = 0;
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
int dirty_ratio_handler(struct ctl_table *table, int write,
|
|
int dirty_ratio_handler(struct ctl_table *table, int write,
|
|
struct file *filp, void __user *buffer, size_t *lenp,
|
|
struct file *filp, void __user *buffer, size_t *lenp,
|
|
loff_t *ppos)
|
|
loff_t *ppos)
|
|
{
|
|
{
|
|
int old_ratio = vm_dirty_ratio;
|
|
int old_ratio = vm_dirty_ratio;
|
|
- int ret = proc_dointvec_minmax(table, write, filp, buffer, lenp, ppos);
|
|
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = proc_dointvec_minmax(table, write, filp, buffer, lenp, ppos);
|
|
if (ret == 0 && write && vm_dirty_ratio != old_ratio) {
|
|
if (ret == 0 && write && vm_dirty_ratio != old_ratio) {
|
|
- int shift = calc_period_shift();
|
|
|
|
- prop_change_shift(&vm_completions, shift);
|
|
|
|
- prop_change_shift(&vm_dirties, shift);
|
|
|
|
|
|
+ update_completion_period();
|
|
|
|
+ vm_dirty_bytes = 0;
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+int dirty_bytes_handler(struct ctl_table *table, int write,
|
|
|
|
+ struct file *filp, void __user *buffer, size_t *lenp,
|
|
|
|
+ loff_t *ppos)
|
|
|
|
+{
|
|
|
|
+ int old_bytes = vm_dirty_bytes;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos);
|
|
|
|
+ if (ret == 0 && write && vm_dirty_bytes != old_bytes) {
|
|
|
|
+ update_completion_period();
|
|
|
|
+ vm_dirty_ratio = 0;
|
|
}
|
|
}
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -365,23 +429,29 @@ void
|
|
get_dirty_limits(unsigned long *pbackground, unsigned long *pdirty,
|
|
get_dirty_limits(unsigned long *pbackground, unsigned long *pdirty,
|
|
unsigned long *pbdi_dirty, struct backing_dev_info *bdi)
|
|
unsigned long *pbdi_dirty, struct backing_dev_info *bdi)
|
|
{
|
|
{
|
|
- int background_ratio; /* Percentages */
|
|
|
|
- int dirty_ratio;
|
|
|
|
unsigned long background;
|
|
unsigned long background;
|
|
unsigned long dirty;
|
|
unsigned long dirty;
|
|
unsigned long available_memory = determine_dirtyable_memory();
|
|
unsigned long available_memory = determine_dirtyable_memory();
|
|
struct task_struct *tsk;
|
|
struct task_struct *tsk;
|
|
|
|
|
|
- dirty_ratio = vm_dirty_ratio;
|
|
|
|
- if (dirty_ratio < 5)
|
|
|
|
- dirty_ratio = 5;
|
|
|
|
|
|
+ if (vm_dirty_bytes)
|
|
|
|
+ dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE);
|
|
|
|
+ else {
|
|
|
|
+ int dirty_ratio;
|
|
|
|
|
|
- background_ratio = dirty_background_ratio;
|
|
|
|
- if (background_ratio >= dirty_ratio)
|
|
|
|
- background_ratio = dirty_ratio / 2;
|
|
|
|
|
|
+ dirty_ratio = vm_dirty_ratio;
|
|
|
|
+ if (dirty_ratio < 5)
|
|
|
|
+ dirty_ratio = 5;
|
|
|
|
+ dirty = (dirty_ratio * available_memory) / 100;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dirty_background_bytes)
|
|
|
|
+ background = DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE);
|
|
|
|
+ else
|
|
|
|
+ background = (dirty_background_ratio * available_memory) / 100;
|
|
|
|
|
|
- background = (background_ratio * available_memory) / 100;
|
|
|
|
- dirty = (dirty_ratio * available_memory) / 100;
|
|
|
|
|
|
+ if (background >= dirty)
|
|
|
|
+ background = dirty / 2;
|
|
tsk = current;
|
|
tsk = current;
|
|
if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) {
|
|
if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) {
|
|
background += background / 4;
|
|
background += background / 4;
|