Ядро Linux в комментариях

       

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 }


Содержание раздела