OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [ext2/] [fsync.c] - Blame information for rev 1628

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
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
 *  Big-endian to little-endian byte-swapping/bitmaps by
15
 *        David S. Miller (davem@caip.rutgers.edu), 1995
16
 *
17
 *  Fast 'fsync' on large files (Scott Laird <laird@pacificrim.net>)
18
 */
19
 
20
#include <asm/segment.h>
21
#include <asm/system.h>
22
 
23
#include <linux/errno.h>
24
#include <linux/fs.h>
25
#include <linux/ext2_fs.h>
26
#include <linux/fcntl.h>
27
#include <linux/sched.h>
28
#include <linux/stat.h>
29
#include <linux/locks.h>
30
 
31
 
32
#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
33
#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
34
 
35
static __inline__ int sync_block (struct inode * inode, u32 * block, int wait)
36
{
37
        struct buffer_head * bh;
38
        int tmp;
39
 
40
        if (!*block)
41
                return 0;
42
        tmp = *block;
43
        bh = get_hash_table (inode->i_dev, *block, blocksize);
44
        if (!bh)
45
                return 0;
46
        if (*block != tmp) {
47
                brelse (bh);
48
                return 1;
49
        }
50
        if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
51
                brelse (bh);
52
                return -1;
53
        }
54
        if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
55
                brelse (bh);
56
                return 0;
57
        }
58
        ll_rw_block (WRITE, 1, &bh);
59
        bh->b_count--;
60
        return 0;
61
}
62
 
63
static __inline__ int sync_block_swab32 (struct inode * inode, u32 * block, int wait)
64
{
65
        struct buffer_head * bh;
66
        int tmp;
67
 
68
        if (!swab32(*block))
69
                return 0;
70
        tmp = swab32(*block);
71
        bh = get_hash_table (inode->i_dev, swab32(*block), blocksize);
72
        if (!bh)
73
                return 0;
74
        if (swab32(*block) != tmp) {
75
                brelse (bh);
76
                return 1;
77
        }
78
        if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
79
                brelse (bh);
80
                return -1;
81
        }
82
        if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
83
                brelse (bh);
84
                return 0;
85
        }
86
        ll_rw_block (WRITE, 1, &bh);
87
        bh->b_count--;
88
        return 0;
89
}
90
 
91
static __inline__ int sync_iblock (struct inode * inode, u32 * iblock,
92
                        struct buffer_head ** bh, int wait)
93
{
94
        int rc, tmp;
95
 
96
        *bh = NULL;
97
        tmp = *iblock;
98
        if (!tmp)
99
                return 0;
100
        rc = sync_block (inode, iblock, wait);
101
        if (rc)
102
                return rc;
103
        *bh = bread (inode->i_dev, tmp, blocksize);
104
        if (tmp != *iblock) {
105
                brelse (*bh);
106
                *bh = NULL;
107
                return 1;
108
        }
109
        if (!*bh)
110
                return -1;
111
        return 0;
112
}
113
 
114
static __inline__ int sync_iblock_swab32 (struct inode * inode, u32 * iblock,
115
                               struct buffer_head ** bh, int wait)
116
{
117
        int rc, tmp;
118
 
119
        *bh = NULL;
120
        tmp = swab32(*iblock);
121
        if (!tmp)
122
                return 0;
123
        rc = sync_block_swab32 (inode, iblock, wait);
124
        if (rc)
125
                return rc;
126
        *bh = bread (inode->i_dev, tmp, blocksize);
127
        if (tmp != swab32(*iblock)) {
128
                brelse (*bh);
129
                *bh = NULL;
130
                return 1;
131
        }
132
        if (!*bh)
133
                return -1;
134
        return 0;
135
}
136
 
137
 
138
static __inline__ int sync_direct (struct inode * inode, int wait)
139
{
140
        int i;
141
        int rc, err = 0;
142
 
143
        for (i = 0; i < EXT2_NDIR_BLOCKS; i++) {
144
                rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait);
145
                if (rc > 0)
146
                        break;
147
                if (rc)
148
                        err = rc;
149
        }
150
        return err;
151
}
152
 
153
static __inline__ int sync_indirect (struct inode * inode, u32 * iblock, int wait)
154
{
155
        int i;
156
        struct buffer_head * ind_bh;
157
        int rc, err = 0;
158
 
159
        rc = sync_iblock (inode, iblock, &ind_bh, wait);
160
        if (rc || !ind_bh)
161
                return rc;
162
 
163
        for (i = 0; i < addr_per_block; i++) {
164
                rc = sync_block_swab32 (inode,
165
                                        ((u32 *) ind_bh->b_data) + i,
166
                                        wait);
167
                if (rc > 0)
168
                        break;
169
                if (rc)
170
                        err = rc;
171
        }
172
        brelse (ind_bh);
173
        return err;
174
}
175
 
176
static __inline__ int sync_indirect_swab32 (struct inode * inode, u32 * iblock, int wait)
177
{
178
        int i;
179
        struct buffer_head * ind_bh;
180
        int rc, err = 0;
181
 
182
        rc = sync_iblock_swab32 (inode, iblock, &ind_bh, wait);
183
        if (rc || !ind_bh)
184
                return rc;
185
 
186
        for (i = 0; i < addr_per_block; i++) {
187
                rc = sync_block_swab32 (inode,
188
                                        ((u32 *) ind_bh->b_data) + i,
189
                                        wait);
190
                if (rc > 0)
191
                        break;
192
                if (rc)
193
                        err = rc;
194
        }
195
        brelse (ind_bh);
196
        return err;
197
}
198
 
199
static __inline__ int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
200
{
201
        int i;
202
        struct buffer_head * dind_bh;
203
        int rc, err = 0;
204
 
205
        rc = sync_iblock (inode, diblock, &dind_bh, wait);
206
        if (rc || !dind_bh)
207
                return rc;
208
 
209
        for (i = 0; i < addr_per_block; i++) {
210
                rc = sync_indirect_swab32 (inode,
211
                                           ((u32 *) dind_bh->b_data) + i,
212
                                           wait);
213
                if (rc > 0)
214
                        break;
215
                if (rc)
216
                        err = rc;
217
        }
218
        brelse (dind_bh);
219
        return err;
220
}
221
 
222
static __inline__ int sync_dindirect_swab32 (struct inode * inode, u32 * diblock, int wait)
223
{
224
        int i;
225
        struct buffer_head * dind_bh;
226
        int rc, err = 0;
227
 
228
        rc = sync_iblock_swab32 (inode, diblock, &dind_bh, wait);
229
        if (rc || !dind_bh)
230
                return rc;
231
 
232
        for (i = 0; i < addr_per_block; i++) {
233
                rc = sync_indirect_swab32 (inode,
234
                                           ((u32 *) dind_bh->b_data) + i,
235
                                           wait);
236
                if (rc > 0)
237
                        break;
238
                if (rc)
239
                        err = rc;
240
        }
241
        brelse (dind_bh);
242
        return err;
243
}
244
 
245
static __inline__ int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
246
{
247
        int i;
248
        struct buffer_head * tind_bh;
249
        int rc, err = 0;
250
 
251
        rc = sync_iblock (inode, tiblock, &tind_bh, wait);
252
        if (rc || !tind_bh)
253
                return rc;
254
 
255
        for (i = 0; i < addr_per_block; i++) {
256
                rc = sync_dindirect_swab32 (inode,
257
                                            ((u32 *) tind_bh->b_data) + i,
258
                                            wait);
259
                if (rc > 0)
260
                        break;
261
                if (rc)
262
                        err = rc;
263
        }
264
        brelse (tind_bh);
265
        return err;
266
}
267
 
268
int ext2_sync_file (struct inode * inode, struct file * file)
269
{
270
        int wait, err = 0;
271
 
272
        if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
273
                /*
274
                 * Don't sync fast links!
275
                 */
276
                goto skip;
277
 
278
        /* fsync on large files is *slow*, so fall back to sync() if
279
         * the file's over 10M */
280
        if (inode->i_size>10000000) {
281
                file_fsync(inode,file);
282
                goto skip;
283
        }
284
 
285
        for (wait=0; wait<=1; wait++)
286
        {
287
                err |= sync_direct (inode, wait);
288
                err |= sync_indirect (inode,
289
                                      inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
290
                                      wait);
291
                err |= sync_dindirect (inode,
292
                                       inode->u.ext2_i.i_data+EXT2_DIND_BLOCK,
293
                                       wait);
294
                err |= sync_tindirect (inode,
295
                                       inode->u.ext2_i.i_data+EXT2_TIND_BLOCK,
296
                                       wait);
297
        }
298
skip:
299
        err |= ext2_sync_inode (inode);
300
        return (err < 0) ? -EIO : 0;
301
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.