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

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