Annotation of linux/fs/buffer.c, revision 1.1.1.11

1.1       root        1: /*
1.1.1.2   root        2:  *  linux/fs/buffer.c
                      3:  *
1.1.1.10  root        4:  *  Copyright (C) 1991, 1992  Linus Torvalds
1.1.1.2   root        5:  */
                      6: 
                      7: /*
1.1       root        8:  *  'buffer.c' implements the buffer-cache functions. Race-conditions have
                      9:  * been avoided by NEVER letting a interrupt change a buffer (except for the
                     10:  * data, of course), but instead letting the caller do it. NOTE! As interrupts
                     11:  * can wake up a caller, some cli-sti sequences are needed to check for
                     12:  * sleep-on-calls. These should be extremely quick, though (I hope).
                     13:  */
                     14: 
1.1.1.2   root       15: /*
                     16:  * NOTE! There is one discordant note here: checking floppies for
                     17:  * disk change. This is where it fits best, I think, as it should
                     18:  * invalidate changed floppy-disk-caches.
                     19:  */
                     20: 
                     21: #include <stdarg.h>
                     22:  
1.1       root       23: #include <linux/config.h>
                     24: #include <linux/sched.h>
                     25: #include <linux/kernel.h>
1.1.1.10  root       26: #include <linux/string.h>
                     27: 
1.1       root       28: #include <asm/system.h>
1.1.1.2   root       29: #include <asm/io.h>
1.1       root       30: 
1.1.1.11! root       31: #if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
        !            32: extern int check_cdrom_media_change(int, int);
        !            33: #endif
        !            34: 
1.1.1.6   root       35: static struct buffer_head * hash_table[NR_HASH];
1.1.1.10  root       36: static struct buffer_head * free_list = NULL;
                     37: static struct buffer_head * unused_list = NULL;
                     38: static struct wait_queue * buffer_wait = NULL;
                     39: 
                     40: int nr_buffers = 0;
                     41: int nr_buffer_heads = 0;
1.1       root       42: 
                     43: static inline void wait_on_buffer(struct buffer_head * bh)
                     44: {
                     45:        cli();
                     46:        while (bh->b_lock)
                     47:                sleep_on(&bh->b_wait);
                     48:        sti();
                     49: }
                     50: 
1.1.1.4   root       51: static void sync_buffers(int dev)
1.1       root       52: {
                     53:        int i;
                     54:        struct buffer_head * bh;
                     55: 
1.1.1.4   root       56:        bh = free_list;
1.1.1.10  root       57:        for (i = nr_buffers*2 ; i-- > 0 ; bh = bh->b_next_free) {
1.1.1.7   root       58:                if (bh->b_lock)
1.1.1.4   root       59:                        continue;
1.1.1.7   root       60:                if (!bh->b_dirt)
1.1.1.4   root       61:                        continue;
1.1.1.7   root       62:                ll_rw_block(WRITE,bh);
1.1       root       63:        }
1.1.1.4   root       64: }
                     65: 
                     66: int sys_sync(void)
                     67: {
1.1.1.9   root       68:        int i;
                     69: 
                     70:        for (i=0 ; i<NR_SUPER ; i++)
                     71:                if (super_block[i].s_dev
                     72:                    && super_block[i].s_op 
                     73:                    && super_block[i].s_op->write_super 
                     74:                    && super_block[i].s_dirt)
                     75:                        super_block[i].s_op->write_super(&super_block[i]);
1.1.1.4   root       76:        sync_inodes();          /* write out inodes into buffers */
                     77:        sync_buffers(0);
1.1       root       78:        return 0;
                     79: }
                     80: 
1.1.1.2   root       81: int sync_dev(int dev)
1.1       root       82: {
1.1.1.9   root       83:        struct super_block * sb;
                     84: 
                     85:        if (sb = get_super (dev))
                     86:                if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
                     87:                        sb->s_op->write_super (sb);
1.1.1.4   root       88:        sync_buffers(dev);
1.1.1.2   root       89:        sync_inodes();
1.1.1.4   root       90:        sync_buffers(dev);
1.1       root       91:        return 0;
                     92: }
                     93: 
