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