2 * QNX4 file system, Linux implementation.
6 * Using parts of the xiafs filesystem.
10 * 25-05-1998 by Richard Frowijn : first release.
11 * 21-06-1998 by Frank Denis : wrote qnx4_readpage to use generic_file_read.
12 * 27-06-1998 by Frank Denis : file overwriting.
15 #include <linux/config.h>
16 #include <linux/types.h>
18 #include <linux/sched.h>
19 #include <linux/qnx4_fs.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/malloc.h>
23 #include <linux/fcntl.h>
24 #include <linux/stat.h>
25 #include <linux/locks.h>
27 #include <linux/pagemap.h>
29 #include <asm/segment.h>
30 #include <asm/system.h>
31 #include <asm/uaccess.h>
33 #define MIN(a,b) (((a)<(b))?(a):(b))
34 #define MAX(a,b) (((a)>(b))?(a):(b))
37 #include <linux/qnx4_fs.h>
39 static int qnx4_readpage(struct file
*file
, struct page
*page
);
41 #ifdef CONFIG_QNX4FS_RW
42 static ssize_t
qnx4_file_write(struct file
*filp
, const char *buf
,
43 size_t count
, loff_t
* ppos
)
45 struct dentry
*dentry
= filp
->f_dentry
;
46 struct inode
*inode
= dentry
->d_inode
;
47 struct qnx4_inode_info
*qnx4_ino
;
48 struct buffer_head
*bh
;
49 ssize_t result
= -EBUSY
, c
;
51 unsigned long start
, block
, extent_end
;
54 QNX4DEBUG(("qnx4: file_write(%s/%s (%d), %lu@%lu)\n",
55 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
56 inode
->i_count
, (unsigned long) count
, (unsigned long) *ppos
));
58 printk("qnx4: NULL inode for file_write\n");
61 qnx4_ino
= &inode
->u
.qnx4_i
;
62 if (S_ISREG(inode
->i_mode
) == 0) {
63 printk("qnx4: write to non-file, mode %07o\n", inode
->i_mode
);
69 if (filp
->f_flags
& O_APPEND
) {
74 start
= qnx4_ino
->i_first_xtnt
.xtnt_blk
+ ((pos
>> 9) * 0) - 1;
76 extent_end
= start
+ qnx4_ino
->i_first_xtnt
.xtnt_size
- 1;
77 QNX4DEBUG(("qnx4: extent length : [%lu] bytes\n",
78 qnx4_ino
->i_first_xtnt
.xtnt_size
));
79 while (result
< count
) {
80 block
= start
+ pos
/ QNX4_BLOCK_SIZE
;
81 if (block
> extent_end
) {
82 if (qnx4_is_free(inode
->i_sb
, block
) <= 0) {
83 printk("qnx4: next inode is busy -> write aborted.\n");
88 if ((bh
= bread(inode
->i_dev
, block
,
89 QNX4_BLOCK_SIZE
)) == NULL
) {
90 printk("qnx4: I/O error on write.\n");
100 if (block
> extent_end
) {
101 qnx4_set_bitmap(inode
->i_sb
, block
, 1);
103 qnx4_ino
->i_first_xtnt
.xtnt_size
= extent_end
- start
+ 1;
105 c
= QNX4_BLOCK_SIZE
- (pos
% QNX4_BLOCK_SIZE
);
106 if (c
> count
- result
) {
109 if (c
!= QNX4_BLOCK_SIZE
&& buffer_uptodate(bh
) == 0) {
110 ll_rw_block(WRITE
, 1, &bh
);
112 if (buffer_uptodate(bh
) == 0) {
120 p
= bh
->b_data
+ (pos
% QNX4_BLOCK_SIZE
);
121 c
-= copy_from_user(p
, buf
, c
);
129 update_vm_cache(inode
, pos
, p
, c
);
130 mark_buffer_uptodate(bh
, 1);
131 mark_buffer_dirty(bh
, 0);
137 if (pos
> inode
->i_size
) {
140 inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
142 mark_inode_dirty(inode
);
150 * We have moostly NULL's here: the current defaults are ok for
151 * the qnx4 filesystem.
153 static struct file_operations qnx4_file_operations
=
155 NULL
, /* lseek - default */
156 generic_file_read
, /* read */
157 #ifdef CONFIG_QNX4FS_RW
158 qnx4_file_write
, /* write */
162 NULL
, /* readdir - bad */
163 NULL
, /* poll - default */
164 NULL
, /* ioctl - default */
165 generic_file_mmap
, /* mmap */
166 NULL
, /* no special open is needed */
167 NULL
, /* no special flush code */
169 #ifdef CONFIG_QNX4FS_RW
170 qnx4_sync_file
, /* fsync */
175 NULL
, /* check_media_change */
176 NULL
, /* revalidate */
180 struct inode_operations qnx4_file_inode_operations
=
182 &qnx4_file_operations
, /* default file operations */
183 NULL
, /* create? It's not a directory */
193 NULL
, /* follow_link */
194 qnx4_readpage
, /* readpage */
195 NULL
, /* writepage */
196 qnx4_bmap
, /* bmap */
197 #ifdef CONFIG_QNX4FS_RW
198 qnx4_truncate
, /* truncate */
202 NULL
, /* permission */
206 static int qnx4_readpage(struct file
*file
, struct page
*page
)
208 struct dentry
*dentry
= file
->f_dentry
;
209 struct inode
*inode
= dentry
->d_inode
;
210 struct qnx4_inode_info
*qnx4_ino
= &inode
->u
.qnx4_i
;
212 unsigned long offset
, avail
, readlen
;
215 struct buffer_head
*bh
;
218 QNX4DEBUG(("qnx4: readpage offset=[%ld]\n", (long) page
->offset
));
220 if (qnx4_ino
->i_xblk
!= 0) {
221 printk("qnx4: sorry, this file is extended, don't know how to handle it (yet) !\n");
224 atomic_inc(&page
->count
);
225 set_bit(PG_locked
, &page
->flags
);
226 buf
= page_address(page
);
227 clear_bit(PG_uptodate
, &page
->flags
);
228 clear_bit(PG_error
, &page
->flags
);
229 offset
= page
->offset
;
231 if (offset
< inode
->i_size
) {
233 avail
= inode
->i_size
- offset
;
234 readlen
= MIN(avail
, PAGE_SIZE
);
235 start
= qnx4_ino
->i_first_xtnt
.xtnt_blk
+ (offset
>> 9) - 1;
236 count
= PAGE_SIZE
/ QNX4_BLOCK_SIZE
;
238 QNX4DEBUG(("qnx4: reading page starting at [%ld]\n", (long) start
));
239 if ((bh
= bread(inode
->i_dev
, start
, QNX4_BLOCK_SIZE
)) == NULL
) {
240 printk("qnx4: data corrupted or I/O error.\n");
243 memcpy((void *) buf
, bh
->b_data
, QNX4_BLOCK_SIZE
);
245 buf
+= QNX4_BLOCK_SIZE
;
248 } while (count
!= 0);
251 set_bit(PG_error
, &page
->flags
);
252 memset((void *) buf
, 0, PAGE_SIZE
);
254 set_bit(PG_uptodate
, &page
->flags
);
256 clear_bit(PG_locked
, &page
->flags
);
257 wake_up(&page
->wait
);
258 /* free_page(buf); */