root/fs/ext2/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. ext2_sync_file

   1 /*
   2  *  linux/fs/ext2/fsync.c
   3  *
   4  *  Copyright (C) 1993  Stephen Tweedie (sct@dcs.ed.ac.uk)
   5  *  from
   6  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
   7  *                      Laboratoire MASI - Institut Blaise Pascal
   8  *                      Universite Pierre et Marie Curie (Paris VI)
   9  *  from
  10  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
  11  * 
  12  *  ext2fs fsync primitive
  13  */
  14 
  15 #include <asm/segment.h>
  16 #include <asm/system.h>
  17 
  18 #include <linux/errno.h>
  19 #include <linux/fs.h>
  20 #include <linux/ext2_fs.h>
  21 #include <linux/fcntl.h>
  22 #include <linux/sched.h>
  23 #include <linux/stat.h>
  24 #include <linux/locks.h>
  25 
  26 
  27 #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
  28 #define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
  29 
  30 static int sync_block (struct inode * inode, u32 * 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 && buffer_req(bh) && !buffer_uptodate(bh)) {
  46                 brelse (bh);
  47                 return -1;
  48         }
  49         if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
  50                 brelse (bh);
  51                 return 0;
  52         }
  53         ll_rw_block (WRITE, 1, &bh);
  54         bh->b_count--;
  55         return 0;
  56 }
  57 
  58 static int sync_iblock (struct inode * inode, u32 * iblock, 
     /* [previous][next][first][last][top][bottom][index][help] */
  59                         struct buffer_head ** bh, int wait) 
  60 {
  61         int rc, tmp;
  62         
  63         *bh = NULL;
  64         tmp = *iblock;
  65         if (!tmp)
  66                 return 0;
  67         rc = sync_block (inode, iblock, wait);
  68         if (rc)
  69                 return rc;
  70         *bh = bread (inode->i_dev, tmp, blocksize);
  71         if (tmp != *iblock) {
  72                 brelse (*bh);
  73                 *bh = NULL;
  74                 return 1;
  75         }
  76         if (!*bh)
  77                 return -1;
  78         return 0;
  79 }
  80 
  81 
  82 static int sync_direct (struct inode * inode, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  83 {
  84         int i;
  85         int rc, err = 0;
  86 
  87         for (i = 0; i < EXT2_NDIR_BLOCKS; i++) {
  88                 rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait);
  89                 if (rc > 0)
  90                         break;
  91                 if (rc)
  92                         err = rc;
  93         }
  94         return err;
  95 }
  96 
  97 static int sync_indirect (struct inode * inode, u32 * iblock, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99         int i;
 100         struct buffer_head * ind_bh;
 101         int rc, err = 0;
 102 
 103         rc = sync_iblock (inode, iblock, &ind_bh, wait);
 104         if (rc || !ind_bh)
 105                 return rc;
 106         
 107         for (i = 0; i < addr_per_block; i++) {
 108                 rc = sync_block (inode, 
 109                                  ((u32 *) ind_bh->b_data) + i,
 110                                  wait);
 111                 if (rc > 0)
 112                         break;
 113                 if (rc)
 114                         err = rc;
 115         }
 116         brelse (ind_bh);
 117         return err;
 118 }
 119 
 120 static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122         int i;
 123         struct buffer_head * dind_bh;
 124         int rc, err = 0;
 125 
 126         rc = sync_iblock (inode, diblock, &dind_bh, wait);
 127         if (rc || !dind_bh)
 128                 return rc;
 129         
 130         for (i = 0; i < addr_per_block; i++) {
 131                 rc = sync_indirect (inode,
 132                                     ((u32 *) dind_bh->b_data) + i,
 133                                     wait);
 134                 if (rc > 0)
 135                         break;
 136                 if (rc)
 137                         err = rc;
 138         }
 139         brelse (dind_bh);
 140         return err;
 141 }
 142 
 143 static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145         int i;
 146         struct buffer_head * tind_bh;
 147         int rc, err = 0;
 148 
 149         rc = sync_iblock (inode, tiblock, &tind_bh, wait);
 150         if (rc || !tind_bh)
 151                 return rc;
 152         
 153         for (i = 0; i < addr_per_block; i++) {
 154                 rc = sync_dindirect (inode,
 155                                      ((u32 *) tind_bh->b_data) + i,
 156                                      wait);
 157                 if (rc > 0)
 158                         break;
 159                 if (rc)
 160                         err = rc;
 161         }
 162         brelse (tind_bh);
 163         return err;
 164 }
 165 
 166 int ext2_sync_file (struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         int wait, err = 0;
 169 
 170         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 171              S_ISLNK(inode->i_mode)))
 172                 return -EINVAL;
 173         if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
 174                 /*
 175                  * Don't sync fast links!
 176                  */
 177                 goto skip;
 178 
 179         for (wait=0; wait<=1; wait++)
 180         {
 181                 err |= sync_direct (inode, wait);
 182                 err |= sync_indirect (inode,
 183                                       inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
 184                                       wait);
 185                 err |= sync_dindirect (inode,
 186                                        inode->u.ext2_i.i_data+EXT2_DIND_BLOCK, 
 187                                        wait);
 188                 err |= sync_tindirect (inode, 
 189                                        inode->u.ext2_i.i_data+EXT2_TIND_BLOCK, 
 190                                        wait);
 191         }
 192 skip:
 193         err |= ext2_sync_inode (inode);
 194         return (err < 0) ? -EIO : 0;
 195 }

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