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 = sv_get_hash_table(sb, inode->i_dev, block);
  42         if (!bh)
  43                 return 0;
  44         if (*blockp != tmp) {
  45                 brelse (bh);
  46                 return 1;
  47         }
  48         if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
  49                 brelse(bh);
  50                 return -1;
  51         }
  52         if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
  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, 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 = sv_bread(inode->i_sb, inode->i_dev, block);
  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         int rc, err = 0;
 109         struct super_block * sb;
 110 
 111         rc = sync_iblock (inode, iblockp, convert, &ind_bh, wait);
 112         if (rc || !ind_bh)
 113                 return rc;
 114 
 115         sb = inode->i_sb;
 116         for (i = 0; i < sb->sv_ind_per_block; i++) {
 117                 rc = sync_block (inode,
 118                                  ((unsigned long *) ind_bh->b_data) + i, sb->sv_convert,
 119                                  wait);
 120                 if (rc > 0)
 121                         break;
 122                 if (rc)
 123                         err = rc;
 124         }
 125         brelse(ind_bh);
 126         return err;
 127 }
 128 
 129 static int sync_dindirect(struct inode *inode, unsigned long *diblockp, int convert,
     /* [previous][next][first][last][top][bottom][index][help] */
 130                           int wait)
 131 {
 132         int i;
 133         struct buffer_head * dind_bh;
 134         int rc, err = 0;
 135         struct super_block * sb;
 136 
 137         rc = sync_iblock (inode, diblockp, convert, &dind_bh, wait);
 138         if (rc || !dind_bh)
 139                 return rc;
 140 
 141         sb = inode->i_sb;
 142         for (i = 0; i < sb->sv_ind_per_block; i++) {
 143                 rc = sync_indirect (inode,
 144                                     ((unsigned long *) dind_bh->b_data) + i, sb->sv_convert,
 145                                     wait);
 146                 if (rc > 0)
 147                         break;
 148                 if (rc)
 149                         err = rc;
 150         }
 151         brelse(dind_bh);
 152         return err;
 153 }
 154 
 155 static int sync_tindirect(struct inode *inode, unsigned long *tiblockp, int convert,
     /* [previous][next][first][last][top][bottom][index][help] */
 156                           int wait)
 157 {
 158         int i;
 159         struct buffer_head * tind_bh;
 160         int rc, err = 0;
 161         struct super_block * sb;
 162 
 163         rc = sync_iblock (inode, tiblockp, convert, &tind_bh, wait);
 164         if (rc || !tind_bh)
 165                 return rc;
 166 
 167         sb = inode->i_sb;
 168         for (i = 0; i < sb->sv_ind_per_block; i++) {
 169                 rc = sync_dindirect (inode,
 170                                      ((unsigned long *) tind_bh->b_data) + i, sb->sv_convert,
 171                                      wait);
 172                 if (rc > 0)
 173                         break;
 174                 if (rc)
 175                         err = rc;
 176         }
 177         brelse(tind_bh);
 178         return err;
 179 }
 180 
 181 int sysv_sync_file(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183         int wait, err = 0;
 184 
 185         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 186              S_ISLNK(inode->i_mode)))
 187                 return -EINVAL;
 188 
 189         for (wait=0; wait<=1; wait++) {
 190                 err |= sync_direct(inode, wait);
 191                 err |= sync_indirect(inode, inode->u.sysv_i.i_data+10, 0, wait);
 192                 err |= sync_dindirect(inode, inode->u.sysv_i.i_data+11, 0, wait);
 193                 err |= sync_tindirect(inode, inode->u.sysv_i.i_data+12, 0, wait);
 194         }
 195         err |= sysv_sync_inode (inode);
 196         return (err < 0) ? -EIO : 0;
 197 }

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