aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>2013-07-04 13:04:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 14:22:46 -0400
commit275f495dbe34300d793466a7d96c70f83fbae1bc (patch)
tree75785e0623188c52360f845419354b3b7cd67051 /fs
parenta0c1b7596323a2323d5f5c7d2404af7b58a1ef4e (diff)
hpfs: implement prefetch to improve performance
This patch implements prefetch to improve performance. It helps mostly when scanning the bitmaps to calculate free space. Signed-off-by: Mikulas Patocka <mpatocka@artax.karlin.mff.cuni.cz> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/hpfs/buffer.c33
-rw-r--r--fs/hpfs/hpfs_fn.h7
-rw-r--r--fs/hpfs/map.c19
-rw-r--r--fs/hpfs/super.c9
4 files changed, 63 insertions, 5 deletions
diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c
index f49d1498aa2e..4d0a1afa058c 100644
--- a/fs/hpfs/buffer.c
+++ b/fs/hpfs/buffer.c
@@ -7,8 +7,37 @@
7 */ 7 */
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/blkdev.h>
10#include "hpfs_fn.h" 11#include "hpfs_fn.h"
11 12
13void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)
14{
15 struct buffer_head *bh;
16 struct blk_plug plug;
17
18 if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size))
19 return;
20
21 bh = sb_find_get_block(s, secno);
22 if (bh) {
23 if (buffer_uptodate(bh)) {
24 brelse(bh);
25 return;
26 }
27 brelse(bh);
28 };
29
30 blk_start_plug(&plug);
31 while (n > 0) {
32 if (unlikely(secno >= hpfs_sb(s)->sb_fs_size))
33 break;
34 sb_breadahead(s, secno);
35 secno++;
36 n--;
37 }
38 blk_finish_plug(&plug);
39}
40
12/* Map a sector into a buffer and return pointers to it and to the buffer. */ 41/* Map a sector into a buffer and return pointers to it and to the buffer. */
13 42
14void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp, 43void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp,
@@ -18,6 +47,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head
18 47
19 hpfs_lock_assert(s); 48 hpfs_lock_assert(s);
20 49
50 hpfs_prefetch_sectors(s, secno, ahead);
51
21 cond_resched(); 52 cond_resched();
22 53
23 *bhp = bh = sb_bread(s, secno); 54 *bhp = bh = sb_bread(s, secno);
@@ -67,6 +98,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
67 return NULL; 98 return NULL;
68 } 99 }
69 100
101 hpfs_prefetch_sectors(s, secno, 4 + ahead);
102
70 qbh->data = data = kmalloc(2048, GFP_NOFS); 103 qbh->data = data = kmalloc(2048, GFP_NOFS);
71 if (!data) { 104 if (!data) {
72 printk("HPFS: hpfs_map_4sectors: out of memory\n"); 105 printk("HPFS: hpfs_map_4sectors: out of memory\n");
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index b7ae286646b5..1b398636e990 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -27,8 +27,9 @@
27#define ALLOC_FWD_MAX 128 27#define ALLOC_FWD_MAX 128
28#define ALLOC_M 1 28#define ALLOC_M 1
29#define FNODE_RD_AHEAD 16 29#define FNODE_RD_AHEAD 16
30#define ANODE_RD_AHEAD 16 30#define ANODE_RD_AHEAD 0
31#define DNODE_RD_AHEAD 4 31#define DNODE_RD_AHEAD 72
32#define COUNT_RD_AHEAD 62
32 33
33#define FREE_DNODES_ADD 58 34#define FREE_DNODES_ADD 58
34#define FREE_DNODES_DEL 29 35#define FREE_DNODES_DEL 29
@@ -207,6 +208,7 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno);
207 208
208/* buffer.c */ 209/* buffer.c */
209 210
211void hpfs_prefetch_sectors(struct super_block *, unsigned, int);
210void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int); 212void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);
211void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **); 213void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);
212void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int); 214void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int);
@@ -271,6 +273,7 @@ void hpfs_evict_inode(struct inode *);
271 273
272__le32 *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *); 274__le32 *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *);
273__le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *); 275__le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *);
276void hpfs_prefetch_bitmap(struct super_block *, unsigned);
274unsigned char *hpfs_load_code_page(struct super_block *, secno); 277unsigned char *hpfs_load_code_page(struct super_block *, secno);
275__le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp); 278__le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp);
276struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **); 279struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **);
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c
index 803d3da3a0fe..3aa66ae1031e 100644
--- a/fs/hpfs/map.c
+++ b/fs/hpfs/map.c
@@ -17,6 +17,7 @@ __le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
17 struct quad_buffer_head *qbh, char *id) 17 struct quad_buffer_head *qbh, char *id)
18{ 18{
19 secno sec; 19 secno sec;
20 __le32 *ret;
20 unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; 21 unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
21 if (hpfs_sb(s)->sb_chk) if (bmp_block >= n_bands) { 22 if (hpfs_sb(s)->sb_chk) if (bmp_block >= n_bands) {
22 hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id); 23 hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);
@@ -27,7 +28,23 @@ __le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
27 hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id); 28 hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id);
28 return NULL; 29 return NULL;
29 } 30 }
30 return hpfs_map_4sectors(s, sec, qbh, 4); 31 ret = hpfs_map_4sectors(s, sec, qbh, 4);
32 if (ret) hpfs_prefetch_bitmap(s, bmp_block + 1);
33 return ret;
34}
35
36void hpfs_prefetch_bitmap(struct super_block *s, unsigned bmp_block)
37{
38 unsigned to_prefetch, next_prefetch;
39 unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
40 if (unlikely(bmp_block >= n_bands))
41 return;
42 to_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]);
43 if (unlikely(bmp_block + 1 >= n_bands))
44 next_prefetch = 0;
45 else
46 next_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block + 1]);
47 hpfs_prefetch_sectors(s, to_prefetch, 4 + 4 * (to_prefetch + 4 == next_prefetch));
31} 48}
32 49
33/* 50/*
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 962e90c37aec..4334cda8dba1 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -121,7 +121,7 @@ unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
121 unsigned long *bits; 121 unsigned long *bits;
122 unsigned count; 122 unsigned count;
123 123
124 bits = hpfs_map_4sectors(s, secno, &qbh, 4); 124 bits = hpfs_map_4sectors(s, secno, &qbh, 0);
125 if (!bits) 125 if (!bits)
126 return 0; 126 return 0;
127 count = bitmap_weight(bits, 2048 * BITS_PER_BYTE); 127 count = bitmap_weight(bits, 2048 * BITS_PER_BYTE);
@@ -134,8 +134,13 @@ static unsigned count_bitmaps(struct super_block *s)
134 unsigned n, count, n_bands; 134 unsigned n, count, n_bands;
135 n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; 135 n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
136 count = 0; 136 count = 0;
137 for (n = 0; n < n_bands; n++) 137 for (n = 0; n < COUNT_RD_AHEAD; n++) {
138 hpfs_prefetch_bitmap(s, n);
139 }
140 for (n = 0; n < n_bands; n++) {
141 hpfs_prefetch_bitmap(s, n + COUNT_RD_AHEAD);
138 count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n])); 142 count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
143 }
139 return count; 144 return count;
140} 145}
141 146