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/tty.h>
  20 #include <linux/stat.h>
  21 #include <linux/fcntl.h>
  22 #include <linux/locks.h>
  23 
  24 #include <linux/fs.h>
  25 #include <linux/ext_fs.h>
  26 
  27 
  28 #define blocksize BLOCK_SIZE
  29 #define addr_per_block 256
  30 
  31 static int sync_block (struct inode * inode, unsigned long * block, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33         struct buffer_head * bh;
  34         int tmp;
  35         
  36         if (!*block)
  37                 return 0;
  38         tmp = *block;
  39         bh = get_hash_table(inode->i_dev, *block, blocksize);
  40         if (!bh)
  41                 return 0;
  42         if (*block != tmp) {
  43                 brelse (bh);
  44                 return 1;
  45         }
  46         if (wait && bh->b_req && !bh->b_uptodate) {
  47                 brelse(bh);
  48                 return -1;
  49         }
  50         if (wait || !bh->b_uptodate || !bh->b_dirt)
  51         {
  52                 brelse(bh);
  53                 return 0;
  54         }
  55         ll_rw_block(WRITE, 1, &bh);
  56         bh->b_count--;
  57         return 0;
  58 }
  59 
  60 static int sync_iblock (struct inode * inode, unsigned long * iblock, 
     /* [previous][next][first][last][top][bottom][index][help] */
  61                         struct buffer_head **bh, int wait) 
  62 {
  63         int rc, tmp;
  64         
  65         *bh = NULL;
  66         tmp = *iblock;
  67         if (!tmp)
  68                 return 0;
  69         rc = sync_block (inode, iblock, wait);
  70         if (rc)
  71                 return rc;
  72         *bh = bread(inode->i_dev, tmp, blocksize);
  73         if (tmp != *iblock) {
  74                 brelse(*bh);
  75                 *bh = NULL;
  76                 return 1;
  77         }
  78         if (!*bh)
  79                 return -1;
  80         return 0;
  81 }
  82 
  83 
  84 static int sync_direct(struct inode *inode, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         int i;
  87         int rc, err = 0;
  88 
  89         for (i = 0; i < 9; i++) {
  90                 rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
  91                 if (rc > 0)
  92                         break;
  93                 if (rc)
  94                         err = rc;
  95         }
  96         return err;
  97 }
  98 
  99 static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 100 {
 101         int i;
 102         struct buffer_head * ind_bh;
 103         int rc, err = 0;
 104 
 105         rc = sync_iblock (inode, iblock, &ind_bh, wait);
 106         if (rc || !ind_bh)
 107                 return rc;
 108         
 109         for (i = 0; i < addr_per_block; i++) {
 110                 rc = sync_block (inode, 
 111                                  ((unsigned long *) ind_bh->b_data) + i,
 112                                  wait);
 113                 if (rc > 0)
 114                         break;
 115                 if (rc)
 116                         err = rc;
 117         }
 118         brelse(ind_bh);
 119         return err;
 120 }
 121 
 122 static int sync_dindirect(struct inode *inode, unsigned long *diblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 123                           int wait)
 124 {
 125         int i;
 126         struct buffer_head * dind_bh;
 127         int rc, err = 0;
 128 
 129         rc = sync_iblock (inode, diblock, &dind_bh, wait);
 130         if (rc || !dind_bh)
 131                 return rc;
 132         
 133         for (i = 0; i < addr_per_block; i++) {
 134                 rc = sync_indirect (inode,
 135                                     ((unsigned long *) dind_bh->b_data) + i,
 136                                     wait);
 137                 if (rc > 0)
 138                         break;
 139                 if (rc)
 140                         err = rc;
 141         }
 142         brelse(dind_bh);
 143         return err;
 144 }
 145 
 146 static int sync_tindirect(struct inode *inode, unsigned long *tiblock, 
     /* [previous][next][first][last][top][bottom][index][help] */
 147                           int wait)
 148 {
 149         int i;
 150         struct buffer_head * tind_bh;
 151         int rc, err = 0;
 152 
 153         rc = sync_iblock (inode, tiblock, &tind_bh, wait);
 154         if (rc || !tind_bh)
 155                 return rc;
 156         
 157         for (i = 0; i < addr_per_block; i++) {
 158                 rc = sync_dindirect (inode,
 159                                      ((unsigned long *) tind_bh->b_data) + i,
 160                                      wait);
 161                 if (rc > 0)
 162                         break;
 163                 if (rc)
 164                         err = rc;
 165         }
 166         brelse(tind_bh);
 167         return err;
 168 }
 169 
 170 int ext_sync_file(struct inode * inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         int wait, err = 0;
 173 
 174         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 175              S_ISLNK(inode->i_mode)))
 176                 return -EINVAL;
 177         for (wait=0; wait<=1; wait++)
 178         {
 179                 err |= sync_direct(inode, wait);
 180                 err |= sync_indirect(inode, inode->u.ext_i.i_data+9, wait);
 181                 err |= sync_dindirect(inode, inode->u.ext_i.i_data+10, wait);
 182                 err |= sync_tindirect(inode, inode->u.ext_i.i_data+11, wait);
 183         }
 184         err |= ext_sync_inode (inode);
 185         return (err < 0) ? -EIO : 0;
 186 }

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