Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / fs / qnx4 / fsync.c
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