netlib.narod.ru< Назад | Оглавление | Далее >

mm/swapfile.c

37811 /*
37812  *  linux/mm/swapfile.c
37813  *
37814  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
37815  *  Swap reorganised 29.12.95, Stephen Tweedie
37816  */
37817 
37818 #include <linux/malloc.h>
37819 #include <linux/smp_lock.h>
37820 #include <linux/kernel_stat.h>
37821 #include <linux/swap.h>
37822 #include <linux/swapctl.h>
37823 #include <linux/blkdev.h> /* for blk_size */
37824 #include <linux/vmalloc.h>
37825 #include <linux/pagemap.h>
37826 #include <linux/shm.h>
37827 
37828 #include <asm/pgtable.h>
37829 
37830 unsigned int nr_swapfiles = 0;
37831 
37832 struct swap_list_t swap_list = {-1, -1};
37833 
37834 struct swap_info_struct swap_info[MAX_SWAPFILES];
37835 
37836 #define SWAPFILE_CLUSTER 256
37837 
37838 static inline int scan_swap_map(
37839   struct swap_info_struct *si)
37840 {
37841   unsigned long offset;
37842   /* We try to cluster swap pages by allocating them
37843    * sequentially in swap.  Once we've allocated
37844    * SWAPFILE_CLUSTER pages this way, however, we resort
37845    * to first-free allocation, starting a new cluster.
37846    * This prevents us from scattering swap pages all over
37847    * the entire swap partition, so that we reduce overall
37848    * disk seek times between swap pages.  -- sct */
37849   if (si->cluster_nr) {
37850     while (si->cluster_next <= si->highest_bit) {
37851       offset = si->cluster_next++;
37852       if (si->swap_map[offset])
37853         continue;
37854       if (test_bit(offset, si->swap_lockmap))
37855         continue;
37856       si->cluster_nr--;
37857       goto got_page;
37858     }
37859   }
37860   si->cluster_nr = SWAPFILE_CLUSTER;
37861   for (offset = si->lowest_bit;
37862        offset <= si->highest_bit ; offset++) {
37863     if (si->swap_map[offset])
37864       continue;
37865     if (test_bit(offset, si->swap_lockmap))
37866       continue;
37867     si->lowest_bit = offset;
37868 got_page:
37869     si->swap_map[offset] = 1;
37870     nr_swap_pages--;
37871     if (offset == si->highest_bit)
37872       si->highest_bit--;
37873     si->cluster_next = offset;
37874     return offset;
37875   }
37876   return 0;
37877 }
37878 
 Комментарий
37879 unsigned long get_swap_page(void)
37880 {
37881   struct swap_info_struct * p;
37882   unsigned long offset, entry;
37883   int type, wrapped = 0;
37884 
37885   type = swap_list.next;
37886   if (type < 0)
37887     return 0;
37888   if (nr_swap_pages == 0)
37889     return 0;
37890 
37891   while (1) {
37892     p = &swap_info[type];
37893     if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
37894       offset = scan_swap_map(p);
37895       if (offset) {
37896         entry = SWP_ENTRY(type,offset);
37897         type = swap_info[type].next;
37898         if (type < 0 ||
37899           p->prio != swap_info[type].prio)
37900         {
37901             swap_list.next = swap_list.head;
37902         }
37903         else
37904         {
37905           swap_list.next = type;
37906         }
37907         return entry;
37908       }
37909     }
 Комментарий
37910     type = p->next;
37911     if (!wrapped) {
37912       if (type < 0 || p->prio != swap_info[type].prio) {
37913         type = swap_list.head;
37914         wrapped = 1;
37915       }
37916     } else if (type < 0) {
37917       return 0;       /* out of swap space */
37918     }
37919   }
37920 }
37921 
37922 
 Комментарий
