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) ...@@ -1447,6 +1447,28 @@ __getblk(struct block_device *bdev, sector_t block, int size)
} }
EXPORT_SYMBOL(__getblk); 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 * __bread() - reads a specified block and returns the bh
* @block: number of block * @block: number of block
......
...@@ -2290,68 +2290,72 @@ void ext3_truncate(struct inode * inode) ...@@ -2290,68 +2290,72 @@ void ext3_truncate(struct inode * inode)
ext3_journal_stop(handle); ext3_journal_stop(handle);
} }
/* static unsigned long ext3_get_inode_block(struct super_block *sb,
* ext3_get_inode_loc returns with an extra refcount against the unsigned long ino, struct ext3_iloc *iloc)
* inode's underlying buffer_head on success.
*/
int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
{ {
struct buffer_head *bh = 0; unsigned long desc, group_desc, block_group;
unsigned long block; unsigned long offset, block;
unsigned long block_group; struct buffer_head *bh;
unsigned long group_desc;
unsigned long desc;
unsigned long offset;
struct ext3_group_desc * gdp; struct ext3_group_desc * gdp;
if ((inode->i_ino != EXT3_ROOT_INO && if ((ino != EXT3_ROOT_INO &&
inode->i_ino != EXT3_JOURNAL_INO && ino != EXT3_JOURNAL_INO &&
inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) || ino < EXT3_FIRST_INO(sb)) ||
inode->i_ino > le32_to_cpu( ino > le32_to_cpu(
EXT3_SB(inode->i_sb)->s_es->s_inodes_count)) { EXT3_SB(sb)->s_es->s_inodes_count)) {
ext3_error (inode->i_sb, "ext3_get_inode_loc", ext3_error (sb, "ext3_get_inode_block",
"bad inode number: %lu", inode->i_ino); "bad inode number: %lu", ino);
goto bad_inode; return 0;
} }
block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb); block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
if (block_group >= EXT3_SB(inode->i_sb)->s_groups_count) { if (block_group >= EXT3_SB(sb)->s_groups_count) {
ext3_error (inode->i_sb, "ext3_get_inode_loc", ext3_error (sb, "ext3_get_inode_block",
"group >= groups count"); "group >= groups count");
goto bad_inode; return 0;
} }
group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb); group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1); desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
bh = EXT3_SB(inode->i_sb)->s_group_desc[group_desc]; bh = EXT3_SB(sb)->s_group_desc[group_desc];
if (!bh) { if (!bh) {
ext3_error (inode->i_sb, "ext3_get_inode_loc", ext3_error (sb, "ext3_get_inode_block",
"Descriptor not loaded"); "Descriptor not loaded");
goto bad_inode; return 0;
} }
gdp = (struct ext3_group_desc *) bh->b_data; gdp = (struct ext3_group_desc *) bh->b_data;
/* /*
* Figure out the offset within the block group inode table * Figure out the offset within the block group inode table
*/ */
offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) * offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb)) *
EXT3_INODE_SIZE(inode->i_sb); EXT3_INODE_SIZE(sb);
block = le32_to_cpu(gdp[desc].bg_inode_table) + block = le32_to_cpu(gdp[desc].bg_inode_table) +
(offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb)); (offset >> EXT3_BLOCK_SIZE_BITS(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);
iloc->bh = bh;
iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
iloc->block_group = block_group; 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; return -EIO;
} }
...@@ -2388,7 +2392,7 @@ void ext3_read_inode(struct inode * inode) ...@@ -2388,7 +2392,7 @@ void ext3_read_inode(struct inode * inode)
if (ext3_get_inode_loc(inode, &iloc)) if (ext3_get_inode_loc(inode, &iloc))
goto bad_inode; goto bad_inode;
bh = iloc.bh; 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_mode = le16_to_cpu(raw_inode->i_mode);
inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); 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); inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
...@@ -2454,11 +2458,9 @@ void ext3_read_inode(struct inode * inode) ...@@ -2454,11 +2458,9 @@ void ext3_read_inode(struct inode * inode)
* even on big-endian machines: we do NOT byteswap the block numbers! * even on big-endian machines: we do NOT byteswap the block numbers!
*/ */
for (block = 0; block < EXT3_N_BLOCKS; block++) 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); INIT_LIST_HEAD(&ei->i_orphan);
brelse (iloc.bh);
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext3_file_inode_operations; inode->i_op = &ext3_file_inode_operations;
inode->i_fop = &ext3_file_operations; inode->i_fop = &ext3_file_operations;
...@@ -2476,8 +2478,9 @@ void ext3_read_inode(struct inode * inode) ...@@ -2476,8 +2478,9 @@ void ext3_read_inode(struct inode * inode)
} else { } else {
inode->i_op = &ext3_special_inode_operations; inode->i_op = &ext3_special_inode_operations;
init_special_inode(inode, inode->i_mode, 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); ext3_set_inode_flags(inode);
return; return;
...@@ -2497,7 +2500,7 @@ static int ext3_do_update_inode(handle_t *handle, ...@@ -2497,7 +2500,7 @@ static int ext3_do_update_inode(handle_t *handle,
struct inode *inode, struct inode *inode,
struct ext3_iloc *iloc) 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 ext3_inode_info *ei = EXT3_I(inode);
struct buffer_head *bh = iloc->bh; struct buffer_head *bh = iloc->bh;
int err = 0, rc, block; int err = 0, rc, block;
......
...@@ -167,6 +167,7 @@ struct buffer_head *__find_get_block(struct block_device *, sector_t, int); ...@@ -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); struct buffer_head * __getblk(struct block_device *, sector_t, int);
void __brelse(struct buffer_head *); void __brelse(struct buffer_head *);
void __bforget(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 *__bread(struct block_device *, sector_t block, int size);
struct buffer_head *alloc_buffer_head(int gfp_flags); struct buffer_head *alloc_buffer_head(int gfp_flags);
void free_buffer_head(struct buffer_head * bh); void free_buffer_head(struct buffer_head * bh);
...@@ -241,6 +242,12 @@ sb_bread(struct super_block *sb, sector_t block) ...@@ -241,6 +242,12 @@ sb_bread(struct super_block *sb, sector_t block)
return __bread(sb->s_bdev, block, sb->s_blocksize); 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 * static inline struct buffer_head *
sb_getblk(struct super_block *sb, sector_t block) sb_getblk(struct super_block *sb, sector_t block)
{ {
......
...@@ -636,10 +636,14 @@ struct dx_hash_info ...@@ -636,10 +636,14 @@ struct dx_hash_info
struct ext3_iloc struct ext3_iloc
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct ext3_inode *raw_inode; unsigned long offset;
unsigned long block_group; 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 * 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