1.1.1.3   root       94: void inline invalidate_buffers(int dev)
                     95: {
                     96:        int i;
                     97:        struct buffer_head * bh;
                     98: 
1.1.1.10  root       99:        bh = free_list;
                    100:        for (i = nr_buffers*2 ; --i > 0 ; bh = bh->b_next_free) {
1.1.1.3   root      101:                if (bh->b_dev != dev)
                    102:                        continue;
                    103:                wait_on_buffer(bh);
                    104:                if (bh->b_dev == dev)
                    105:                        bh->b_uptodate = bh->b_dirt = 0;
                    106:        }
                    107: }
                    108: 
1.1.1.2   root      109: /*
                    110:  * This routine checks whether a floppy has been changed, and
                    111:  * invalidates all buffer-cache-entries in that case. This
                    112:  * is a relatively slow routine, so we have to try to minimize using
                    113:  * it. Thus it is called only upon a 'mount' or 'open'. This
                    114:  * is the best way of combining speed and utility, I think.
                    115:  * People changing diskettes in the middle of an operation deserve
                    116:  * to loose :-)
                    117:  *
                    118:  * NOTE! Although currently this is only for floppies, the idea is
                    119:  * that any additional removable block-device will use this routine,
                    120:  * and that mount/open needn't know that floppies/whatever are
                    121:  * special.
                    122:  */
                    123: void check_disk_change(int dev)
                    124: {
                    125:        int i;
1.1.1.5   root      126:        struct buffer_head * bh;
1.1.1.2   root      127: 
1.1.1.11! root      128:        switch(MAJOR(dev)){
        !           129:        case 2: /* floppy disc */
        !           130:                if (!(bh = getblk(dev,0,1024)))
        !           131:                        return;
        !           132:                i = floppy_change(bh);
        !           133:                brelse(bh);
        !           134:                break;
        !           135: 
        !           136: #if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
        !           137:          case 11: /* CDROM */
        !           138:                i = check_cdrom_media_change(dev, 0);
        !           139:                if (i) printk("Flushing buffers and inodes for CDROM\n");
        !           140:                break;
        !           141: #endif
        !           142: 
        !           143:          default:
1.1.1.2   root      144:                return;
1.1.1.11! root      145:        };
        !           146: 
        !           147:        if (!i) return;
        !           148: 
1.1.1.2   root      149:        for (i=0 ; i<NR_SUPER ; i++)
1.1.1.3   root      150:                if (super_block[i].s_dev == dev)
1.1.1.2   root      151:                        put_super(super_block[i].s_dev);
1.1.1.3   root      152:        invalidate_inodes(dev);
                    153:        invalidate_buffers(dev);
1.1.1.2   root      154: }
                    155: 
1.1       root      156: #define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
                    157: #define hash(dev,block) hash_table[_hashfn(dev,block)]
                    158: 
