Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Wed, 16 Oct 2002 11:23:26 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Wed, 16 Oct 2002 11:23:25 -0400 Received: from dell-paw-3.cambridge.redhat.com ([195.224.55.237]:55286 "EHLO executor.cambridge.redhat.com") by vger.kernel.org with ESMTP id ; Wed, 16 Oct 2002 11:23:20 -0400 From: David Howells To: riel@surriel.com Cc: dhowells@redhat.com, linux-kernel@vger.kernel.org Subject: [PATCH] do_generic_file_read / readahead adjustments User-Agent: EMH/1.14.1 SEMI/1.14.3 (Ushinoya) FLIM/1.14.3 (=?ISO-8859-4?Q?Unebigory=F2mae?=) APEL/10.3 Emacs/21.2 (i686-pc-linux-gnu) MULE/5.0 (SAKAKI) MIME-Version: 1.0 (generated by SEMI 1.14.3 - "Ushinoya") Content-Type: text/plain; charset=US-ASCII Date: Wed, 16 Oct 2002 16:29:13 +0100 Message-ID: <30738.1034782153@warthog.cambridge.redhat.com> Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 12896 Lines: 361 The attached patch does the following three things: (1) Makes the functions in mm/readahead.c only use struct file* to pass to readpage(). address_mapping* and file_ra_state* are used instead to keep track of readahead stuff. (2) Adds a new function do_generic_mapping_read() that is similar to do_generic_file_read(), except that it uses a mapping pointer and a readahead state pointer to access a file. The file* is only used to pass to readpage(). (3) Turns do_generic_file_read() into an inline function in linux/fs.h that simply wraps do_generic_mapping_read(). This should mean that it is no longer necessary to have a struct file to access a file in this manner. Just an inode or address space should be sufficient. It also means alternate read-ahead structures can be maintained. It may be worth adding a read-ahead struct init function too. David diff -u -x '*.o' -x '*.cmd' -x '*~' linux-2.5.43/include/linux/fs.h linux-readahead-2543/include/linux/fs.h --- linux-2.5.43/include/linux/fs.h 2002-10-16 09:26:02.000000000 +0100 +++ linux-readahead-2543/include/linux/fs.h 2002-10-16 16:16:11.000000000 +0100 @@ -1251,7 +1251,8 @@ ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *ppos); extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t); -extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t); +extern void do_generic_mapping_read(struct address_space *, struct file_ra_state *, struct file *, + loff_t *, read_descriptor_t *, read_actor_t); extern ssize_t generic_file_direct_IO(int rw, struct file *file, const struct iovec *iov, loff_t offset, unsigned long nr_segs); extern int generic_direct_IO(int rw, struct inode *inode, const struct iovec @@ -1268,6 +1269,18 @@ extern int generic_vm_writeback(struct page *page, struct writeback_control *wbc); +static inline void do_generic_file_read(struct file * filp, loff_t *ppos, + read_descriptor_t * desc, + read_actor_t actor) +{ + do_generic_mapping_read(filp->f_dentry->d_inode->i_mapping, + &filp->f_ra, + filp, + ppos, + desc, + actor); +} + extern struct file_operations generic_ro_fops; extern int vfs_readlink(struct dentry *, char *, int, const char *); diff -u -x '*.o' -x '*.cmd' -x '*~' linux-2.5.43/include/linux/mm.h linux-readahead-2543/include/linux/mm.h --- linux-2.5.43/include/linux/mm.h 2002-10-16 09:26:02.000000000 +0100 +++ linux-readahead-2543/include/linux/mm.h 2002-10-16 15:58:20.000000000 +0100 @@ -513,11 +513,18 @@ /* readahead.c */ #define VM_MAX_READAHEAD 128 /* kbytes */ #define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */ -int do_page_cache_readahead(struct file *file, +int do_page_cache_readahead(struct address_space *mapping, struct file *filp, unsigned long offset, unsigned long nr_to_read); -void page_cache_readahead(struct file *file, unsigned long offset); -void page_cache_readaround(struct file *file, unsigned long offset); -void handle_ra_miss(struct file *file); +void page_cache_readahead(struct address_space *mapping, + struct file_ra_state *ra, + struct file *filp, + unsigned long offset); +void page_cache_readaround(struct address_space *mapping, + struct file_ra_state *ra, + struct file *filp, + unsigned long offset); +void handle_ra_miss(struct address_space *mapping, + struct file_ra_state *ra); /* Do stack extension */ extern int expand_stack(struct vm_area_struct * vma, unsigned long address); diff -ur -x '*.o' -x '*.cmd' -x '*~' linux-2.5.43/kernel/ksyms.c linux-readahead-2543/kernel/ksyms.c --- linux-2.5.43/kernel/ksyms.c 2002-10-16 09:26:03.000000000 +0100 +++ linux-readahead-2543/kernel/ksyms.c 2002-10-16 16:17:30.000000000 +0100 @@ -229,7 +229,7 @@ EXPORT_SYMBOL(generic_block_bmap); EXPORT_SYMBOL(generic_file_read); EXPORT_SYMBOL(generic_file_sendfile); -EXPORT_SYMBOL(do_generic_file_read); +EXPORT_SYMBOL(do_generic_mapping_read); EXPORT_SYMBOL(generic_file_write); EXPORT_SYMBOL(generic_file_write_nolock); EXPORT_SYMBOL(generic_file_mmap); diff -ur -x '*.o' -x '*.cmd' -x '*~' linux-2.5.43/mm/filemap.c linux-readahead-2543/mm/filemap.c --- linux-2.5.43/mm/filemap.c 2002-10-16 09:26:03.000000000 +0100 +++ linux-readahead-2543/mm/filemap.c 2002-10-16 16:18:17.000000000 +0100 @@ -572,10 +572,14 @@ * This is really ugly. But the goto's actually try to clarify some * of the logic when it comes to error handling etc. * - note the struct file * is only passed for the use of readpage */ -void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor) +void do_generic_mapping_read(struct address_space *mapping, + struct file_ra_state *ra, + struct file * filp, + loff_t *ppos, + read_descriptor_t * desc, + read_actor_t actor) { - struct address_space *mapping = filp->f_dentry->d_inode->i_mapping; struct inode *inode = mapping->host; unsigned long index, offset; struct page *cached_page; @@ -599,7 +603,7 @@ break; } - page_cache_readahead(filp, index); + page_cache_readahead(mapping, ra, filp, index); nr = nr - offset; @@ -611,7 +615,7 @@ page = radix_tree_lookup(&mapping->page_tree, index); if (!page) { read_unlock(&mapping->page_lock); - handle_ra_miss(filp); + handle_ra_miss(mapping,ra); goto no_cached_page; } page_cache_get(page); @@ -947,9 +951,9 @@ } static ssize_t -do_readahead(struct file *file, unsigned long index, unsigned long nr) +do_readahead(struct address_space *mapping, struct file *filp, + unsigned long index, unsigned long nr) { - struct address_space *mapping = file->f_dentry->d_inode->i_mapping; unsigned long max; unsigned long active; unsigned long inactive; @@ -963,7 +967,7 @@ if (nr > max) nr = max; - do_page_cache_readahead(file, index, nr); + do_page_cache_readahead(mapping, filp, index, nr); return 0; } @@ -976,10 +980,11 @@ file = fget(fd); if (file) { if (file->f_mode & FMODE_READ) { + struct address_space *mapping = file->f_dentry->d_inode->i_mapping; unsigned long start = offset >> PAGE_CACHE_SHIFT; unsigned long end = (offset + count - 1) >> PAGE_CACHE_SHIFT; unsigned long len = end - start + 1; - ret = do_readahead(file, start, len); + ret = do_readahead(mapping, file, start, len); } fput(file); } @@ -1000,6 +1005,7 @@ int error; struct file *file = area->vm_file; struct address_space *mapping = file->f_dentry->d_inode->i_mapping; + struct file_ra_state *ra = &file->f_ra; struct inode *inode = mapping->host; struct page *page; unsigned long size, pgoff, endoff; @@ -1032,7 +1038,7 @@ */ if (VM_SequentialReadHint(area)) { did_readahead = 1; - page_cache_readahead(area->vm_file, pgoff); + page_cache_readahead(mapping, ra, file, pgoff); } /* @@ -1041,7 +1047,7 @@ */ if ((pgoff < size) && !VM_RandomReadHint(area)) { did_readahead = 1; - page_cache_readaround(file, pgoff); + page_cache_readaround(mapping, ra, file, pgoff); } /* @@ -1051,7 +1057,7 @@ page = find_get_page(mapping, pgoff); if (!page) { if (did_readahead) { - handle_ra_miss(file); + handle_ra_miss(mapping,ra); did_readahead = 0; } goto no_cached_page; diff -ur -x '*.o' -x '*.cmd' -x '*~' linux-2.5.43/mm/madvise.c linux-readahead-2543/mm/madvise.c --- linux-2.5.43/mm/madvise.c 2002-09-27 22:49:16.000000000 +0100 +++ linux-readahead-2543/mm/madvise.c 2002-10-16 16:02:53.000000000 +0100 @@ -80,7 +80,7 @@ if ((vma->vm_mm->rss + (end - start)) > rlim_rss) return error; - do_page_cache_readahead(file, start, end - start); + do_page_cache_readahead(file->f_dentry->d_inode->i_mapping, file, start, end - start); return 0; } diff -ur -x '*.o' -x '*.cmd' -x '*~' linux-2.5.43/mm/readahead.c linux-readahead-2543/mm/readahead.c --- linux-2.5.43/mm/readahead.c 2002-09-27 22:49:04.000000000 +0100 +++ linux-readahead-2543/mm/readahead.c 2002-10-16 16:02:23.000000000 +0100 @@ -22,18 +22,18 @@ /* * Return max readahead size for this inode in number-of-pages. */ -static inline unsigned long get_max_readahead(struct file *file) +static inline unsigned long get_max_readahead(struct file_ra_state *ra) { - return file->f_ra.ra_pages; + return ra->ra_pages; } -static inline unsigned long get_min_readahead(struct file *file) +static inline unsigned long get_min_readahead(struct file_ra_state *ra) { return (VM_MIN_READAHEAD * 1024) / PAGE_CACHE_SIZE; } static int -read_pages(struct file *file, struct address_space *mapping, +read_pages(struct address_space *mapping, struct file *filp, struct list_head *pages, unsigned nr_pages) { unsigned page_idx; @@ -48,7 +48,7 @@ struct page *page = list_entry(pages->prev, struct page, list); list_del(&page->list); if (!add_to_page_cache(page, mapping, page->index)) { - mapping->a_ops->readpage(file, page); + mapping->a_ops->readpage(filp, page); if (!pagevec_add(&lru_pvec, page)) __pagevec_lru_add(&lru_pvec); } else { @@ -134,10 +134,11 @@ * * Returns the number of pages which actually had IO started against them. */ -int do_page_cache_readahead(struct file *file, - unsigned long offset, unsigned long nr_to_read) +int do_page_cache_readahead(struct address_space *mapping, + struct file *filp, + unsigned long offset, + unsigned long nr_to_read) { - struct address_space *mapping = file->f_dentry->d_inode->i_mapping; struct inode *inode = mapping->host; struct page *page; unsigned long end_index; /* The last page we want to read */ @@ -181,7 +182,7 @@ * will then handle the error. */ if (ret) { - read_pages(file, mapping, &page_pool, ret); + read_pages(mapping, filp, &page_pool, ret); blk_run_queues(); } BUG_ON(!list_empty(&page_pool)); @@ -216,9 +217,9 @@ * page_cache_readahead is the main function. If performs the adaptive * readahead window size management and submits the readahead I/O. */ -void page_cache_readahead(struct file *file, unsigned long offset) +void page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, + struct file *filp, unsigned long offset) { - struct file_ra_state *ra = &file->f_ra; unsigned max; unsigned min; unsigned orig_next_size; @@ -239,11 +240,11 @@ if (ra->next_size == -1UL) goto out; /* Maximally shrunk */ - max = get_max_readahead(file); + max = get_max_readahead(ra); if (max == 0) goto out; /* No readahead */ - min = get_min_readahead(file); + min = get_min_readahead(ra); orig_next_size = ra->next_size; if (ra->next_size == 0 && offset == 0) { @@ -316,7 +317,8 @@ ra->ahead_start = 0; /* Invalidate these */ ra->ahead_size = 0; - actual = do_page_cache_readahead(file, offset, ra->size); + actual = do_page_cache_readahead(mapping, filp, offset, + ra->size); check_ra_success(ra, ra->size, actual, orig_next_size); } else { /* @@ -327,7 +329,7 @@ if (ra->ahead_start == 0) { ra->ahead_start = ra->start + ra->size; ra->ahead_size = ra->next_size; - actual = do_page_cache_readahead(file, + actual = do_page_cache_readahead(mapping, filp, ra->ahead_start, ra->ahead_size); check_ra_success(ra, ra->ahead_size, actual, orig_next_size); @@ -342,12 +344,11 @@ * but somewhat ascending. So readaround favours pages beyond the target one. * We also boost the window size, as it can easily shrink due to misses. */ -void page_cache_readaround(struct file *file, unsigned long offset) +void page_cache_readaround(struct address_space *mapping, struct file_ra_state *ra, + struct file *filp, unsigned long offset) { - struct file_ra_state *ra = &file->f_ra; - if (ra->next_size != -1UL) { - const unsigned long min = get_min_readahead(file) * 2; + const unsigned long min = get_min_readahead(ra) * 2; unsigned long target; unsigned long backward; @@ -365,7 +366,7 @@ target = 0; else target -= backward; - page_cache_readahead(file, target); + page_cache_readahead(mapping, ra, filp, target); } } @@ -383,10 +384,9 @@ * that the readahead window size will stabilise around the maximum level at * which there is no thrashing. */ -void handle_ra_miss(struct file *file) +void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra) { - struct file_ra_state *ra = &file->f_ra; - const unsigned long min = get_min_readahead(file); + const unsigned long min = get_min_readahead(ra); if (ra->next_size == -1UL) { ra->next_size = min; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/