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 static int qnx4_readpage(struct file
*file
, struct page
*page
);
39 #ifdef CONFIG_QNX4FS_RW
40 static ssize_t
qnx4_file_write(struct file
*filp
, const char *buf
,
41 size_t count
, loff_t
* ppos
)
43 struct dentry
*dentry
= filp
->f_dentry
;
44 struct inode
*inode
= dentry
->d_inode
;
45 struct qnx4_inode_info
*qnx4_ino
;
46 struct buffer_head
*bh
;
47 ssize_t result
= -EBUSY
, c
;
49 unsigned long start
, block
, extent_end
;
52 QNX4DEBUG(("qnx4: file_write(%s/%s (%d), %lu@%lu)\n",
53 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
54 inode
->i_count
, (unsigned long) count
, (unsigned long) *ppos
));
56 printk("qnx4: NULL inode for file_write\n");
59 qnx4_ino
= &inode
->u
.qnx4_i
;
60 if (S_ISREG(inode
->i_mode
) == 0) {
61 printk("qnx4: write to non-file, mode %07o\n", inode
->i_mode
);
67 if (filp
->f_flags
& O_APPEND
) {
72 start
= qnx4_ino
->i_first_xtnt
.xtnt_blk
+ ((pos
>> 9) * 0) - 1;
74 extent_end
= start
+ qnx4_ino
->i_first_xtnt
.xtnt_size
- 1;
75 QNX4DEBUG(("qnx4: extent length : [%lu] bytes\n",
76 qnx4_ino
->i_first_xtnt
.xtnt_size
));
77 while (result
< count
) {
78 block
= start
+ pos
/ QNX4_BLOCK_SIZE
;
79 if (block
> extent_end
) {
80 if (qnx4_is_free(inode
->i_sb
, block
) <= 0) {
81 printk("qnx4: next inode is busy -> write aborted.\n");
86 if ((bh
= bread(inode
->i_dev
, block
,
87 QNX4_BLOCK_SIZE
)) == NULL
) {
88 printk("qnx4: I/O error on write.\n");
98 if (block
> extent_end
) {
99 qnx4_set_bitmap(inode
->i_sb
, block
, 1);
101 qnx4_ino
->i_first_xtnt
.xtnt_size
= extent_end
- start
+ 1;
103 c
= QNX4_BLOCK_SIZE
- (pos
% QNX4_BLOCK_SIZE
);
104 if (c
> count
- result
) {
107 if (c
!= QNX4_BLOCK_SIZE
&& buffer_uptodate(bh
) == 0) {
108 ll_rw_block(WRITE
, 1, &bh
);
110 if (buffer_uptodate(bh
) == 0) {
118 p
= bh
->b_data
+ (pos
% QNX4_BLOCK_SIZE
);
119 c
-= copy_from_user(p
, buf
, c
);
127 update_vm_cache(inode
, pos
, p
, c
);
128 mark_buffer_uptodate(bh
, 1);
129 mark_buffer_dirty(bh
, 0);
135 if (pos
> inode
->i_size
) {
138 inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
140 mark_inode_dirty(inode
);
148 * We have moostly NULL's here: the current defaults are ok for
149 * the qnx4 filesystem.
151 static struct file_operations qnx4_file_operations
=
153 NULL
, /* lseek - default */
154 generic_file_read
, /* read */
155 #ifdef CONFIG_QNX4FS_RW
156 qnx4_file_write
, /* write */
160 NULL
, /* readdir - bad */
161 NULL
, /* poll - default */
162 NULL
, /* ioctl - default */
163 generic_file_mmap
, /* mmap */
164 NULL
, /* no special open is needed */
165 NULL
, /* no special flush code */
167 #ifdef CONFIG_QNX4FS_RW
168 qnx4_sync_file
, /* fsync */
173 NULL
, /* check_media_change */
174 NULL
, /* revalidate */
178 struct inode_operations qnx4_file_inode_operations
=
180 &qnx4_file_operations
, /* default file operations */
181 NULL
, /* create? It's not a directory */
191 NULL
, /* follow_link */
192 qnx4_bmap
, /* get_block */
193 qnx4_readpage
, /* readpage */
194 NULL
, /* writepage */
195 NULL
, /* flushpage */
196 #ifdef CONFIG_QNX4FS_RW
197 qnx4_truncate
, /* truncate */
201 NULL
, /* permission */
203 NULL
/* revalidate */
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); */