summaryrefslogtreecommitdiffstats
path: root/fs/ntfs/aops.h
AgeCommit message (Expand)Author
2019-05-24treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 96Thomas Gleixner
2016-04-04mm, fs: remove remaining PAGE_CACHE_* and page_cache_{get,release} usageKirill A. Shutemov
2016-04-04mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macrosKirill A. Shutemov
2007-05-07mm: make read_cache_page synchronousNick Piggin
2006-10-01[PATCH] fs/ntfs: Conversion to generic booleanRichard Knutsson
2006-06-23[PATCH] read_mapping_page for address spacePekka Enberg
2005-04-16Linux-2.6.12-rc2Linus Torvalds
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
/*
 * lib/plist.c
 *
 * Descending-priority-sorted double-linked list
 *
 * (C) 2002-2003 Intel Corp
 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
 *
 * 2001-2005 (c) MontaVista Software, Inc.
 * Daniel Walker <dwalker@mvista.com>
 *
 * (C) 2005 Thomas Gleixner <tglx@linutronix.de>
 *
 * Simplifications of the original code by
 * Oleg Nesterov <oleg@tv-sign.ru>
 *
 * Licensed under the FSF's GNU Public License v2 or later.
 *
 * Based on simple lists (include/linux/list.h).
 *
 * This file contains the add / del functions which are considered to
 * be too large to inline. See include/linux/plist.h for further
 * information.
 */

#include <linux/plist.h>
#include <linux/spinlock.h>

#ifdef CONFIG_DEBUG_PI_LIST

static void plist_check_prev_next(struct list_head *t, struct list_head *p,
				  struct list_head *n)
{
	if (n->prev != p || p->next != n) {
		printk("top: %p, n: %p, p: %p\n", t, t->next, t->prev);
		printk("prev: %p, n: %p, p: %p\n", p, p->next, p->prev);
		printk("next: %p, n: %p, p: %p\n", n, n->next, n->prev);
		WARN_ON(1);
	}
}

static void plist_check_list(struct list_head *top)
{
	struct list_head *prev = top, *next = top->next;

	plist_check_prev_next(top, prev, next);
	while (next != top) {
		prev = next;
		next = prev->next;
		plist_check_prev_next(top, prev, next);
	}
}

static void plist_check_head(struct plist_head *head)
{
	WARN_ON(!head->lock);
	if (head->lock)
		WARN_ON_SMP(!spin_is_locked(head->lock));
	plist_check_list(&head->prio_list);
	plist_check_list(&head->node_list);
}

#else
# define plist_check_head(h)	do { } while (0)
#endif

/**
 * plist_add - add @node to @head
 *
 * @node:	&struct plist_node pointer
 * @head:	&struct plist_head pointer
 */
void plist_add(struct plist_node *node, struct plist_head *head)
{
	struct plist_node *iter;

	plist_check_head(head);
	WARN_ON(!plist_node_empty(node));

	list_for_each_entry(iter, &head->prio_list, plist.prio_list) {
		if (node->prio < iter->prio)
			goto lt_prio;
		else if (node->prio == iter->prio) {
			iter = list_entry(iter->plist.prio_list.next,
					struct plist_node, plist.prio_list);
			goto eq_prio;
		}
	}

lt_prio:
	list_add_tail(&node->plist.prio_list, &iter->plist.prio_list);
eq_prio:
	list_add_tail(&node->plist.node_list, &iter->plist.node_list);

	plist_check_head(head);
}

/**
 * plist_del - Remove a @node from plist.
 *
 * @node:	&struct plist_node pointer - entry to be removed
 * @head:	&struct plist_head pointer - list head
 */
void plist_del(struct plist_node *node, struct plist_head *head)
{
	plist_check_head(head);

	if (!list_empty(&node->plist.prio_list)) {
		struct plist_node *next = plist_first(&node->plist);

		list_move_tail(&next->plist.prio_list, &node->plist.prio_list);
		list_del_init(&node->plist.prio_list);
	}

	list_del_init(&node->plist.node_list);

	plist_check_head(head);
}