mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-13 20:33:15 +00:00
Merge branch 'hpfs' from Mikulas Patocka
Merge hpfs patches from Mikulas Patocka. * emailed patches from Mikulas Patocka <mpatocka@artax.karlin.mff.cuni.cz>: hpfs: implement prefetch to improve performance hpfs: use mpage hpfs: better test for errors
This commit is contained in:
commit
da67db4e55
@ -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,
|
||||
@ -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);
|
||||
@ -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");
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "hpfs_fn.h"
|
||||
#include <linux/mpage.h>
|
||||
|
||||
#define BLOCKS(size) (((size) + 511) >> 9)
|
||||
|
||||
@ -34,7 +35,7 @@ int hpfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
* so we must ignore such errors.
|
||||
*/
|
||||
|
||||
static secno hpfs_bmap(struct inode *inode, unsigned file_secno)
|
||||
static secno hpfs_bmap(struct inode *inode, unsigned file_secno, unsigned *n_secs)
|
||||
{
|
||||
struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
|
||||
unsigned n, disk_secno;
|
||||
@ -42,11 +43,20 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno)
|
||||
struct buffer_head *bh;
|
||||
if (BLOCKS(hpfs_i(inode)->mmu_private) <= file_secno) return 0;
|
||||
n = file_secno - hpfs_inode->i_file_sec;
|
||||
if (n < hpfs_inode->i_n_secs) return hpfs_inode->i_disk_sec + n;
|
||||
if (n < hpfs_inode->i_n_secs) {
|
||||
*n_secs = hpfs_inode->i_n_secs - n;
|
||||
return hpfs_inode->i_disk_sec + n;
|
||||
}
|
||||
if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0;
|
||||
disk_secno = hpfs_bplus_lookup(inode->i_sb, inode, &fnode->btree, file_secno, bh);
|
||||
if (disk_secno == -1) return 0;
|
||||
if (hpfs_chk_sectors(inode->i_sb, disk_secno, 1, "bmap")) return 0;
|
||||
n = file_secno - hpfs_inode->i_file_sec;
|
||||
if (n < hpfs_inode->i_n_secs) {
|
||||
*n_secs = hpfs_inode->i_n_secs - n;
|
||||
return hpfs_inode->i_disk_sec + n;
|
||||
}
|
||||
*n_secs = 1;
|
||||
return disk_secno;
|
||||
}
|
||||
|
||||
@ -67,10 +77,14 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he
|
||||
{
|
||||
int r;
|
||||
secno s;
|
||||
unsigned n_secs;
|
||||
hpfs_lock(inode->i_sb);
|
||||
s = hpfs_bmap(inode, iblock);
|
||||
s = hpfs_bmap(inode, iblock, &n_secs);
|
||||
if (s) {
|
||||
if (bh_result->b_size >> 9 < n_secs)
|
||||
n_secs = bh_result->b_size >> 9;
|
||||
map_bh(bh_result, inode->i_sb, s);
|
||||
bh_result->b_size = n_secs << 9;
|
||||
goto ret_0;
|
||||
}
|
||||
if (!create) goto ret_0;
|
||||
@ -95,14 +109,26 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he
|
||||
return r;
|
||||
}
|
||||
|
||||
static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
|
||||
{
|
||||
return block_write_full_page(page,hpfs_get_block, wbc);
|
||||
}
|
||||
|
||||
static int hpfs_readpage(struct file *file, struct page *page)
|
||||
{
|
||||
return block_read_full_page(page,hpfs_get_block);
|
||||
return mpage_readpage(page, hpfs_get_block);
|
||||
}
|
||||
|
||||
static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
|
||||
{
|
||||
return block_write_full_page(page, hpfs_get_block, wbc);
|
||||
}
|
||||
|
||||
static int hpfs_readpages(struct file *file, struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages)
|
||||
{
|
||||
return mpage_readpages(mapping, pages, nr_pages, hpfs_get_block);
|
||||
}
|
||||
|
||||
static int hpfs_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
return mpage_writepages(mapping, wbc, hpfs_get_block);
|
||||
}
|
||||
|
||||
static void hpfs_write_failed(struct address_space *mapping, loff_t to)
|
||||
@ -161,6 +187,8 @@ static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
|
||||
const struct address_space_operations hpfs_aops = {
|
||||
.readpage = hpfs_readpage,
|
||||
.writepage = hpfs_writepage,
|
||||
.readpages = hpfs_readpages,
|
||||
.writepages = hpfs_writepages,
|
||||
.write_begin = hpfs_write_begin,
|
||||
.write_end = hpfs_write_end,
|
||||
.bmap = _hpfs_bmap
|
||||
|
@ -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
|
||||
@ -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);
|
||||
@ -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 **);
|
||||
|
@ -17,7 +17,9 @@ __le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
|
||||
struct quad_buffer_head *qbh, char *id)
|
||||
{
|
||||
secno sec;
|
||||
if (hpfs_sb(s)->sb_chk) if (bmp_block * 16384 > hpfs_sb(s)->sb_fs_size) {
|
||||
__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);
|
||||
return NULL;
|
||||
}
|
||||
@ -26,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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -558,7 +563,13 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
sbi->sb_cp_table = NULL;
|
||||
sbi->sb_c_bitmap = -1;
|
||||
sbi->sb_max_fwd_alloc = 0xffffff;
|
||||
|
||||
|
||||
if (sbi->sb_fs_size >= 0x80000000) {
|
||||
hpfs_error(s, "invalid size in superblock: %08x",
|
||||
(unsigned)sbi->sb_fs_size);
|
||||
goto bail4;
|
||||
}
|
||||
|
||||
/* Load bitmap directory */
|
||||
if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
|
||||
goto bail4;
|
||||
|
Loading…
Reference in New Issue
Block a user