示例#1
0
/*
 * 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;
}
示例#2
0
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);
}
示例#3
0
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);
}
示例#4
0
/*
 * 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;
		}
	}
}
示例#5
0
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);
}