37923 void swap_free(unsigned long entry)
37924 {
37925   struct swap_info_struct * p;
37926   unsigned long offset, type;
37927 
37928   if (!entry)
37929     goto out;
37930 
37931   type = SWP_TYPE(entry);
37932   if (type & SHM_SWP_TYPE)
37933     goto out;
37934   if (type >= nr_swapfiles)
37935     goto bad_nofile;
37936   p = & swap_info[type];
37937   if (!(p->flags & SWP_USED))
37938     goto bad_device;
37939   if (p->prio > swap_info[swap_list.next].prio)
37940     swap_list.next = swap_list.head;
37941   offset = SWP_OFFSET(entry);
37942   if (offset >= p->max)
37943     goto bad_offset;
37944   if (offset < p->lowest_bit)
37945     p->lowest_bit = offset;
37946   if (offset > p->highest_bit)
37947     p->highest_bit = offset;
37948   if (!p->swap_map[offset])
37949     goto bad_free;
37950   if (p->swap_map[offset] < SWAP_MAP_MAX) {
37951     if (!--p->swap_map[offset])
37952       nr_swap_pages++;
37953   }
37954 #ifdef DEBUG_SWAP
37955   printk("DebugVM: "
37956          "swap_free(entry %08lx, count now %d)\n",
37957          entry, p->swap_map[offset]);
37958 #endif
37959 out:
37960   return;
37961 
37962 bad_nofile:
37963   printk("swap_free: "
37964          "Trying to free nonexistent swap-page\n");
37965   goto out;
37966 bad_device:
37967   printk("swap_free: "
37968         "Trying to free swap from unused swap-device\n");
37969   goto out;
37970 bad_offset:
37971   printk("swap_free: offset exceeds max\n");
37972   goto out;
37973 bad_free:
37974   printk("swap_free: "
37975          "swap-space map bad (entry %08lx)\n",entry);
37976   goto out;
37977 }
37978 
37979 /* The swap entry has been read in advance, and we return
37980  * 1 to indicate that the page has been used or is no
37981  * longer needed.
37982  *
37983  * Always set the resulting pte to be nowrite (the same
37984  * as COW pages after one process has exited).  We don't
37985  * know just how many PTEs will share this swap entry, so
37986  * be cautious and let do_wp_page work out what to do if
37987  * a write is requested later.  */
37988 static inline void unuse_pte(struct vm_area_struct * vma,
37989   unsigned long address, pte_t *dir, unsigned long entry,
37990   unsigned long page)
37991 {
37992   pte_t pte = *dir;
37993 
37994   if (pte_none(pte))
37995     return;
37996   if (pte_present(pte)) {
37997     /* If this entry is swap-cached, then page must
37998      * already hold the right address for any copies in
37999      * physical memory */
38000     if (pte_page(pte) != page)
38001       return;
38002     /* We will be removing the swap cache in a moment,
38003      * so... */
38004     set_pte(dir, pte_mkdirty(pte));
38005     return;
38006   }
38007   if (pte_val(pte) != entry)
38008     return;
38009   set_pte(dir, pte_mkdirty(mk_pte(page,
38010                                   vma->vm_page_prot)));
38011   swap_free(entry);
38012   atomic_inc(&mem_map[MAP_NR(page)].count);
38013   ++vma->vm_mm->rss;
38014 }
38015 
38016 static inline void unuse_pmd(struct vm_area_struct * vma,
38017   pmd_t *dir, unsigned long address, unsigned long size,
38018   unsigned long offset, unsigned long entry,
38019   unsigned long page)
38020 {
38021   pte_t * pte;
38022   unsigned long end;
38023 
38024   if (pmd_none(*dir))
38025     return;
38026   if (pmd_bad(*dir)) {
38027     printk("unuse_pmd: bad pmd (%08lx)\n",pmd_val(*dir));
38028     pmd_clear(dir);
38029     return;
38030   }
38031   pte = pte_offset(dir, address);
38032   offset += address & PMD_MASK;
38033   address &= ~PMD_MASK;
38034   end = address + size;
38035   if (end > PMD_SIZE)
38036     end = PMD_SIZE;
38037   do {
38038     unuse_pte(vma, offset+address-vma->vm_start, pte,
38039               entry, page);
38040     address += PAGE_SIZE;
38041     pte++;
38042   } while (address < end);
38043 }
38044 
38045 static inline void unuse_pgd(struct vm_area_struct * vma,
38046   pgd_t *dir, unsigned long address, unsigned long size,
38047   unsigned long entry, unsigned long page)
38048 {
38049   pmd_t * pmd;
38050   unsigned long offset, end;
38051 
38052   if (pgd_none(*dir))
38053     return;
38054   if (pgd_bad(*dir)) {
38055     printk("unuse_pgd: bad pgd (%08lx)\n",pgd_val(*dir));
38056     pgd_clear(dir);
38057     return;
38058   }
38059   pmd = pmd_offset(dir, address);
38060   offset = address & PGDIR_MASK;
38061   address &= ~PGDIR_MASK;
38062   end = address + size;
38063   if (end > PGDIR_SIZE)
38064     end = PGDIR_SIZE;
38065   do {
38066     unuse_pmd(vma, pmd, address, end - address, offset,
38067               entry, page);
38068     address = (address + PMD_SIZE) & PMD_MASK;
38069     pmd++;
38070   } while (address < end);
38071 }
38072 
38073 static void unuse_vma(struct vm_area_struct * vma,
38074   pgd_t *pgdir, unsigned long entry, unsigned long page)
38075 {
38076   unsigned long start = vma->vm_start, end = vma->vm_end;
38077 
38078   while (start < end) {
38079     unuse_pgd(vma, pgdir, start, end - start, entry,
38080               page);
38081     start = (start + PGDIR_SIZE) & PGDIR_MASK;
38082     pgdir++;
38083   }
38084 }
38085 
38086 static void unuse_process(struct mm_struct * mm,
38087   unsigned long entry, unsigned long page)
38088 {
38089   struct vm_area_struct* vma;
38090 
38091   /* Go through process's page directory. */
38092   if (!mm || mm == &init_mm)
38093     return;
38094   for (vma = mm->mmap; vma; vma = vma->vm_next) {
38095     pgd_t * pgd = pgd_offset(mm, vma->vm_start);
38096     unuse_vma(vma, pgd, entry, page);
38097   }
38098   return;
38099 }
38100 
38101 /* We completely avoid races by reading each swap page in
38102  * advance, and then search for the process using it.
38103  * All the necessary page table adjustments can then be
38104  * made atomically.  */
38105 static int try_to_unuse(unsigned int type)
38106 {
38107   struct swap_info_struct * si = &swap_info[type];
38108   struct task_struct *p;
38109   struct page *page_map;
38110   unsigned long entry, page;
38111   int i;
38112 
38113   while (1) {
38114     /* Find a swap page in use and read it in. */
38115     for (i = 1; i < si->max ; i++) {
38116       if (si->swap_map[i] > 0 &&
38117           si->swap_map[i] != SWAP_MAP_BAD) {
38118         goto found_entry;
38119       }
38120     }
38121     break;
38122 
38123   found_entry:
38124     entry = SWP_ENTRY(type, i);
38125 
38126     /* Get a page for the entry, using the existing swap
38127      * cache page if there is one.  Otherwise, get a
38128      * clean page and read the swap into it. */
38129     page_map = read_swap_cache(entry);
38130     if (!page_map) {
38131       /* Continue searching if entry became unused. */
38132       if (si->swap_map[i] == 0)
38133         continue;
38134       return -ENOMEM;
38135     }
38136     page = page_address(page_map);
38137     read_lock(&tasklist_lock);
38138     for_each_task(p)
38139       unuse_process(p->mm, entry, page);
38140     read_unlock(&tasklist_lock);
38141     shm_unuse(entry, page);
38142     /* Now get rid of the extra reference to the
38143      * temporary page we've been using. */
38144     if (PageSwapCache(page_map))
38145       delete_from_swap_cache(page_map);
38146     __free_page(page_map);
38147     /* Check for and clear any overflowed swap map
38148      * counts.  */
38149     if (si->swap_map[i] != 0) {
38150       if (si->swap_map[i] != SWAP_MAP_MAX)
38151         printk(KERN_ERR
38152           "try_to_unuse: entry %08lx count=%d\n",
38153           entry, si->swap_map[i]);
38154       si->swap_map[i] = 0;
38155       nr_swap_pages++;
38156     }
38157   }
38158   return 0;
38159 }
38160 
 Комментарий
