/*
* linux/mm/swap_state.c
*
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
* Swap reorganised 29.12.95, Stephen Tweedie
*/
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/head.h>
#include <linux/kernel.h>
#include <linux/kernel_stat.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/swap.h>
#include <linux/fs.h>
#include <linux/swapctl.h>
#include <asm/dma.h>
#include <asm/system.h> /* for cli()/sti() */
#include <asm/segment.h> /* for memcpy_to/fromfs */
#include <asm/bitops.h>
#include <asm/pgtable.h>
/*
* To save us from swapping out pages which have just been swapped in and
* have not been modified since then, we keep in swap_cache[page>>PAGE_SHIFT]
* the swap entry which was last used to fill the page, or zero if the
* page does not currently correspond to a page in swap. PAGE_DIRTY makes
* this info useless.
*/
unsigned long *swap_cache;
#ifdef SWAP_CACHE_INFO
unsigned long swap_cache_add_total = 0;
unsigned long swap_cache_add_success = 0;
unsigned long swap_cache_del_total = 0;
unsigned long swap_cache_del_success = 0;
unsigned long swap_cache_find_total = 0;
unsigned long swap_cache_find_success = 0;
void show_swap_cache_info(void)
/* Funkcja wypisuje informacje statystyczne o wykorzystaniu swap_cache. */
{
printk("Swap cache: add %ld/%ld, delete %ld/%ld, find %ld/%ld\n",
swap_cache_add_total, swap_cache_add_success,
swap_cache_del_total, swap_cache_del_success,
swap_cache_find_total, swap_cache_find_success);
}
#endif
int add_to_swap_cache(unsigned long index, unsigned long entry)
/* Funkcja dodaje stonę w ramce o indeksie index umieszczoną na urządzeniu
wymiany w miejscu oznaczonym kluczem entry do do swap cache. */
{
struct swap_info_struct * p = &swap_info[SWP_TYPE(entry)];
#ifdef SWAP_CACHE_INFO
swap_cache_add_total++;
#endif
if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
entry = xchg(swap_cache + index, entry);
if (entry) {
printk("swap_cache: replacing non-NULL entry\n");
}
#ifdef SWAP_CACHE_INFO
swap_cache_add_success++;
#endif
return 1;
}
return 0;
}
unsigned long init_swap_cache(unsigned long mem_start,
unsigned long mem_end)
/* Funkcja inicjalizujeme tablicę swap_cache, tak aby miała wielkość rowną
liczbie ramek w systemie, zeruje tą tablicę; tablica swap_cache bedzie
zaczynać się od słowa następnego wolnego po mem_start; funkcja zwraca
pierwszy wolny adres za swap_cache. */
{
unsigned long swap_cache_size;
/* swap_cache ma zaczynać sie od słowa */
mem_start = (mem_start + 15) & ~15;
swap_cache = (unsigned long *) mem_start;
/* ilość pól w swap_cache jest taka sama, jak liczba ramek */
swap_cache_size = MAP_NR(mem_end);
/* wypełniamy tablicę zerami */
memset(swap_cache, 0, swap_cache_size * sizeof (unsigned long));
return (unsigned long) (swap_cache + swap_cache_size);
}
void swap_duplicate(unsigned long entry)
/* Funkja zwieksza ilość odwołań do strony o kluczu entry na urządzeniu
wymiany */
{
struct swap_info_struct * p;
unsigned long offset, type;
if (!entry)
return;
/* wyznaczamy numer strony na urządzeniu wymiany */
offset = SWP_OFFSET(entry);
/* wyznaczamy numer urządzenia wymiany */
type = SWP_TYPE(entry);
/* jeśli numer jest zły (nie jest przewidziany dla urządzenia wymiany), to
wracamy */
if (type & SHM_SWP_TYPE)
return;
/* jeśli urządzenie wymiany o numerze type nie istnieje, to wypisujemy
błąd */
if (type >= nr_swapfiles)
{
printk("Trying to duplicate nonexistent swap-page\n");
return;
}
/* p jest wskaźnikiem na informacje o urzadzeniu wymiany, na którym jest
ramka o kluczu entry */
p = type + swap_info;
/* jeżeli numer strony na urządzeniu wymiany jest większy od maksymalnego
przewidzianego dla tego urządzenia, to wypisujemy błąd */
if (offset >= p->max) {
printk("swap_duplicate: weirdness\n");
return;
}
/* jeśli pole na urządzeniu wymiany, w którym ma się znajdować duplikowana
ramka o kluczu entry jest puste, to wypisujemy błąd */
if (!p->swap_map[offset]) {
printk("swap_duplicate: trying to duplicate unused page\n");
return;
}
/* zwiekszamy ilość odwołań do tej strony na urządzeniu wymiany */
p->swap_map[offset]++;
return;
}
Andrzej Kuczyński