Import 2.1.128
[davej-history.git] / fs / qnx4 / file.c
blob49998012677bc0a7b8ac0ba68c58b9baadcfd552
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 * 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>
17 #include <linux/fs.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>
26 #include <linux/mm.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))
36 #include <linux/fs.h>
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;
50 off_t pos;
51 unsigned long start, block, extent_end;
52 char *p;
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));
57 if (inode == NULL) {
58 printk("qnx4: NULL inode for file_write\n");
59 return -EINVAL;
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);
64 return -EINVAL;
66 if (count == 0) {
67 goto out;
69 if (filp->f_flags & O_APPEND) {
70 pos = inode->i_size;
71 } else {
72 pos = *ppos;
74 start = qnx4_ino->i_first_xtnt.xtnt_blk + ((pos >> 9) * 0) - 1;
75 result = 0;
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");
84 result = -ENOSPC;
85 break;
88 if ((bh = bread(inode->i_dev, block,
89 QNX4_BLOCK_SIZE)) == NULL) {
90 printk("qnx4: I/O error on write.\n");
91 result = -EIO;
92 goto out;
94 if (bh == NULL) {
95 if (result != 0) {
96 result = -ENOSPC;
98 break;
100 if (block > extent_end) {
101 qnx4_set_bitmap(inode->i_sb, block, 1);
102 extent_end++;
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) {
107 c = count - result;
109 if (c != QNX4_BLOCK_SIZE && buffer_uptodate(bh) == 0) {
110 ll_rw_block(WRITE, 1, &bh);
111 wait_on_buffer(bh);
112 if (buffer_uptodate(bh) == 0) {
113 brelse(bh);
114 if (result != 0) {
115 result = -EIO;
117 break;
120 p = bh->b_data + (pos % QNX4_BLOCK_SIZE);
121 c -= copy_from_user(p, buf, c);
122 if (c == 0) {
123 brelse(bh);
124 if (result == 0) {
125 result = -EFAULT;
127 break;
129 update_vm_cache(inode, pos, p, c);
130 mark_buffer_uptodate(bh, 1);
131 mark_buffer_dirty(bh, 0);
132 brelse(bh);
133 pos += c;
134 buf += c;
135 result += c;
137 if (pos > inode->i_size) {
138 inode->i_size = pos;
140 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
141 *ppos = pos;
142 mark_inode_dirty(inode);
144 out:
145 return result;
147 #endif
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 */
159 #else
160 NULL,
161 #endif
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 */
168 NULL, /* release */
169 #ifdef CONFIG_QNX4FS_RW
170 qnx4_sync_file, /* fsync */
171 #else
172 NULL,
173 #endif
174 NULL, /* fasync */
175 NULL, /* check_media_change */
176 NULL, /* revalidate */
177 NULL /* lock */
180 struct inode_operations qnx4_file_inode_operations =
182 &qnx4_file_operations, /* default file operations */
183 NULL, /* create? It's not a directory */
184 NULL, /* lookup */
185 NULL, /* link */
186 NULL, /* unlink */
187 NULL, /* symlink */
188 NULL, /* mkdir */
189 NULL, /* rmdir */
190 NULL, /* mknod */
191 NULL, /* rename */
192 NULL, /* readlink */
193 NULL, /* follow_link */
194 qnx4_readpage, /* readpage */
195 NULL, /* writepage */
196 qnx4_bmap, /* bmap */
197 #ifdef CONFIG_QNX4FS_RW
198 qnx4_truncate, /* truncate */
199 #else
200 NULL,
201 #endif
202 NULL, /* permission */
203 NULL /* smap */
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;
211 unsigned long buf;
212 unsigned long offset, avail, readlen;
213 unsigned long start;
214 unsigned long count;
215 struct buffer_head *bh;
216 int res = -EIO;
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");
222 return -EIO;
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) {
232 res = 0;
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;
237 do {
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");
241 res = -EIO;
242 } else {
243 memcpy((void *) buf, bh->b_data, QNX4_BLOCK_SIZE);
245 buf += QNX4_BLOCK_SIZE;
246 start++;
247 count--;
248 } while (count != 0);
250 if (res != 0) {
251 set_bit(PG_error, &page->flags);
252 memset((void *) buf, 0, PAGE_SIZE);
253 } else {
254 set_bit(PG_uptodate, &page->flags);
256 clear_bit(PG_locked, &page->flags);
257 wake_up(&page->wait);
258 /* free_page(buf); */
260 return res;