All of lore.kernel.org
 help / color / mirror / Atom feed
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;

             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.