~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/sysv/fsync.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.