root/fs/ext/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. ext_sync_file

   1 
   2 /*
   3  *  linux/fs/ext/fsync.c
   4  *
   5  *  Copyright (C) 1993  Stephen Tweedie (sct@dcs.ed.ac.uk)
   6  *  from
   7  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
   8  *  from
   9  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
  10  * 
  11  *  extfs fsync primitive
  12  */
  13 
  14 #include <asm/segment.h>
  15 #include <asm/system.h>
  16 
  17 #include <linux/errno.h>
  18 #include <linux/sched.h>
  19 #include <linux/stat.h>
  20 #include <linux/fcntl.h>
  21 #include <linux/locks.h>
  22 
  23 #include <linux/fs.h>
  24 #include <linux/ext_fs.h>
  25 
  26 
  27 #define blocksize BLOCK_SIZE
  28 #define addr_per_block 256
  29 
  30 static int sync_block (struct inode * inode, unsigned long * block, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  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         {
  51                 brelse(bh);
  52                 return 0;
  53         }
  54         ll_rw_block(WRITE, 1, &bh);
  55         bh->b_count--;
  56         return 0;
  57 }
  58 
  59 static int sync_iblock (struct inode * inode, unsigned long * iblock, 
     /* [previous][next][first][last][top][bottom][index][help] */
  60                         struct buffer_head **bh, int wait) 
  61 {
  62         int rc, tmp;
  63         
  64         *bh = NULL;
  65         tmp = *iblock;
  66         if (!tmp)
  67                 return 0;
  68         rc = sync_block (inode, iblock, wait);
  69         if (rc)
  70                 return rc;
  71         *bh = bread(inode->i_dev, tmp, blocksize);
  72         if (tmp != *iblock) {
  73                 brelse(*bh);
  74                 *bh = NULL;
  75                 return 1;
  76         }
  77         if (!*bh)
  78                 return -1;
  79         return 0;
  80 }
  81 
  82 
  83 static int sync_direct(struct inode *inode, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85         int i;
  86         int rc, err = 0;
  87 
  88         for (i = 0; i < 9; i++) {
  89                 rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
  90                 if (rc > 0)
  91                         break;
  92                 if (rc)
  93                         err = rc;
  94         }
  95         return err;
  96 }
  97 
  98 static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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, 
     /* [previous][next][first][last][top][bottom][index][help] */
 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 ext_sync_file(struct inode * inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 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         for (wait=0; wait<=1; wait++)
 177         {
 178                 err |= sync_direct(inode, wait);
 179                 err |= sync_indirect(inode, inode->u.ext_i.i_data+9, wait);
 180                 err |= sync_dindirect(inode, inode->u.ext_i.i_data+10, wait);
 181                 err |= sync_tindirect(inode, inode->u.ext_i.i_data+11, wait);
 182         }
 183         err |= ext_sync_inode (inode);
 184         return (err < 0) ? -EIO : 0;
 185 }

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