From: Kirill Korotaev <kk@sw.ru>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] Invalidate_inodes can be very slow
Date: Mon, 13 Oct 2003 13:18:09 +0400 [thread overview]
Message-ID: <200310131318.09234.kk@sw.ru> (raw)
[-- Attachment #1: Type: text/plain, Size: 636 bytes --]
I'm not sure whom this patch should be send to, so I'm posting it here.
this patch fixes the problem that huge inode cache
can make invalidate_inodes() calls very long. Meanwhile
lock_kernel() and inode_lock are being held and system
can freeze for seconds.
I detected this problem on kernel with 4gb split. When inode cache
was 2.5Gb (1,000,000 of inodes in cache) it took seconds to umount
or turn quota off.
This patch is against 2.4.22 kernel. But as far as I can see the problem
still exists in 2.6 kernels.
This patch introduces per-super block inode list which makes
possible to scan sb's only inodes when doing umount.
Kirill
[-- Attachment #2: diff-invlinodes-20031013 --]
[-- Type: text/plain, Size: 4846 bytes --]
--- ./fs/super.c.ii 2003-08-25 15:44:43.000000000 +0400
+++ ./fs/super.c 2003-10-13 12:08:43.000000000 +0400
@@ -271,6 +271,7 @@ static struct super_block *alloc_super(v
INIT_LIST_HEAD(&s->s_locked_inodes);
INIT_LIST_HEAD(&s->s_files);
INIT_LIST_HEAD(&s->s_instances);
+ INIT_LIST_HEAD(&s->s_inodes);
init_rwsem(&s->s_umount);
sema_init(&s->s_lock, 1);
down_write(&s->s_umount);
--- ./fs/inode.c.ii 2003-08-25 15:44:43.000000000 +0400
+++ ./fs/inode.c 2003-10-13 12:18:25.000000000 +0400
@@ -604,7 +604,7 @@ static void dispose_list(struct list_hea
/*
* Invalidate all inodes for a device.
*/
-static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose)
+static int invalidate_list(struct list_head *head, struct list_head * dispose)
{
struct list_head *next;
int busy = 0, count = 0;
@@ -617,12 +617,11 @@ static int invalidate_list(struct list_h
next = next->next;
if (tmp == head)
break;
- inode = list_entry(tmp, struct inode, i_list);
- if (inode->i_sb != sb)
- continue;
+ inode = list_entry(tmp, struct inode, i_sb_list);
invalidate_inode_buffers(inode);
if (!atomic_read(&inode->i_count)) {
list_del_init(&inode->i_hash);
+ list_del(&inode->i_sb_list);
list_del(&inode->i_list);
list_add(&inode->i_list, dispose);
inode->i_state |= I_FREEING;
@@ -659,10 +658,7 @@ int invalidate_inodes(struct super_block
LIST_HEAD(throw_away);
spin_lock(&inode_lock);
- busy = invalidate_list(&inode_in_use, sb, &throw_away);
- busy |= invalidate_list(&inode_unused, sb, &throw_away);
- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);
- busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away);
+ busy = invalidate_list(&sb->s_inodes, &throw_away);
spin_unlock(&inode_lock);
dispose_list(&throw_away);
@@ -738,6 +734,7 @@ void prune_icache(int goal)
list_del(tmp);
list_del(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_hash);
+ list_del(&inode->i_sb_list);
list_add(tmp, freeable);
inode->i_state |= I_FREEING;
count++;
@@ -827,6 +824,7 @@ struct inode * new_inode(struct super_bl
spin_lock(&inode_lock);
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
+ list_add(&inode->i_sb_list, &sb->s_inodes);
inode->i_ino = ++last_ino;
inode->i_state = 0;
spin_unlock(&inode_lock);
@@ -854,6 +852,7 @@ static struct inode * get_new_inode(stru
if (!old) {
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
+ list_add(&inode->i_sb_list, &sb->s_inodes);
list_add(&inode->i_hash, head);
inode->i_ino = ino;
inode->i_state = I_LOCK;
@@ -1046,6 +1045,7 @@ void iput(struct inode *inode)
INIT_LIST_HEAD(&inode->i_hash);
list_del(&inode->i_list);
INIT_LIST_HEAD(&inode->i_list);
+ list_del(&inode->i_sb_list);
inode->i_state|=I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
@@ -1079,6 +1079,7 @@ void iput(struct inode *inode)
list_del_init(&inode->i_hash);
}
list_del_init(&inode->i_list);
+ list_del(&inode->i_sb_list);
inode->i_state|=I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
@@ -1239,26 +1240,10 @@ void remove_dquot_ref(struct super_block
lock_kernel(); /* This lock is for quota code */
spin_lock(&inode_lock); /* This lock is for inodes code */
- list_for_each(act_head, &inode_in_use) {
- inode = list_entry(act_head, struct inode, i_list);
- if (inode->i_sb == sb && IS_QUOTAINIT(inode))
- remove_inode_dquot_ref(inode, type, &tofree_head);
- }
- list_for_each(act_head, &inode_unused) {
- inode = list_entry(act_head, struct inode, i_list);
- if (inode->i_sb == sb && IS_QUOTAINIT(inode))
- remove_inode_dquot_ref(inode, type, &tofree_head);
- }
- list_for_each(act_head, &sb->s_dirty) {
- inode = list_entry(act_head, struct inode, i_list);
+ list_for_each_entry(inode, act_head, &sb->s_inodes)
if (IS_QUOTAINIT(inode))
remove_inode_dquot_ref(inode, type, &tofree_head);
- }
- list_for_each(act_head, &sb->s_locked_inodes) {
- inode = list_entry(act_head, struct inode, i_list);
- if (IS_QUOTAINIT(inode))
- remove_inode_dquot_ref(inode, type, &tofree_head);
- }
+
spin_unlock(&inode_lock);
unlock_kernel();
--- ./include/linux/fs.h.ii 2003-08-25 15:44:44.000000000 +0400
+++ ./include/linux/fs.h 2003-10-13 12:23:53.000000000 +0400
@@ -438,6 +438,7 @@ struct block_device {
struct inode {
struct list_head i_hash;
struct list_head i_list;
+ struct list_head i_sb_list;
struct list_head i_dentry;
struct list_head i_dirty_buffers;
@@ -756,6 +757,7 @@ struct super_block {
int s_count;
atomic_t s_active;
+ struct list_head s_inodes; /* all inodes */
struct list_head s_dirty; /* dirty inodes */
struct list_head s_locked_inodes;/* inodes being synced */
struct list_head s_files;
next reply other threads:[~2003-10-13 9:17 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-10-13 9:18 Kirill Korotaev [this message]
2003-10-13 9:53 ` [PATCH] Invalidate_inodes can be very slow William Lee Irwin III
2003-10-13 10:46 ` Kirill Korotaev
2003-10-13 11:06 ` William Lee Irwin III
2003-10-13 11:08 ` Andrew Morton
2003-10-13 11:19 ` William Lee Irwin III
2003-10-13 11:45 ` Kirill Korotaev
2003-10-13 11:54 ` William Lee Irwin III
2003-10-13 12:02 ` Kirill Korotaev
2003-10-13 12:11 ` William Lee Irwin III
2003-10-13 12:21 ` Kirill Korotaev
2003-10-13 12:29 ` Nikita Danilov
2003-10-13 13:08 ` Kirill Korotaev
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=200310131318.09234.kk@sw.ru \
--to=kk@sw.ru \
--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.