1.1.1.4   root      159: static inline void remove_from_hash_queue(struct buffer_head * bh)
1.1       root      160: {
                    161:        if (bh->b_next)
                    162:                bh->b_next->b_prev = bh->b_prev;
                    163:        if (bh->b_prev)
                    164:                bh->b_prev->b_next = bh->b_next;
                    165:        if (hash(bh->b_dev,bh->b_blocknr) == bh)
                    166:                hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
1.1.1.4   root      167:        bh->b_next = bh->b_prev = NULL;
                    168: }
                    169: 
                    170: static inline void remove_from_free_list(struct buffer_head * bh)
                    171: {
1.1       root      172:        if (!(bh->b_prev_free) || !(bh->b_next_free))
                    173:                panic("Free block list corrupted");
                    174:        bh->b_prev_free->b_next_free = bh->b_next_free;
                    175:        bh->b_next_free->b_prev_free = bh->b_prev_free;
                    176:        if (free_list == bh)
                    177:                free_list = bh->b_next_free;
1.1.1.4   root      178:        bh->b_next_free = bh->b_prev_free = NULL;
                    179: }
                    180: 
                    181: static inline void remove_from_queues(struct buffer_head * bh)
                    182: {
                    183:        remove_from_hash_queue(bh);
                    184:        remove_from_free_list(bh);
                    185: }
                    186: 
                    187: static inline void put_first_free(struct buffer_head * bh)
                    188: {
                    189:        if (!bh || (bh == free_list))
                    190:                return;
                    191:        remove_from_free_list(bh);
                    192: /* add to front of free list */
                    193:        bh->b_next_free = free_list;
                    194:        bh->b_prev_free = free_list->b_prev_free;
                    195:        free_list->b_prev_free->b_next_free = bh;
                    196:        free_list->b_prev_free = bh;
                    197:        free_list = bh;
                    198: }
                    199: 
                    200: static inline void put_last_free(struct buffer_head * bh)
                    201: {
                    202:        if (!bh)
                    203:                return;
                    204:        if (bh == free_list) {
                    205:                free_list = bh->b_next_free;
                    206:                return;
                    207:        }
                    208:        remove_from_free_list(bh);
                    209: /* add to back of free list */
                    210:        bh->b_next_free = free_list;
                    211:        bh->b_prev_free = free_list->b_prev_free;
                    212:        free_list->b_prev_free->b_next_free = bh;
                    213:        free_list->b_prev_free = bh;
1.1       root      214: }
                    215: 
                    216: static inline void insert_into_queues(struct buffer_head * bh)
                    217: {
                    218: /* put at end of free list */
                    219:        bh->b_next_free = free_list;
                    220:        bh->b_prev_free = free_list->b_prev_free;
                    221:        free_list->b_prev_free->b_next_free = bh;
                    222:        free_list->b_prev_free = bh;
                    223: /* put the buffer in new hash-queue if it has a device */
                    224:        bh->b_prev = NULL;
                    225:        bh->b_next = NULL;
                    226:        if (!bh->b_dev)
                    227:                return;
                    228:        bh->b_next = hash(bh->b_dev,bh->b_blocknr);
                    229:        hash(bh->b_dev,bh->b_blocknr) = bh;
1.1.1.7   root      230:        if (bh->b_next)
                    231:                bh->b_next->b_prev = bh;
1.1       root      232: }
                    233: 
1.1.1.10  root      234: static struct buffer_head * find_buffer(int dev, int block, int size)
1.1       root      235: {              
                    236:        struct buffer_head * tmp;
                    237: 
                    238:        for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
                    239:                if (tmp->b_dev==dev && tmp->b_blocknr==block)
1.1.1.10  root      240:                        if (tmp->b_size == size)
                    241:                                return tmp;
                    242:                        else {
                    243:                                printk("wrong block-size on device %04x\n",dev);
                    244:                                return NULL;
                    245:                        }
1.1       root      246:        return NULL;
                    247: }
                    248: 
                    249: /*
                    250:  * Why like this, I hear you say... The reason is race-conditions.
                    251:  * As we don't lock buffers (unless we are readint them, that is),
                    252:  * something might happen to it while we sleep (ie a read-error
                    253:  * will force it bad). This shouldn't really happen currently, but
                    254:  * the code is ready.
                    255:  */
