This source file includes following definitions.
- msdos_prefetch
- msdos_file_read
- msdos_file_write
- msdos_truncate
1
2
3
4
5
6
7
8
9 #include <asm/segment.h>
10 #include <asm/system.h>
11
12 #include <linux/sched.h>
13 #include <linux/locks.h>
14 #include <linux/fs.h>
15 #include <linux/msdos_fs.h>
16 #include <linux/errno.h>
17 #include <linux/fcntl.h>
18 #include <linux/stat.h>
19 #include <linux/string.h>
20
21 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
22 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
23
24 #define PRINTK(x)
25 #define Printk(x) printk x
26
27 static struct file_operations msdos_file_operations = {
28 NULL,
29 msdos_file_read,
30 msdos_file_write,
31 NULL,
32 NULL,
33 NULL,
34 generic_mmap,
35 NULL,
36 NULL,
37 file_fsync
38 };
39
40 struct inode_operations msdos_file_inode_operations = {
41 &msdos_file_operations,
42 NULL,
43 NULL,
44 NULL,
45 NULL,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 NULL,
53 msdos_bmap,
54 msdos_truncate,
55 NULL,
56 NULL
57 };
58
59 #define MSDOS_PREFETCH 32
60 struct msdos_pre {
61 int file_sector;
62
63 struct buffer_head *bhlist[MSDOS_PREFETCH];
64 int nblist;
65 int nolist;
66 };
67
68
69
70 static void msdos_prefetch (
71 struct inode *inode,
72 struct msdos_pre *pre,
73 int nb)
74 {
75 struct buffer_head *bhreq[MSDOS_PREFETCH];
76
77 int nbreq=0;
78 int i;
79 for (i=0; i<nb; i++){
80 int sector = msdos_smap(inode,pre->file_sector);
81 if (sector != 0){
82 struct buffer_head *bh;
83 PRINTK (("fsector2 %d -> %d\n",pre->file_sector-1,sector));
84 pre->file_sector++;
85 bh = getblk(inode->i_dev,sector,SECTOR_SIZE);
86 if (bh == NULL) break;
87 pre->bhlist[pre->nblist++] = bh;
88 if (!bh->b_uptodate) bhreq[nbreq++] = bh;
89 }else{
90 break;
91 }
92 }
93 if (nbreq > 0) ll_rw_block (READ,nbreq,bhreq);
94 for (i=pre->nblist; i<MSDOS_PREFETCH; i++) pre->bhlist[i] = NULL;
95 }
96
97
98
99
100 int msdos_file_read(
101 struct inode *inode,
102 struct file *filp,
103 char *buf,
104 int count)
105 {
106 char *start = buf;
107 char *end = buf + count;
108 int i;
109 int left_in_file;
110 struct msdos_pre pre;
111
112
113 if (!inode) {
114 printk("msdos_file_read: inode = NULL\n");
115 return -EINVAL;
116 }
117
118 if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
119 printk("msdos_file_read: mode = %07o\n",inode->i_mode);
120 return -EINVAL;
121 }
122 if (filp->f_pos >= inode->i_size || count <= 0) return 0;
123
124
125
126
127
128
129
130
131
132 PRINTK (("#### ino %ld pos %ld size %ld count %d\n",inode->i_ino,filp->f_pos,inode->i_size,count));
133 {
134
135
136
137
138 int count_max = (filp->f_pos & (SECTOR_SIZE-1)) + count;
139 int to_reada;
140 pre.file_sector = filp->f_pos >> SECTOR_BITS;
141 to_reada = count_max / SECTOR_SIZE;
142 if (count_max & (SECTOR_SIZE-1)) to_reada++;
143 if (filp->f_reada || !MSDOS_I(inode)->i_binary){
144
145
146
147 int ahead = read_ahead[MAJOR(inode->i_dev)];
148 PRINTK (("to_reada %d ahead %d\n",to_reada,ahead));
149 if (ahead == 0) ahead = 8;
150 to_reada += ahead;
151 }
152 if (to_reada > MSDOS_PREFETCH) to_reada = MSDOS_PREFETCH;
153 pre.nblist = 0;
154 msdos_prefetch (inode,&pre,to_reada);
155 }
156 pre.nolist = 0;
157 PRINTK (("count %d ahead %d nblist %d\n",count,read_ahead[MAJOR(inode->i_dev)],pre.nblist));
158 while ((left_in_file = inode->i_size - filp->f_pos) > 0
159 && buf < end){
160 struct buffer_head *bh = pre.bhlist[pre.nolist];
161 char *data;
162 int size,offset;
163 if (bh == NULL) break;
164 pre.bhlist[pre.nolist] = NULL;
165 pre.nolist++;
166 if (pre.nolist == MSDOS_PREFETCH/2){
167 memcpy (pre.bhlist,pre.bhlist+MSDOS_PREFETCH/2
168 ,(MSDOS_PREFETCH/2)*sizeof(pre.bhlist[0]));
169 pre.nblist -= MSDOS_PREFETCH/2;
170 msdos_prefetch (inode,&pre,MSDOS_PREFETCH/2);
171 pre.nolist = 0;
172 }
173 PRINTK (("file_read pos %ld nblist %d %d %d\n",filp->f_pos,pre.nblist,pre.fetched,count));
174 wait_on_buffer(bh);
175 if (!bh->b_uptodate){
176
177 brelse (bh);
178 break;
179 }
180 offset = filp->f_pos & (SECTOR_SIZE-1);
181 data = bh->b_data + offset;
182 size = MIN(SECTOR_SIZE-offset,left_in_file);
183 if (MSDOS_I(inode)->i_binary) {
184 size = MIN(size,end-buf);
185 memcpy_tofs(buf,data,size);
186 buf += size;
187 filp->f_pos += size;
188 }else{
189 for (; size && buf < end; size--) {
190 char ch = *data++;
191 filp->f_pos++;
192 if (ch == 26){
193 filp->f_pos = inode->i_size;
194 break;
195 }else if (ch != '\r'){
196 put_fs_byte(ch,buf++);
197 }
198 }
199 }
200 brelse(bh);
201 }
202 PRINTK (("--- %d -> %d\n",count,(int)(buf-start)));
203 for (i=0; i<pre.nblist; i++) brelse (pre.bhlist[i]);
204 if (start == buf) return -EIO;
205 if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME;
206 filp->f_reada = 1;
207 return buf-start;
208 }
209
210
211
212
213 int msdos_file_write(
214 struct inode *inode,
215 struct file *filp,
216 char *buf,
217 int count)
218 {
219 int sector,offset,size,left,written;
220 int error,carry;
221 char *start,*to,ch;
222 struct buffer_head *bh;
223 int binary_mode = MSDOS_I(inode)->i_binary;
224
225 if (!inode) {
226 printk("msdos_file_write: inode = NULL\n");
227 return -EINVAL;
228 }
229
230 if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
231 printk("msdos_file_write: mode = %07o\n",inode->i_mode);
232 return -EINVAL;
233 }
234
235
236
237
238 if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
239 if (count <= 0) return 0;
240 error = carry = 0;
241 for (start = buf; count || carry; count -= size) {
242 while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
243 if ((error = msdos_add_cluster(inode)) < 0) break;
244 if (error) {
245 msdos_truncate(inode);
246 break;
247 }
248 offset = filp->f_pos & (SECTOR_SIZE-1);
249 size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
250 if (binary_mode
251 && offset == 0
252 && (size == SECTOR_SIZE
253 || filp->f_pos + size >= inode->i_size)){
254
255
256
257 if (!(bh = getblk(inode->i_dev,sector,SECTOR_SIZE))){
258 error = -EIO;
259 break;
260 }
261 }else if (!(bh = msdos_sread(inode->i_dev,sector))) {
262 error = -EIO;
263 break;
264 }
265 if (binary_mode) {
266 memcpy_fromfs(bh->b_data+offset,buf,written = size);
267 buf += size;
268 }
269 else {
270 written = left = SECTOR_SIZE-offset;
271 to = (char *) bh->b_data+(filp->f_pos & (SECTOR_SIZE-1));
272 if (carry) {
273 *to++ = '\n';
274 left--;
275 carry = 0;
276 }
277 for (size = 0; size < count && left; size++) {
278 if ((ch = get_fs_byte(buf++)) == '\n') {
279 *to++ = '\r';
280 left--;
281 }
282 if (!left) carry = 1;
283 else {
284 *to++ = ch;
285 left--;
286 }
287 }
288 written -= left;
289 }
290 filp->f_pos += written;
291 if (filp->f_pos > inode->i_size) {
292 inode->i_size = filp->f_pos;
293 inode->i_dirt = 1;
294 }
295 bh->b_uptodate = 1;
296 mark_buffer_dirty(bh, 0);
297 brelse(bh);
298 }
299 if (start == buf)
300 return error;
301 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
302 MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
303 inode->i_dirt = 1;
304 return buf-start;
305 }
306
307 void msdos_truncate(struct inode *inode)
308 {
309 int cluster;
310
311 cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
312 (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
313 MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
314 inode->i_dirt = 1;
315 }