--- 2.2.12-final/fs/buffer.c Tue Aug 17 22:42:50 1999 +++ /tmp/buffer.c Wed Aug 18 11:29:56 1999 @@ -395,31 +395,6 @@ return err; } -void invalidate_buffers(kdev_t dev) -{ - int i; - int nlist; - struct buffer_head * bh; - - for(nlist = 0; nlist < NR_LIST; nlist++) { - bh = lru_list[nlist]; - for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bh->b_next_free) { - if (bh->b_dev != dev) - continue; - wait_on_buffer(bh); - if (bh->b_dev != dev) - continue; - if (bh->b_count) - continue; - bh->b_flushtime = 0; - clear_bit(BH_Protected, &bh->b_state); - clear_bit(BH_Uptodate, &bh->b_state); - clear_bit(BH_Dirty, &bh->b_state); - clear_bit(BH_Req, &bh->b_state); - } - } -} - #define _hashfn(dev,block) (((unsigned)(HASHDEV(dev)^block)) & bh_hash_mask) #define hash(dev,block) hash_table[_hashfn(dev,block)] @@ -486,11 +461,14 @@ remove_from_lru_list(bh); } -static inline void put_last_free(struct buffer_head * bh) +static void put_last_free(struct buffer_head * bh) { if (bh) { struct buffer_head **bhp = &free_list[BUFSIZE_INDEX(bh->b_size)]; + bh->b_count = 0; + bh->b_state = 0; + remove_from_queues(bh); bh->b_dev = B_FREE; /* So it is obvious we are on the free list. */ /* Add to back of free list. */ @@ -510,7 +488,7 @@ { /* put at end of free list */ if(bh->b_dev == B_FREE) { - put_last_free(bh); + panic("B_FREE inserted into queues"); } else { struct buffer_head **bhp = &lru_list[bh->b_list]; @@ -600,64 +578,46 @@ return 0; } -#if 0 -void set_blocksize(kdev_t dev, int size) +void invalidate_buffers(kdev_t dev) { - extern int *blksize_size[]; - int i, nlist; - struct buffer_head * bh, *bhnext; - - if (!blksize_size[MAJOR(dev)]) - return; + int i, nlist, slept; + struct buffer_head * bh, * bhnext; - /* Size must be a power of two, and between 512 and PAGE_SIZE */ - if (size > PAGE_SIZE || size < 512 || (size & (size-1))) - panic("Invalid blocksize passed to set_blocksize"); - - if (blksize_size[MAJOR(dev)][MINOR(dev)] == 0 && size == BLOCK_SIZE) { - blksize_size[MAJOR(dev)][MINOR(dev)] = size; - return; - } - if (blksize_size[MAJOR(dev)][MINOR(dev)] == size) - return; - sync_buffers(dev, 2); - blksize_size[MAJOR(dev)][MINOR(dev)] = size; - - /* We need to be quite careful how we do this - we are moving entries - * around on the free list, and we can get in a loop if we are not careful. - */ + again: + slept = 0; for(nlist = 0; nlist < NR_LIST; nlist++) { bh = lru_list[nlist]; - for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bhnext) { - if(!bh) - break; - - bhnext = bh->b_next_free; + if (!bh) + continue; + for (i = nr_buffers_type[nlist] ; i > 0 ; + bh = bhnext, i--) + { + bhnext = bh->b_next_free; if (bh->b_dev != dev) - continue; - if (bh->b_size == size) - continue; - bhnext->b_count++; - wait_on_buffer(bh); - bhnext->b_count--; - if (bh->b_dev == dev && bh->b_size != size) { - clear_bit(BH_Dirty, &bh->b_state); - clear_bit(BH_Uptodate, &bh->b_state); - clear_bit(BH_Req, &bh->b_state); - bh->b_flushtime = 0; + continue; + if (buffer_locked(bh)) + { + slept = 1; + wait_on_buffer(bh); } - remove_from_queues(bh); - bh->b_dev=B_FREE; - insert_into_queues(bh); + if (bh->b_dev != dev) + goto panic_changed; + if (!bh->b_count) + put_last_free(bh); + if (slept) + goto again; } } + return; + + panic_changed: + panic("invalidate_buffers: buffer changed under us"); } -#else void set_blocksize(kdev_t dev, int size) { extern int *blksize_size[]; - int i, nlist; + int i, nlist, slept; struct buffer_head * bh, *bhnext; if (!blksize_size[MAJOR(dev)]) @@ -679,52 +639,42 @@ /* We need to be quite careful how we do this - we are moving entries * around on the free list, and we can get in a loop if we are not careful. */ + again: + slept = 0; for(nlist = 0; nlist < NR_LIST; nlist++) { bh = lru_list[nlist]; - for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bhnext) { - if(!bh) - break; - - bhnext = bh->b_next_free; - if (bh->b_dev != dev) - continue; - if (bh->b_size == size) + if (!bh) + continue; + for (i = nr_buffers_type[nlist] ; i > 0 ; + bh = bhnext, i--) + { + bhnext = bh->b_next_free; + if (bh->b_dev != dev || bh->b_size == size) continue; - if (bhnext) - bhnext->b_count++; - wait_on_buffer(bh); - if (bh->b_dev == dev && bh->b_size != size) { - clear_bit(BH_Dirty, &bh->b_state); - clear_bit(BH_Uptodate, &bh->b_state); - clear_bit(BH_Req, &bh->b_state); - bh->b_flushtime = 0; + if (buffer_locked(bh)) + { + slept = 1; + wait_on_buffer(bh); } - - /* - * lets be mega-conservative about what to free: - */ - if (!(bh->b_dev != dev) && - !(bh->b_size == size) && - !bh->b_count && - !buffer_protected(bh) && - !buffer_dirty(bh) && - !buffer_locked(bh) && - !waitqueue_active(&bh->b_wait)) { - remove_from_hash_queue(bh); - bh->b_dev = NODEV; - refile_buffer(bh); - try_to_free_buffers(buffer_page(bh)); - } else { - remove_from_queues(bh); - bh->b_dev=B_FREE; - insert_into_queues(bh); - } - if (bhnext) - bhnext->b_count--; + if (bh->b_dev != dev || bh->b_size == size) + goto panic_changed; + if (!bh->b_count) + put_last_free(bh); + else + printk(KERN_ERR + "set_blocksize: " + "b_count %d, dev %s, block %lu!\n", + bh->b_count, bdevname(bh->b_dev), + bh->b_blocknr); + if (slept) + goto again; } } + return; + + panic_changed: + panic("set_blocksize: buffer changed under us"); } -#endif /* * This function knows that we do a linear pass over the whole array, @@ -741,17 +691,11 @@ /* * We are up to something dangerous ... rather be careful */ - if ((bh->b_count != 1) || buffer_protected(bh) || - buffer_dirty(bh) || buffer_locked(bh) || - !buffer_lowprio(bh) || waitqueue_active(&bh->b_wait)) { - brelse(bh); - } else { - bh->b_count--; - remove_from_hash_queue(bh); - bh->b_dev = NODEV; - refile_buffer(bh); - try_to_free_buffers(buffer_page(bh)); - } + if (buffer_protected(bh) || buffer_dirty(bh) || + !buffer_lowprio(bh)) + __brelse(bh); + else + __bforget(bh); } /* @@ -929,9 +873,6 @@ __brelse(buf); return; } - buf->b_count = 0; - buf->b_state = 0; - remove_from_queues(buf); put_last_free(buf); }