38161 asmlinkage int sys_swapoff(const char * specialfile)
38162 {
38163   struct swap_info_struct * p = NULL;
38164   struct dentry * dentry;
38165   struct file filp;
38166   int i, type, prev;
38167   int err = -EPERM;
38168 
38169   lock_kernel();
38170   if (!capable(CAP_SYS_ADMIN))
38171     goto out;
38172 
38173   dentry = namei(specialfile);
38174   err = PTR_ERR(dentry);
38175   if (IS_ERR(dentry))
38176     goto out;
38177 
38178   prev = -1;
38179   for (type = swap_list.head; type >= 0;
38180        type = swap_info[type].next) {
38181     p = swap_info + type;
38182     if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
38183       if (p->swap_file) {
38184         if (p->swap_file == dentry)
38185           break;
38186       } else {
38187         if (S_ISBLK(dentry->d_inode->i_mode) &&
38188             (p->swap_device == dentry->d_inode->i_rdev))
38189           break;
38190       }
38191     }
38192     prev = type;
38193   }
38194   err = -EINVAL;
38195   if (type < 0)
38196     goto out_dput;
38197 
38198   if (prev < 0) {
38199     swap_list.head = p->next;
38200   } else {
38201     swap_info[prev].next = p->next;
38202   }
38203   if (type == swap_list.next) {
38204     /* just pick something that's safe... */
38205     swap_list.next = swap_list.head;
38206   }
38207   p->flags = SWP_USED;
38208   err = try_to_unuse(type);
38209   if (err) {
38210     /* re-insert swap space back into swap_list */
38211     for (prev = -1, i = swap_list.head; i >= 0;
38212          prev = i, i = swap_info[i].next)
38213       if (p->prio >= swap_info[i].prio)
38214         break;
38215     p->next = i;
38216     if (prev < 0)
38217       swap_list.head = swap_list.next = p - swap_info;
38218     else
38219       swap_info[prev].next = p - swap_info;
38220     p->flags = SWP_WRITEOK;
38221     goto out_dput;
38222   }
38223   if(p->swap_device){
38224     memset(&filp, 0, sizeof(filp));
38225     filp.f_dentry = dentry;
38226     filp.f_mode = 3; /* read write */
38227     /* open it again to get fops */
38228     if( !blkdev_open(dentry->d_inode, &filp) &&
38229        filp.f_op && filp.f_op->release){
38230       filp.f_op->release(dentry->d_inode,&filp);
38231       filp.f_op->release(dentry->d_inode,&filp);
38232     }
38233   }
38234   dput(dentry);
38235 
38236   dentry = p->swap_file;
38237   p->swap_file = NULL;
38238   nr_swap_pages -= p->pages;
38239   p->swap_device = 0;
38240   vfree(p->swap_map);
38241   p->swap_map = NULL;
38242   vfree(p->swap_lockmap);
38243   p->swap_lockmap = NULL;
38244   p->flags = 0;
38245   err = 0;
38246 
38247 out_dput:
38248   dput(dentry);
38249 out:
38250   unlock_kernel();
38251   return err;
38252 }
38253 
38254 int get_swaparea_info(char *buf)
38255 {
38256   char * page = (char *) __get_free_page(GFP_KERNEL);
38257   struct swap_info_struct *ptr = swap_info;
38258   int i, j, len = 0, usedswap;
38259 
38260   if (!page)
38261     return -ENOMEM;
38262 
38263   len += sprintf(buf, "Filename\t\t\tType\t\tSize\tUsed"
38264                  "\tPriority\n");
38265   for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
38266     if (ptr->flags & SWP_USED) {
38267       char * path = d_path(ptr->swap_file, page,
38268                            PAGE_SIZE);
38269 
38270       len += sprintf(buf + len, "%-31s ", path);
38271 
38272       if (!ptr->swap_device)
38273         len += sprintf(buf + len, "file\t\t");
38274       else
38275         len += sprintf(buf + len, "partition\t");
38276 
38277       usedswap = 0;
38278       for (j = 0; j < ptr->max; ++j)
38279         switch (ptr->swap_map[j]) {
38280           case SWAP_MAP_BAD:
38281           case 0:
38282             continue;
38283           default:
38284             usedswap++;
38285         }
38286       len +=
38287         sprintf(buf + len, "%d\t%d\t%d\n",
38288                 ptr->pages << (PAGE_SHIFT - 10),
38289                 usedswap << (PAGE_SHIFT - 10),ptr->prio);
38290     }
38291   }
38292   free_page((unsigned long) page);
38293   return len;
38294 }
38295 
38296 /* Written 01/25/92 by Simmule Turner, heavily changed by
38297  * Linus.
38298  *
38299  * The swapon system call */
 Комментарий
