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

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