Annotation of linux/mm/swap.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  *  linux/mm/swap.c
                      3:  *
1.1.1.7   root        4:  *  Copyright (C) 1991, 1992  Linus Torvalds
1.1       root        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>
1.1.1.7   root       16: #include <linux/errno.h>
                     17: #include <linux/string.h>
                     18: #include <linux/stat.h>
1.1.1.8 ! root       19: #include <asm/system.h> /* for cli()/sti() */
1.1.1.7   root       20: 
1.1.1.8 ! root       21: #define MAX_SWAPFILES 8
        !            22: 
        !            23: #define SWP_USED       1
        !            24: #define SWP_WRITEOK    3
        !            25: 
        !            26: static int nr_swapfiles = 0;
        !            27: static struct wait_queue * lock_queue = NULL;
        !            28: 
        !            29: static struct swap_info_struct {
        !            30:        unsigned long flags;
        !            31:        struct inode * swap_file;
        !            32:        unsigned int swap_device;
        !            33:        unsigned char * swap_map;
        !            34:        char * swap_lockmap;
        !            35:        int lowest_bit;
        !            36:        int highest_bit;
        !            37: } swap_info[MAX_SWAPFILES];
        !            38: 
        !            39: extern unsigned long free_page_list;
1.1.1.7   root       40: 
                     41: /*
                     42:  * The following are used to make sure we don't thrash too much...
                     43:  */
                     44: #define NR_LAST_FREE_PAGES 32
                     45: static unsigned long last_free_pages[NR_LAST_FREE_PAGES] = {0,};
1.1       root       46: 
1.1.1.8 ! root       47: #define SWAP_BITS 4096
1.1       root       48: 
                     49: #define bitop(name,op) \
                     50: static inline int name(char * addr,unsigned int nr) \
                     51: { \
                     52: int __res; \
                     53: __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
                     54: :"=g" (__res) \
                     55: :"r" (nr),"m" (*(addr)),"0" (0)); \
                     56: return __res; \
                     57: }
                     58: 
                     59: bitop(bit,"")
                     60: bitop(setbit,"s")
                     61: bitop(clrbit,"r")
                     62: 
1.1.1.2   root       63: void rw_swap_page(int rw, unsigned int nr, char * buf)
                     64: {
1.1.1.8 ! root       65:        struct swap_info_struct * p;
1.1.1.2   root       66: 
1.1.1.8 ! root       67:        if ((nr >> 24) >= nr_swapfiles) {
        !            68:                printk("Internal error: bad swap-device\n");
        !            69:                return;
        !            70:        }
        !            71:        p = swap_info + (nr >> 24);
        !            72:        nr &= 0x00ffffff;
        !            73:        if (nr >= SWAP_BITS) {
        !            74:                printk("rw_swap_page: weirdness\n");
        !            75:                return;
        !            76:        }
        !            77:        if (!(p->flags & SWP_USED)) {
        !            78:                printk("Trying to swap to unused swap-device\n");
1.1.1.2   root       79:                return;
                     80:        }
1.1.1.8 ! root       81:        while (setbit(p->swap_lockmap,nr))
1.1.1.7   root       82:                sleep_on(&lock_queue);
1.1.1.8 ! root       83:        if (p->swap_device) {
        !            84:                ll_rw_page(rw,p->swap_device,nr,buf);
        !            85:        } else if (p->swap_file) {
1.1.1.7   root       86:                unsigned int zones[4];
                     87:                unsigned int block = nr << 2;
                     88:                int i;
                     89: 
1.1.1.2   root       90:                for (i = 0; i < 4; i++)
1.1.1.8 ! root       91:                        if (!(zones[i] = bmap(p->swap_file,block++))) {
1.1.1.2   root       92:                                printk("rw_swap_page: bad swap file\n");
                     93:                                return;
                     94:                        }
1.1.1.8 ! root       95:                ll_rw_swap_file(rw,p->swap_file->i_dev, zones,4,buf);
1.1.1.7   root       96:        } else
                     97:                printk("re_swap_page: no swap file or device\n");
1.1.1.8 ! root       98:        if (!clrbit(p->swap_lockmap,nr))
1.1.1.7   root       99:                printk("rw_swap_page: lock already cleared\n");
                    100:        wake_up(&lock_queue);
1.1.1.2   root      101: }
1.1       root      102: 
1.1.1.7   root      103: static unsigned int get_swap_page(void)
1.1       root      104: {
1.1.1.8 ! root      105:        struct swap_info_struct * p;
        !           106:        unsigned int block_nr, swap_nr;
1.1       root      107: 
1.1.1.8 ! root      108:        p = swap_info;
        !           109:        for (swap_nr = 0 ; swap_nr < nr_swapfiles ; swap_nr++,p++) {
        !           110:                if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK)
        !           111:                        continue;
        !           112:                for (block_nr = p->lowest_bit; block_nr <= p->highest_bit ; block_nr++) {
        !           113:                        if (p->swap_map[block_nr])
        !           114:                                continue;
        !           115:                        p->swap_map[block_nr] = 1;
        !           116:                        if (block_nr == p->highest_bit)
        !           117:                                p->highest_bit--;
        !           118:                        p->lowest_bit = block_nr;
        !           119:                        return block_nr + (swap_nr << 24);
1.1.1.7   root      120:                }
1.1.1.8 ! root      121:        }
1.1       root      122:        return 0;
                    123: }
                    124: 