38300 asmlinkage int sys_swapon(const char * specialfile,
38301                           int swap_flags)
38302 {
38303   struct swap_info_struct * p;
38304   struct dentry * swap_dentry;
38305   unsigned int type;
38306   int i, j, prev;
38307   int error = -EPERM;
38308   struct file filp;
38309   static int least_priority = 0;
38310   union swap_header *swap_header = 0;
38311   int swap_header_version;
38312   int lock_map_size = PAGE_SIZE;
38313   int nr_good_pages = 0;
38314   unsigned long tmp_lock_map = 0;
38315 
38316   lock_kernel();
38317   if (!capable(CAP_SYS_ADMIN))
38318     goto out;
38319   memset(&filp, 0, sizeof(filp));
38320   p = swap_info;
38321   for (type = 0 ; type < nr_swapfiles ; type++,p++)
38322     if (!(p->flags & SWP_USED))
38323       break;
38324   if (type >= MAX_SWAPFILES)
38325     goto out;
38326   if (type >= nr_swapfiles)
38327     nr_swapfiles = type+1;
 Комментарий
38328   p->flags = SWP_USED;
38329   p->swap_file = NULL;
38330   p->swap_device = 0;
38331   p->swap_map = NULL;
38332   p->swap_lockmap = NULL;
38333   p->lowest_bit = 0;
38334   p->highest_bit = 0;
38335   p->cluster_nr = 0;
38336   p->max = 1;
38337   p->next = -1;
38338   if (swap_flags & SWAP_FLAG_PREFER) {
38339     p->prio = (swap_flags & SWAP_FLAG_PRIO_MASK)
38340               >> SWAP_FLAG_PRIO_SHIFT;
38341   } else {
38342     p->prio = --least_priority;
38343   }
38344   swap_dentry = namei(specialfile);
38345   error = PTR_ERR(swap_dentry);
38346   if (IS_ERR(swap_dentry))
38347     goto bad_swap_2;
38348 
38349   p->swap_file = swap_dentry;
38350   error = -EINVAL;
38351 
38352   if (S_ISBLK(swap_dentry->d_inode->i_mode)) {
38353     p->swap_device = swap_dentry->d_inode->i_rdev;
38354     set_blocksize(p->swap_device, PAGE_SIZE);
38355 
38356     filp.f_dentry = swap_dentry;
38357     filp.f_mode = 3; /* read write */
38358     error = blkdev_open(swap_dentry->d_inode, &filp);
38359     if (error)
38360       goto bad_swap_2;
38361     set_blocksize(p->swap_device, PAGE_SIZE);
38362     error = -ENODEV;
38363     if (!p->swap_device ||
38364         (blk_size[MAJOR(p->swap_device)] &&
38365          !blk_size[MAJOR(p->swap_device)]
38366                   [MINOR(p->swap_device)]))
38367       goto bad_swap;
38368     error = -EBUSY;
38369     for (i = 0 ; i < nr_swapfiles ; i++) {
38370       if (i == type)
38371         continue;
38372       if (p->swap_device == swap_info[i].swap_device)
38373         goto bad_swap;
38374     }
38375   } else if (S_ISREG(swap_dentry->d_inode->i_mode)) {
38376     error = -EBUSY;
38377     for (i = 0 ; i < nr_swapfiles ; i++) {
38378       if (i == type)
38379         continue;
38380       if (swap_dentry->d_inode ==
38381           swap_info[i].swap_file->d_inode)
38382         goto bad_swap;
38383     }
38384   } else
38385     goto bad_swap;
38386 
38387   swap_header = (void *) __get_free_page(GFP_USER);
38388   if (!swap_header) {
38389     printk("Unable to start swapping: "
38390            "out of memory :-)\n");
38391     error = -ENOMEM;
38392     goto bad_swap;
38393   }
38394 
38395   p->swap_lockmap = (char *) &tmp_lock_map;
38396   rw_swap_page_nocache(READ, SWP_ENTRY(type,0),
38397                        (char *) swap_header);
38398   p->swap_lockmap = NULL;
38399 
38400   if (!memcmp("SWAP-SPACE", swap_header->magic.magic,10))
38401     swap_header_version = 1;
38402   else if (!memcmp("SWAPSPACE2",
38403                    swap_header->magic.magic, 10))
38404     swap_header_version = 2;
38405   else {
38406     printk("Unable to find swap-space signature\n");
38407     error = -EINVAL;
38408     goto bad_swap;
38409   }
38410 
38411   switch (swap_header_version) {
38412   case 1:
38413     memset(((char *) swap_header)+PAGE_SIZE-10,0,10);
38414     j = 0;
38415     p->lowest_bit = 0;
38416     p->highest_bit = 0;
38417     for (i = 1 ; i < 8*PAGE_SIZE ; i++) {
38418       if (test_bit(i,(char *) swap_header)) {
38419         if (!p->lowest_bit)
38420           p->lowest_bit = i;
38421         p->highest_bit = i;
38422         p->max = i+1;
38423         j++;
38424       }
38425     }
38426     nr_good_pages = j;
38427     p->swap_map = vmalloc(p->max * sizeof(short));
38428     if (!p->swap_map) {
38429       error = -ENOMEM;
38430       goto bad_swap;
38431     }
38432     for (i = 1 ; i < p->max ; i++) {
38433       if (test_bit(i,(char *) swap_header))
38434         p->swap_map[i] = 0;
38435       else
38436         p->swap_map[i] = SWAP_MAP_BAD;
38437     }
38438     break;
38439 
38440   case 2:
38441     /* Check the swap header's sub-version and the size
38442      * of the swap file and bad block lists */
38443     if (swap_header->info.version != 1) {
38444       printk(KERN_WARNING
38445              "Unable to handle swap header version %d\n",
38446              swap_header->info.version);
38447       error = -EINVAL;
38448       goto bad_swap;
38449     }
38450 
38451     p->lowest_bit  = 1;
38452     p->highest_bit = swap_header->info.last_page - 1;
38453     p->max         = swap_header->info.last_page;
38454 
38455     error = -EINVAL;
38456     if (swap_header->info.nr_badpages >
38457         MAX_SWAP_BADPAGES)
38458       goto bad_swap;
38459     if (p->max >= SWP_OFFSET(SWP_ENTRY(0,~0UL)))
38460       goto bad_swap;
38461 
38462     /* OK, set up the swap map and apply the bad block
38463      * list */
38464     if (!(p->swap_map =
38465           vmalloc(p->max * sizeof(short)))) {
38466       error = -ENOMEM;
38467       goto bad_swap;
38468     }
38469 
38470     error = 0;
38471     memset(p->swap_map, 0, p->max * sizeof(short));
38472     for (i=0; i<swap_header->info.nr_badpages; i++) {
38473       int page = swap_header->info.badpages[i];
38474       if (page <= 0 ||
38475           page >= swap_header->info.last_page)
38476         error = -EINVAL;
38477       else
38478         p->swap_map[page] = SWAP_MAP_BAD;
38479     }
38480     nr_good_pages = swap_header->info.last_page - i;
38481     lock_map_size = (p->max + 7) / 8;
38482     if (error)
38483       goto bad_swap;
38484   }
38485 
38486   if (!nr_good_pages) {
38487     printk(KERN_WARNING "Empty swap-file\n");
38488     error = -EINVAL;
38489     goto bad_swap;
38490   }
38491   p->swap_map[0] = SWAP_MAP_BAD;
38492   if (!(p->swap_lockmap = vmalloc (lock_map_size))) {
38493     error = -ENOMEM;
38494     goto bad_swap;
38495   }
38496   memset(p->swap_lockmap,0,lock_map_size);
38497   p->flags = SWP_WRITEOK;
38498   p->pages = nr_good_pages;
38499   nr_swap_pages += nr_good_pages;
38500   printk(KERN_INFO
38501          "Adding Swap: %dk swap-space (priority %d)\n",
38502          nr_good_pages<<(PAGE_SHIFT-10), p->prio);
38503 
38504   /* insert swap space into swap_list: */
38505   prev = -1;
38506   for (i = swap_list.head; i >= 0;
38507        i = swap_info[i].next) {
38508     if (p->prio >= swap_info[i].prio) {
38509       break;
38510     }
38511     prev = i;
38512   }
38513   p->next = i;
38514   if (prev < 0) {
38515     swap_list.head = swap_list.next = p - swap_info;
38516   } else {
38517     swap_info[prev].next = p - swap_info;
38518   }
38519   error = 0;
38520   goto out;
38521 bad_swap:
38522   if(filp.f_op && filp.f_op->release)
38523     filp.f_op->release(filp.f_dentry->d_inode,&filp);
38524 bad_swap_2:
38525   if (p->swap_lockmap)
38526     vfree(p->swap_lockmap);
38527   if (p->swap_map)
38528     vfree(p->swap_map);
38529   dput(p->swap_file);
38530   p->swap_device = 0;
38531   p->swap_file = NULL;
38532   p->swap_map = NULL;
38533   p->swap_lockmap = NULL;
38534   p->flags = 0;
38535   if (!(swap_flags & SWAP_FLAG_PREFER))
38536     ++least_priority;
38537 out:
38538   if (swap_header)
38539     free_page((long) swap_header);
38540   unlock_kernel();
38541   return error;
38542 }
38543 
38544 void si_swapinfo(struct sysinfo *val)
38545 {
38546   unsigned int i, j;
38547 
38548   val->freeswap = val->totalswap = 0;
38549   for (i = 0; i < nr_swapfiles; i++) {
38550     if ((swap_info[i].flags & SWP_WRITEOK) !=
38551         SWP_WRITEOK)
38552       continue;
38553     for (j = 0; j < swap_info[i].max; ++j)
38554       switch (swap_info[i].swap_map[j]) {
38555         case SWAP_MAP_BAD:
38556           continue;
38557         case 0:
38558           ++val->freeswap;
38559         default:
38560           ++val->totalswap;
38561       }
38562   }
38563   val->freeswap <<= PAGE_SHIFT;
38564   val->totalswap <<= PAGE_SHIFT;
38565   return;
38566 }

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz