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

Subversion Repositories or1k_old

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
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
 
20
#include <linux/fs.h>
21
#include <linux/sysv_fs.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, unsigned long * blockp, int convert, int wait)
30
{
31
        struct buffer_head * bh;
32
        unsigned long 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
        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, unsigned long * iblockp, int convert,
63
                        struct buffer_head * *bh, int wait)
64
{
65
        int rc;
66
        unsigned long 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, unsigned long *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
                                 ((unsigned long *) 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, unsigned long *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
                                    ((unsigned long *) 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, unsigned long *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
                                     ((unsigned long *) 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 inode * inode, struct file * file)
182
{
183
        int wait, err = 0;
184
 
185
        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
186
             S_ISLNK(inode->i_mode)))
187
                return -EINVAL;
188
 
189
        for (wait=0; wait<=1; wait++) {
190
                err |= sync_direct(inode, wait);
191
                err |= sync_indirect(inode, inode->u.sysv_i.i_data+10, 0, wait);
192
                err |= sync_dindirect(inode, inode->u.sysv_i.i_data+11, 0, wait);
193
                err |= sync_tindirect(inode, inode->u.sysv_i.i_data+12, 0, wait);
194
        }
195
        err |= sysv_sync_inode (inode);
196
        return (err < 0) ? -EIO : 0;
197
}

powered by: WebSVN 2.1.0

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