/* * Shrink the dcache. This is done when we need * more memory, or simply when we need to unmount * something (at which point we need to unuse * all dentries). * * If you don't want a limit on the number of * inodes that will be released then call * with i_nr = -1. * * If you don't want a limit on the number of * dentries that will be released then call * with d_nr = 0. * * Returns the number of inodes released. */ int prune_dcache(int d_nr, int i_nr) { int __i_nr = i_nr; for (;;) { struct dentry *dentry; struct list_head *tmp = dentry_unused.prev; if (tmp == &dentry_unused) break; dentry_stat.nr_unused--; list_del(tmp); INIT_LIST_HEAD(tmp); dentry = list_entry(tmp, struct dentry, d_lru); if (!dentry->d_count) { i_nr -= prune_one_dentry(dentry); if (!i_nr) break; if (!--d_nr) break; } } return __i_nr - i_nr; }
void prune_dcache(int count) { spin_lock(&dcache_lock); for (;;) { struct dentry *dentry; struct list_head *tmp; tmp = dentry_unused.prev; if (tmp == &dentry_unused) break; list_del_init(tmp); dentry = list_entry(tmp, struct dentry, d_lru); /* If the dentry was recently referenced, don't free it. */ if (dentry->d_vfs_flags & DCACHE_REFERENCED) { dentry->d_vfs_flags &= ~DCACHE_REFERENCED; list_add(&dentry->d_lru, &dentry_unused); continue; } dentry_stat.nr_unused--; /* Unused dentry with a count? */ if (atomic_read(&dentry->d_count)) BUG(); prune_one_dentry(dentry); if (!--count) break; } spin_unlock(&dcache_lock); }
void prune_dcache(int count) { DEFINE_LOCK_COUNT(); spin_lock(&dcache_lock); redo: for (;;) { struct dentry *dentry; struct list_head *tmp; if (TEST_LOCK_COUNT(100)) { RESET_LOCK_COUNT(); debug_lock_break(1); if (conditional_schedule_needed()) { break_spin_lock(&dcache_lock); goto redo; } } tmp = dentry_unused.prev; if (tmp == &dentry_unused) break; list_del_init(tmp); dentry = list_entry(tmp, struct dentry, d_lru); /* If the dentry was recently referenced, don't free it. */ if (dentry->d_vfs_flags & DCACHE_REFERENCED) { dentry->d_vfs_flags &= ~DCACHE_REFERENCED; list_add(&dentry->d_lru, &dentry_unused); continue; } dentry_stat.nr_unused--; /* Unused dentry with a count? */ if (atomic_read(&dentry->d_count)) BUG(); prune_one_dentry(dentry); if (!--count) break; } spin_unlock(&dcache_lock); }
/* * Shrink the dcache. This is done when we need * more memory, or simply when we need to unmount * something (at which point we need to unuse * all dentries). */ void prune_dcache(int count) { for (;;) { struct dentry *dentry; struct list_head *tmp = dentry_unused.prev; if (tmp == &dentry_unused) break; dentry_stat.nr_unused--; list_del(tmp); INIT_LIST_HEAD(tmp); dentry = list_entry(tmp, struct dentry, d_lru); if (!dentry->d_count) { prune_one_dentry(dentry); if (!--count) break; } } }
void shrink_dcache_sb(struct super_block * sb) { struct list_head *tmp, *next; struct dentry *dentry; /* * Pass one ... move the dentries for the specified * superblock to the most recent end of the unused list. */ spin_lock(&dcache_lock); next = dentry_unused.next; while (next != &dentry_unused) { tmp = next; next = tmp->next; dentry = list_entry(tmp, struct dentry, d_lru); if (dentry->d_sb != sb) continue; list_del(tmp); list_add(tmp, &dentry_unused); } /* * Pass two ... free the dentries for this superblock. */ 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_sb != sb) continue; if (atomic_read(&dentry->d_count)) continue; dentry_stat.nr_unused--; list_del_init(tmp); prune_one_dentry(dentry); goto repeat; } spin_unlock(&dcache_lock); }