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