]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * QNX4 file system, Linux implementation. | |
3 | * | |
4 | * Version : 0.1 | |
5 | * | |
6 | * Using parts of the xiafs filesystem. | |
7 | * | |
8 | * History : | |
9 | * | |
10 | * 24-03-1998 by Richard Frowijn : first release. | |
11 | */ | |
12 | ||
1da177e4 LT |
13 | #include <linux/errno.h> |
14 | #include <linux/time.h> | |
15 | #include <linux/stat.h> | |
16 | #include <linux/fcntl.h> | |
17 | #include <linux/smp_lock.h> | |
18 | #include <linux/buffer_head.h> | |
19 | ||
20 | #include <linux/fs.h> | |
21 | #include <linux/qnx4_fs.h> | |
22 | ||
23 | #include <asm/system.h> | |
24 | ||
25 | /* | |
26 | * The functions for qnx4 fs file synchronization. | |
27 | */ | |
28 | ||
29 | #ifdef CONFIG_QNX4FS_RW | |
30 | ||
31 | static int sync_block(struct inode *inode, unsigned short *block, int wait) | |
32 | { | |
33 | struct buffer_head *bh; | |
34 | unsigned short tmp; | |
35 | ||
36 | if (!*block) | |
37 | return 0; | |
38 | tmp = *block; | |
39 | bh = sb_find_get_block(inode->i_sb, *block); | |
40 | if (!bh) | |
41 | return 0; | |
42 | if (*block != tmp) { | |
43 | brelse(bh); | |
44 | return 1; | |
45 | } | |
46 | if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { | |
47 | brelse(bh); | |
48 | return -1; | |
49 | } | |
50 | if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { | |
51 | brelse(bh); | |
52 | return 0; | |
53 | } | |
54 | ll_rw_block(WRITE, 1, &bh); | |
55 | atomic_dec(&bh->b_count); | |
56 | return 0; | |
57 | } | |
58 | ||
59 | #ifdef WTF | |
60 | static int sync_iblock(struct inode *inode, unsigned short *iblock, | |
61 | struct buffer_head **bh, int wait) | |
62 | { | |
63 | int rc; | |
64 | unsigned short tmp; | |
65 | ||
66 | *bh = NULL; | |
67 | tmp = *iblock; | |
68 | if (!tmp) | |
69 | return 0; | |
70 | rc = sync_block(inode, iblock, wait); | |
71 | if (rc) | |
72 | return rc; | |
73 | *bh = sb_bread(inode->i_sb, tmp); | |
74 | if (tmp != *iblock) { | |
75 | brelse(*bh); | |
76 | *bh = NULL; | |
77 | return 1; | |
78 | } | |
79 | if (!*bh) | |
80 | return -1; | |
81 | return 0; | |
82 | } | |
83 | #endif | |
84 | ||
85 | static int sync_direct(struct inode *inode, int wait) | |
86 | { | |
87 | int i; | |
88 | int rc, err = 0; | |
89 | ||
90 | for (i = 0; i < 7; i++) { | |
91 | rc = sync_block(inode, | |
92 | (unsigned short *) qnx4_raw_inode(inode)->di_first_xtnt.xtnt_blk + i, wait); | |
93 | if (rc > 0) | |
94 | break; | |
95 | if (rc) | |
96 | err = rc; | |
97 | } | |
98 | return err; | |
99 | } | |
100 | ||
101 | #ifdef WTF | |
102 | static int sync_indirect(struct inode *inode, unsigned short *iblock, int wait) | |
103 | { | |
104 | int i; | |
105 | struct buffer_head *ind_bh; | |
106 | int rc, err = 0; | |
107 | ||
108 | rc = sync_iblock(inode, iblock, &ind_bh, wait); | |
109 | if (rc || !ind_bh) | |
110 | return rc; | |
111 | ||
112 | for (i = 0; i < 512; i++) { | |
113 | rc = sync_block(inode, | |
114 | ((unsigned short *) ind_bh->b_data) + i, | |
115 | wait); | |
116 | if (rc > 0) | |
117 | break; | |
118 | if (rc) | |
119 | err = rc; | |
120 | } | |
121 | brelse(ind_bh); | |
122 | return err; | |
123 | } | |
124 | ||
125 | static int sync_dindirect(struct inode *inode, unsigned short *diblock, | |
126 | int wait) | |
127 | { | |
128 | int i; | |
129 | struct buffer_head *dind_bh; | |
130 | int rc, err = 0; | |
131 | ||
132 | rc = sync_iblock(inode, diblock, &dind_bh, wait); | |
133 | if (rc || !dind_bh) | |
134 | return rc; | |
135 | ||
136 | for (i = 0; i < 512; i++) { | |
137 | rc = sync_indirect(inode, | |
138 | ((unsigned short *) dind_bh->b_data) + i, | |
139 | wait); | |
140 | if (rc > 0) | |
141 | break; | |
142 | if (rc) | |
143 | err = rc; | |
144 | } | |
145 | brelse(dind_bh); | |
146 | return err; | |
147 | } | |
148 | #endif | |
149 | ||
150 | int qnx4_sync_file(struct file *file, struct dentry *dentry, int unused) | |
151 | { | |
152 | struct inode *inode = dentry->d_inode; | |
153 | int wait, err = 0; | |
154 | ||
155 | (void) file; | |
156 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | |
157 | S_ISLNK(inode->i_mode))) | |
158 | return -EINVAL; | |
159 | ||
160 | lock_kernel(); | |
161 | for (wait = 0; wait <= 1; wait++) { | |
162 | err |= sync_direct(inode, wait); | |
163 | } | |
164 | err |= qnx4_sync_inode(inode); | |
165 | unlock_kernel(); | |
166 | return (err < 0) ? -EIO : 0; | |
167 | } | |
168 | ||
169 | #endif |