alternative shrink_dcache_sb

Bill Hawes (whawes@star.net)
Sat, 20 Sep 1997 15:41:51 -0400


This is a multi-part message in MIME format.
--------------99B911C6D4737E2A63E52AB3
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch is a slightly different approach to shrinking the
dcache for one super block. Instead of moving dentries to a temp list,
it starts at the recent end of the unused list and frees dentries from
there. This requires restarting after each time, but since newly freed
dentries go to the recent end, it should require fewer traverses of the
list.

My first implementation required as many passes as the directories on
the sb are deep, whereas this approach (in the optimistic case) might
require (effectively) only one full pass. Since the more common case of
unmounting is probably to unmount a volume you just finished using, the
dentries are more likely to be at the recently unused end.

Anyway, both approaches work fine, but I think I like this better.

Reagards,
Bill
--------------99B911C6D4737E2A63E52AB3
Content-Type: text/plain; charset=us-ascii; name="dcache_sb56-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="dcache_sb56-patch"

--- fs/dcache.c.old Sat Sep 20 08:16:14 1997
+++ fs/dcache.c Sat Sep 20 15:22:19 1997
@@ -148,6 +216,47 @@
}
}
}
+
+/* N.B. move to include/linux/dcache.h */
+extern void shrink_dcache_sb(struct super_block *);
+/*
+ * Shrink the dcache for the specified super block.
+ * This allows us to unmount a device without disturbing
+ * the dcache for the other devices.
+ *
+ * Note that in this implementation we want to look first
+ * at the _most recently_ (un)used dentries. Each dput()
+ * forces us to restart, but any newly unused dentries will
+ * be at the front of the list.
+ */
+void shrink_dcache_sb(struct super_block * sb)
+{
+ struct list_head *tmp, *next;
+ struct dentry *dentry;
+
+repeat:
+ next = dentry_unused.next;
+ while (next != &dentry_unused) {
+ tmp = next;
+ next = tmp->next;
+ dentry = list_entry(tmp, struct dentry, d_lru);
+ if (!dentry->d_count) {
+ if (dentry->d_sb == sb) {
+ dentry->d_count++;
+ d_drop(dentry);
+ dput(dentry);
+ goto repeat;
+ }
+ continue;
+ }
+ /*
+ * If the dentry is in use, we can always remove it.
+ * This makes less work for the next pass ...
+ */
+ list_del(tmp);
+ INIT_LIST_HEAD(tmp);
+ }
+}

#define NAME_ALLOC_LEN(len) ((len+16) & ~15)

--------------99B911C6D4737E2A63E52AB3--