1.1.1.10  root      256: struct buffer_head * get_hash_table(int dev, int block, int size)
1.1       root      257: {
                    258:        struct buffer_head * bh;
                    259: 
1.1.1.2   root      260:        for (;;) {
1.1.1.10  root      261:                if (!(bh=find_buffer(dev,block,size)))
1.1.1.2   root      262:                        return NULL;
                    263:                bh->b_count++;
                    264:                wait_on_buffer(bh);
1.1.1.10  root      265:                if (bh->b_dev == dev && bh->b_blocknr == block && bh->b_size == size) {
1.1.1.4   root      266:                        put_last_free(bh);
1.1.1.2   root      267:                        return bh;
1.1.1.4   root      268:                }
1.1.1.2   root      269:                bh->b_count--;
1.1       root      270:        }
                    271: }
                    272: 
                    273: /*
                    274:  * Ok, this is getblk, and it isn't very clear, again to hinder
                    275:  * race-conditions. Most of the code is seldom used, (ie repeating),
                    276:  * so it should be much more efficient than it looks.
1.1.1.2   root      277:  *
1.1.1.3   root      278:  * The algoritm is changed: hopefully better, and an elusive bug removed.
1.1.1.4   root      279:  *
                    280:  * 14.02.92: changed it to sync dirty buffers a bit: better performance
                    281:  * when the filesystem starts to get full of dirty blocks (I hope).
1.1       root      282:  */
1.1.1.2   root      283: #define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
1.1.1.10  root      284: struct buffer_head * getblk(int dev, int block, int size)
1.1       root      285: {
1.1.1.4   root      286:        struct buffer_head * bh, * tmp;
                    287:        int buffers;
1.1       root      288: 
                    289: repeat:
1.1.1.10  root      290:        if (bh = get_hash_table(dev, block, size))
1.1.1.2   root      291:                return bh;
1.1.1.10  root      292: 
                    293:        if (nr_free_pages > 30)
                    294:                grow_buffers(size);
                    295: 
                    296:        buffers = nr_buffers;
                    297:        bh = NULL;
                    298: 
                    299:        for (tmp = free_list; buffers-- > 0 ; tmp = tmp->b_next_free) {
                    300:                if (tmp->b_count || tmp->b_size != size)
1.1.1.2   root      301:                        continue;
                    302:                if (!bh || BADNESS(tmp)<BADNESS(bh)) {
                    303:                        bh = tmp;
                    304:                        if (!BADNESS(tmp))
1.1       root      305:                                break;
                    306:                }
1.1.1.7   root      307: #if 0
1.1.1.4   root      308:                if (tmp->b_dirt)
                    309:                        ll_rw_block(WRITEA,tmp);
1.1.1.7   root      310: #endif
                    311:        }
1.1.1.10  root      312: 
                    313:        if (!bh && nr_free_pages > 5) {
                    314:                grow_buffers(size);
                    315:                goto repeat;
                    316:        }
                    317:        
1.1.1.3   root      318: /* and repeat until we find something good */
1.1.1.2   root      319:        if (!bh) {
1.1       root      320:                sleep_on(&buffer_wait);
                    321:                goto repeat;
                    322:        }
1.1.1.2   root      323:        wait_on_buffer(bh);
1.1.1.10  root      324:        if (bh->b_count || bh->b_size != size)
1.1       root      325:                goto repeat;
1.1.1.8   root      326:        if (bh->b_dirt) {
1.1.1.7   root      327:                sync_buffers(bh->b_dev);
1.1.1.8   root      328:                goto repeat;
1.1       root      329:        }
1.1.1.2   root      330: /* NOTE!! While we slept waiting for this block, somebody else might */
                    331: /* already have added "this" block to the cache. check it */
1.1.1.10  root      332:        if (find_buffer(dev,block,size))
1.1.1.2   root      333:                goto repeat;
                    334: /* OK, FINALLY we know that this buffer is the only one of it's kind, */
                    335: /* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */
                    336:        bh->b_count=1;
                    337:        bh->b_dirt=0;
                    338:        bh->b_uptodate=0;
                    339:        remove_from_queues(bh);
                    340:        bh->b_dev=dev;
                    341:        bh->b_blocknr=block;
                    342:        insert_into_queues(bh);
                    343:        return bh;
1.1       root      344: }
                    345: 
                    346: void brelse(struct buffer_head * buf)
                    347: {
                    348:        if (!buf)
                    349:                return;
                    350:        wait_on_buffer(buf);
                    351:        if (!(buf->b_count--))
                    352:                panic("Trying to free free buffer");
                    353:        wake_up(&buffer_wait);
                    354: }
                    355: 
                    356: /*
                    357:  * bread() reads a specified block and returns the buffer that contains
                    358:  * it. It returns NULL if the block was unreadable.
                    359:  */
