[patch] real fix [Re: [patch] fixed 2.2.1 inode-leakage due bogus design of the free_inodes algorith

Andrea Arcangeli (andrea@e-mind.com)
Thu, 4 Feb 1999 16:43:14 +0100 (CET)


On Thu, 4 Feb 1999, Andrea Arcangeli wrote:

> better that you backup your machine before trying it, since I had only two
> seconds to think about it. I think as worse you should lockup again but...

Infact the patch was bogus (and the previous code was bogus too not only
by design). Here the _right_ fix (this time I didn't cared about other
no-linux things I have to do today and I taken the time to think about
it). I also removed the preshirnk mess that was not allowing an admin to
increase inode-max (to have a bigger inode caching beahvior) if preshirnk
was incidentally just 1.

Here the _right_ patch against 2.2.2-pre1 (2.2.1 clean make no
differences). This time I checked and I am pretty sure you'll be happy as
me ;).

I am not forwarding this to Linus because he asked me to go away and so I
don't want to hurt him further.

Index: inode.c
===================================================================
RCS file: /var/cvs/linux/fs/inode.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 inode.c
--- inode.c 1999/01/26 18:30:24 1.1.1.2
+++ inode.c 1999/02/04 15:35:46
@@ -4,6 +4,10 @@
* (C) 1997 Linus Torvalds
*/

+/*
+ * Fixed inode leakage in 2.2.1. Copyright (C) 1999 Andrea Arcangeli
+ */
+
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mm.h>
@@ -62,9 +66,8 @@
struct {
int nr_inodes;
int nr_free_inodes;
- int preshrink; /* pre-shrink dcache? */
- int dummy[4];
-} inodes_stat = {0, 0, 0,};
+ int dummy[5];
+} inodes_stat = {0, 0, };

int max_inodes;

@@ -329,12 +332,14 @@

static int free_inodes(int goal)
{
- struct list_head *tmp, *head = &inode_in_use;
+ struct list_head * head = &inode_in_use, * tmp, * this = head->prev;
LIST_HEAD(freeable);
- int found = 0, depth = goal << 1;
+ int found = 0;

- while ((tmp = head->prev) != head && depth--) {
+ while ((tmp = this) != head)
+ {
struct inode * inode = list_entry(tmp, struct inode, i_list);
+ this = this->prev;
list_del(tmp);
if (CAN_UNUSE(inode)) {
list_del(&inode->i_hash);
@@ -403,7 +408,7 @@
/*
* Check whether to restock the unused list.
*/
- if (inodes_stat.preshrink) {
+ if (inodes_stat.nr_inodes > max_inodes) {
struct list_head *tmp;
try_to_free_inodes(8);
tmp = inode_unused.next;
@@ -436,9 +441,6 @@
*/
inodes_stat.nr_inodes += INODES_PER_PAGE;
inodes_stat.nr_free_inodes += INODES_PER_PAGE - 1;
- inodes_stat.preshrink = 0;
- if (inodes_stat.nr_inodes > max_inodes)
- inodes_stat.preshrink = 1;
return inode;
}

@@ -447,7 +449,6 @@
* the dcache and then try again to free some inodes.
*/
prune_dcache(inodes_stat.nr_inodes >> 2);
- inodes_stat.preshrink = 1;

spin_lock(&inode_lock);
free_inodes(inodes_stat.nr_inodes >> 2);

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/