home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / vmount-0.6a-I / src / buffers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-30  |  9.3 KB  |  365 lines

  1. /*
  2.  * Name: buffers.c
  3.  * Description: Functions for buffering disk blocks and inodes.
  4.  * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
  5.  * Date: 1996-11-14
  6.  * Copyright: GNU-GPL
  7.  * Tabsize: 4
  8.  */
  9.  
  10. #include <linux/fs.h>
  11. #include <linux/sched.h>
  12. #include "my_defines.h"
  13. #include "cache.h"
  14.  
  15. /* ------------------------------------------------------------------------- */
  16.  
  17. extern void    bzero(void *block, int size);
  18.  
  19. /* ------------------------------------------------------------------------- */
  20.  
  21. #define    DPRINTF(arg)    if(debug_mode & DEBUG_BUFFERS)    dprintf arg
  22.  
  23. #define    BLOCKBUFFER_CNT        103
  24. #define    INODEBUFFER_CNT        15
  25.  
  26. /* ------------------------------------------------------------------------- */
  27.  
  28. extern void    *malloc(unsigned long size);
  29. extern void    *realloc(void *prev, unsigned long newsize);
  30. extern void    free(void *p);
  31.  
  32. /* ------------------------------------------------------------------------- */
  33.  
  34. static struct buffer_head    block_buffer[BLOCKBUFFER_CNT];
  35. static struct inode            inode_buffer[INODEBUFFER_CNT];
  36.  
  37. /* ------------------------------------------------------------------------- */
  38.  
  39. struct buffer_head    *getblk(kdev_t dev, int blocknr, int blocksize)
  40. {
  41. int                    i, j;
  42. void                *data;
  43. struct buffer_head    *bh;
  44.  
  45.     i = blocknr;
  46.     for(j=0;j<BLOCKBUFFER_CNT;j++,i++){        /* maybe we have the buffer */
  47.         i %= BLOCKBUFFER_CNT;
  48.         if(block_buffer[i].b_blocknr == blocknr
  49.                         && block_buffer[i].b_size == blocksize){
  50.             block_buffer[i].b_count ++;
  51.             set_bit(BH_Touched, &block_buffer[i].b_state);
  52.             DPRINTF(("getblk(block=%d): returning buffer %d\n", blocknr, i));
  53.             return &block_buffer[i];
  54.         }
  55.     }
  56.     i = blocknr;
  57.     for(j=0;j<BLOCKBUFFER_CNT;j++,i++){
  58.         i %= BLOCKBUFFER_CNT;
  59.         if(buffer_locked(&block_buffer[i]))        /* don't use locked buffers */
  60.             continue;
  61.         if(!block_buffer[i].b_count){
  62.             if(buffer_dirty(&block_buffer[i])){
  63.                 bh = &block_buffer[i];
  64.                 ll_rw_block(WRITE, 1, &bh);
  65.             }
  66.             data = block_buffer[i].b_data;
  67.             if(block_buffer[i].b_size != blocksize){
  68.                 data = data ? realloc(data, blocksize) : malloc(blocksize);
  69.             }
  70.             DPRINTF(("getblk(block=%d): allocating buffer %d\n", blocknr, i));
  71.             bzero(&block_buffer[i], sizeof(struct buffer_head));
  72.             block_buffer[i].b_count = 1;
  73.             block_buffer[i].b_flushtime = 0;
  74.             block_buffer[i].b_state = (1<<BH_Touched);
  75.             block_buffer[i].b_dev = dev;
  76.             block_buffer[i].b_blocknr = blocknr;
  77.             block_buffer[i].b_size = blocksize;
  78.             block_buffer[i].b_data = data;
  79.             return &block_buffer[i];
  80.         }
  81.     }
  82.     panic("no free block buffers\n");
  83.     return NULL;
  84. }
  85.  
  86. /* ------------------------------------------------------------------------- */
  87.  
  88. struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
  89. {
  90. int                    i, j;
  91.  
  92.     i = block;
  93.     for(j=0;j<BLOCKBUFFER_CNT;j++,i++){        /* maybe we have the buffer */
  94.         i %= BLOCKBUFFER_CNT;
  95.         if(block_buffer[i].b_blocknr == block){
  96.             if(block_buffer[i].b_size == size){
  97.                 block_buffer[i].b_count ++;
  98.                 DPRINTF(("get_hash_table(block=%d): buffered\n", block));
  99.                 return &block_buffer[i];
  100.             }else{
  101.                 eprintf("VFS: Wrong blocksize on device (%ld / %d)\n",
  102.                                             block_buffer[i].b_size, size);
  103.                 return NULL;
  104.             }
  105.         }
  106.     }
  107.     DPRINTF(("get_hash_table(block=%d): not buffered\n", block));
  108.     return NULL;
  109. }
  110.  
  111. /* ------------------------------------------------------------------------- */
  112.  
  113. struct buffer_head     *bread(kdev_t dev, int block, int size)
  114. {
  115. struct buffer_head    *bh = getblk(dev, block, size);
  116.  
  117.     if(buffer_uptodate(bh)){
  118.         DPRINTF(("bread(block=%d, size=%d): buffered\n", block, size));
  119.         return bh;
  120.     }
  121.     DPRINTF(("bread(block=%d, size=%d): read\n", block, size));
  122.     ll_rw_block(READ, 1, &bh);
  123.     return bh;
  124. }
  125.  
  126. /* ------------------------------------------------------------------------- */
  127.  
  128. struct buffer_head    *breada(kdev_t dev, int block, int bufsize,
  129.     unsigned int pos, unsigned int filesize)
  130. {    /* no read ahead implemented */
  131.     return bread(dev, block, bufsize);
  132. }
  133.  
  134. /* ------------------------------------------------------------------------- */
  135.  
  136. void    __brelse(struct buffer_head * buf)
  137. {
  138.     DPRINTF(("__brelse(block=%ld)\n", buf->b_blocknr));
  139.     if (buf->b_count) {
  140.         buf->b_count--;
  141.         return;
  142.     }
  143.     eprintf("VFS: brelse: Trying to release free buffer\n");
  144. }
  145.  
  146. /* ------------------------------------------------------------------------- */
  147.  
  148. void __bforget(struct buffer_head * buf)
  149. {
  150.     DPRINTF(("** someone uses bforget() .... why???"));
  151.     mark_buffer_clean(buf);
  152.     clear_bit(BH_Protected, &buf->b_state);
  153.     buf->b_count = 0;
  154.     buf->b_blocknr = -1;
  155. }
  156.  
  157. /* ------------------------------------------------------------------------- */
  158.  
  159. void mark_buffer_uptodate(struct buffer_head *bh, int on)
  160. {
  161.     if (on){
  162.         set_bit(BH_Uptodate, &bh->b_state);
  163.     }else{
  164.         clear_bit(BH_Uptodate, &bh->b_state);
  165.     }
  166. }
  167.  
  168. /* ------------------------------------------------------------------------- */
  169.  
  170. void    my_sync_blocks(void)
  171. {
  172. int                    i;
  173. struct buffer_head    *bh;
  174.  
  175.     for(i=0;i<BLOCKBUFFER_CNT;i++){
  176.         if(block_buffer[i].b_data != NULL && buffer_dirty(&block_buffer[i])){
  177.             bh = &block_buffer[i];
  178.             ll_rw_block(WRITE, 1, &bh);
  179.             clear_bit(BH_Dirty, &block_buffer[i].b_state);
  180.         }
  181.     }
  182.     cache_sync();
  183. }
  184.  
  185. /* ------------------------------------------------------------------------- */
  186. /* ------------------------------------------------------------------------- */
  187.  
  188. static inline struct inode    *find_inode(int ino)
  189. {
  190. int        i, j;
  191.  
  192.     i = ino;
  193.     for(j=0;j<INODEBUFFER_CNT;j++,i++){
  194.         i %= INODEBUFFER_CNT;
  195.         if(inode_buffer[i].i_ino == ino){
  196.             DPRINTF(("find_inode(ino=%d): found in buffer %d\n", ino, i));
  197.             return &inode_buffer[i];
  198.         }
  199.     }
  200.     DPRINTF(("find_inode(ino=%d): not found\n", ino));
  201.     return NULL;
  202. }
  203.  
  204. /* ------------------------------------------------------------------------- */
  205.  
  206. struct inode    *get_empty_inode(void)
  207. {
  208. int            i, released = -1, j;
  209. static int    ino = 0, start = 0;
  210.  
  211.     j = start++;
  212.     for(i=0;i<INODEBUFFER_CNT;i++,j++){
  213.         j %= INODEBUFFER_CNT;
  214.         if(inode_buffer[j].i_count <= 0){
  215.             released = j;
  216.             if(!inode_buffer[j].i_dirt)
  217.                 break;
  218.         }
  219.     }
  220.     if(i >= INODEBUFFER_CNT){
  221.         if(released < 0){
  222.             panic("no free inode buffers\n");
  223.             return NULL;
  224.         }
  225.         i = released;
  226.     }else{
  227.         i = j;
  228.     }
  229.     if (inode_buffer[i].i_dirt) {
  230.         if (!inode_buffer[i].i_sb || !inode_buffer[i].i_sb->s_op
  231.                                 || !inode_buffer[i].i_sb->s_op->write_inode) {
  232.             inode_buffer[i].i_dirt = 0;
  233.         }else{
  234.             inode_buffer[i].i_sb->s_op->write_inode(&inode_buffer[i]);
  235.         }
  236.     }
  237.     bzero(&inode_buffer[i], sizeof(struct inode));
  238.     inode_buffer[i].i_count = 1;
  239.     inode_buffer[i].i_nlink = 1;
  240.     inode_buffer[i].i_version = ++event;
  241.     inode_buffer[i].i_sem.count = 1;
  242.     inode_buffer[i].i_ino = ++ino;
  243.     inode_buffer[i].i_dev = 0;
  244.     inode_buffer[i].i_mode = 0777;
  245.     DPRINTF(("get_empty_inode(): using buffer %d\n", i));
  246.     return &inode_buffer[i];
  247. }
  248.  
  249. /* ------------------------------------------------------------------------- */
  250.  
  251. void    clear_inode(struct inode *inode)
  252. {
  253.     bzero(inode, sizeof(struct inode));
  254. }
  255.  
  256. /* ------------------------------------------------------------------------- */
  257.  
  258. struct inode    *__iget(struct super_block *sb, int nr, int crossmntp)
  259. {
  260. struct inode    *inode;
  261.  
  262.     DPRINTF(("__iget(ino=%d)\n", nr));
  263.     if (!sb)
  264.         panic("VFS: iget with sb==NULL");
  265.     if((inode = find_inode(nr)) == NULL){
  266.         inode = get_empty_inode();
  267.         inode->i_sb = sb;
  268.         inode->i_dev = sb->s_dev;
  269.         inode->i_ino = nr;
  270.         inode->i_flags = sb->s_flags;
  271.         if (inode->i_sb->s_op && inode->i_sb->s_op->read_inode)
  272.             inode->i_sb->s_op->read_inode(inode);
  273.     }else{
  274.         inode->i_count++;
  275.     }
  276.     return inode;
  277. }
  278.  
  279. /* ------------------------------------------------------------------------- */
  280.  
  281. void iput(struct inode * inode)
  282. {
  283.     if (!inode)
  284.         return;
  285.     if (!inode->i_count) {
  286.         eprintf("** iput(): trying to release free inode %ld\n", inode->i_ino);
  287.         return;
  288.     }
  289.  
  290.     DPRINTF(("iput(ino=%ld)\n", inode->i_ino));
  291.     inode->i_count--;
  292.     if(inode->i_count > 0) {
  293.         return;
  294.     }
  295.     inode->i_count = 0;
  296.  
  297.     if(inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) {
  298.         inode->i_count++;    /* operations require retained inode */
  299.         inode->i_sb->s_op->put_inode(inode);
  300.         inode->i_count = 0;
  301.         if (!inode->i_nlink)
  302.             return;
  303.     }
  304.     if(!inode->i_dirt)
  305.         return;
  306.     if(!inode->i_sb || !inode->i_sb->s_op || !inode->i_sb->s_op->write_inode){
  307.         inode->i_dirt = 0;
  308.         return;
  309.     }
  310.     inode->i_count++;    /* operations require retained inode */
  311.     inode->i_sb->s_op->write_inode(inode);
  312.     inode->i_count = 0;
  313. }
  314.  
  315. /* ------------------------------------------------------------------------- */
  316.  
  317. void    my_sync_inodes(void)
  318. {
  319. int        i;
  320.  
  321.     for(i=0;i<INODEBUFFER_CNT;i++){
  322.         if(inode_buffer[i].i_op != NULL && inode_buffer[i].i_dirt){
  323.             if(inode_buffer[i].i_sb && inode_buffer[i].i_sb->s_op
  324.                     && inode_buffer[i].i_sb->s_op->write_inode)
  325.                 (inode_buffer[i].i_sb->s_op->write_inode)(&inode_buffer[i]);
  326.             inode_buffer[i].i_dirt = 0;
  327.         }
  328.     }
  329. }
  330.  
  331. /* ------------------------------------------------------------------------- */
  332.  
  333. void set_writetime(struct buffer_head * buf, int flag)
  334. {
  335. }
  336.  
  337. /* ------------------------------------------------------------------------- */
  338.  
  339. void    buffer_regular(void)
  340. {
  341. }
  342.  
  343. /* ------------------------------------------------------------------------- */
  344.  
  345. void    buffer_invalidate(void)
  346. {
  347. int        i;
  348.  
  349.     for(i=0;i<BLOCKBUFFER_CNT;i++){
  350.         if(block_buffer[i].b_data != NULL)
  351.             free(block_buffer[i].b_data);
  352.     }
  353.     bzero(block_buffer, sizeof(block_buffer));
  354.     bzero(inode_buffer, sizeof(inode_buffer));
  355. }
  356.  
  357. /* ------------------------------------------------------------------------- */
  358.  
  359. void    buffer_initialize(int use_small_buffer)
  360. {
  361.     cache_init_buffers(use_small_buffer);
  362. }
  363.  
  364. /* ------------------------------------------------------------------------- */
  365.