diff options
author | plougher <plougher> | 2009-01-31 07:29:10 +0000 |
---|---|---|
committer | Mohamad Ayyash <mkayyash@google.com> | 2015-02-23 12:34:11 -0800 |
commit | 93911cbac69fbc999c52939d8d8b10698cb14051 (patch) | |
tree | 3d71bec78c09956871130377627ccdde12c0d3c3 /kernel | |
parent | a96ba00226795862b5e1cb7d8242d4576c374ada (diff) | |
download | squashfs-tools-93911cbac69fbc999c52939d8d8b10698cb14051.tar.gz |
Use the squashfs cache to read datablocks, rather than directly call
squashfs_read_data(). This improves performance in race conditions
where squashfs_readpage is called simultaneously to read pages in the same
datablock.
Also when vmalloc is replaced with multiple PAGE_CACHE_SIZEd pages, it
centralises necessary support to the squashfs cache code.
Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/fs/squashfs/cache.c | 16 | ||||
-rw-r--r-- | kernel/fs/squashfs/file.c | 19 | ||||
-rw-r--r-- | kernel/fs/squashfs/squashfs.h | 4 | ||||
-rw-r--r-- | kernel/fs/squashfs/squashfs_fs_sb.h | 3 | ||||
-rw-r--r-- | kernel/fs/squashfs/super.c | 9 |
5 files changed, 33 insertions, 18 deletions
diff --git a/kernel/fs/squashfs/cache.c b/kernel/fs/squashfs/cache.c index d121f31..bfd9845 100644 --- a/kernel/fs/squashfs/cache.c +++ b/kernel/fs/squashfs/cache.c @@ -313,3 +313,19 @@ void release_cached_fragment(struct squashfs_sb_info *msblk, squashfs_cache_put(msblk->fragment_cache, fragment); } + +struct squashfs_cache_entry *get_datablock(struct super_block *sb, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = sb->s_fs_info; + + return squashfs_cache_get(sb, msblk->read_page, start_block, length); +} + + +void release_datablock(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *datablock) +{ + squashfs_cache_put(msblk->read_page, datablock); +} + diff --git a/kernel/fs/squashfs/file.c b/kernel/fs/squashfs/file.c index 136663c..019603c 100644 --- a/kernel/fs/squashfs/file.c +++ b/kernel/fs/squashfs/file.c @@ -382,8 +382,8 @@ static int squashfs_readpage(struct file *file, struct page *page) long long block; unsigned int bsize = 0, i; int bytes, index = page->index >> (msblk->block_log - PAGE_CACHE_SHIFT); - struct squashfs_cache_entry *fragment = NULL; - void *pageaddr, *data_ptr = msblk->read_page; + struct squashfs_cache_entry *fragment = NULL, *datablock = NULL; + void *pageaddr, *data_ptr = NULL; int mask = (1 << (msblk->block_log - PAGE_CACHE_SHIFT)) - 1; int start_index = page->index & ~mask; @@ -414,21 +414,18 @@ static int squashfs_readpage(struct file *file, struct page *page) msblk->block_size; sparse = 1; } else { - mutex_lock(&msblk->read_page_mutex); - /* * Read and decompress datablock. */ - bytes = squashfs_read_data(inode->i_sb, - msblk->read_page, block, bsize, NULL, - msblk->block_size); - - if (bytes < 0) { + datablock = get_datablock(inode->i_sb, block, bsize); + if (datablock->error) { ERROR("Unable to read page, block %llx, size %x" "\n", block, bsize); - mutex_unlock(&msblk->read_page_mutex); + release_datablock(msblk, datablock); goto error_out; } + bytes = datablock->length; + data_ptr = datablock->data; } } else { /* @@ -488,7 +485,7 @@ skip_page: if (fragment) release_cached_fragment(msblk, fragment); else if (!sparse) - mutex_unlock(&msblk->read_page_mutex); + release_datablock(msblk, datablock); return 0; diff --git a/kernel/fs/squashfs/squashfs.h b/kernel/fs/squashfs/squashfs.h index b852934..536cecc 100644 --- a/kernel/fs/squashfs/squashfs.h +++ b/kernel/fs/squashfs/squashfs.h @@ -48,6 +48,10 @@ extern struct squashfs_cache_entry *get_cached_fragment(struct super_block *, long long, int); extern void release_cached_fragment(struct squashfs_sb_info *, struct squashfs_cache_entry *); +extern struct squashfs_cache_entry *get_datablock(struct super_block *, + long long, int); +extern void release_datablock(struct squashfs_sb_info *, + struct squashfs_cache_entry *); /* export.c */ extern __le64 *read_inode_lookup_table(struct super_block *, long long, diff --git a/kernel/fs/squashfs/squashfs_fs_sb.h b/kernel/fs/squashfs/squashfs_fs_sb.h index cc9fd5d..18e5af4 100644 --- a/kernel/fs/squashfs/squashfs_fs_sb.h +++ b/kernel/fs/squashfs/squashfs_fs_sb.h @@ -55,13 +55,12 @@ struct squashfs_sb_info { int devblksize_log2; struct squashfs_cache *block_cache; struct squashfs_cache *fragment_cache; + struct squashfs_cache *read_page; int next_meta_index; __le64 *id_table; __le64 *fragment_index; unsigned int *fragment_index_2; - char *read_page; struct mutex read_data_mutex; - struct mutex read_page_mutex; struct mutex meta_index_mutex; struct meta_index *meta_index; z_stream stream; diff --git a/kernel/fs/squashfs/super.c b/kernel/fs/squashfs/super.c index 65a5fbd..44f94aa 100644 --- a/kernel/fs/squashfs/super.c +++ b/kernel/fs/squashfs/super.c @@ -102,7 +102,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) msblk->devblksize_log2 = ffz(~msblk->devblksize); mutex_init(&msblk->read_data_mutex); - mutex_init(&msblk->read_page_mutex); mutex_init(&msblk->meta_index_mutex); /* @@ -201,7 +200,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; /* Allocate read_page block */ - msblk->read_page = vmalloc(msblk->block_size); + msblk->read_page = squashfs_cache_init("datablock", 1, msblk->block_size, 1); if (msblk->read_page == NULL) { ERROR("Failed to allocate read_page block\n"); goto failed_mount; @@ -281,10 +280,10 @@ allocate_root: failed_mount: squashfs_cache_delete(msblk->block_cache); squashfs_cache_delete(msblk->fragment_cache); + squashfs_cache_delete(msblk->read_page); kfree(msblk->inode_lookup_table); kfree(msblk->fragment_index); kfree(msblk->id_table); - vfree(msblk->read_page); vfree(msblk->stream.workspace); kfree(sb->s_fs_info); sb->s_fs_info = NULL; @@ -330,7 +329,7 @@ static void squashfs_put_super(struct super_block *sb) struct squashfs_sb_info *sbi = sb->s_fs_info; squashfs_cache_delete(sbi->block_cache); squashfs_cache_delete(sbi->fragment_cache); - vfree(sbi->read_page); + squashfs_cache_delete(sbi->read_page); kfree(sbi->id_table); kfree(sbi->fragment_index); kfree(sbi->meta_index); @@ -390,7 +389,7 @@ static int __init init_squashfs_fs(void) return err; } - printk(KERN_INFO "squashfs: version 4.0 (2008/10/28) " + printk(KERN_INFO "squashfs: version 4.0 (2008/11/14) " "Phillip Lougher\n"); return 0; |