aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorplougher <plougher>2009-01-31 07:29:10 +0000
committerMohamad Ayyash <mkayyash@google.com>2015-02-23 12:34:11 -0800
commit93911cbac69fbc999c52939d8d8b10698cb14051 (patch)
tree3d71bec78c09956871130377627ccdde12c0d3c3 /kernel
parenta96ba00226795862b5e1cb7d8242d4576c374ada (diff)
downloadsquashfs-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.c16
-rw-r--r--kernel/fs/squashfs/file.c19
-rw-r--r--kernel/fs/squashfs/squashfs.h4
-rw-r--r--kernel/fs/squashfs/squashfs_fs_sb.h3
-rw-r--r--kernel/fs/squashfs/super.c9
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;