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

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