1 /*
2 * linux/fs/minix/file.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * minix regular file handling primitives
7 */
8
9 #include <asm/segment.h>
10 #include <asm/system.h>
11
12 #include <linux/sched.h>
13 #include <linux/minix_fs.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/fcntl.h>
17 #include <linux/stat.h>
18 #include <linux/locks.h>
19
20 #define NBUF 32
21
22 #define MIN(a,b) (((a)<(b))?(a):(b))
23 #define MAX(a,b) (((a)>(b))?(a):(b))
24
25 #include <linux/fs.h>
26 #include <linux/minix_fs.h>
27
28 static int minix_file_read(struct inode *, struct file *, char *, int);
29 static int minix_file_write(struct inode *, struct file *, char *, int);
30
31 /*
32 * We have mostly NULL's here: the current defaults are ok for
33 * the minix filesystem.
34 */
35 static struct file_operations minix_file_operations = {
36 NULL, /* lseek - default */
37 minix_file_read, /* read */
38 minix_file_write, /* write */
39 NULL, /* readdir - bad */
40 NULL, /* select - default */
41 NULL, /* ioctl - default */
42 generic_mmap, /* mmap */
43 NULL, /* no special open is needed */
44 NULL, /* release */
45 minix_sync_file /* fsync */
46 };
47
48 struct inode_operations minix_file_inode_operations = {
49 &minix_file_operations, /* default file operations */
50 NULL, /* create */
51 NULL, /* lookup */
52 NULL, /* link */
53 NULL, /* unlink */
54 NULL, /* symlink */
55 NULL, /* mkdir */
56 NULL, /* rmdir */
57 NULL, /* mknod */
58 NULL, /* rename */
59 NULL, /* readlink */
60 NULL, /* follow_link */
61 minix_bmap, /* bmap */
62 minix_truncate, /* truncate */
63 NULL /* permission */
64 };
65
66 static int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
67 {
68 int read,left,chars;
69 int block, blocks, offset;
70 int bhrequest, uptodate;
71 struct buffer_head ** bhb, ** bhe;
72 struct buffer_head * bhreq[NBUF];
73 struct buffer_head * buflist[NBUF];
74 unsigned int size;
75
76 if (!inode) {
77 printk("minix_file_read: inode = NULL\n");
78 return -EINVAL;
79 }
80 if (!S_ISREG(inode->i_mode)) {
81 printk("minix_file_read: mode = %07o\n",inode->i_mode);
82 return -EINVAL;
83 }
84 offset = filp->f_pos;
85 size = inode->i_size;
86 if (offset > size)
87 left = 0;
88 else
89 left = size - offset;
90 if (left > count)
91 left = count;
92 if (left <= 0)
93 return 0;
94 read = 0;
95 block = offset >> BLOCK_SIZE_BITS;
96 offset &= BLOCK_SIZE-1;
97 size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS;
98 blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
99 bhb = bhe = buflist;
100 if (filp->f_reada) {
101 if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
102 blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
103 if (block + blocks > size)
104 blocks = size - block;
105 }
106
107 /* We do this in a two stage process. We first try and request
108 as many blocks as we can, then we wait for the first one to
109 complete, and then we try and wrap up as many as are actually
110 done. This routine is rather generic, in that it can be used
111 in a filesystem by substituting the appropriate function in
112 for getblk.
113
114 This routine is optimized to make maximum use of the various
115 buffers and caches. */
116
117 do {
118 bhrequest = 0;
119 uptodate = 1;
120 while (blocks) {
121 --blocks;
122 *bhb = minix_getblk(inode, block++, 0);
123 if (*bhb && !(*bhb)->b_uptodate) {
124 uptodate = 0;
125 bhreq[bhrequest++] = *bhb;
126 }
127
128 if (++bhb == &buflist[NBUF])
129 bhb = buflist;
130
131 /* If the block we have on hand is uptodate, go ahead
132 and complete processing. */
133 if (uptodate)
134 break;
135 if (bhb == bhe)
136 break;
137 }
138
139 /* Now request them all */
140 if (bhrequest)
141 ll_rw_block(READ, bhrequest, bhreq);
142
143 do { /* Finish off all I/O that has actually completed */
144 if (*bhe) {
145 wait_on_buffer(*bhe);
146 if (!(*bhe)->b_uptodate) { /* read error? */
147 brelse(*bhe);
148 if (++bhe == &buflist[NBUF])
149 bhe = buflist;
150 left = 0;
151 break;
152 }
153 }
154 if (left < BLOCK_SIZE - offset)
155 chars = left;
156 else
157 chars = BLOCK_SIZE - offset;
158 filp->f_pos += chars;
159 left -= chars;
160 read += chars;
161 if (*bhe) {
162 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
163 brelse(*bhe);
164 buf += chars;
165 } else {
166 while (chars-->0)
167 put_fs_byte(0,buf++);
168 }
169 offset = 0;
170 if (++bhe == &buflist[NBUF])
171 bhe = buflist;
172 } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
173 } while (left > 0);
174
175 /* Release the read-ahead blocks */
176 while (bhe != bhb) {
177 brelse(*bhe);
178 if (++bhe == &buflist[NBUF])
179 bhe = buflist;
180 };
181 if (!read)
182 return -EIO;
183 filp->f_reada = 1;
184 if (!IS_RDONLY(inode))
185 inode->i_atime = CURRENT_TIME;
186 return read;
187 }
188
189 static int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
190 {
191 off_t pos;
192 int written,c;
193 struct buffer_head * bh;
194 char * p;
195
196 if (!inode) {
197 printk("minix_file_write: inode = NULL\n");
198 return -EINVAL;
199 }
200 if (!S_ISREG(inode->i_mode)) {
201 printk("minix_file_write: mode = %07o\n",inode->i_mode);
202 return -EINVAL;
203 }
204 /*
205 * ok, append may not work when many processes are writing at the same time
206 * but so what. That way leads to madness anyway.
207 */
208 if (filp->f_flags & O_APPEND)
209 pos = inode->i_size;
210 else
211 pos = filp->f_pos;
212 written = 0;
213 while (written<count) {
214 bh = minix_getblk(inode,pos/BLOCK_SIZE,1);
215 if (!bh) {
216 if (!written)
217 written = -ENOSPC;
218 break;
219 }
220 c = BLOCK_SIZE - (pos % BLOCK_SIZE);
221 if (c > count-written)
222 c = count-written;
223 if (c != BLOCK_SIZE && !bh->b_uptodate) {
224 ll_rw_block(READ, 1, &bh);
225 wait_on_buffer(bh);
226 if (!bh->b_uptodate) {
227 brelse(bh);
228 if (!written)
229 written = -EIO;
230 break;
231 }
232 }
233 p = (pos % BLOCK_SIZE) + bh->b_data;
234 pos += c;
235 if (pos > inode->i_size) {
236 inode->i_size = pos;
237 inode->i_dirt = 1;
238 }
239 written += c;
240 memcpy_fromfs(p,buf,c);
241 buf += c;
242 bh->b_uptodate = 1;
243 mark_buffer_dirty(bh, 0);
244 brelse(bh);
245 }
246 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
247 filp->f_pos = pos;
248 inode->i_dirt = 1;
249 return written;
250 }