

The problem with PF_READAHEAD is that if someone does a non-GFP_ATOMIC memory
allocation we can enter page reclaim and then call writepage, while
PF_READAHEAD is set.  The block layer then drops writes or the wrong reads on
the floor.  It can cause data loss.

A fix is complex (well, intrusive).  Given that the readahead code is now
skipping the entire readahead attempt if the queue is congested, the setting
of PF_READAHEAD probably is not doing anything useful anyway, so simply
remove it.



 drivers/block/ll_rw_blk.c |    2 +-
 fs/buffer.c               |    3 +--
 include/linux/sched.h     |    1 -
 mm/readahead.c            |   11 +++--------
 4 files changed, 5 insertions(+), 12 deletions(-)

diff -puN mm/readahead.c~remove-PF_READAHEAD mm/readahead.c
--- 25/mm/readahead.c~remove-PF_READAHEAD	2003-08-06 19:53:14.000000000 -0700
+++ 25-akpm/mm/readahead.c	2003-08-06 19:53:14.000000000 -0700
@@ -298,15 +298,10 @@ int force_page_cache_readahead(struct ad
 int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
 			unsigned long offset, unsigned long nr_to_read)
 {
-	int ret = 0;
-
-	if (!bdi_read_congested(mapping->backing_dev_info)) {
-		current->flags |= PF_READAHEAD;
-		ret = __do_page_cache_readahead(mapping, filp,
+	if (!bdi_read_congested(mapping->backing_dev_info))
+		return __do_page_cache_readahead(mapping, filp,
 						offset, nr_to_read);
-		current->flags &= ~PF_READAHEAD;
-	}
-	return ret;
+	return 0;
 }
 
 /*
diff -puN fs/buffer.c~remove-PF_READAHEAD fs/buffer.c
--- 25/fs/buffer.c~remove-PF_READAHEAD	2003-08-06 19:53:14.000000000 -0700
+++ 25-akpm/fs/buffer.c	2003-08-06 19:53:14.000000000 -0700
@@ -506,8 +506,7 @@ static void end_buffer_async_read(struct
 		set_buffer_uptodate(bh);
 	} else {
 		clear_buffer_uptodate(bh);
-		if (!(current->flags & PF_READAHEAD))
-			buffer_io_error(bh);
+		buffer_io_error(bh);
 		SetPageError(page);
 	}
 
diff -puN drivers/block/ll_rw_blk.c~remove-PF_READAHEAD drivers/block/ll_rw_blk.c
--- 25/drivers/block/ll_rw_blk.c~remove-PF_READAHEAD	2003-08-06 19:53:14.000000000 -0700
+++ 25-akpm/drivers/block/ll_rw_blk.c	2003-08-06 19:53:14.000000000 -0700
@@ -1833,7 +1833,7 @@ static int __make_request(request_queue_
 
 	barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw);
 
-	ra = bio_flagged(bio, BIO_RW_AHEAD) || current->flags & PF_READAHEAD;
+	ra = bio_flagged(bio, BIO_RW_AHEAD);
 
 again:
 	insert_here = NULL;
diff -puN include/linux/sched.h~remove-PF_READAHEAD include/linux/sched.h
--- 25/include/linux/sched.h~remove-PF_READAHEAD	2003-08-06 19:53:14.000000000 -0700
+++ 25-akpm/include/linux/sched.h	2003-08-06 19:53:14.000000000 -0700
@@ -487,7 +487,6 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_SWAPOFF	0x00080000	/* I am in swapoff */
 #define PF_LESS_THROTTLE 0x00100000	/* Throttle me less: I clean memory */
 #define PF_SYNCWRITE	0x00200000	/* I am doing a sync write */
-#define PF_READAHEAD	0x00400000	/* I am doing read-ahead */
 
 #ifdef CONFIG_SMP
 extern int set_cpus_allowed(task_t *p, unsigned long new_mask);

_
