From: Alex Tomas <bzzz@tmi.comex.ru>
To: Andrew Morton <akpm@osdl.org>
Cc: bzzz@tmi.comex.ru, linux-kernel@vger.kernel.org,
ext2-devel@lists.sourceforge.net
Subject: Re: [PATCH] minor optimization for EXT3
Date: Thu, 10 Jul 2003 20:46:59 +0000 [thread overview]
Message-ID: <877k6qgldo.fsf@gw.home.net> (raw)
In-Reply-To: <20030710085155.40c78883.akpm@osdl.org> (Andrew Morton's message of "Thu, 10 Jul 2003 08:51:55 -0700")
>>>>> Andrew Morton (AM) writes:
AM> ext3_read_inode() got reorganised. Your latest patch will not apply to
AM> current kernels.
OK. fixed version:
ext3_get_inode_loc() read inode's block only if:
1) this inode has no copy in memory
2) inode's block has another valid inode(s)
this optimization allows to avoid needless I/O in two cases:
1) just allocated inode is first valid in the inode's block
2) kernel wants to write inode, but buffer in which inode
belongs to gets freed by VM
diff -puN fs/ext3/inode.c~ext3-noread-inode fs/ext3/inode.c
--- linux-2.5.74/fs/ext3/inode.c~ext3-noread-inode Thu Jul 10 20:05:25 2003
+++ linux-2.5.74-alexey/fs/ext3/inode.c Thu Jul 10 20:25:24 2003
@@ -2339,24 +2339,106 @@ static unsigned long ext3_get_inode_bloc
/*
* ext3_get_inode_loc returns with an extra refcount against the
* inode's underlying buffer_head on success.
+ * in_mem arg enables optimization
*/
-int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc, int in_mem)
{
unsigned long block;
-
+ struct buffer_head *bh;
+
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;
- }
+ if (!block)
+ return -EIO;
+
+ bh = sb_getblk(inode->i_sb, block);
+ if (!bh) {
ext3_error (inode->i_sb, "ext3_get_inode_loc",
- "unable to read inode block - "
- "inode=%lu, block=%lu", inode->i_ino, block);
+ "unable to read inode block - "
+ "inode=%lu, block=%lu", inode->i_ino, block);
+ return -EIO;
+ }
+ if (!buffer_uptodate(bh)) {
+ lock_buffer(bh);
+ if (buffer_uptodate(bh)) {
+ /* someone has already initialized buffer */
+ unlock_buffer(bh);
+ goto has_buffer;
+ }
+
+ /* we can't skip I/O if inode is on a disk only */
+ if (in_mem) {
+ struct buffer_head *bitmap_bh;
+ struct ext3_group_desc *desc;
+ int inodes_per_buffer;
+ int inode_offset, i;
+ int block_group;
+ int start;
+
+ /*
+ * if this inode is only valid in buffer we need not I/O
+ */
+ block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
+ inodes_per_buffer = bh->b_size /
+ EXT3_INODE_SIZE(inode->i_sb);
+ inode_offset = ((inode->i_ino - 1) %
+ EXT3_INODES_PER_GROUP(inode->i_sb));
+ start = inode_offset & ~(inodes_per_buffer - 1);
+
+ /* check is inode bitmap is in cache? */
+ desc = ext3_get_group_desc(inode->i_sb, block_group, NULL);
+ if (!desc)
+ goto make_io;
+
+ bitmap_bh = sb_getblk(inode->i_sb, le32_to_cpu(desc->bg_inode_bitmap));
+ if (!bitmap_bh)
+ goto make_io;
+
+ /*
+ * if inode bitmap isn't in cache then we may end up by 2 reads
+ * instead of 1 read before optimizing. skip it
+ */
+ if (!buffer_uptodate(bitmap_bh)) {
+ brelse(bitmap_bh);
+ goto make_io;
+ }
+ for (i = start; i < start + inodes_per_buffer; i++) {
+ if (i == inode_offset)
+ continue;
+ if (ext3_test_bit(i, bitmap_bh->b_data))
+ break;
+ }
+ brelse(bitmap_bh);
+ if (i == start + inodes_per_buffer) {
+ /* all inodes (but our) are free. so, we skip I/O */
+ memset(bh->b_data, 0, bh->b_size);
+ set_buffer_uptodate(bh);
+ unlock_buffer(bh);
+ goto has_buffer;
+ }
+ }
+
+make_io:
+ /*
+ * No, there are another valid inodes in the buffer
+ * so, to preserve them we have to read buffer from
+ * the disk
+ */
+ get_bh(bh);
+ bh->b_end_io = end_buffer_io_sync;
+ submit_bh(READ, bh);
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ ext3_error (inode->i_sb, "ext3_get_inode_loc",
+ "unable to read inode block - "
+ "inode=%lu, block=%lu", inode->i_ino, block);
+ brelse(bh);
+ return -EIO;
+ }
}
- return -EIO;
+has_buffer:
+ iloc->bh = bh;
+ return 0;
}
void ext3_set_inode_flags(struct inode *inode)
@@ -2389,7 +2471,7 @@ void ext3_read_inode(struct inode * inod
ei->i_acl = EXT3_ACL_NOT_CACHED;
ei->i_default_acl = EXT3_ACL_NOT_CACHED;
#endif
- if (ext3_get_inode_loc(inode, &iloc))
+ if (ext3_get_inode_loc(inode, &iloc, 0))
goto bad_inode;
bh = iloc.bh;
raw_inode = ext3_raw_inode(&iloc);
@@ -2793,7 +2875,7 @@ ext3_reserve_inode_write(handle_t *handl
{
int err = 0;
if (handle) {
- err = ext3_get_inode_loc(inode, iloc);
+ err = ext3_get_inode_loc(inode, iloc, 1);
if (!err) {
BUFFER_TRACE(iloc->bh, "get_write_access");
err = ext3_journal_get_write_access(handle, iloc->bh);
@@ -2891,7 +2973,7 @@ ext3_pin_inode(handle_t *handle, struct
int err = 0;
if (handle) {
- err = ext3_get_inode_loc(inode, &iloc);
+ err = ext3_get_inode_loc(inode, &iloc, 1);
if (!err) {
BUFFER_TRACE(iloc.bh, "get_write_access");
err = journal_get_write_access(handle, iloc.bh);
diff -puN include/linux/ext3_fs.h~ext3-noread-inode include/linux/ext3_fs.h
--- linux-2.5.74/include/linux/ext3_fs.h~ext3-noread-inode Thu Jul 10 20:24:39 2003
+++ linux-2.5.74-alexey/include/linux/ext3_fs.h Thu Jul 10 20:25:08 2003
@@ -721,7 +721,7 @@ extern int ext3_forget(handle_t *, int,
extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-extern int ext3_get_inode_loc (struct inode *, struct ext3_iloc *);
+extern int ext3_get_inode_loc (struct inode *, struct ext3_iloc *, int);
extern void ext3_read_inode (struct inode *);
extern void ext3_write_inode (struct inode *, int);
extern int ext3_setattr (struct dentry *, struct iattr *);
_
next prev parent reply other threads:[~2003-07-10 16:33 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-07-10 14:49 [PATCH] minor optimization for EXT3 Alex Tomas
2003-07-10 11:20 ` Andrew Morton
2003-07-10 15:33 ` bzzz
2003-07-10 15:51 ` Andrew Morton
2003-07-10 20:46 ` Alex Tomas [this message]
2003-07-10 17:01 ` Andrew Morton
2003-07-10 21:09 ` Alex Tomas
2003-07-10 19:14 ` Andreas Dilger
2003-07-10 15:56 ` Alex Tomas
[not found] <87smpeigio.fsf@gw.home.net.suse.lists.linux.kernel>
[not found] ` <20030710042016.1b12113b.akpm@osdl.org.suse.lists.linux.kernel>
[not found] ` <87y8z6gyt3.fsf@gw.home.net.suse.lists.linux.kernel>
2003-07-10 12:43 ` Andi Kleen
2003-07-10 16:51 ` Alex Tomas
2003-07-10 12:55 ` Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=877k6qgldo.fsf@gw.home.net \
--to=bzzz@tmi.comex.ru \
--cc=akpm@osdl.org \
--cc=ext2-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.