1.1.1.8 ! root      125: void swap_duplicate(unsigned int nr)
1.1       root      126: {
1.1.1.8 ! root      127:        struct swap_info_struct * p;
        !           128: 
        !           129:        if (!nr)
        !           130:                return;
        !           131:        if ((nr >> 24) >= nr_swapfiles) {
        !           132:                printk("Trying to free nonexistent swap-page\n");
1.1       root      133:                return;
1.1.1.7   root      134:        }
1.1.1.8 ! root      135:        p = (nr >> 24) + swap_info;
        !           136:        nr &= 0x00ffffff;
        !           137:        if (nr >= SWAP_BITS) {
        !           138:                printk("swap_free: weirness\n");
        !           139:                return;
        !           140:        }
        !           141:        if (!p->swap_map[nr]) {
        !           142:                printk("swap_duplicate: trying to duplicate unused page\n");
        !           143:                return;
        !           144:        }
        !           145:        p->swap_map[nr]++;
        !           146: }
        !           147: 
        !           148: void swap_free(unsigned int nr)
        !           149: {
        !           150:        struct swap_info_struct * p;
        !           151: 
        !           152:        if (!nr)
        !           153:                return;
        !           154:        if ((nr >> 24) >= nr_swapfiles) {
        !           155:                printk("Trying to free nonexistent swap-page\n");
        !           156:                return;
        !           157:        }
        !           158:        p = (nr >> 24) + swap_info;
        !           159:        nr &= 0x00ffffff;
        !           160:        if (nr >= 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 (setbit(p->swap_lockmap,nr))
        !           169:                sleep_on(&lock_queue);
        !           170:        if (nr < p->lowest_bit)
        !           171:                p->lowest_bit = nr;
        !           172:        if (nr > p->highest_bit)
        !           173:                p->highest_bit = nr;
        !           174:        if (!p->swap_map[nr])
        !           175:                printk("swap_free: swap-space map bad (page %d)\n",nr);
        !           176:        else
        !           177:                p->swap_map[nr]--;
        !           178:        if (!clrbit(p->swap_lockmap,nr))
        !           179:                printk("swap_free: lock already cleared\n");
        !           180:        wake_up(&lock_queue);
1.1       root      181: }
                    182: 
                    183: void swap_in(unsigned long *table_ptr)
                    184: {
1.1.1.7   root      185:        unsigned long swap_nr;
1.1       root      186:        unsigned long page;
                    187: 
1.1.1.7   root      188:        swap_nr = *table_ptr;
                    189:        if (1 & swap_nr) {
1.1       root      190:                printk("trying to swap in present page\n\r");
                    191:                return;
                    192:        }
                    193:        if (!swap_nr) {
                    194:                printk("No swap page in swap_in\n\r");
                    195:                return;
                    196:        }
1.1.1.7   root      197:        page = get_free_page(GFP_KERNEL);
                    198:        if (!page) {
                    199:                oom(current);
                    200:                page = BAD_PAGE;
                    201:        } else  
                    202:                read_swap_page(swap_nr>>1, (char *) page);
                    203:        if (*table_ptr != swap_nr) {
                    204:                free_page(page);
                    205:                return;
                    206:        }
1.1       root      207:        *table_ptr = page | (PAGE_DIRTY | 7);
1.1.1.8 ! root      208:        swap_free(swap_nr>>1);
1.1       root      209: }
                    210: 
1.1.1.8 ! root      211: static int try_to_swap_out(unsigned long * table_ptr)
1.1       root      212: {
1.1.1.7   root      213:        int i;
1.1       root      214:        unsigned long page;
                    215:        unsigned long swap_nr;
                    216: 
                    217:        page = *table_ptr;
                    218:        if (!(PAGE_PRESENT & page))
                    219:                return 0;
1.1.1.8 ! root      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;
1.1       root      229:                return 0;
1.1.1.8 ! root      230:        }
1.1.1.7   root      231:        for (i = 0; i < NR_LAST_FREE_PAGES; i++)
                    232:                if (last_free_pages[i] == (page & 0xfffff000))
                    233:                        return 0;
1.1       root      234:        if (PAGE_DIRTY & page) {
                    235:                page &= 0xfffff000;
                    236:                if (mem_map[MAP_NR(page)] != 1)
                    237:                        return 0;
                    238:                if (!(swap_nr = get_swap_page()))
                    239:                        return 0;
                    240:                *table_ptr = swap_nr<<1;
                    241:                invalidate();
                    242:                write_swap_page(swap_nr, (char *) page);
                    243:                free_page(page);
                    244:                return 1;
                    245:        }
1.1.1.2   root      246:        page &= 0xfffff000;
1.1       root      247:        *table_ptr = 0;
                    248:        invalidate();
                    249:        free_page(page);
1.1.1.8 ! root      250:        return 1 + mem_map[MAP_NR(page)];
1.1       root      251: }
                    252: 
                    253: /*
1.1.1.8 ! root      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.
1.1.1.7   root      257:  */
1.1.1.8 ! root      258: int sys_idle(void)
        !           259: {
        !           260:        need_resched = 1;
        !           261:        return 0;
        !           262: }
