• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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 
sync_block(struct inode * inode,unsigned short * block,int wait)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
sync_iblock(struct inode * inode,unsigned short * iblock,struct buffer_head ** bh,int wait)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 
sync_direct(struct inode * inode,int wait)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
sync_indirect(struct inode * inode,unsigned short * iblock,int wait)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 
sync_dindirect(struct inode * inode,unsigned short * diblock,int wait)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 
qnx4_sync_file(struct file * file,struct dentry * dentry,int unused)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
170