[patch] `cp /dev/zero /tmp' (patch against 2.2.9)

Andrea Arcangeli (andrea@suse.de)
Fri, 4 Jun 1999 15:35:36 +0200 (CEST)


I think the problem is the current flushing that is not able to share the
I/O bandwith with readers.

Here it is my idea that I am testing since some day ago. It completly
avoid the DoS doing `cp /dev/zero /tmp'. Now a `find` go fast near as
there wouldn't be a `cp /dev/zero /tmp' in background. It improves (or
better it gives you :) the iteractive response while kflushd is doing its
work. It seems to have no impact on normal write performances. It seems to
only avoid the readers-starvation and I am quite happy with it.

I suggest people to try this out this patch and compare a `cp /dev/zero
/tmp' with a without my patch. I suggest also to make sure that the write
performances are not decreasing. I am only worried it may looks like an
hack or a band aid, but I can't think something of better. We have tons of
buffer dirty and the writer can write them at exponential rate without
waiting for I/O completation (and that make perfect sense if there are no
readers request in act, if there are no reads we must fill the I/O
subsystem as much as possible). Readers instead "always" wait for I/O
compleataion so we must someway _stop_ the writers writing at exponential
rate otherwise we'll take the pipe fill and _no_ way for readers to go
ahead.

Patch against 2.2.9.

Index: linux/fs/buffer.c
===================================================================
RCS file: /var/cvs/linux/fs/buffer.c,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 buffer.c
--- linux/fs/buffer.c 1999/05/14 18:22:39 1.1.1.13
+++ linux/fs/buffer.c 1999/06/04 13:18:08
@@ -117,6 +117,8 @@

void wakeup_bdflush(int);

+atomic_t wait_for_IO = ATOMIC_INIT(0);
+
/*
* Rewrote the wait-routines to use the "new" wait-queue functionality,
* and getting rid of the cli-sti pairs. The wait-queue routines still
@@ -133,6 +135,7 @@

bh->b_count++;
wait.task = tsk;
+ atomic_inc(&wait_for_IO);
add_wait_queue(&bh->b_wait, &wait);
repeat:
tsk->state = TASK_UNINTERRUPTIBLE;
@@ -143,6 +146,7 @@
}
tsk->state = TASK_RUNNING;
remove_wait_queue(&bh->b_wait, &wait);
+ atomic_dec(&wait_for_IO);
bh->b_count--;
}

@@ -1636,6 +1640,8 @@
#endif
ll_rw_block(WRITE, 1, &bh);
bh->b_count--;
+ if (atomic_read(&wait_for_IO))
+ wait_on_buffer(bh);
next->b_count--;
}
}
@@ -1796,6 +1802,8 @@
if(nlist != BUF_DIRTY) ncount++;
#endif
bh->b_count--;
+ if (atomic_read(&wait_for_IO))
+ wait_on_buffer(bh);
next->b_count--;
}
}
Index: linux/mm/filemap.c
===================================================================
RCS file: /var/cvs/linux/mm/filemap.c,v
retrieving revision 1.1.1.12
diff -u -r1.1.1.12 filemap.c
--- linux/mm/filemap.c 1999/05/14 18:25:05 1.1.1.12
+++ linux/mm/filemap.c 1999/06/04 13:19:06
@@ -303,6 +303,7 @@
struct wait_queue wait;

wait.task = tsk;
+ atomic_inc(&wait_for_IO);
add_wait_queue(&page->wait, &wait);
repeat:
tsk->state = TASK_UNINTERRUPTIBLE;
@@ -313,6 +314,7 @@
}
tsk->state = TASK_RUNNING;
remove_wait_queue(&page->wait, &wait);
+ atomic_dec(&wait_for_IO);
}

#if 0
Index: linux/include/linux/fs.h
===================================================================
RCS file: /var/cvs/linux/include/linux/fs.h,v
retrieving revision 1.1.1.10
diff -u -r1.1.1.10 fs.h
--- linux/include/linux/fs.h 1999/05/14 18:24:35 1.1.1.10
+++ linux/include/linux/fs.h 1999/06/04 13:18:34
@@ -25,6 +25,7 @@

struct poll_table_struct;

+extern atomic_t wait_for_IO;

/*
* It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/