1.1.1.7   root      263: 
                    264: /*
1.1.1.2   root      265:  * Go through the page tables, searching for a user page that
                    266:  * we can swap out.
1.1.1.8 ! root      267:  * 
1.1.1.7   root      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)).
1.1       root      271:  */
1.1.1.8 ! root      272: static int swap_out(unsigned int priority)
1.1       root      273: {
1.1.1.8 ! root      274:        static int swap_task = 1;
        !           275:        static int swap_table = 0;
        !           276:        static int swap_page = 0;
        !           277:        int counter = NR_TASKS*8;
1.1.1.3   root      278:        int pg_table;
1.1.1.5   root      279:        struct task_struct * p;
1.1       root      280: 
1.1.1.8 ! root      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:        }
1.1.1.3   root      294: check_dir:
1.1.1.8 ! root      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++;
1.1.1.5   root      303:                goto check_dir;
                    304:        }
1.1.1.8 ! root      305:        if (!(1 & pg_table)) {
        !           306:                printk("bad page-table at pg_dir[%d]: %08x\n\r",
        !           307:                        swap_table,pg_table);
        !           308:                ((unsigned long *) p->tss.cr3)[swap_table] = 0;
        !           309:                swap_table++;
1.1.1.3   root      310:                goto check_dir;
1.1       root      311:        }
                    312:        pg_table &= 0xfffff000;
1.1.1.3   root      313: check_table:
1.1.1.8 ! root      314:        if (swap_page >= 1024) {
        !           315:                swap_page = 0;
        !           316:                swap_table++;
1.1.1.3   root      317:                goto check_dir;
1.1       root      318:        }
1.1.1.8 ! root      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--;
1.1.1.4   root      323:        }
1.1.1.8 ! root      324:        swap_page++;
1.1.1.3   root      325:        goto check_table;
1.1.1.8 ! root      326: }
        !           327: 
        !           328: static int try_to_free_page(void)
        !           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:        }
