root/fs/sysv/fsync.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sync_block
  2. sync_iblock
  3. sync_direct
  4. sync_indirect
  5. sync_dindirect
  6. sync_tindirect
  7. sysv_sync_file

   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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }

/* [previous][next][first][last][top][bottom][index][help] */