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 / ext2 / fsync.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-31  |  3.9 KB  |  199 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, 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.         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, unsigned long * 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, unsigned long * iblock,
  98.               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 ext2_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.     if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
  177.         /*
  178.          * Don't sync fast links!
  179.          */
  180.         goto skip;
  181.  
  182.     for (wait=0; wait<=1; wait++)
  183.     {
  184.         err |= sync_direct (inode, wait);
  185.         err |= sync_indirect (inode,
  186.                       inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
  187.                       wait);
  188.         err |= sync_dindirect (inode,
  189.                        inode->u.ext2_i.i_data+EXT2_DIND_BLOCK, 
  190.                        wait);
  191.         err |= sync_tindirect (inode, 
  192.                        inode->u.ext2_i.i_data+EXT2_TIND_BLOCK, 
  193.                        wait);
  194.     }
  195. skip:
  196.     err |= ext2_sync_inode (inode);
  197.     return (err < 0) ? -EIO : 0;
  198. }
  199.