1.1       root      338:        return 0;
                    339: }
                    340: 
                    341: /*
1.1.1.8 ! root      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)
        !           347: {
        !           348:        addr &= 0xfffff000;
        !           349:        *(unsigned long *) addr = *queue;
        !           350:        *queue = addr;
        !           351: }
        !           352: 
        !           353: void free_page(unsigned long addr)
        !           354: {
        !           355:        unsigned long i;
        !           356:        unsigned long flag;
        !           357: 
        !           358:        if (addr >= high_memory) {
        !           359:                printk("Trying to free nonexistent page %08x\n",addr);
        !           360:                return;
        !           361:        }
        !           362:        i = MAP_NR(addr);
        !           363:        if (mem_map[i] & MAP_PAGE_RESERVED)
        !           364:                return;
        !           365:        __asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flag));
        !           366:        if (!mem_map[i])
        !           367:                goto bad_free_page;
        !           368:        if (!--mem_map[i])
        !           369:                if (nr_secondary_pages < MAX_SECONDARY_PAGES) {
        !           370:                        add_mem_queue(addr,&secondary_page_list);
        !           371:                        nr_secondary_pages++;
        !           372:                } else {
        !           373:                        add_mem_queue(addr,&free_page_list);
        !           374:                        nr_free_pages++;
        !           375:                }
        !           376:        __asm__ __volatile__("pushl %0 ; popfl"::"r" (flag));
        !           377:        return;
        !           378: bad_free_page:
        !           379:        __asm__ __volatile__("pushl %0 ; popfl"::"r" (flag));
        !           380:        printk("Trying to free free memory (%08x): memory probabably corrupted\n");
        !           381: }
        !           382: 
        !           383: static unsigned long remove_from_mem_queue(unsigned long * queue)
        !           384: {
        !           385:        unsigned long result;
        !           386:        static unsigned long index = 0;
        !           387: 
        !           388:        cli();
        !           389:        result = *queue;
        !           390:        if (!result) {
        !           391:                sti();
        !           392:                return 0;
        !           393:        }
        !           394:        if ((result & 0xfff) || result >= high_memory) {
        !           395:                *queue = 0;
        !           396:                printk("Result = %08x - memory map destroyed\n");
        !           397:                sti();
        !           398:                panic("mm error");
        !           399:        }
        !           400:        *queue = *(unsigned long *) result;
        !           401:        sti();
        !           402:        if (mem_map[MAP_NR(result)]) {
        !           403:                printk("Free page %08x has mem_map = %d\n",
        !           404:                        result,mem_map[MAP_NR(result)]);
        !           405:                return 0;
        !           406:        }
        !           407:        mem_map[MAP_NR(result)] = 1;
        !           408:        cli();
        !           409:        if (index >= NR_LAST_FREE_PAGES)
        !           410:                index = 0;
        !           411:        last_free_pages[index] = result;
        !           412:        index++;
        !           413:        sti();
        !           414:        __asm__ __volatile__("cld ; rep ; stosl"
        !           415:                ::"a" (0),"c" (1024),"D" (result)
        !           416:                :"di","cx");
        !           417:        return result;
        !           418: }
        !           419: 
        !           420: /*
1.1       root      421:  * Get physical address of first (actually last :-) free page, and mark it
                    422:  * used. If no free pages left, return 0.
                    423:  */
