This is buffers.c in view mode; [Download] [Up]
/* * 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); } /* ------------------------------------------------------------------------- */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.