linux/mm/swap_state.c

/*
 *  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