1.1.1.7   root      424: unsigned long get_free_page(int priority)
1.1       root      425: {
1.1.1.2   root      426:        unsigned long result;
1.1.1.8 ! root      427: 
        !           428:        /* this routine can be called at interrupt time via
        !           429:           malloc.  We want to make sure that the critical
        !           430:           sections of code have interrupts disabled. -RAB
        !           431:           Is this code reentrant? */
1.1       root      432: 
                    433: repeat:
1.1.1.8 ! root      434:        result = remove_from_mem_queue(&free_page_list);
1.1.1.7   root      435:        if (result) {
1.1.1.8 ! root      436:                nr_free_pages--;
1.1.1.7   root      437:                return result;
                    438:        }
                    439:        if (nr_free_pages) {
1.1.1.8 ! root      440:                printk("nr_free_pages is %d, but no free memory found\n",nr_free_pages);
1.1.1.7   root      441:                nr_free_pages = 0;
                    442:        }
1.1.1.8 ! root      443:        if (priority == GFP_BUFFER)
1.1.1.7   root      444:                return 0;
1.1.1.8 ! root      445:        if (priority != GFP_ATOMIC)
        !           446:                if (try_to_free_page())
        !           447:                        goto repeat;
        !           448:        result = remove_from_mem_queue(&secondary_page_list);
        !           449:        if (result) {
        !           450:                nr_secondary_pages--;
        !           451:                return result;
        !           452:        }
        !           453:        if (nr_secondary_pages) {
        !           454:                printk("nr_secondary_pages is %d, but no free memory found\n",nr_secondary_pages);
        !           455:                nr_secondary_pages = 0;
        !           456:        }
        !           457:        return 0;
        !           458: }
        !           459: 
        !           460: /*
        !           461:  * Trying to stop swapping from a file is fraught with races, so
        !           462:  * we repeat quite a bit here when we have to pause. swapoff()
        !           463:  * isn't exactly timing-critical, so who cares?
        !           464:  *
        !           465:  * Note the '>> 25' instead of '>> 24' when checking against
        !           466:  * swap_nr: remember that the low bit in a page-address is used
        !           467:  * for the PAGE_PRESENT bit, and is not part of the swap address.
        !           468:  */
        !           469: static int try_to_unuse(unsigned int swap_nr)
        !           470: {
        !           471:        int nr, pgt, pg;
        !           472:        unsigned long page, *ppage;
        !           473:        unsigned long tmp = 0;
        !           474:        struct task_struct *p;
        !           475: 
        !           476:        nr = 0;
        !           477: /*
        !           478:  * When we have to sleep, we restart the whole algorithm from the same
        !           479:  * task we stopped in. That at least rids us of all races.
        !           480:  */
        !           481: repeat:
        !           482:        for (; nr < NR_TASKS ; nr++) {
        !           483:                p = task[nr];
        !           484:                if (!p)
        !           485:                        continue;
        !           486:                for (pgt = 0 ; pgt < 1024 ; pgt++) {
        !           487:                        ppage = pgt + ((unsigned long *) p->tss.cr3);
        !           488:                        page = *ppage;
        !           489:                        if (!page)
        !           490:                                continue;
        !           491:                        if (!(page & PAGE_PRESENT) || (page >= high_memory)) {
        !           492:                                printk("try_to_unuse: bad page directory (%d,%d:%08x)\n",nr,pgt,page);
        !           493:                                *ppage = 0;
        !           494:                                continue;
        !           495:                        }
        !           496:                        if (mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED)
        !           497:                                continue;
        !           498:                        ppage = (unsigned long *) (page & 0xfffff000);  
        !           499:                        for (pg = 0 ; pg < 1024 ; pg++,ppage++) {
        !           500:                                page = *ppage;
        !           501:                                if (!page)
        !           502:                                        continue;
        !           503:                                if (page & PAGE_PRESENT) {
        !           504:                                        if (page >= high_memory) {
        !           505:                                                printk("try_to_unuse: bad page table (%d,%d,%d:%08x)\n",nr,pgt,pg,page);
        !           506:                                                *ppage = 0;
        !           507:                                        }
        !           508:                                        continue;
        !           509:                                }
        !           510:                                if ((page >> 25) != swap_nr)
        !           511:                                        continue;
        !           512:                                if (!tmp) {
        !           513:                                        tmp = get_free_page(GFP_KERNEL);
        !           514:                                        if (!tmp)
        !           515:                                                return -ENOMEM;
        !           516:                                        goto repeat;
        !           517:                                }
        !           518:                                read_swap_page(page>>1, (char *) tmp);
        !           519:                                if (*ppage == page) {
        !           520:                                        *ppage = tmp | (PAGE_DIRTY | 7);
        !           521:                                        ++p->rss;
        !           522:                                        swap_free(page>>1);
        !           523:                                        tmp = 0;
        !           524:                                }
        !           525:                                goto repeat;
        !           526:                        }
        !           527:                }
        !           528:        }
        !           529:        free_page(tmp);
        !           530:        return 0;
        !           531: }
        !           532: 
        !           533: int sys_swapoff(const char * specialfile)
        !           534: {
        !           535:        struct swap_info_struct * p;
        !           536:        struct inode * inode;
        !           537:        unsigned int swap_nr;
        !           538:        int i;
        !           539: 
        !           540:        if (!suser())
        !           541:                return -EPERM;
        !           542:        i = namei(specialfile,&inode);
        !           543:        if (i)
        !           544:                return i;
        !           545:        p = swap_info;
        !           546:        for (swap_nr = 0 ; swap_nr < nr_swapfiles ; swap_nr++,p++) {
        !           547:                if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK)
        !           548:                        continue;
        !           549:                if (p->swap_file) {
        !           550:                        if (p->swap_file == inode)
        !           551:                                break;
        !           552:                } else {
        !           553:                        if (!S_ISBLK(inode->i_mode))
        !           554:                                continue;
        !           555:                        if (p->swap_device == inode->i_rdev)
        !           556:                                break;
        !           557:                }
1.1.1.7   root      558:        }
1.1.1.8 ! root      559:        iput(inode);
        !           560:        if (swap_nr >= nr_swapfiles)
        !           561:                return -EINVAL;
        !           562:        p->flags = SWP_USED;
        !           563:        i = try_to_unuse(swap_nr);
        !           564:        if (i) {
        !           565:                p->flags = SWP_WRITEOK;
        !           566:                return i;
        !           567:        }
        !           568:        iput(p->swap_file);
        !           569:        p->swap_file = NULL;
        !           570:        p->swap_device = 0;
        !           571:        free_page((long) p->swap_map);
        !           572:        p->swap_map = NULL;
        !           573:        free_page((long) p->swap_lockmap);
        !           574:        p->swap_lockmap = NULL;
        !           575:        p->flags = 0;
