Skip to content

Commit

Permalink
hpfs: implement prefetch to improve performance
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mikulas Patocka authored and torvalds committed Jul 4, 2013
1 parent a0c1b75 commit 275f495
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
33 changes: 33 additions & 0 deletions fs/hpfs/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,37 @@
*/
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
#include "hpfs_fn.h"

void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)
{
struct buffer_head *bh;
struct blk_plug plug;

if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size))
return;

bh = sb_find_get_block(s, secno);
if (bh) {
if (buffer_uptodate(bh)) {
brelse(bh);
return;
}
brelse(bh);
};

blk_start_plug(&plug);
while (n > 0) {
if (unlikely(secno >= hpfs_sb(s)->sb_fs_size))
break;
sb_breadahead(s, secno);
secno++;
n--;
}
blk_finish_plug(&plug);
}

/* Map a sector into a buffer and return pointers to it and to the buffer. */

void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp,
Expand All @@ -18,6 +47,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head

hpfs_lock_assert(s);

hpfs_prefetch_sectors(s, secno, ahead);

cond_resched();

*bhp = bh = sb_bread(s, secno);
Expand Down Expand Up @@ -67,6 +98,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
return NULL;
}

hpfs_prefetch_sectors(s, secno, 4 + ahead);

qbh->data = data = kmalloc(2048, GFP_NOFS);
if (!data) {
printk("HPFS: hpfs_map_4sectors: out of memory\n");
Expand Down
7 changes: 5 additions & 2 deletions fs/hpfs/hpfs_fn.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
#define ALLOC_FWD_MAX 128
#define ALLOC_M 1
#define FNODE_RD_AHEAD 16
#define ANODE_RD_AHEAD 16
#define DNODE_RD_AHEAD 4
#define ANODE_RD_AHEAD 0
#define DNODE_RD_AHEAD 72
#define COUNT_RD_AHEAD 62

#define FREE_DNODES_ADD 58
#define FREE_DNODES_DEL 29
Expand Down Expand Up @@ -207,6 +208,7 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno);

/* buffer.c */

void hpfs_prefetch_sectors(struct super_block *, unsigned, int);
void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);
void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);
void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int);
Expand Down Expand Up @@ -271,6 +273,7 @@ void hpfs_evict_inode(struct inode *);

__le32 *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *);
__le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *);
void hpfs_prefetch_bitmap(struct super_block *, unsigned);
unsigned char *hpfs_load_code_page(struct super_block *, secno);
__le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp);
struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **);
Expand Down
19 changes: 18 additions & 1 deletion fs/hpfs/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ __le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
struct quad_buffer_head *qbh, char *id)
{
secno sec;
__le32 *ret;
unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
if (hpfs_sb(s)->sb_chk) if (bmp_block >= n_bands) {
hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);
Expand All @@ -27,7 +28,23 @@ __le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id);
return NULL;
}
return hpfs_map_4sectors(s, sec, qbh, 4);
ret = hpfs_map_4sectors(s, sec, qbh, 4);
if (ret) hpfs_prefetch_bitmap(s, bmp_block + 1);
return ret;
}

void hpfs_prefetch_bitmap(struct super_block *s, unsigned bmp_block)
{
unsigned to_prefetch, next_prefetch;
unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
if (unlikely(bmp_block >= n_bands))
return;
to_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]);
if (unlikely(bmp_block + 1 >= n_bands))
next_prefetch = 0;
else
next_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block + 1]);
hpfs_prefetch_sectors(s, to_prefetch, 4 + 4 * (to_prefetch + 4 == next_prefetch));
}

/*
Expand Down
9 changes: 7 additions & 2 deletions fs/hpfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
unsigned long *bits;
unsigned count;

bits = hpfs_map_4sectors(s, secno, &qbh, 4);
bits = hpfs_map_4sectors(s, secno, &qbh, 0);
if (!bits)
return 0;
count = bitmap_weight(bits, 2048 * BITS_PER_BYTE);
Expand All @@ -134,8 +134,13 @@ static unsigned count_bitmaps(struct super_block *s)
unsigned n, count, n_bands;
n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
count = 0;
for (n = 0; n < n_bands; n++)
for (n = 0; n < COUNT_RD_AHEAD; n++) {
hpfs_prefetch_bitmap(s, n);
}
for (n = 0; n < n_bands; n++) {
hpfs_prefetch_bitmap(s, n + COUNT_RD_AHEAD);
count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
}
return count;
}

Expand Down

0 comments on commit 275f495

Please sign in to comment.