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 / sysv / fsync.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-20  |  4.3 KB  |  201 lines

  1. /*
  2.  *  linux/fs/sysv/fsync.c
  3.  *
  4.  *  minix/fsync.c
  5.  *  Copyright (C) 1991, 1992  Linus Torvalds
  6.  *  Copyright (C) 1993  Stephen Tweedie (sct@dcs.ed.ac.uk)
  7.  *
  8.  *  coh/fsync.c
  9.  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
  10.  *
  11.  *  sysv/fsync.c
  12.  *  Copyright (C) 1993  Bruno Haible
  13.  *
  14.  *  SystemV/Coherent fsync primitive
  15.  */
  16.  
  17. #include <linux/errno.h>
  18. #include <linux/stat.h>
  19.  
  20. #include <linux/fs.h>
  21. #include <linux/sysv_fs.h>
  22.  
  23.  
  24. /* return values: 0 means OK/done, 1 means redo, -1 means I/O error. */
  25.  
  26. /* Sync one block. The block number is
  27.  * from_coh_ulong(*blockp) if convert=1, *blockp if convert=0.
  28.  */
  29. static int sync_block (struct inode * inode, unsigned long * blockp, int convert, int wait)
  30. {
  31.     struct buffer_head * bh;
  32.     unsigned long tmp, block;
  33.     struct super_block * sb;
  34.  
  35.     block = tmp = *blockp;
  36.     if (convert)
  37.         block = from_coh_ulong(block);
  38.     if (!block)
  39.         return 0;
  40.     sb = inode->i_sb;
  41.     bh = get_hash_table(inode->i_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
  42.     if (!bh)
  43.         return 0;
  44.     if (*blockp != tmp) {
  45.         brelse (bh);
  46.         return 1;
  47.     }
  48.     if (wait && bh->b_req && !bh->b_uptodate) {
  49.         brelse(bh);
  50.         return -1;
  51.     }
  52.     if (wait || !bh->b_uptodate || !bh->b_dirt) {
  53.         brelse(bh);
  54.         return 0;
  55.     }
  56.     ll_rw_block(WRITE, 1, &bh);
  57.     bh->b_count--;
  58.     return 0;
  59. }
  60.  
  61. /* Sync one block full of indirect pointers and read it because we'll need it. */
  62. static int sync_iblock (struct inode * inode, unsigned long * iblockp, int convert,
  63.             struct buffer_head * *bh, char * *bh_data, int wait)
  64. {
  65.     int rc;
  66.     unsigned long tmp, block;
  67.  
  68.     *bh = NULL;
  69.     block = tmp = *iblockp;
  70.     if (convert)
  71.         block = from_coh_ulong(block);
  72.     if (!block)
  73.         return 0;
  74.     rc = sync_block (inode, iblockp, convert, wait);
  75.     if (rc)
  76.         return rc;
  77.     *bh = sysv_bread(inode->i_sb, inode->i_dev, block, bh_data);
  78.     if (tmp != *iblockp) {
  79.         brelse(*bh);
  80.         *bh = NULL;
  81.         return 1;
  82.     }
  83.     if (!*bh)
  84.         return -1;
  85.     return 0;
  86. }
  87.  
  88.  
  89. static int sync_direct(struct inode *inode, int wait)
  90. {
  91.     int i;
  92.     int rc, err = 0;
  93.  
  94.     for (i = 0; i < 10; i++) {
  95.         rc = sync_block (inode, inode->u.sysv_i.i_data + i, 0, wait);
  96.         if (rc > 0)
  97.             break;
  98.         if (rc)
  99.             err = rc;
  100.     }
  101.     return err;
  102. }
  103.  
  104. static int sync_indirect(struct inode *inode, unsigned long *iblockp, int convert, int wait)
  105. {
  106.     int i;
  107.     struct buffer_head * ind_bh;
  108.     char * ind_bh_data;
  109.     int rc, err = 0;
  110.     struct super_block * sb;
  111.  
  112.     rc = sync_iblock (inode, iblockp, convert, &ind_bh, &ind_bh_data, wait);
  113.     if (rc || !ind_bh)
  114.         return rc;
  115.  
  116.     sb = inode->i_sb;
  117.     for (i = 0; i < sb->sv_ind_per_block; i++) {
  118.         rc = sync_block (inode,
  119.                  ((unsigned long *) ind_bh_data) + i, sb->sv_convert,
  120.                  wait);
  121.         if (rc > 0)
  122.             break;
  123.         if (rc)
  124.             err = rc;
  125.     }
  126.     brelse(ind_bh);
  127.     return err;
  128. }
  129.  
  130. static int sync_dindirect(struct inode *inode, unsigned long *diblockp, int convert,
  131.               int wait)
  132. {
  133.     int i;
  134.     struct buffer_head * dind_bh;
  135.     char * dind_bh_data;
  136.     int rc, err = 0;
  137.     struct super_block * sb;
  138.  
  139.     rc = sync_iblock (inode, diblockp, convert, &dind_bh, &dind_bh_data, wait);
  140.     if (rc || !dind_bh)
  141.         return rc;
  142.  
  143.     sb = inode->i_sb;
  144.     for (i = 0; i < sb->sv_ind_per_block; i++) {
  145.         rc = sync_indirect (inode,
  146.                     ((unsigned long *) dind_bh_data) + i, sb->sv_convert,
  147.                     wait);
  148.         if (rc > 0)
  149.             break;
  150.         if (rc)
  151.             err = rc;
  152.     }
  153.     brelse(dind_bh);
  154.     return err;
  155. }
  156.  
  157. static int sync_tindirect(struct inode *inode, unsigned long *tiblockp, int convert,
  158.               int wait)
  159. {
  160.     int i;
  161.     struct buffer_head * tind_bh;
  162.     char * tind_bh_data;
  163.     int rc, err = 0;
  164.     struct super_block * sb;
  165.  
  166.     rc = sync_iblock (inode, tiblockp, convert, &tind_bh, &tind_bh_data, wait);
  167.     if (rc || !tind_bh)
  168.         return rc;
  169.  
  170.     sb = inode->i_sb;
  171.     for (i = 0; i < sb->sv_ind_per_block; i++) {
  172.         rc = sync_dindirect (inode,
  173.                      ((unsigned long *) tind_bh_data) + i, sb->sv_convert,
  174.                      wait);
  175.         if (rc > 0)
  176.             break;
  177.         if (rc)
  178.             err = rc;
  179.     }
  180.     brelse(tind_bh);
  181.     return err;
  182. }
  183.  
  184. int sysv_sync_file(struct inode * inode, struct file * file)
  185. {
  186.     int wait, err = 0;
  187.  
  188.     if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
  189.          S_ISLNK(inode->i_mode)))
  190.         return -EINVAL;
  191.  
  192.     for (wait=0; wait<=1; wait++) {
  193.         err |= sync_direct(inode, wait);
  194.         err |= sync_indirect(inode, inode->u.sysv_i.i_data+10, 0, wait);
  195.         err |= sync_dindirect(inode, inode->u.sysv_i.i_data+11, 0, wait);
  196.         err |= sync_tindirect(inode, inode->u.sysv_i.i_data+12, 0, wait);
  197.     }
  198.     err |= sysv_sync_inode (inode);
  199.     return (err < 0) ? -EIO : 0;
  200. }
  201.