1.1.1.7   root      576:        return 0;
1.1       root      577: }
                    578: 
1.1.1.2   root      579: /*
                    580:  * Written 01/25/92 by Simmule Turner, heavily changed by Linus.
                    581:  *
                    582:  * The swapon system call
                    583:  */
                    584: int sys_swapon(const char * specialfile)
1.1       root      585: {
1.1.1.8 ! root      586:        struct swap_info_struct * p;
1.1.1.2   root      587:        struct inode * swap_inode;
1.1.1.8 ! root      588:        unsigned int swap_nr;
1.1.1.5   root      589:        char * tmp;
1.1.1.2   root      590:        int i,j;
1.1       root      591: 
1.1.1.2   root      592:        if (!suser())
                    593:                return -EPERM;
1.1.1.8 ! root      594:        p = swap_info;
        !           595:        for (swap_nr = 0 ; swap_nr < nr_swapfiles ; swap_nr++,p++)
        !           596:                if (!(p->flags & SWP_USED))
        !           597:                        break;
        !           598:        if (swap_nr >= MAX_SWAPFILES)
        !           599:                return -EPERM;
        !           600:        if (swap_nr >= nr_swapfiles)
        !           601:                nr_swapfiles = swap_nr+1;
        !           602:        p->flags = SWP_USED;
        !           603:        p->swap_file = NULL;
        !           604:        p->swap_device = 0;
        !           605:        p->swap_map = NULL;
        !           606:        p->swap_lockmap = NULL;
        !           607:        p->lowest_bit = 0;
        !           608:        p->highest_bit = 0;
        !           609:        i = namei(specialfile,&swap_inode);
        !           610:        if (i) {
        !           611:                p->flags = 0;
        !           612:                return i;
        !           613:        }
        !           614:        if (swap_inode->i_count != 1) {
1.1.1.2   root      615:                iput(swap_inode);
1.1.1.8 ! root      616:                p->flags = 0;
1.1.1.2   root      617:                return -EBUSY;
                    618:        }
                    619:        if (S_ISBLK(swap_inode->i_mode)) {
1.1.1.8 ! root      620:                p->swap_device = swap_inode->i_rdev;
1.1.1.2   root      621:                iput(swap_inode);
1.1.1.8 ! root      622:                if (!p->swap_device) {
        !           623:                        p->flags = 0;
        !           624:                        return -ENODEV;
        !           625:                }
        !           626:                for (i = 0 ; i < nr_swapfiles ; i++) {
        !           627:                        if (i == swap_nr)
        !           628:                                continue;
        !           629:                        if (p->swap_device == swap_info[i].swap_device) {
        !           630:                                p->swap_device = 0;
        !           631:                                p->flags = 0;
        !           632:                                return -EBUSY;
        !           633:                        }
        !           634:                }
1.1.1.2   root      635:        } else if (S_ISREG(swap_inode->i_mode))
1.1.1.8 ! root      636:                p->swap_file = swap_inode;
1.1.1.2   root      637:        else {
                    638:                iput(swap_inode);
1.1.1.8 ! root      639:                p->flags = 0;
1.1.1.2   root      640:                return -EINVAL;
1.1       root      641:        }
1.1.1.7   root      642:        tmp = (char *) get_free_page(GFP_USER);
1.1.1.8 ! root      643:        p->swap_lockmap = (char *) get_free_page(GFP_USER);
        !           644:        if (!tmp || !p->swap_lockmap) {
1.1.1.7   root      645:                printk("Unable to start swapping: out of memory :-)\n");
                    646:                free_page((long) tmp);
1.1.1.8 ! root      647:                free_page((long) p->swap_lockmap);
        !           648:                iput(p->swap_file);
        !           649:                p->swap_device = 0;
        !           650:                p->swap_file = NULL;
        !           651:                p->swap_map = NULL;
        !           652:                p->swap_lockmap = NULL;
        !           653:                p->flags = 0;
1.1.1.2   root      654:                return -ENOMEM;
1.1       root      655:        }
1.1.1.8 ! root      656:        read_swap_page(swap_nr << 24,tmp);
1.1.1.5   root      657:        if (strncmp("SWAP-SPACE",tmp+4086,10)) {
1.1       root      658:                printk("Unable to find swap-space signature\n\r");
1.1.1.5   root      659:                free_page((long) tmp);
1.1.1.8 ! root      660:                free_page((long) p->swap_lockmap);
        !           661:                iput(p->swap_file);
        !           662:                p->swap_device = 0;
        !           663:                p->swap_file = NULL;
        !           664:                p->swap_map = NULL;
        !           665:                p->swap_lockmap = NULL;
        !           666:                p->flags = 0;
1.1.1.2   root      667:                return -EINVAL;
1.1       root      668:        }
1.1.1.5   root      669:        memset(tmp+4086,0,10);
1.1       root      670:        j = 0;
1.1.1.8 ! root      671:        p->lowest_bit = 0;
        !           672:        p->highest_bit = 0;
1.1.1.2   root      673:        for (i = 1 ; i < SWAP_BITS ; i++)
1.1.1.7   root      674:                if (bit(tmp,i)) {
1.1.1.8 ! root      675:                        if (!p->lowest_bit)
        !           676:                                p->lowest_bit = i;
        !           677:                        p->highest_bit = i;
1.1       root      678:                        j++;
1.1.1.7   root      679:                }
1.1       root      680:        if (!j) {
1.1.1.2   root      681:                printk("Empty swap-file\n");
1.1.1.5   root      682:                free_page((long) tmp);
1.1.1.8 ! root      683:                free_page((long) p->swap_lockmap);
        !           684:                iput(p->swap_file);
        !           685:                p->swap_device = 0;
        !           686:                p->swap_file = NULL;
        !           687:                p->swap_map = NULL;
        !           688:                p->swap_lockmap = NULL;
        !           689:                p->flags = 0;
1.1.1.2   root      690:                return -EINVAL;
1.1       root      691:        }
1.1.1.8 ! root      692:        i = SWAP_BITS;
        !           693:        while (i--)
        !           694:                if (bit(tmp,i))
        !           695:                        tmp[i] = 0;
        !           696:                else
        !           697:                        tmp[i] = 128;
        !           698:        tmp[0] = 128;
        !           699:        p->swap_map = tmp;
        !           700:        p->flags = SWP_WRITEOK;
        !           701:        printk("Adding Swap: %dk swap-space\n\r",j<<2);
1.1.1.2   root      702:        return 0;
1.1       root      703: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.