root/mm/swap.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rw_swap_page
  2. get_swap_page
  3. swap_duplicate
  4. swap_free
  5. swap_in
  6. try_to_swap_out
  7. sys_idle
  8. swap_out
  9. swap_out
  10. try_to_free_page
  11. add_mem_queue
  12. free_page
  13. __get_free_page
  14. try_to_unuse
  15. sys_swapoff
  16. sys_swapon
  17. si_swapinfo

   1 /*
   2  *  linux/mm/swap.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * This file should contain most things doing the swapping from/to disk.
   9  * Started 18.12.91
  10  */
  11 
  12 #include <linux/mm.h>
  13 #include <linux/sched.h>
  14 #include <linux/head.h>
  15 #include <linux/kernel.h>
  16 #include <linux/kernel_stat.h>
  17 #include <linux/errno.h>
  18 #include <linux/string.h>
  19 #include <linux/stat.h>
  20 
  21 #include <asm/system.h> /* for cli()/sti() */
  22 #include <asm/bitops.h>
  23 
  24 #define MAX_SWAPFILES 8
  25 
  26 #define SWP_USED        1
  27 #define SWP_WRITEOK     3
  28 
  29 #define SWP_TYPE(entry) (((entry) & 0xfe) >> 1)
  30 #define SWP_OFFSET(entry) ((entry) >> PAGE_SHIFT)
  31 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << PAGE_SHIFT))
  32 
  33 static int nr_swapfiles = 0;
  34 static struct wait_queue * lock_queue = NULL;
  35 
  36 static struct swap_info_struct {
  37         unsigned long flags;
  38         struct inode * swap_file;
  39         unsigned int swap_device;
  40         unsigned char * swap_map;
  41         unsigned char * swap_lockmap;
  42         int pages;
  43         int lowest_bit;
  44         int highest_bit;
  45         unsigned long max;
  46 } swap_info[MAX_SWAPFILES];
  47 
  48 extern unsigned long free_page_list;
  49 extern int shm_swap (int);
  50 
  51 /*
  52  * The following are used to make sure we don't thrash too much...
  53  * NOTE!! NR_LAST_FREE_PAGES must be a power of 2...
  54  */
  55 #define NR_LAST_FREE_PAGES 32
  56 static unsigned long last_free_pages[NR_LAST_FREE_PAGES] = {0,};
  57 
  58 void rw_swap_page(int rw, unsigned long entry, char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         unsigned long type, offset;
  61         struct swap_info_struct * p;
  62 
  63         type = SWP_TYPE(entry);
  64         if (type >= nr_swapfiles) {
  65                 printk("Internal error: bad swap-device\n");
  66                 return;
  67         }
  68         p = &swap_info[type];
  69         offset = SWP_OFFSET(entry);
  70         if (offset >= p->max) {
  71                 printk("rw_swap_page: weirdness\n");
  72                 return;
  73         }
  74         if (!(p->flags & SWP_USED)) {
  75                 printk("Trying to swap to unused swap-device\n");
  76                 return;
  77         }
  78         while (set_bit(offset,p->swap_lockmap))
  79                 sleep_on(&lock_queue);
  80         if (rw == READ)
  81                 kstat.pswpin++;
  82         else
  83                 kstat.pswpout++;
  84         if (p->swap_device) {
  85                 ll_rw_page(rw,p->swap_device,offset,buf);
  86         } else if (p->swap_file) {
  87                 unsigned int zones[8];
  88                 unsigned int block;
  89                 int i, j;
  90 
  91                 block = offset << (12 - p->swap_file->i_sb->s_blocksize_bits);
  92 
  93                 for (i=0, j=0; j< PAGE_SIZE ; i++, j +=p->swap_file->i_sb->s_blocksize)
  94                         if (!(zones[i] = bmap(p->swap_file,block++))) {
  95                                 printk("rw_swap_page: bad swap file\n");
  96                                 return;
  97                         }
  98                 ll_rw_swap_file(rw,p->swap_file->i_dev, zones, i,buf);
  99         } else
 100                 printk("re_swap_page: no swap file or device\n");
 101         if (offset && !clear_bit(offset,p->swap_lockmap))
 102                 printk("rw_swap_page: lock already cleared\n");
 103         wake_up(&lock_queue);
 104 }
 105 
 106 unsigned int get_swap_page(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         struct swap_info_struct * p;
 109         unsigned int offset, type;
 110 
 111         p = swap_info;
 112         for (type = 0 ; type < nr_swapfiles ; type++,p++) {
 113                 if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK)
 114                         continue;
 115                 for (offset = p->lowest_bit; offset <= p->highest_bit ; offset++) {
 116                         if (p->swap_map[offset])
 117                                 continue;
 118                         p->swap_map[offset] = 1;
 119                         nr_swap_pages--;
 120                         if (offset == p->highest_bit)
 121                                 p->highest_bit--;
 122                         p->lowest_bit = offset;
 123                         return SWP_ENTRY(type,offset);
 124                 }
 125         }
 126         return 0;
 127 }
 128 
 129 unsigned long swap_duplicate(unsigned long entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         struct swap_info_struct * p;
 132         unsigned long offset, type;
 133 
 134         if (!entry)
 135                 return 0;
 136         offset = SWP_OFFSET(entry);
 137         type = SWP_TYPE(entry);
 138         if (type == SHM_SWP_TYPE)
 139                 return entry;
 140         if (type >= nr_swapfiles) {
 141                 printk("Trying to duplicate nonexistent swap-page\n");
 142                 return 0;
 143         }
 144         p = type + swap_info;
 145         if (offset >= p->max) {
 146                 printk("swap_free: weirdness\n");
 147                 return 0;
 148         }
 149         if (!p->swap_map[offset]) {
 150                 printk("swap_duplicate: trying to duplicate unused page\n");
 151                 return 0;
 152         }
 153         p->swap_map[offset]++;
 154         return entry;
 155 }
 156 
 157 void swap_free(unsigned long entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159         struct swap_info_struct * p;
 160         unsigned long offset, type;
 161 
 162         if (!entry)
 163                 return;
 164         type = SWP_TYPE(entry);
 165         if (type == SHM_SWP_TYPE)
 166                 return;
 167         if (type >= nr_swapfiles) {
 168                 printk("Trying to free nonexistent swap-page\n");
 169                 return;
 170         }
 171         p = & swap_info[type];
 172         offset = SWP_OFFSET(entry);
 173         if (offset >= p->max) {
 174                 printk("swap_free: weirdness\n");
 175                 return;
 176         }
 177         if (!(p->flags & SWP_USED)) {
 178                 printk("Trying to free swap from unused swap-device\n");
 179                 return;
 180         }
 181         while (set_bit(offset,p->swap_lockmap))
 182                 sleep_on(&lock_queue);
 183         if (offset < p->lowest_bit)
 184                 p->lowest_bit = offset;
 185         if (offset > p->highest_bit)
 186                 p->highest_bit = offset;
 187         if (!p->swap_map[offset])
 188                 printk("swap_free: swap-space map bad (entry %08lx)\n",entry);
 189         else
 190                 if (!--p->swap_map[offset])
 191                         nr_swap_pages++;
 192         if (!clear_bit(offset,p->swap_lockmap))
 193                 printk("swap_free: lock already cleared\n");
 194         wake_up(&lock_queue);
 195 }
 196 
 197 void swap_in(unsigned long *table_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 198 {
 199         unsigned long entry;
 200         unsigned long page;
 201 
 202         entry = *table_ptr;
 203         if (PAGE_PRESENT & entry) {
 204                 printk("trying to swap in present page\n");
 205                 return;
 206         }
 207         if (!entry) {
 208                 printk("No swap page in swap_in\n");
 209                 return;
 210         }
 211         if (SWP_TYPE(entry) == SHM_SWP_TYPE) {
 212                 shm_no_page ((unsigned long *) table_ptr);
 213                 return;
 214         }
 215         if (!(page = get_free_page(GFP_KERNEL))) {
 216                 oom(current);
 217                 page = BAD_PAGE;
 218         } else  
 219                 read_swap_page(entry, (char *) page);
 220         if (*table_ptr != entry) {
 221                 free_page(page);
 222                 return;
 223         }
 224         *table_ptr = page | (PAGE_DIRTY | PAGE_PRIVATE);
 225         swap_free(entry);
 226 }
 227 
 228 static inline int try_to_swap_out(unsigned long * table_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230         int i;
 231         unsigned long page;
 232         unsigned long entry;
 233 
 234         page = *table_ptr;
 235         if (!(PAGE_PRESENT & page))
 236                 return 0;
 237         if (page >= high_memory)
 238                 return 0;
 239         if (mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED)
 240                 return 0;
 241         if (PAGE_ACCESSED & page) {
 242                 *table_ptr &= ~PAGE_ACCESSED;
 243                 return 0;
 244         }
 245         for (i = 0; i < NR_LAST_FREE_PAGES; i++)
 246                 if (last_free_pages[i] == (page & PAGE_MASK))
 247                         return 0;
 248         if (PAGE_DIRTY & page) {
 249                 page &= PAGE_MASK;
 250                 if (mem_map[MAP_NR(page)] != 1)
 251                         return 0;
 252                 if (!(entry = get_swap_page()))
 253                         return 0;
 254                 *table_ptr = entry;
 255                 invalidate();
 256                 write_swap_page(entry, (char *) page);
 257                 free_page(page);
 258                 return 1;
 259         }
 260         page &= PAGE_MASK;
 261         *table_ptr = 0;
 262         invalidate();
 263         free_page(page);
 264         return 1 + mem_map[MAP_NR(page)];
 265 }
 266 
 267 /*
 268  * sys_idle() does nothing much: it just searches for likely candidates for
 269  * swapping out or forgetting about. This speeds up the search when we
 270  * actually have to swap.
 271  */
 272 asmlinkage int sys_idle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 273 {
 274         need_resched = 1;
 275         return 0;
 276 }
 277 
 278 /*
 279  * A new implementation of swap_out().  We do not swap complete processes,
 280  * but only a small number of blocks, before we continue with the next
 281  * process.  The number of blocks actually swapped is determined on the
 282  * number of page faults, that this process actually had in the last time,
 283  * so we won't swap heavily used processes all the time ...
 284  *
 285  * Note: the priority argument is a hint on much CPU to waste with the
 286  *       swap block search, not a hint, of how much blocks to swap with
 287  *       each process.
 288  *
 289  * (C) 1993 Kai Petzke, wpp@marie.physik.tu-berlin.de
 290  */
 291 #ifdef NEW_SWAP
 292 /*
 293  * These are the miminum and maximum number of pages to swap from one process,
 294  * before proceeding to the next:
 295  */
 296 #define SWAP_MIN        4
 297 #define SWAP_MAX        32
 298 
 299 /*
 300  * The actual number of pages to swap is determined as:
 301  * SWAP_RATIO / (number of recent major page faults)
 302  */
 303 #define SWAP_RATIO      128
 304 
 305 static int swap_out(unsigned int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 306 {
 307     static int swap_task;
 308     int table;
 309     int page;
 310     long pg_table;
 311     int loop;
 312     int counter = NR_TASKS * 2 >> priority;
 313     struct task_struct *p;
 314 
 315     counter = NR_TASKS * 2 >> priority;
 316     for(; counter >= 0; counter--, swap_task++) {
 317         /*
 318          * Check that swap_task is suitable for swapping.  If not, look for
 319          * the next suitable process.
 320          */
 321         loop = 0;
 322         while(1) {
 323             if(swap_task >= NR_TASKS) {
 324                 swap_task = 1;
 325                 if(loop)
 326                     /* all processes are unswappable or already swapped out */
 327                     return 0;
 328                 loop = 1;
 329             }
 330 
 331             p = task[swap_task];
 332             if(p && p->swappable && p->rss)
 333                 break;
 334 
 335             swap_task++;
 336         }
 337 
 338         /*
 339          * Determine the number of pages to swap from this process.
 340          */
 341         if(! p -> swap_cnt) {
 342             p->dec_flt = (p->dec_flt * 3) / 4 + p->maj_flt - p->old_maj_flt;
 343             p->old_maj_flt = p->maj_flt;
 344 
 345             if(p->dec_flt >= SWAP_RATIO / SWAP_MIN) {
 346                 p->dec_flt = SWAP_RATIO / SWAP_MIN;
 347                 p->swap_cnt = SWAP_MIN;
 348             } else if(p->dec_flt <= SWAP_RATIO / SWAP_MAX)
 349                 p->swap_cnt = SWAP_MAX;
 350             else
 351                 p->swap_cnt = SWAP_RATIO / p->dec_flt;
 352         }
 353 
 354         /*
 355          * Go through process' page directory.
 356          */
 357         for(table = p->swap_table; table < 1024; table++) {
 358             pg_table = ((unsigned long *) p->tss.cr3)[table];
 359             if(pg_table >= high_memory)
 360                     continue;
 361             if(mem_map[MAP_NR(pg_table)] & MAP_PAGE_RESERVED)
 362                     continue;
 363             if(!(PAGE_PRESENT & pg_table)) {
 364                     printk("swap_out: bad page-table at pg_dir[%d]: %08lx\n",
 365                             table, pg_table);
 366                     ((unsigned long *) p->tss.cr3)[table] = 0;
 367                     continue;
 368             }
 369             pg_table &= 0xfffff000;
 370 
 371             /*
 372              * Go through this page table.
 373              */
 374             for(page = p->swap_page; page < 1024; page++) {
 375                 switch(try_to_swap_out(page + (unsigned long *) pg_table)) {
 376                     case 0:
 377                         break;
 378 
 379                     case 1:
 380                         p->rss--;
 381                         /* continue with the following page the next time */
 382                         p->swap_table = table;
 383                         p->swap_page  = page + 1;
 384                         if((--p->swap_cnt) == 0)
 385                             swap_task++;
 386                         return 1;
 387 
 388                     default:
 389                         p->rss--;
 390                         break;
 391                 }
 392             }
 393 
 394             p->swap_page = 0;
 395         }
 396 
 397         /*
 398          * Finish work with this process, if we reached the end of the page
 399          * directory.  Mark restart from the beginning the next time.
 400          */
 401         p->swap_table = 0;
 402     }
 403     return 0;
 404 }
 405 
 406 #else /* old swapping procedure */
 407 
 408 /*
 409  * Go through the page tables, searching for a user page that
 410  * we can swap out.
 411  * 
 412  * We now check that the process is swappable (normally only 'init'
 413  * is un-swappable), allowing high-priority processes which cannot be
 414  * swapped out (things like user-level device drivers (Not implemented)).
 415  */
 416 static int swap_out(unsigned int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 417 {
 418         static int swap_task = 1;
 419         static int swap_table = 0;
 420         static int swap_page = 0;
 421         int counter = NR_TASKS*8;
 422         int pg_table;
 423         struct task_struct * p;
 424 
 425         counter >>= priority;
 426 check_task:
 427         if (counter-- < 0)
 428                 return 0;
 429         if (swap_task >= NR_TASKS) {
 430                 swap_task = 1;
 431                 goto check_task;
 432         }
 433         p = task[swap_task];
 434         if (!p || !p->swappable) {
 435                 swap_task++;
 436                 goto check_task;
 437         }
 438 check_dir:
 439         if (swap_table >= PTRS_PER_PAGE) {
 440                 swap_table = 0;
 441                 swap_task++;
 442                 goto check_task;
 443         }
 444         pg_table = ((unsigned long *) p->tss.cr3)[swap_table];
 445         if (pg_table >= high_memory || (mem_map[MAP_NR(pg_table)] & MAP_PAGE_RESERVED)) {
 446                 swap_table++;
 447                 goto check_dir;
 448         }
 449         if (!(PAGE_PRESENT & pg_table)) {
 450                 printk("bad page-table at pg_dir[%d]: %08x\n",
 451                         swap_table,pg_table);
 452                 ((unsigned long *) p->tss.cr3)[swap_table] = 0;
 453                 swap_table++;
 454                 goto check_dir;
 455         }
 456         pg_table &= PAGE_MASK;
 457 check_table:
 458         if (swap_page >= PTRS_PER_PAGE) {
 459                 swap_page = 0;
 460                 swap_table++;
 461                 goto check_dir;
 462         }
 463         switch (try_to_swap_out(swap_page + (unsigned long *) pg_table)) {
 464                 case 0: break;
 465                 case 1: p->rss--; return 1;
 466                 default: p->rss--;
 467         }
 468         swap_page++;
 469         goto check_table;
 470 }
 471 
 472 #endif
 473 
 474 static int try_to_free_page(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 475 {
 476         int i=6;
 477 
 478         while (i--) {
 479                 if (shrink_buffers(i))
 480                         return 1;
 481                 if (shm_swap(i))
 482                         return 1;
 483                 if (swap_out(i))
 484                         return 1;
 485         }
 486         return 0;
 487 }
 488 
 489 /*
 490  * Note that this must be atomic, or bad things will happen when
 491  * pages are requested in interrupts (as malloc can do). Thus the
 492  * cli/sti's.
 493  */
 494 static inline void add_mem_queue(unsigned long addr, unsigned long * queue)
     /* [previous][next][first][last][top][bottom][index][help] */
 495 {
 496         addr &= PAGE_MASK;
 497         *(unsigned long *) addr = *queue;
 498         *queue = addr;
 499 }
 500 
 501 /*
 502  * Free_page() adds the page to the free lists. This is optimized for
 503  * fast normal cases (no error jumps taken normally).
 504  *
 505  * The way to optimize jumps for gcc-2.2.2 is to:
 506  *  - select the "normal" case and put it inside the if () { XXX }
 507  *  - no else-statements if you can avoid them
 508  *
 509  * With the above two rules, you get a straight-line execution path
 510  * for the normal case, giving better asm-code.
 511  */
 512 void free_page(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 513 {
 514         if (addr < high_memory) {
 515                 unsigned short * map = mem_map + MAP_NR(addr);
 516 
 517                 if (*map) {
 518                         if (!(*map & MAP_PAGE_RESERVED)) {
 519                                 unsigned long flag;
 520 
 521                                 save_flags(flag);
 522                                 cli();
 523                                 if (!--*map) {
 524                                         if (nr_secondary_pages < MAX_SECONDARY_PAGES) {
 525                                                 add_mem_queue(addr,&secondary_page_list);
 526                                                 nr_secondary_pages++;
 527                                                 restore_flags(flag);
 528                                                 return;
 529                                         }
 530                                         add_mem_queue(addr,&free_page_list);
 531                                         nr_free_pages++;
 532                                 }
 533                                 restore_flags(flag);
 534                         }
 535                         return;
 536                 }
 537                 printk("Trying to free free memory (%08lx): memory probabably corrupted\n",addr);
 538                 printk("PC = %08lx\n",*(((unsigned long *)&addr)-1));
 539                 return;
 540         }
 541 }
 542 
 543 /*
 544  * This is one ugly macro, but it simplifies checking, and makes
 545  * this speed-critical place reasonably fast, especially as we have
 546  * to do things with the interrupt flag etc.
 547  *
 548  * Note that this #define is heavily optimized to give fast code
 549  * for the normal case - the if-statements are ordered so that gcc-2.2.2
 550  * will make *no* jumps for the normal code. Don't touch unless you
 551  * know what you are doing.
 552  */
 553 #define REMOVE_FROM_MEM_QUEUE(queue,nr) \
 554         cli(); \
 555         if ((result = queue) != 0) { \
 556                 if (!(result & ~PAGE_MASK) && result < high_memory) { \
 557                         queue = *(unsigned long *) result; \
 558                         if (!mem_map[MAP_NR(result)]) { \
 559                                 mem_map[MAP_NR(result)] = 1; \
 560                                 nr--; \
 561 last_free_pages[index = (index + 1) & (NR_LAST_FREE_PAGES - 1)] = result; \
 562                                 restore_flags(flag); \
 563                                 return result; \
 564                         } \
 565                         printk("Free page %08lx has mem_map = %d\n", \
 566                                 result,mem_map[MAP_NR(result)]); \
 567                 } else \
 568                         printk("Result = 0x%08lx - memory map destroyed\n", result); \
 569                 queue = 0; \
 570                 nr = 0; \
 571         } else if (nr) { \
 572                 printk(#nr " is %d, but " #queue " is empty\n",nr); \
 573                 nr = 0; \
 574         } \
 575         restore_flags(flag)
 576 
 577 /*
 578  * Get physical address of first (actually last :-) free page, and mark it
 579  * used. If no free pages left, return 0.
 580  *
 581  * Note that this is one of the most heavily called functions in the kernel,
 582  * so it's a bit timing-critical (especially as we have to disable interrupts
 583  * in it). See the above macro which does most of the work, and which is
 584  * optimized for a fast normal path of execution.
 585  */
 586 unsigned long __get_free_page(int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 587 {
 588         unsigned long result, flag;
 589         static unsigned long index = 0;
 590 
 591         /* this routine can be called at interrupt time via
 592            malloc.  We want to make sure that the critical
 593            sections of code have interrupts disabled. -RAB
 594            Is this code reentrant? */
 595 
 596         save_flags(flag);
 597 repeat:
 598         REMOVE_FROM_MEM_QUEUE(free_page_list,nr_free_pages);
 599         if (priority == GFP_BUFFER)
 600                 return 0;
 601         if (priority != GFP_ATOMIC)
 602                 if (try_to_free_page())
 603                         goto repeat;
 604         REMOVE_FROM_MEM_QUEUE(secondary_page_list,nr_secondary_pages);
 605         return 0;
 606 }
 607 
 608 /*
 609  * Trying to stop swapping from a file is fraught with races, so
 610  * we repeat quite a bit here when we have to pause. swapoff()
 611  * isn't exactly timing-critical, so who cares?
 612  */
 613 static int try_to_unuse(unsigned int type)
     /* [previous][next][first][last][top][bottom][index][help] */
 614 {
 615         int nr, pgt, pg;
 616         unsigned long page, *ppage;
 617         unsigned long tmp = 0;
 618         struct task_struct *p;
 619 
 620         nr = 0;
 621 /*
 622  * When we have to sleep, we restart the whole algorithm from the same
 623  * task we stopped in. That at least rids us of all races.
 624  */
 625 repeat:
 626         for (; nr < NR_TASKS ; nr++) {
 627                 p = task[nr];
 628                 if (!p)
 629                         continue;
 630                 for (pgt = 0 ; pgt < PTRS_PER_PAGE ; pgt++) {
 631                         ppage = pgt + ((unsigned long *) p->tss.cr3);
 632                         page = *ppage;
 633                         if (!page)
 634                                 continue;
 635                         if (!(page & PAGE_PRESENT) || (page >= high_memory))
 636                                 continue;
 637                         if (mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED)
 638                                 continue;
 639                         ppage = (unsigned long *) (page & PAGE_MASK);   
 640                         for (pg = 0 ; pg < PTRS_PER_PAGE ; pg++,ppage++) {
 641                                 page = *ppage;
 642                                 if (!page)
 643                                         continue;
 644                                 if (page & PAGE_PRESENT)
 645                                         continue;
 646                                 if (SWP_TYPE(page) != type)
 647                                         continue;
 648                                 if (!tmp) {
 649                                         if (!(tmp = __get_free_page(GFP_KERNEL)))
 650                                                 return -ENOMEM;
 651                                         goto repeat;
 652                                 }
 653                                 read_swap_page(page, (char *) tmp);
 654                                 if (*ppage == page) {
 655                                         *ppage = tmp | (PAGE_DIRTY | PAGE_PRIVATE);
 656                                         ++p->rss;
 657                                         swap_free(page);
 658                                         tmp = 0;
 659                                 }
 660                                 goto repeat;
 661                         }
 662                 }
 663         }
 664         free_page(tmp);
 665         return 0;
 666 }
 667 
 668 asmlinkage int sys_swapoff(const char * specialfile)
     /* [previous][next][first][last][top][bottom][index][help] */
 669 {
 670         struct swap_info_struct * p;
 671         struct inode * inode;
 672         unsigned int type;
 673         int i;
 674 
 675         if (!suser())
 676                 return -EPERM;
 677         i = namei(specialfile,&inode);
 678         if (i)
 679                 return i;
 680         p = swap_info;
 681         for (type = 0 ; type < nr_swapfiles ; type++,p++) {
 682                 if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK)
 683                         continue;
 684                 if (p->swap_file) {
 685                         if (p->swap_file == inode)
 686                                 break;
 687                 } else {
 688                         if (!S_ISBLK(inode->i_mode))
 689                                 continue;
 690                         if (p->swap_device == inode->i_rdev)
 691                                 break;
 692                 }
 693         }
 694         iput(inode);
 695         if (type >= nr_swapfiles)
 696                 return -EINVAL;
 697         p->flags = SWP_USED;
 698         i = try_to_unuse(type);
 699         if (i) {
 700                 p->flags = SWP_WRITEOK;
 701                 return i;
 702         }
 703         nr_swap_pages -= p->pages;
 704         iput(p->swap_file);
 705         p->swap_file = NULL;
 706         p->swap_device = 0;
 707         vfree(p->swap_map);
 708         p->swap_map = NULL;
 709         free_page((long) p->swap_lockmap);
 710         p->swap_lockmap = NULL;
 711         p->flags = 0;
 712         return 0;
 713 }
 714 
 715 /*
 716  * Written 01/25/92 by Simmule Turner, heavily changed by Linus.
 717  *
 718  * The swapon system call
 719  */
 720 asmlinkage int sys_swapon(const char * specialfile)
     /* [previous][next][first][last][top][bottom][index][help] */
 721 {
 722         struct swap_info_struct * p;
 723         struct inode * swap_inode;
 724         unsigned int type;
 725         int i,j;
 726         int error;
 727 
 728         if (!suser())
 729                 return -EPERM;
 730         p = swap_info;
 731         for (type = 0 ; type < nr_swapfiles ; type++,p++)
 732                 if (!(p->flags & SWP_USED))
 733                         break;
 734         if (type >= MAX_SWAPFILES)
 735                 return -EPERM;
 736         if (type >= nr_swapfiles)
 737                 nr_swapfiles = type+1;
 738         p->flags = SWP_USED;
 739         p->swap_file = NULL;
 740         p->swap_device = 0;
 741         p->swap_map = NULL;
 742         p->swap_lockmap = NULL;
 743         p->lowest_bit = 0;
 744         p->highest_bit = 0;
 745         p->max = 1;
 746         error = namei(specialfile,&swap_inode);
 747         if (error)
 748                 goto bad_swap;
 749         error = -EBUSY;
 750         if (swap_inode->i_count != 1)
 751                 goto bad_swap;
 752         error = -EINVAL;
 753         if (S_ISBLK(swap_inode->i_mode)) {
 754                 p->swap_device = swap_inode->i_rdev;
 755                 iput(swap_inode);
 756                 error = -ENODEV;
 757                 if (!p->swap_device)
 758                         goto bad_swap;
 759                 error = -EBUSY;
 760                 for (i = 0 ; i < nr_swapfiles ; i++) {
 761                         if (i == type)
 762                                 continue;
 763                         if (p->swap_device == swap_info[i].swap_device)
 764                                 goto bad_swap;
 765                 }
 766         } else if (S_ISREG(swap_inode->i_mode))
 767                 p->swap_file = swap_inode;
 768         else
 769                 goto bad_swap;
 770         p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER);
 771         if (!p->swap_lockmap) {
 772                 printk("Unable to start swapping: out of memory :-)\n");
 773                 error = -ENOMEM;
 774                 goto bad_swap;
 775         }
 776         read_swap_page(SWP_ENTRY(type,0), (char *) p->swap_lockmap);
 777         if (memcmp("SWAP-SPACE",p->swap_lockmap+4086,10)) {
 778                 printk("Unable to find swap-space signature\n");
 779                 error = -EINVAL;
 780                 goto bad_swap;
 781         }
 782         memset(p->swap_lockmap+PAGE_SIZE-10,0,10);
 783         j = 0;
 784         p->lowest_bit = 0;
 785         p->highest_bit = 0;
 786         for (i = 1 ; i < 8*PAGE_SIZE ; i++) {
 787                 if (test_bit(i,p->swap_lockmap)) {
 788                         if (!p->lowest_bit)
 789                                 p->lowest_bit = i;
 790                         p->highest_bit = i;
 791                         p->max = i+1;
 792                         j++;
 793                 }
 794         }
 795         if (!j) {
 796                 printk("Empty swap-file\n");
 797                 error = -EINVAL;
 798                 goto bad_swap;
 799         }
 800         p->swap_map = (unsigned char *) vmalloc(p->max);
 801         if (!p->swap_map) {
 802                 error = -ENOMEM;
 803                 goto bad_swap;
 804         }
 805         for (i = 1 ; i < p->max ; i++) {
 806                 if (test_bit(i,p->swap_lockmap))
 807                         p->swap_map[i] = 0;
 808                 else
 809                         p->swap_map[i] = 0x80;
 810         }
 811         p->swap_map[0] = 0x80;
 812         memset(p->swap_lockmap,0,PAGE_SIZE);
 813         p->flags = SWP_WRITEOK;
 814         p->pages = j;
 815         nr_swap_pages += j;
 816         printk("Adding Swap: %dk swap-space\n",j<<2);
 817         return 0;
 818 bad_swap:
 819         free_page((long) p->swap_lockmap);
 820         vfree(p->swap_map);
 821         iput(p->swap_file);
 822         p->swap_device = 0;
 823         p->swap_file = NULL;
 824         p->swap_map = NULL;
 825         p->swap_lockmap = NULL;
 826         p->flags = 0;
 827         return error;
 828 }
 829 
 830 void si_swapinfo(struct sysinfo *val)
     /* [previous][next][first][last][top][bottom][index][help] */
 831 {
 832         unsigned int i, j;
 833 
 834         val->freeswap = val->totalswap = 0;
 835         for (i = 0; i < nr_swapfiles; i++) {
 836                 if (!(swap_info[i].flags & SWP_USED))
 837                         continue;
 838                 for (j = 0; j < swap_info[i].max; ++j)
 839                         switch (swap_info[i].swap_map[j]) {
 840                                 case 128:
 841                                         continue;
 842                                 case 0:
 843                                         ++val->freeswap;
 844                                 default:
 845                                         ++val->totalswap;
 846                         }
 847         }
 848         val->freeswap <<= PAGE_SHIFT;
 849         val->totalswap <<= PAGE_SHIFT;
 850         return;
 851 }

/* [previous][next][first][last][top][bottom][index][help] */