1.1.1.10  root      360: struct buffer_head * bread(int dev, int block, int size)
1.1       root      361: {
                    362:        struct buffer_head * bh;
                    363: 
1.1.1.10  root      364:        if (!(bh = getblk(dev, block, size))) {
                    365:                printk("bread: getblk returned NULL\n");
                    366:                return NULL;
                    367:        }
1.1       root      368:        if (bh->b_uptodate)
                    369:                return bh;
                    370:        ll_rw_block(READ,bh);
1.1.1.2   root      371:        wait_on_buffer(bh);
                    372:        if (bh->b_uptodate)
                    373:                return bh;
                    374:        brelse(bh);
                    375:        return NULL;
                    376: }
                    377: 
1.1.1.3   root      378: #define COPYBLK(from,to) \
                    379: __asm__("cld\n\t" \
                    380:        "rep\n\t" \
                    381:        "movsl\n\t" \
                    382:        ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
                    383:        :"cx","di","si")
                    384: 
                    385: /*
                    386:  * bread_page reads four buffers into memory at the desired address. It's
                    387:  * a function of its own, as there is some speed to be got by reading them
                    388:  * all at the same time, not waiting for one to be read, and then another
                    389:  * etc.
                    390:  */
                    391: void bread_page(unsigned long address,int dev,int b[4])
                    392: {
                    393:        struct buffer_head * bh[4];
                    394:        int i;
                    395: 
                    396:        for (i=0 ; i<4 ; i++)
                    397:                if (b[i]) {
1.1.1.10  root      398:                        if (bh[i] = getblk(dev, b[i], 1024))
1.1.1.3   root      399:                                if (!bh[i]->b_uptodate)
                    400:                                        ll_rw_block(READ,bh[i]);
                    401:                } else
                    402:                        bh[i] = NULL;
                    403:        for (i=0 ; i<4 ; i++,address += BLOCK_SIZE)
                    404:                if (bh[i]) {
                    405:                        wait_on_buffer(bh[i]);
                    406:                        if (bh[i]->b_uptodate)
                    407:                                COPYBLK((unsigned long) bh[i]->b_data,address);
                    408:                        brelse(bh[i]);
                    409:                }
                    410: }
                    411: 
1.1.1.2   root      412: /*
                    413:  * Ok, breada can be used as bread, but additionally to mark other
                    414:  * blocks for reading as well. End the argument list with a negative
                    415:  * number.
                    416:  */
                    417: struct buffer_head * breada(int dev,int first, ...)
                    418: {
                    419:        va_list args;
                    420:        struct buffer_head * bh, *tmp;
                    421: 
                    422:        va_start(args,first);
1.1.1.10  root      423:        if (!(bh = getblk(dev, first, 1024))) {
                    424:                printk("breada: getblk returned NULL\n");
                    425:                return NULL;
                    426:        }
1.1.1.2   root      427:        if (!bh->b_uptodate)
                    428:                ll_rw_block(READ,bh);
                    429:        while ((first=va_arg(args,int))>=0) {
1.1.1.10  root      430:                tmp = getblk(dev, first, 1024);
1.1.1.2   root      431:                if (tmp) {
                    432:                        if (!tmp->b_uptodate)
1.1.1.7   root      433:                                ll_rw_block(READA,tmp);
1.1.1.2   root      434:                        tmp->b_count--;
                    435:                }
                    436:        }
                    437:        va_end(args);
                    438:        wait_on_buffer(bh);
1.1       root      439:        if (bh->b_uptodate)
                    440:                return bh;
                    441:        brelse(bh);
                    442:        return (NULL);
                    443: }
                    444: 
