diff options
Diffstat (limited to 'fs/qnx4/fsync.c')
-rw-r--r-- | fs/qnx4/fsync.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/fs/qnx4/fsync.c b/fs/qnx4/fsync.c new file mode 100644 index 000000000000..df5bc75d5414 --- /dev/null +++ b/fs/qnx4/fsync.c | |||
@@ -0,0 +1,170 @@ | |||
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 | ||