home *** CD-ROM | disk | FTP | other *** search
- /*
- * Name: buffers.c
- * Description: Functions for buffering disk blocks and inodes.
- * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
- * Date: 1996-11-14
- * Copyright: GNU-GPL
- * Tabsize: 4
- */
-
- #include <linux/fs.h>
- #include <linux/sched.h>
- #include "my_defines.h"
- #include "cache.h"
-
- /* ------------------------------------------------------------------------- */
-
- extern void bzero(void *block, int size);
-
- /* ------------------------------------------------------------------------- */
-
- #define DPRINTF(arg) if(debug_mode & DEBUG_BUFFERS) dprintf arg
-
- #define BLOCKBUFFER_CNT 103
- #define INODEBUFFER_CNT 15
-
- /* ------------------------------------------------------------------------- */
-
- extern void *malloc(unsigned long size);
- extern void *realloc(void *prev, unsigned long newsize);
- extern void free(void *p);
-
- /* ------------------------------------------------------------------------- */
-
- static struct buffer_head block_buffer[BLOCKBUFFER_CNT];
- static struct inode inode_buffer[INODEBUFFER_CNT];
-
- /* ------------------------------------------------------------------------- */
-
- struct buffer_head *getblk(kdev_t dev, int blocknr, int blocksize)
- {
- int i, j;
- void *data;
- struct buffer_head *bh;
-
- i = blocknr;
- for(j=0;j<BLOCKBUFFER_CNT;j++,i++){ /* maybe we have the buffer */
- i %= BLOCKBUFFER_CNT;
- if(block_buffer[i].b_blocknr == blocknr
- && block_buffer[i].b_size == blocksize){
- block_buffer[i].b_count ++;
- set_bit(BH_Touched, &block_buffer[i].b_state);
- DPRINTF(("getblk(block=%d): returning buffer %d\n", blocknr, i));
- return &block_buffer[i];
- }
- }
- i = blocknr;
- for(j=0;j<BLOCKBUFFER_CNT;j++,i++){
- i %= BLOCKBUFFER_CNT;
- if(buffer_locked(&block_buffer[i])) /* don't use locked buffers */
- continue;
- if(!block_buffer[i].b_count){
- if(buffer_dirty(&block_buffer[i])){
- bh = &block_buffer[i];
- ll_rw_block(WRITE, 1, &bh);
- }
- data = block_buffer[i].b_data;
- if(block_buffer[i].b_size != blocksize){
- data = data ? realloc(data, blocksize) : malloc(blocksize);
- }
- DPRINTF(("getblk(block=%d): allocating buffer %d\n", blocknr, i));
- bzero(&block_buffer[i], sizeof(struct buffer_head));
- block_buffer[i].b_count = 1;
- block_buffer[i].b_flushtime = 0;
- block_buffer[i].b_state = (1<<BH_Touched);
- block_buffer[i].b_dev = dev;
- block_buffer[i].b_blocknr = blocknr;
- block_buffer[i].b_size = blocksize;
- block_buffer[i].b_data = data;
- return &block_buffer[i];
- }
- }
- panic("no free block buffers\n");
- return NULL;
- }
-
- /* ------------------------------------------------------------------------- */
-
- struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
- {
- int i, j;
-
- i = block;
- for(j=0;j<BLOCKBUFFER_CNT;j++,i++){ /* maybe we have the buffer */
- i %= BLOCKBUFFER_CNT;
- if(block_buffer[i].b_blocknr == block){
- if(block_buffer[i].b_size == size){
- block_buffer[i].b_count ++;
- DPRINTF(("get_hash_table(block=%d): buffered\n", block));
- return &block_buffer[i];
- }else{
- eprintf("VFS: Wrong blocksize on device (%ld / %d)\n",
- block_buffer[i].b_size, size);
- return NULL;
- }
- }
- }
- DPRINTF(("get_hash_table(block=%d): not buffered\n", block));
- return NULL;
- }
-
- /* ------------------------------------------------------------------------- */
-
- struct buffer_head *bread(kdev_t dev, int block, int size)
- {
- struct buffer_head *bh = getblk(dev, block, size);
-
- if(buffer_uptodate(bh)){
- DPRINTF(("bread(block=%d, size=%d): buffered\n", block, size));
- return bh;
- }
- DPRINTF(("bread(block=%d, size=%d): read\n", block, size));
- ll_rw_block(READ, 1, &bh);
- return bh;
- }
-
- /* ------------------------------------------------------------------------- */
-
- struct buffer_head *breada(kdev_t dev, int block, int bufsize,
- unsigned int pos, unsigned int filesize)
- { /* no read ahead implemented */
- return bread(dev, block, bufsize);
- }
-
- /* ------------------------------------------------------------------------- */
-
- void __brelse(struct buffer_head * buf)
- {
- DPRINTF(("__brelse(block=%ld)\n", buf->b_blocknr));
- if (buf->b_count) {
- buf->b_count--;
- return;
- }
- eprintf("VFS: brelse: Trying to release free buffer\n");
- }
-
- /* ------------------------------------------------------------------------- */
-
- void __bforget(struct buffer_head * buf)
- {
- DPRINTF(("** someone uses bforget() .... why???"));
- mark_buffer_clean(buf);
- clear_bit(BH_Protected, &buf->b_state);
- buf->b_count = 0;
- buf->b_blocknr = -1;
- }
-
- /* ------------------------------------------------------------------------- */
-
- void mark_buffer_uptodate(struct buffer_head *bh, int on)
- {
- if (on){
- set_bit(BH_Uptodate, &bh->b_state);
- }else{
- clear_bit(BH_Uptodate, &bh->b_state);
- }
- }
-
- /* ------------------------------------------------------------------------- */
-
- void my_sync_blocks(void)
- {
- int i;
- struct buffer_head *bh;
-
- for(i=0;i<BLOCKBUFFER_CNT;i++){
- if(block_buffer[i].b_data != NULL && buffer_dirty(&block_buffer[i])){
- bh = &block_buffer[i];
- ll_rw_block(WRITE, 1, &bh);
- clear_bit(BH_Dirty, &block_buffer[i].b_state);
- }
- }
- cache_sync();
- }
-
- /* ------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------- */
-
- static inline struct inode *find_inode(int ino)
- {
- int i, j;
-
- i = ino;
- for(j=0;j<INODEBUFFER_CNT;j++,i++){
- i %= INODEBUFFER_CNT;
- if(inode_buffer[i].i_ino == ino){
- DPRINTF(("find_inode(ino=%d): found in buffer %d\n", ino, i));
- return &inode_buffer[i];
- }
- }
- DPRINTF(("find_inode(ino=%d): not found\n", ino));
- return NULL;
- }
-
- /* ------------------------------------------------------------------------- */
-
- struct inode *get_empty_inode(void)
- {
- int i, released = -1, j;
- static int ino = 0, start = 0;
-
- j = start++;
- for(i=0;i<INODEBUFFER_CNT;i++,j++){
- j %= INODEBUFFER_CNT;
- if(inode_buffer[j].i_count <= 0){
- released = j;
- if(!inode_buffer[j].i_dirt)
- break;
- }
- }
- if(i >= INODEBUFFER_CNT){
- if(released < 0){
- panic("no free inode buffers\n");
- return NULL;
- }
- i = released;
- }else{
- i = j;
- }
- if (inode_buffer[i].i_dirt) {
- if (!inode_buffer[i].i_sb || !inode_buffer[i].i_sb->s_op
- || !inode_buffer[i].i_sb->s_op->write_inode) {
- inode_buffer[i].i_dirt = 0;
- }else{
- inode_buffer[i].i_sb->s_op->write_inode(&inode_buffer[i]);
- }
- }
- bzero(&inode_buffer[i], sizeof(struct inode));
- inode_buffer[i].i_count = 1;
- inode_buffer[i].i_nlink = 1;
- inode_buffer[i].i_version = ++event;
- inode_buffer[i].i_sem.count = 1;
- inode_buffer[i].i_ino = ++ino;
- inode_buffer[i].i_dev = 0;
- inode_buffer[i].i_mode = 0777;
- DPRINTF(("get_empty_inode(): using buffer %d\n", i));
- return &inode_buffer[i];
- }
-
- /* ------------------------------------------------------------------------- */
-
- void clear_inode(struct inode *inode)
- {
- bzero(inode, sizeof(struct inode));
- }
-
- /* ------------------------------------------------------------------------- */
-
- struct inode *__iget(struct super_block *sb, int nr, int crossmntp)
- {
- struct inode *inode;
-
- DPRINTF(("__iget(ino=%d)\n", nr));
- if (!sb)
- panic("VFS: iget with sb==NULL");
- if((inode = find_inode(nr)) == NULL){
- inode = get_empty_inode();
- inode->i_sb = sb;
- inode->i_dev = sb->s_dev;
- inode->i_ino = nr;
- inode->i_flags = sb->s_flags;
- if (inode->i_sb->s_op && inode->i_sb->s_op->read_inode)
- inode->i_sb->s_op->read_inode(inode);
- }else{
- inode->i_count++;
- }
- return inode;
- }
-
- /* ------------------------------------------------------------------------- */
-
- void iput(struct inode * inode)
- {
- if (!inode)
- return;
- if (!inode->i_count) {
- eprintf("** iput(): trying to release free inode %ld\n", inode->i_ino);
- return;
- }
-
- DPRINTF(("iput(ino=%ld)\n", inode->i_ino));
- inode->i_count--;
- if(inode->i_count > 0) {
- return;
- }
- inode->i_count = 0;
-
- if(inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) {
- inode->i_count++; /* operations require retained inode */
- inode->i_sb->s_op->put_inode(inode);
- inode->i_count = 0;
- if (!inode->i_nlink)
- return;
- }
- if(!inode->i_dirt)
- return;
- if(!inode->i_sb || !inode->i_sb->s_op || !inode->i_sb->s_op->write_inode){
- inode->i_dirt = 0;
- return;
- }
- inode->i_count++; /* operations require retained inode */
- inode->i_sb->s_op->write_inode(inode);
- inode->i_count = 0;
- }
-
- /* ------------------------------------------------------------------------- */
-
- void my_sync_inodes(void)
- {
- int i;
-
- for(i=0;i<INODEBUFFER_CNT;i++){
- if(inode_buffer[i].i_op != NULL && inode_buffer[i].i_dirt){
- if(inode_buffer[i].i_sb && inode_buffer[i].i_sb->s_op
- && inode_buffer[i].i_sb->s_op->write_inode)
- (inode_buffer[i].i_sb->s_op->write_inode)(&inode_buffer[i]);
- inode_buffer[i].i_dirt = 0;
- }
- }
- }
-
- /* ------------------------------------------------------------------------- */
-
- void set_writetime(struct buffer_head * buf, int flag)
- {
- }
-
- /* ------------------------------------------------------------------------- */
-
- void buffer_regular(void)
- {
- }
-
- /* ------------------------------------------------------------------------- */
-
- void buffer_invalidate(void)
- {
- int i;
-
- for(i=0;i<BLOCKBUFFER_CNT;i++){
- if(block_buffer[i].b_data != NULL)
- free(block_buffer[i].b_data);
- }
- bzero(block_buffer, sizeof(block_buffer));
- bzero(inode_buffer, sizeof(inode_buffer));
- }
-
- /* ------------------------------------------------------------------------- */
-
- void buffer_initialize(int use_small_buffer)
- {
- cache_init_buffers(use_small_buffer);
- }
-
- /* ------------------------------------------------------------------------- */
-