1.1.1.10  root      445: static void put_unused_buffer_head(struct buffer_head * bh)
                    446: {
                    447:        memset((void *) bh,0,sizeof(*bh));
                    448:        bh->b_next_free = unused_list;
                    449:        unused_list = bh;
                    450: }
                    451: 
                    452: static void get_more_buffer_heads(void)
                    453: {
                    454:        unsigned long page;
                    455:        struct buffer_head * bh;
                    456: 
                    457:        if (unused_list)
                    458:                return;
                    459:        page = get_free_page(GFP_KERNEL);
                    460:        if (!page)
                    461:                return;
                    462:        bh = (struct buffer_head *) page;
                    463:        while ((unsigned long) (bh+1) <= page+4096) {
                    464:                put_unused_buffer_head(bh);
                    465:                bh++;
                    466:                nr_buffer_heads++;
                    467:        }
                    468: }
                    469: 
                    470: static struct buffer_head * get_unused_buffer_head(void)
1.1       root      471: {
1.1.1.10  root      472:        struct buffer_head * bh;
                    473: 
                    474:        get_more_buffer_heads();
                    475:        if (!unused_list)
                    476:                return NULL;
                    477:        bh = unused_list;
                    478:        unused_list = bh->b_next_free;
                    479:        bh->b_next_free = NULL;
                    480:        bh->b_data = NULL;
                    481:        bh->b_size = 0;
                    482:        return bh;
                    483: }
                    484: 
                    485: /*
                    486:  * Try to increase the number of buffers available: the size argument
                    487:  * is used to determine what kind of buffers we want. Currently only
                    488:  * 1024-byte buffers are supported by the rest of the system, but I
                    489:  * think this will change eventually.
                    490:  */
                    491: void grow_buffers(int size)
                    492: {
                    493:        unsigned long page;
1.1       root      494:        int i;
1.1.1.10  root      495:        struct buffer_head *bh, *tmp;
1.1       root      496: 
1.1.1.10  root      497:        if ((size & 511) || (size > 4096)) {
                    498:                printk("grow_buffers: size = %d\n",size);
                    499:                return;
                    500:        }
                    501:        page = get_free_page(GFP_BUFFER);
                    502:        if (!page)
                    503:                return;
                    504:        tmp = NULL;
                    505:        i = 0;
                    506:        for (i = 0 ; i+size <= 4096 ; i += size) {
                    507:                bh = get_unused_buffer_head();
                    508:                if (!bh)
                    509:                        goto no_grow;
                    510:                bh->b_this_page = tmp;
                    511:                tmp = bh;
                    512:                bh->b_data = (char * ) (page+i);
                    513:                bh->b_size = size;
                    514:        }
                    515:        tmp = bh;
                    516:        while (1) {
1.1.1.11! root      517:                if (free_list) {
        !           518:                        tmp->b_next_free = free_list;
        !           519:                        tmp->b_prev_free = free_list->b_prev_free;
        !           520:                        free_list->b_prev_free->b_next_free = tmp;
        !           521:                        free_list->b_prev_free = tmp;
        !           522:                } else {
        !           523:                        tmp->b_prev_free = tmp;
        !           524:                        tmp->b_next_free = tmp;
        !           525:                }
1.1.1.10  root      526:                free_list = tmp;
                    527:                ++nr_buffers;
                    528:                if (tmp->b_this_page)
                    529:                        tmp = tmp->b_this_page;
                    530:                else
1.1.1.6   root      531:                        break;
1.1.1.10  root      532:        }
                    533:        tmp->b_this_page = bh;
                    534:        return;
                    535: /*
                    536:  * In case anything failed, we just free everything we got.
                    537:  */
                    538: no_grow:
                    539:        bh = tmp;
                    540:        while (bh) {
                    541:                tmp = bh;
                    542:                bh = bh->b_this_page;
                    543:                put_unused_buffer_head(tmp);
                    544:        }       
                    545:        free_page(page);
                    546: }
                    547: 
                    548: /*
                    549:  * try_to_free() checks if all the buffers on this particular page
                    550:  * are unused, and free's the page if so.
                    551:  */
                    552: static int try_to_free(struct buffer_head * bh)
                    553: {
                    554:        unsigned long page;
                    555:        struct buffer_head * tmp, * p;
                    556: 
                    557:        tmp = bh;
                    558:        do {
                    559:                if (!tmp)
                    560:                        return 0;
                    561:                if (tmp->b_count || tmp->b_dirt || tmp->b_lock)
                    562:                        return 0;
                    563:                tmp = tmp->b_this_page;
                    564:        } while (tmp != bh);
                    565:        page = (unsigned long) bh->b_data;
                    566:        page &= 0xfffff000;
                    567:        tmp = bh;
                    568:        do {
                    569:                p = tmp;
                    570:                tmp = tmp->b_this_page;
                    571:                nr_buffers--;
                    572:                remove_from_queues(p);
                    573:                put_unused_buffer_head(p);
                    574:        } while (tmp != bh);
                    575:        free_page(page);
                    576:        return 1;
                    577: }
                    578: 
                    579: /*
                    580:  * Try to free up some pages by shrinking the buffer-cache
1.1.1.11! root      581:  *
        !           582:  * Priority tells the routine how hard to try to shrink the
        !           583:  * buffers: 3 means "don't bother too much", while a value
        !           584:  * of 0 means "we'd better get some free pages now".
1.1.1.10  root      585:  */
1.1.1.11! root      586: int shrink_buffers(unsigned int priority)
1.1.1.10  root      587: {
                    588:        struct buffer_head *bh;
                    589:        int i;
                    590: 
1.1.1.11! root      591:        if (priority < 2)
        !           592:                sync_buffers(0);
1.1.1.10  root      593:        bh = free_list;
1.1.1.11! root      594:        i = nr_buffers >> priority;
        !           595:        for ( ; i-- > 0 ; bh = bh->b_next_free) {
1.1.1.10  root      596:                if (bh->b_count || !bh->b_this_page)
                    597:                        continue;
1.1.1.11! root      598:                if (bh->b_lock)
        !           599:                        if (priority)
        !           600:                                continue;
        !           601:                        else
        !           602:                                wait_on_buffer(bh);
1.1.1.10  root      603:                if (bh->b_dirt) {
                    604:                        ll_rw_block(WRITEA,bh);
                    605:                        continue;
1.1.1.6   root      606:                }
1.1.1.10  root      607:                if (try_to_free(bh))
                    608:                        return 1;
                    609:        }
                    610:        return 0;
                    611: }
                    612: 
                    613: /*
1.1.1.11! root      614:  * This initializes the initial buffer free list.  nr_buffers is set
        !           615:  * to one less the actual number of buffers, as a sop to backwards
        !           616:  * compatibility --- the old code did this (I think unintentionally,
        !           617:  * but I'm not sure), and programs in the ps package expect it.
        !           618:  *                                     - TYT 8/30/92
1.1.1.10  root      619:  */
                    620: void buffer_init(void)
                    621: {
                    622:        int i;
                    623: 
                    624:        for (i = 0 ; i < NR_HASH ; i++)
1.1.1.4   root      625:                hash_table[i] = NULL;
1.1.1.11! root      626:        free_list = 0;
        !           627:        grow_buffers(BLOCK_SIZE);
1.1.1.10  root      628:        if (!free_list)
1.1.1.11! root      629:                panic("Unable to initialize buffer free list!");
1.1.1.10  root      630:        return;
                    631: }

unix.superglobalmegacorp.com

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