home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / ext / fsync.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-27  |  3.4 KB  |  186 lines

  1.  
  2. /*
  3.  *  linux/fs/ext/fsync.c
  4.  *
  5.  *  Copyright (C) 1993  Stephen Tweedie (sct@dcs.ed.ac.uk)
  6.  *  from
  7.  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  8.  *  from
  9.  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
  10.  * 
  11.  *  extfs fsync primitive
  12.  */
  13.  
  14. #include <asm/segment.h>
  15. #include <asm/system.h>
  16.  
  17. #include <linux/errno.h>
  18. #include <linux/sched.h>
  19. #include <linux/stat.h>
  20. #include <linux/fcntl.h>
  21. #include <linux/locks.h>
  22.  
  23. #include <linux/fs.h>
  24. #include <linux/ext_fs.h>
  25.  
  26.  
  27. #define blocksize BLOCK_SIZE
  28. #define addr_per_block 256
  29.  
  30. static int sync_block (struct inode * inode, unsigned long * block, int wait)
  31. {
  32.     struct buffer_head * bh;
  33.     int tmp;
  34.     
  35.     if (!*block)
  36.         return 0;
  37.     tmp = *block;
  38.     bh = get_hash_table(inode->i_dev, *block, blocksize);
  39.     if (!bh)
  40.         return 0;
  41.     if (*block != tmp) {
  42.         brelse (bh);
  43.         return 1;
  44.     }
  45.     if (wait && bh->b_req && !bh->b_uptodate) {
  46.         brelse(bh);
  47.         return -1;
  48.     }
  49.     if (wait || !bh->b_uptodate || !bh->b_dirt)
  50.     {
  51.         brelse(bh);
  52.         return 0;
  53.     }
  54.     ll_rw_block(WRITE, 1, &bh);
  55.     bh->b_count--;
  56.     return 0;
  57. }
  58.  
  59. static int sync_iblock (struct inode * inode, unsigned long * iblock, 
  60.             struct buffer_head **bh, int wait) 
  61. {
  62.     int rc, tmp;
  63.     
  64.     *bh = NULL;
  65.     tmp = *iblock;
  66.     if (!tmp)
  67.         return 0;
  68.     rc = sync_block (inode, iblock, wait);
  69.     if (rc)
  70.         return rc;
  71.     *bh = bread(inode->i_dev, tmp, blocksize);
  72.     if (tmp != *iblock) {
  73.         brelse(*bh);
  74.         *bh = NULL;
  75.         return 1;
  76.     }
  77.     if (!*bh)
  78.         return -1;
  79.     return 0;
  80. }
  81.  
  82.  
  83. static int sync_direct(struct inode *inode, int wait)
  84. {
  85.     int i;
  86.     int rc, err = 0;
  87.  
  88.     for (i = 0; i < 9; i++) {
  89.         rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
  90.         if (rc > 0)
  91.             break;
  92.         if (rc)
  93.             err = rc;
  94.     }
  95.     return err;
  96. }
  97.  
  98. static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
  99. {
  100.     int i;
  101.     struct buffer_head * ind_bh;
  102.     int rc, err = 0;
  103.  
  104.     rc = sync_iblock (inode, iblock, &ind_bh, wait);
  105.     if (rc || !ind_bh)
  106.         return rc;
  107.     
  108.     for (i = 0; i < addr_per_block; i++) {
  109.         rc = sync_block (inode, 
  110.                  ((unsigned long *) ind_bh->b_data) + i,
  111.                  wait);
  112.         if (rc > 0)
  113.             break;
  114.         if (rc)
  115.             err = rc;
  116.     }
  117.     brelse(ind_bh);
  118.     return err;
  119. }
  120.  
  121. static int sync_dindirect(struct inode *inode, unsigned long *diblock,
  122.               int wait)
  123. {
  124.     int i;
  125.     struct buffer_head * dind_bh;
  126.     int rc, err = 0;
  127.  
  128.     rc = sync_iblock (inode, diblock, &dind_bh, wait);
  129.     if (rc || !dind_bh)
  130.         return rc;
  131.     
  132.     for (i = 0; i < addr_per_block; i++) {
  133.         rc = sync_indirect (inode,
  134.                     ((unsigned long *) dind_bh->b_data) + i,
  135.                     wait);
  136.         if (rc > 0)
  137.             break;
  138.         if (rc)
  139.             err = rc;
  140.     }
  141.     brelse(dind_bh);
  142.     return err;
  143. }
  144.  
  145. static int sync_tindirect(struct inode *inode, unsigned long *tiblock, 
  146.               int wait)
  147. {
  148.     int i;
  149.     struct buffer_head * tind_bh;
  150.     int rc, err = 0;
  151.  
  152.     rc = sync_iblock (inode, tiblock, &tind_bh, wait);
  153.     if (rc || !tind_bh)
  154.         return rc;
  155.     
  156.     for (i = 0; i < addr_per_block; i++) {
  157.         rc = sync_dindirect (inode,
  158.                      ((unsigned long *) tind_bh->b_data) + i,
  159.                      wait);
  160.         if (rc > 0)
  161.             break;
  162.         if (rc)
  163.             err = rc;
  164.     }
  165.     brelse(tind_bh);
  166.     return err;
  167. }
  168.  
  169. int ext_sync_file(struct inode * inode, struct file *file)
  170. {
  171.     int wait, err = 0;
  172.  
  173.     if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
  174.          S_ISLNK(inode->i_mode)))
  175.         return -EINVAL;
  176.     for (wait=0; wait<=1; wait++)
  177.     {
  178.         err |= sync_direct(inode, wait);
  179.         err |= sync_indirect(inode, inode->u.ext_i.i_data+9, wait);
  180.         err |= sync_dindirect(inode, inode->u.ext_i.i_data+10, wait);
  181.         err |= sync_tindirect(inode, inode->u.ext_i.i_data+11, wait);
  182.     }
  183.     err |= ext_sync_inode (inode);
  184.     return (err < 0) ? -EIO : 0;
  185. }
  186.