Import 2.1.118
[davej-history.git] / fs / sysv / file.c
blobd60be8fa5ebf50ad70a9263a19ca994de46a2579
1 /*
2 * linux/fs/sysv/file.c
4 * minix/file.c
5 * Copyright (C) 1991, 1992 Linus Torvalds
7 * coh/file.c
8 * Copyright (C) 1993 Pascal Haible, Bruno Haible
10 * sysv/file.c
11 * Copyright (C) 1993 Bruno Haible
13 * SystemV/Coherent regular file handling primitives
16 #include <linux/kernel.h>
17 #include <linux/fs.h>
18 #include <linux/sysv_fs.h>
19 #include <linux/errno.h>
20 #include <linux/fcntl.h>
21 #include <linux/stat.h>
22 #include <linux/string.h>
23 #include <linux/locks.h>
24 #include <linux/pagemap.h>
26 #include <asm/uaccess.h>
28 #define NBUF 32
30 #define MIN(a,b) (((a)<(b))?(a):(b))
31 #define MAX(a,b) (((a)>(b))?(a):(b))
33 #include <linux/fs.h>
34 #include <linux/sysv_fs.h>
36 static ssize_t sysv_file_write(struct file *, const char *, size_t, loff_t *);
39 * We have mostly NULLs here: the current defaults are OK for
40 * the coh filesystem.
42 static struct file_operations sysv_file_operations = {
43 NULL, /* lseek - default */
44 sysv_file_read, /* read */
45 sysv_file_write, /* write */
46 NULL, /* readdir - bad */
47 NULL, /* poll - default */
48 NULL, /* ioctl - default */
49 generic_file_mmap, /* mmap */
50 NULL, /* no special open is needed */
51 NULL, /* flush */
52 NULL, /* release */
53 sysv_sync_file /* fsync */
56 struct inode_operations sysv_file_inode_operations = {
57 &sysv_file_operations, /* default file operations */
58 NULL, /* create */
59 NULL, /* lookup */
60 NULL, /* link */
61 NULL, /* unlink */
62 NULL, /* symlink */
63 NULL, /* mkdir */
64 NULL, /* rmdir */
65 NULL, /* mknod */
66 NULL, /* rename */
67 NULL, /* readlink */
68 NULL, /* follow_link */
69 generic_readpage, /* readpage */
70 NULL, /* writepage */
71 sysv_bmap, /* bmap */
72 sysv_truncate, /* truncate */
73 NULL /* permission */
76 ssize_t sysv_file_read(struct file * filp, char * buf,
77 size_t count, loff_t *ppos)
79 struct inode * inode = filp->f_dentry->d_inode;
80 struct super_block * sb = inode->i_sb;
81 ssize_t read,left,chars;
82 size_t block;
83 ssize_t blocks, offset;
84 int bhrequest, uptodate;
85 struct buffer_head ** bhb, ** bhe;
86 struct buffer_head * bhreq[NBUF];
87 struct buffer_head * buflist[NBUF];
88 size_t size;
90 if (!inode) {
91 printk("sysv_file_read: inode = NULL\n");
92 return -EINVAL;
94 if (!S_ISREG(inode->i_mode)) {
95 printk("sysv_file_read: mode = %07o\n",inode->i_mode);
96 return -EINVAL;
98 offset = *ppos;
99 size = inode->i_size;
100 if (offset > size)
101 left = 0;
102 else
103 left = size - offset;
104 if (left > count)
105 left = count;
106 if (left <= 0)
107 return 0;
108 read = 0;
109 block = offset >> sb->sv_block_size_bits;
110 offset &= sb->sv_block_size_1;
111 size = (size + sb->sv_block_size_1) >> sb->sv_block_size_bits;
112 blocks = (left + offset + sb->sv_block_size_1) >> sb->sv_block_size_bits;
113 bhb = bhe = buflist;
114 if (filp->f_reada) {
115 blocks += read_ahead[MAJOR(inode->i_dev)] >> (sb->sv_block_size_bits - 9);
116 if (block + blocks > size)
117 blocks = size - block;
120 /* We do this in a two stage process. We first try to request
121 as many blocks as we can, then we wait for the first one to
122 complete, and then we try to wrap up as many as are actually
123 done. This routine is rather generic, in that it can be used
124 in a filesystem by substituting the appropriate function in
125 for getblk.
127 This routine is optimized to make maximum use of the various
128 buffers and caches.
131 do {
132 bhrequest = 0;
133 uptodate = 1;
134 while (blocks) {
135 --blocks;
136 *bhb = sysv_getblk(inode, block++, 0);
137 if (*bhb && !buffer_uptodate(*bhb)) {
138 uptodate = 0;
139 bhreq[bhrequest++] = *bhb;
142 if (++bhb == &buflist[NBUF])
143 bhb = buflist;
145 /* If the block we have on hand is uptodate, go ahead
146 and complete processing. */
147 if (uptodate)
148 break;
149 if (bhb == bhe)
150 break;
153 /* Now request them all */
154 if (bhrequest)
155 ll_rw_block(READ, bhrequest, bhreq);
157 do { /* Finish off all I/O that has actually completed */
158 if (*bhe) {
159 wait_on_buffer(*bhe);
160 if (!buffer_uptodate(*bhe)) { /* read error? */
161 brelse(*bhe);
162 if (++bhe == &buflist[NBUF])
163 bhe = buflist;
164 left = 0;
165 break;
168 if (left < sb->sv_block_size - offset)
169 chars = left;
170 else
171 chars = sb->sv_block_size - offset;
172 *ppos += chars;
173 left -= chars;
174 read += chars;
175 if (*bhe) {
176 copy_to_user(buf,offset+(*bhe)->b_data,chars);
177 brelse(*bhe);
178 buf += chars;
179 } else {
180 while (chars-- > 0)
181 put_user(0,buf++);
183 offset = 0;
184 if (++bhe == &buflist[NBUF])
185 bhe = buflist;
186 } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
187 } while (left > 0);
189 /* Release the read-ahead blocks */
190 while (bhe != bhb) {
191 brelse(*bhe);
192 if (++bhe == &buflist[NBUF])
193 bhe = buflist;
195 if (!read)
196 return -EIO;
197 filp->f_reada = 1;
198 if (!IS_RDONLY(inode)) {
199 inode->i_atime = CURRENT_TIME;
200 mark_inode_dirty(inode);
202 return read;
205 static ssize_t sysv_file_write(struct file * filp, const char * buf,
206 size_t count, loff_t *ppos)
208 struct inode * inode = filp->f_dentry->d_inode;
209 struct super_block * sb = inode->i_sb;
210 off_t pos;
211 ssize_t written, c;
212 struct buffer_head * bh;
213 char * p;
215 if (!inode) {
216 printk("sysv_file_write: inode = NULL\n");
217 return -EINVAL;
219 if (!S_ISREG(inode->i_mode)) {
220 printk("sysv_file_write: mode = %07o\n",inode->i_mode);
221 return -EINVAL;
224 * OK, append may not work when many processes are writing at the same time
225 * but so what. That way leads to madness anyway.
226 * But we need to protect against simultaneous truncate as we may end up
227 * writing our data into blocks that have meanwhile been incorporated into
228 * the freelist, thereby trashing the freelist.
230 if (filp->f_flags & O_APPEND)
231 pos = inode->i_size;
232 else
233 pos = *ppos;
234 written = 0;
235 while (written<count) {
236 bh = sysv_getblk (inode, pos >> sb->sv_block_size_bits, 1);
237 if (!bh) {
238 if (!written)
239 written = -ENOSPC;
240 break;
242 c = sb->sv_block_size - (pos & sb->sv_block_size_1);
243 if (c > count-written)
244 c = count-written;
245 if (c != sb->sv_block_size && !buffer_uptodate(bh)) {
246 ll_rw_block(READ, 1, &bh);
247 wait_on_buffer(bh);
248 if (!buffer_uptodate(bh)) {
249 brelse(bh);
250 if (!written)
251 written = -EIO;
252 break;
255 /* now either c==sb->sv_block_size or buffer_uptodate(bh) */
256 p = (pos & sb->sv_block_size_1) + bh->b_data;
257 copy_from_user(p, buf, c);
258 update_vm_cache(inode, pos, p, c);
259 pos += c;
260 if (pos > inode->i_size) {
261 inode->i_size = pos;
262 mark_inode_dirty(inode);
264 written += c;
265 buf += c;
266 mark_buffer_uptodate(bh, 1);
267 mark_buffer_dirty(bh, 0);
268 brelse(bh);
270 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
271 *ppos = pos;
272 mark_inode_dirty(inode);
273 return written;