do_generic_file_read / readahead adjustments
Subsystems (5)
PATCH 1/1 do_generic_file_read / readahead adjustments
Hi Linus,
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.
The reason I want this is that I'm writing a general cache manager for filesystems such as AFS, NFSv4, and Lustre. Block devices are made available to the "cache manager" by means of a filesystem that can be mounted. I'm storing meta data in an inode in the cache, but to scan this at the moment I need to gain a "struct file" to use with do_generic_file_read().
This involves either creating a dummy dentry and struct file (which will cause Al Viro to come looking for me with a shotgun), or to use an extra auxilliary filesystem mounted with do_kern_mount(), neither of which are particularly appealing.
This patch is the alternative... it provides a function that I can pass an address_space to. This also allows me to make use of readahead semantics without having to reinvent them for myself.
Quoted 9 lines · Rik van Riel
Quoted 5 lines · Andrew Morton
Quoted 2 lines · David Howells
The attached patch does the following three things:
Seems sensible. Is there something out there which actually uses this?
I think David has a few things up his sleeve. The patch looks sensible.
Are you willing to take this from me directly, or do I need to pass it via someone else?
David
include/linux/fs.h +14 -1
@@ -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 *);
include/linux/mm.h +11 -4
@@ -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);
kernel/ksyms.c +1 -1
@@ -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);
mm/filemap.c +17 -11
@@ -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;
mm/madvise.c +1 -1
@@ -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 ; }
mm/readahead.c +23 -23
128 lines not on this page · raw message