5 * Copyright (C) 1991, 1992 Linus Torvalds
8 * Copyright (C) 1993 Pascal Haible, Bruno Haible
11 * Copyright (C) 1993 Bruno Haible
13 * SystemV/Coherent regular file handling primitives
16 #include <linux/kernel.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>
30 #define MIN(a,b) (((a)<(b))?(a):(b))
31 #define MAX(a,b) (((a)>(b))?(a):(b))
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
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 */
53 sysv_sync_file
/* fsync */
56 struct inode_operations sysv_file_inode_operations
= {
57 &sysv_file_operations
, /* default file operations */
68 NULL
, /* follow_link */
69 generic_readpage
, /* readpage */
72 sysv_truncate
, /* truncate */
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
;
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
];
91 printk("sysv_file_read: inode = NULL\n");
94 if (!S_ISREG(inode
->i_mode
)) {
95 printk("sysv_file_read: mode = %07o\n",inode
->i_mode
);
103 left
= size
- offset
;
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
;
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
127 This routine is optimized to make maximum use of the various
136 *bhb
= sysv_getblk(inode
, block
++, 0);
137 if (*bhb
&& !buffer_uptodate(*bhb
)) {
139 bhreq
[bhrequest
++] = *bhb
;
142 if (++bhb
== &buflist
[NBUF
])
145 /* If the block we have on hand is uptodate, go ahead
146 and complete processing. */
153 /* Now request them all */
155 ll_rw_block(READ
, bhrequest
, bhreq
);
157 do { /* Finish off all I/O that has actually completed */
159 wait_on_buffer(*bhe
);
160 if (!buffer_uptodate(*bhe
)) { /* read error? */
162 if (++bhe
== &buflist
[NBUF
])
168 if (left
< sb
->sv_block_size
- offset
)
171 chars
= sb
->sv_block_size
- offset
;
176 copy_to_user(buf
,offset
+(*bhe
)->b_data
,chars
);
184 if (++bhe
== &buflist
[NBUF
])
186 } while (left
> 0 && bhe
!= bhb
&& (!*bhe
|| !buffer_locked(*bhe
)));
189 /* Release the read-ahead blocks */
192 if (++bhe
== &buflist
[NBUF
])
198 if (!IS_RDONLY(inode
)) {
199 inode
->i_atime
= CURRENT_TIME
;
200 mark_inode_dirty(inode
);
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
;
212 struct buffer_head
* bh
;
216 printk("sysv_file_write: inode = NULL\n");
219 if (!S_ISREG(inode
->i_mode
)) {
220 printk("sysv_file_write: mode = %07o\n",inode
->i_mode
);
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
)
235 while (written
<count
) {
236 bh
= sysv_getblk (inode
, pos
>> sb
->sv_block_size_bits
, 1);
242 c
= sb
->sv_block_size
- (pos
& sb
->sv_block_size_1
);
243 if (c
> count
-written
)
245 if (c
!= sb
->sv_block_size
&& !buffer_uptodate(bh
)) {
246 ll_rw_block(READ
, 1, &bh
);
248 if (!buffer_uptodate(bh
)) {
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
);
260 if (pos
> inode
->i_size
) {
262 mark_inode_dirty(inode
);
266 mark_buffer_uptodate(bh
, 1);
267 mark_buffer_dirty(bh
, 0);
270 inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
272 mark_inode_dirty(inode
);