home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / ext2 / fsync.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-26  |  3.8 KB  |  196 lines

  1. /*
  2.  *  linux/fs/ext2/fsync.c
  3.  *
  4.  *  Copyright (C) 1993  Stephen Tweedie (sct@dcs.ed.ac.uk)
  5.  *  from
  6.  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  7.  *                      Laboratoire MASI - Institut Blaise Pascal
  8.  *                      Universite Pierre et Marie Curie (Paris VI)
  9.  *  from
  10.  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
  11.  * 
  12.  *  ext2fs fsync primitive
  13.  */
  14.  
  15. #include <asm/segment.h>
  16. #include <asm/system.h>
  17.  
  18. #include <linux/errno.h>
  19. #include <linux/fs.h>
  20. #include <linux/ext2_fs.h>
  21. #include <linux/fcntl.h>
  22. #include <linux/sched.h>
  23. #include <linux/stat.h>
  24. #include <linux/locks.h>
  25.  
  26.  
  27. #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
  28. #define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
  29.  
  30. static int sync_block (struct inode * inode, u32 * 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.         brelse (bh);
  51.         return 0;
  52.     }
  53.     ll_rw_block (WRITE, 1, &bh);
  54.     bh->b_count--;
  55.     return 0;
  56. }
  57.  
  58. static int sync_iblock (struct inode * inode, u32 * iblock, 
  59.             struct buffer_head ** bh, int wait) 
  60. {
  61.     int rc, tmp;
  62.     
  63.     *bh = NULL;
  64.     tmp = *iblock;
  65.     if (!tmp)
  66.         return 0;
  67.     rc = sync_block (inode, iblock, wait);
  68.     if (rc)
  69.         return rc;
  70.     *bh = bread (inode->i_dev, tmp, blocksize);
  71.     if (tmp != *iblock) {
  72.         brelse (*bh);
  73.         *bh = NULL;
  74.         return 1;
  75.     }
  76.     if (!*bh)
  77.         return -1;
  78.     return 0;
  79. }
  80.  
  81.  
  82. static int sync_direct (struct inode * inode, int wait)
  83. {
  84.     int i;
  85.     int rc, err = 0;
  86.  
  87.     for (i = 0; i < EXT2_NDIR_BLOCKS; i++) {
  88.         rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait);
  89.         if (rc > 0)
  90.             break;
  91.         if (rc)
  92.             err = rc;
  93.     }
  94.     return err;
  95. }
  96.  
  97. static int sync_indirect (struct inode * inode, u32 * iblock, int wait)
  98. {
  99.     int i;
  100.     struct buffer_head * ind_bh;
  101.     int rc, err = 0;
  102.  
  103.     rc = sync_iblock (inode, iblock, &ind_bh, wait);
  104.     if (rc || !ind_bh)
  105.         return rc;
  106.     
  107.     for (i = 0; i < addr_per_block; i++) {
  108.         rc = sync_block (inode, 
  109.                  ((u32 *) ind_bh->b_data) + i,
  110.                  wait);
  111.         if (rc > 0)
  112.             break;
  113.         if (rc)
  114.             err = rc;
  115.     }
  116.     brelse (ind_bh);
  117.     return err;
  118. }
  119.  
  120. static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
  121. {
  122.     int i;
  123.     struct buffer_head * dind_bh;
  124.     int rc, err = 0;
  125.  
  126.     rc = sync_iblock (inode, diblock, &dind_bh, wait);
  127.     if (rc || !dind_bh)
  128.         return rc;
  129.     
  130.     for (i = 0; i < addr_per_block; i++) {
  131.         rc = sync_indirect (inode,
  132.                     ((u32 *) dind_bh->b_data) + i,
  133.                     wait);
  134.         if (rc > 0)
  135.             break;
  136.         if (rc)
  137.             err = rc;
  138.     }
  139.     brelse (dind_bh);
  140.     return err;
  141. }
  142.  
  143. static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
  144. {
  145.     int i;
  146.     struct buffer_head * tind_bh;
  147.     int rc, err = 0;
  148.  
  149.     rc = sync_iblock (inode, tiblock, &tind_bh, wait);
  150.     if (rc || !tind_bh)
  151.         return rc;
  152.     
  153.     for (i = 0; i < addr_per_block; i++) {
  154.         rc = sync_dindirect (inode,
  155.                      ((u32 *) tind_bh->b_data) + i,
  156.                      wait);
  157.         if (rc > 0)
  158.             break;
  159.         if (rc)
  160.             err = rc;
  161.     }
  162.     brelse (tind_bh);
  163.     return err;
  164. }
  165.  
  166. int ext2_sync_file (struct inode * inode, struct file * file)
  167. {
  168.     int wait, err = 0;
  169.  
  170.     if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
  171.          S_ISLNK(inode->i_mode)))
  172.         return -EINVAL;
  173.     if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
  174.         /*
  175.          * Don't sync fast links!
  176.          */
  177.         goto skip;
  178.  
  179.     for (wait=0; wait<=1; wait++)
  180.     {
  181.         err |= sync_direct (inode, wait);
  182.         err |= sync_indirect (inode,
  183.                       inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
  184.                       wait);
  185.         err |= sync_dindirect (inode,
  186.                        inode->u.ext2_i.i_data+EXT2_DIND_BLOCK, 
  187.                        wait);
  188.         err |= sync_tindirect (inode, 
  189.                        inode->u.ext2_i.i_data+EXT2_TIND_BLOCK, 
  190.                        wait);
  191.     }
  192. skip:
  193.     err |= ext2_sync_inode (inode);
  194.     return (err < 0) ? -EIO : 0;
  195. }
  196.