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  *  from
   8  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
   9  * 
  10  *  ext2fs fsync primitive
  11  */
  12 
  13 #include <asm/segment.h>
  14 #include <asm/system.h>
  15 
  16 #include <linux/errno.h>
  17 #include <linux/fs.h>
  18 #include <linux/ext2_fs.h>
  19 #include <linux/fcntl.h>
  20 #include <linux/sched.h>
  21 #include <linux/stat.h>
  22 #include <linux/locks.h>
  23 
  24 
  25 #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
  26 #define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
  27 
  28 static int sync_block (struct inode * inode, unsigned long * block, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  29 {
  30         struct buffer_head * bh;
  31         int tmp;
  32         
  33         if (!*block)
  34                 return 0;
  35         tmp = *block;
  36         bh = get_hash_table (inode->i_dev, *block, blocksize);
  37         if (!bh)
  38                 return 0;
  39         if (*block != tmp) {
  40                 brelse (bh);
  41                 return 1;
  42         }
  43         if (wait && bh->b_req && !bh->b_uptodate) {
  44                 brelse (bh);
  45                 return -1;
  46         }
  47         if (wait || !bh->b_uptodate || !bh->b_dirt) {
  48                 brelse (bh);
  49                 return 0;
  50         }
  51         ll_rw_block (WRITE, 1, &bh);
  52         bh->b_count--;
  53         return 0;
  54 }
  55 
  56 static int sync_iblock (struct inode * inode, unsigned long * iblock, 
     /* [previous][next][first][last][top][bottom][index][help] */
  57                         struct buffer_head ** bh, int wait) 
  58 {
  59         int rc, tmp;
  60         
  61         *bh = NULL;
  62         tmp = *iblock;
  63         if (!tmp)
  64                 return 0;
  65         rc = sync_block (inode, iblock, wait);
  66         if (rc)
  67                 return rc;
  68         *bh = bread (inode->i_dev, tmp, blocksize);
  69         if (tmp != *iblock) {
  70                 brelse (*bh);
  71                 *bh = NULL;
  72                 return 1;
  73         }
  74         if (!*bh)
  75                 return -1;
  76         return 0;
  77 }
  78 
  79 
  80 static int sync_direct (struct inode * inode, int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82         int i;
  83         int rc, err = 0;
  84 
  85         for (i = 0; i < EXT2_NDIR_BLOCKS; i++) {
  86                 rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait);
  87                 if (rc > 0)
  88                         break;
  89                 if (rc)
  90                         err = rc;
  91         }
  92         return err;
  93 }
  94 
  95 static int sync_indirect (struct inode * inode, unsigned long * iblock,
     /* [previous][next][first][last][top][bottom][index][help] */
  96                           int wait)
  97 {
  98         int i;
  99         struct buffer_head * ind_bh;
 100         int rc, err = 0;
 101 
 102         rc = sync_iblock (inode, iblock, &ind_bh, wait);
 103         if (rc || !ind_bh)
 104                 return rc;
 105         
 106         for (i = 0; i < addr_per_block; i++) {
 107                 rc = sync_block (inode, 
 108                                  ((unsigned long *) ind_bh->b_data) + i,
 109                                  wait);
 110                 if (rc > 0)
 111                         break;
 112                 if (rc)
 113                         err = rc;
 114         }
 115         brelse (ind_bh);
 116         return err;
 117 }
 118 
 119 static int sync_dindirect (struct inode * inode, unsigned long * diblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 120                            int wait)
 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                                     ((unsigned long *) 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, unsigned long * tiblock, 
     /* [previous][next][first][last][top][bottom][index][help] */
 144                            int wait)
 145 {
 146         int i;
 147         struct buffer_head * tind_bh;
 148         int rc, err = 0;
 149 
 150         rc = sync_iblock (inode, tiblock, &tind_bh, wait);
 151         if (rc || !tind_bh)
 152                 return rc;
 153         
 154         for (i = 0; i < addr_per_block; i++) {
 155                 rc = sync_dindirect (inode,
 156                                      ((unsigned long *) tind_bh->b_data) + i,
 157                                      wait);
 158                 if (rc > 0)
 159                         break;
 160                 if (rc)
 161                         err = rc;
 162         }
 163         brelse (tind_bh);
 164         return err;
 165 }
 166 
 167 int ext2_sync_file (struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169         int wait, err = 0;
 170 
 171         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 172              S_ISLNK(inode->i_mode)))
 173                 return -EINVAL;
 174         /* Don't sync fast links! */
 175         if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
 176                 goto skip;
 177 
 178         for (wait=0; wait<=1; wait++)
 179         {
 180                 err |= sync_direct (inode, wait);
 181                 err |= sync_indirect (inode,
 182                                       inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
 183                                       wait);
 184                 err |= sync_dindirect (inode,
 185                                        inode->u.ext2_i.i_data+EXT2_DIND_BLOCK, 
 186                                        wait);
 187                 err |= sync_tindirect (inode, 
 188                                        inode->u.ext2_i.i_data+EXT2_TIND_BLOCK, 
 189                                        wait);
 190         }
 191 skip:
 192         err |= ext2_sync_inode (inode);
 193         return (err < 0) ? -EIO : 0;
 194 }

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