Commit e631aa44 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents 8394c855 9c67eccb
......@@ -1447,6 +1447,28 @@ __getblk(struct block_device *bdev, sector_t block, int size)
}
EXPORT_SYMBOL(__getblk);
/*
* Do async read-ahead on a buffer..
*/
void
__breadahead(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *bh = __getblk(bdev, block, size);
if (!test_set_buffer_locked(bh)) {
if (!buffer_uptodate(bh)) {
/*
* This eats the bh count from __getblk() and
* unlocks when the read is done.
*/
bh->b_end_io = end_buffer_io_sync;
submit_bh(READ, bh);
return;
}
unlock_buffer(bh);
}
brelse(bh);
}
/**
* __bread() - reads a specified block and returns the bh
* @block: number of block
......
......@@ -2290,68 +2290,72 @@ void ext3_truncate(struct inode * inode)
ext3_journal_stop(handle);
}
/*
* ext3_get_inode_loc returns with an extra refcount against the
* inode's underlying buffer_head on success.
*/
int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
static unsigned long ext3_get_inode_block(struct super_block *sb,
unsigned long ino, struct ext3_iloc *iloc)
{
struct buffer_head *bh = 0;
unsigned long block;
unsigned long block_group;
unsigned long group_desc;
unsigned long desc;
unsigned long offset;
unsigned long desc, group_desc, block_group;
unsigned long offset, block;
struct buffer_head *bh;
struct ext3_group_desc * gdp;
if ((inode->i_ino != EXT3_ROOT_INO &&
inode->i_ino != EXT3_JOURNAL_INO &&
inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
inode->i_ino > le32_to_cpu(
EXT3_SB(inode->i_sb)->s_es->s_inodes_count)) {
ext3_error (inode->i_sb, "ext3_get_inode_loc",
"bad inode number: %lu", inode->i_ino);
goto bad_inode;
if ((ino != EXT3_ROOT_INO &&
ino != EXT3_JOURNAL_INO &&
ino < EXT3_FIRST_INO(sb)) ||
ino > le32_to_cpu(
EXT3_SB(sb)->s_es->s_inodes_count)) {
ext3_error (sb, "ext3_get_inode_block",
"bad inode number: %lu", ino);
return 0;
}
block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
if (block_group >= EXT3_SB(inode->i_sb)->s_groups_count) {
ext3_error (inode->i_sb, "ext3_get_inode_loc",
block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
if (block_group >= EXT3_SB(sb)->s_groups_count) {
ext3_error (sb, "ext3_get_inode_block",
"group >= groups count");
goto bad_inode;
return 0;
}
group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
bh = EXT3_SB(inode->i_sb)->s_group_desc[group_desc];
group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
bh = EXT3_SB(sb)->s_group_desc[group_desc];
if (!bh) {
ext3_error (inode->i_sb, "ext3_get_inode_loc",
ext3_error (sb, "ext3_get_inode_block",
"Descriptor not loaded");
goto bad_inode;
return 0;
}
gdp = (struct ext3_group_desc *) bh->b_data;
/*
* Figure out the offset within the block group inode table
*/
offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
EXT3_INODE_SIZE(inode->i_sb);
offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb)) *
EXT3_INODE_SIZE(sb);
block = le32_to_cpu(gdp[desc].bg_inode_table) +
(offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
if (!(bh = sb_bread(inode->i_sb, block))) {
ext3_error (inode->i_sb, "ext3_get_inode_loc",
"unable to read inode block - "
"inode=%lu, block=%lu", inode->i_ino, block);
goto bad_inode;
}
offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
(offset >> EXT3_BLOCK_SIZE_BITS(sb));
iloc->bh = bh;
iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
iloc->block_group = block_group;
iloc->offset = offset & (EXT3_BLOCK_SIZE(sb) - 1);
return block;
}
return 0;
/*
* ext3_get_inode_loc returns with an extra refcount against the
* inode's underlying buffer_head on success.
*/
int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
{
unsigned long block;
bad_inode:
block = ext3_get_inode_block(inode->i_sb, inode->i_ino, iloc);
if (block) {
struct buffer_head *bh = sb_bread(inode->i_sb, block);
if (bh) {
iloc->bh = bh;
return 0;
}
ext3_error (inode->i_sb, "ext3_get_inode_loc",
"unable to read inode block - "
"inode=%lu, block=%lu", inode->i_ino, block);
}
return -EIO;
}
......@@ -2388,7 +2392,7 @@ void ext3_read_inode(struct inode * inode)
if (ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
raw_inode = iloc.raw_inode;
raw_inode = ext3_raw_inode(&iloc);
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
......@@ -2454,11 +2458,9 @@ void ext3_read_inode(struct inode * inode)
* even on big-endian machines: we do NOT byteswap the block numbers!
*/
for (block = 0; block < EXT3_N_BLOCKS; block++)
ei->i_data[block] = iloc.raw_inode->i_block[block];
ei->i_data[block] = raw_inode->i_block[block];
INIT_LIST_HEAD(&ei->i_orphan);
brelse (iloc.bh);
if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext3_file_inode_operations;
inode->i_fop = &ext3_file_operations;
......@@ -2476,8 +2478,9 @@ void ext3_read_inode(struct inode * inode)
} else {
inode->i_op = &ext3_special_inode_operations;
init_special_inode(inode, inode->i_mode,
le32_to_cpu(iloc.raw_inode->i_block[0]));
le32_to_cpu(raw_inode->i_block[0]));
}
brelse (iloc.bh);
ext3_set_inode_flags(inode);
return;
......@@ -2497,7 +2500,7 @@ static int ext3_do_update_inode(handle_t *handle,
struct inode *inode,
struct ext3_iloc *iloc)
{
struct ext3_inode *raw_inode = iloc->raw_inode;
struct ext3_inode *raw_inode = ext3_raw_inode(iloc);
struct ext3_inode_info *ei = EXT3_I(inode);
struct buffer_head *bh = iloc->bh;
int err = 0, rc, block;
......
......@@ -167,6 +167,7 @@ struct buffer_head *__find_get_block(struct block_device *, sector_t, int);
struct buffer_head * __getblk(struct block_device *, sector_t, int);
void __brelse(struct buffer_head *);
void __bforget(struct buffer_head *);
void __breadahead(struct block_device *, sector_t block, int size);
struct buffer_head *__bread(struct block_device *, sector_t block, int size);
struct buffer_head *alloc_buffer_head(int gfp_flags);
void free_buffer_head(struct buffer_head * bh);
......@@ -241,6 +242,12 @@ sb_bread(struct super_block *sb, sector_t block)
return __bread(sb->s_bdev, block, sb->s_blocksize);
}
static inline void
sb_breadahead(struct super_block *sb, sector_t block)
{
__breadahead(sb->s_bdev, block, sb->s_blocksize);
}
static inline struct buffer_head *
sb_getblk(struct super_block *sb, sector_t block)
{
......
......@@ -636,10 +636,14 @@ struct dx_hash_info
struct ext3_iloc
{
struct buffer_head *bh;
struct ext3_inode *raw_inode;
unsigned long offset;
unsigned long block_group;
};
static inline struct ext3_inode *ext3_raw_inode(struct ext3_iloc *iloc)
{
return (struct ext3_inode *) (iloc->bh->b_data + iloc->offset);
}
/*
* This structure is stuffed into the struct file's private_data field
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment