4 * Written 1992,1993 by Werner Almesberger
6 * regular file handling primitives for fat-based filesystems
9 #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
10 #include <linux/version.h>
11 #include <linux/sched.h>
12 #include <linux/locks.h>
14 #include <linux/msdos_fs.h>
15 #include <linux/errno.h>
16 #include <linux/fcntl.h>
17 #include <linux/stat.h>
18 #include <linux/string.h>
19 #include <linux/pagemap.h>
20 #include <linux/fat_cvf.h>
22 #include <asm/uaccess.h>
23 #include <asm/system.h>
27 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
28 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
31 #define Printk(x) printk x
33 static struct file_operations fat_file_operations
= {
34 NULL
, /* lseek - default */
35 fat_file_read
, /* read */
36 fat_file_write
, /* write */
37 NULL
, /* readdir - bad */
38 NULL
, /* select v2.0.x/poll v2.1.x - default */
39 NULL
, /* ioctl - default */
40 generic_file_mmap
, /* mmap */
41 NULL
, /* no special open is needed */
44 file_fsync
/* fsync */
47 struct inode_operations fat_file_inode_operations
= {
48 &fat_file_operations
, /* default file operations */
59 NULL
, /* follow_link */
60 generic_readpage
, /* readpage */
63 fat_truncate
, /* truncate */
64 NULL
, /* permission */
68 /* #Specification: msdos / special devices / mmap
69 Mmapping does work because a special mmap is provide in that case.
70 Note that it is much less efficient than the generic_file_mmap normally
71 used since it allocate extra buffer. generic_file_mmap is used for
72 normal device (512 bytes hardware sectors).
74 static struct file_operations fat_file_operations_1024
= {
75 NULL
, /* lseek - default */
76 fat_file_read
, /* read */
77 fat_file_write
, /* write */
78 NULL
, /* readdir - bad */
79 NULL
, /* select v2.0.x/poll v2.1.x - default */
80 NULL
, /* ioctl - default */
82 NULL
, /* no special open is needed */
85 file_fsync
/* fsync */
88 /* #Specification: msdos / special devices / swap file
89 Swap file can't work on special devices with a large sector
90 size (1024 bytes hard sector). Those devices have a weird
91 MS-DOS filesystem layout. Generally a single hardware sector
92 may contain 2 unrelated logical sector. This mean that there is
93 no easy way to do a mapping between disk sector of a file and virtual
94 memory. So swap file is difficult (not available right now)
95 on those devices. Off course, Ext2 does not have this problem.
97 struct inode_operations fat_file_inode_operations_1024
= {
98 &fat_file_operations_1024
, /* default file operations */
109 NULL
, /* follow_link */
110 generic_readpage
, /* readpage */
111 NULL
, /* writepage */
113 fat_truncate
, /* truncate */
114 NULL
, /* permission */
118 static struct file_operations fat_file_operations_readpage
= {
119 NULL
, /* lseek - default */
120 fat_file_read
, /* read */
121 fat_file_write
, /* write */
122 NULL
, /* readdir - bad */
123 NULL
, /* select v2.0.x/poll v2.1.x - default */
124 NULL
, /* ioctl - default */
125 generic_file_mmap
, /* mmap */
126 NULL
, /* no special open is needed */
129 file_fsync
/* fsync */
132 struct inode_operations fat_file_inode_operations_readpage
= {
133 &fat_file_operations_readpage
, /* default file operations */
144 NULL
, /* follow_link */
145 fat_readpage
, /* readpage */
146 NULL
, /* writepage */
148 fat_truncate
, /* truncate */
149 NULL
, /* permission */
153 #define MSDOS_PREFETCH 32
155 int file_sector
;/* Next sector to read in the prefetch table */
156 /* This is relative to the file, not the disk */
157 struct buffer_head
*bhlist
[MSDOS_PREFETCH
]; /* All buffers needed */
158 int nblist
; /* Number of buffers in bhlist */
159 int nolist
; /* index in bhlist */
162 Order the prefetch of more sectors.
164 static void fat_prefetch (
167 int nb
) /* How many must we prefetch at once */
169 struct super_block
*sb
= inode
->i_sb
;
170 struct buffer_head
*bhreq
[MSDOS_PREFETCH
]; /* Buffers not */
172 int nbreq
= 0; /* Number of buffers in bhreq */
174 for (i
=0; i
<nb
; i
++){
175 int sector
= fat_smap(inode
,pre
->file_sector
);
177 struct buffer_head
*bh
;
178 PRINTK (("fsector2 %d -> %d\n",pre
->file_sector
-1,sector
));
180 bh
= fat_getblk(sb
, sector
);
181 if (bh
== NULL
) break;
182 pre
->bhlist
[pre
->nblist
++] = bh
;
183 if (!fat_is_uptodate(sb
,bh
))
189 if (nbreq
> 0) fat_ll_rw_block (sb
,READ
,nbreq
,bhreq
);
190 for (i
=pre
->nblist
; i
<MSDOS_PREFETCH
; i
++) pre
->bhlist
[i
] = NULL
;
194 Read a file into user space
196 static ssize_t
fat_file_read_text(
202 struct inode
*inode
= filp
->f_dentry
->d_inode
;
203 struct super_block
*sb
= inode
->i_sb
;
205 char *end
= buf
+ count
;
212 printk("fat_file_read: inode = NULL\n");
215 /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
216 if (!S_ISREG(inode
->i_mode
) && !S_ISLNK(inode
->i_mode
)) {
217 printk("fat_file_read: mode = %07o\n",inode
->i_mode
);
220 if (*ppos
>= inode
->i_size
|| count
== 0) return 0;
222 Tell the buffer cache which block we expect to read in advance
223 Since we are limited with the stack, we preread only MSDOS_PREFETCH
224 because we have to keep the result into the local
225 arrays pre.bhlist and bhreq.
227 Each time we process one block in bhlist, we replace
228 it by a new prefetch block if needed.
230 PRINTK (("#### ino %ld pos %ld size %ld count %d\n",inode
->i_ino
,*ppos
,inode
->i_size
,count
));
233 We must prefetch complete block, so we must
234 take in account the offset in the first block.
236 int count_max
= (*ppos
& (SECTOR_SIZE
-1)) + count
;
237 int to_reada
; /* How many block to read all at once */
238 pre
.file_sector
= *ppos
>> SECTOR_BITS
;
239 to_reada
= count_max
/ SECTOR_SIZE
;
240 if (count_max
& (SECTOR_SIZE
-1)) to_reada
++;
241 if (filp
->f_reada
|| !MSDOS_I(inode
)->i_binary
){
242 /* Doing a read ahead on ASCII file make sure we always */
243 /* read enough, since we don't know how many blocks */
245 int ahead
= read_ahead
[MAJOR(inode
->i_dev
)];
246 PRINTK (("to_reada %d ahead %d\n",to_reada
,ahead
));
247 if (ahead
== 0) ahead
= 8;
250 if (to_reada
> MSDOS_PREFETCH
) to_reada
= MSDOS_PREFETCH
;
252 fat_prefetch (inode
,&pre
,to_reada
);
255 PRINTK (("count %d ahead %d nblist %d\n",count
,read_ahead
[MAJOR(inode
->i_dev
)],pre
.nblist
));
256 while ((left_in_file
= inode
->i_size
- *ppos
) > 0
258 struct buffer_head
*bh
= pre
.bhlist
[pre
.nolist
];
261 if (bh
== NULL
) break;
262 pre
.bhlist
[pre
.nolist
] = NULL
;
264 if (pre
.nolist
== MSDOS_PREFETCH
/2){
265 memcpy (pre
.bhlist
,pre
.bhlist
+MSDOS_PREFETCH
/2
266 ,(MSDOS_PREFETCH
/2)*sizeof(pre
.bhlist
[0]));
267 pre
.nblist
-= MSDOS_PREFETCH
/2;
268 fat_prefetch (inode
,&pre
,MSDOS_PREFETCH
/2);
271 PRINTK (("file_read pos %ld nblist %d %d %d\n",*ppos
,pre
.nblist
,pre
.fetched
,count
));
273 if (!fat_is_uptodate(sb
,bh
)){
278 offset
= *ppos
& (SECTOR_SIZE
-1);
279 data
= bh
->b_data
+ offset
;
280 size
= MIN(SECTOR_SIZE
-offset
,left_in_file
);
281 if (MSDOS_I(inode
)->i_binary
) {
282 size
= MIN(size
,end
-buf
);
283 copy_to_user(buf
,data
,size
);
287 for (; size
&& buf
< end
; size
--) {
291 *ppos
= inode
->i_size
;
293 }else if (ch
!= '\r'){
300 PRINTK (("--- %d -> %d\n",count
,(int)(buf
-start
)));
301 for (i
=0; i
<pre
.nblist
; i
++)
302 fat_brelse (sb
, pre
.bhlist
[i
]);
305 if (!IS_RDONLY(inode
))
306 inode
->i_atime
= CURRENT_TIME
;
307 filp
->f_reada
= 1; /* Will be reset if a lseek is done */
311 ssize_t
fat_file_read(
317 struct inode
*inode
= filp
->f_dentry
->d_inode
;
318 if (MSDOS_SB(inode
->i_sb
)->cvf_format
&&
319 MSDOS_SB(inode
->i_sb
)->cvf_format
->cvf_file_read
)
320 return MSDOS_SB(inode
->i_sb
)->cvf_format
321 ->cvf_file_read(filp
,buf
,count
,ppos
);
324 * MS-DOS filesystems with a blocksize > 512 may have blocks
325 * spread over several hardware sectors (unaligned), which
326 * is not something the generic routines can (or would want
329 if (!MSDOS_I(inode
)->i_binary
|| inode
->i_sb
->s_blocksize
> 512)
330 return fat_file_read_text(filp
, buf
, count
, ppos
);
331 return generic_file_read(filp
, buf
, count
, ppos
);
334 Write to a file either from user space
336 ssize_t
fat_file_write(
342 struct inode
*inode
= filp
->f_dentry
->d_inode
;
343 struct super_block
*sb
= inode
->i_sb
;
344 int sector
,offset
,size
,left
,written
;
348 struct buffer_head
*bh
;
349 int binary_mode
= MSDOS_I(inode
)->i_binary
;
351 PRINTK(("fat_file_write: dentry=%p, inode=%p, ino=%ld\n",
352 filp
->f_dentry
, inode
, inode
->i_ino
));
354 printk("fat_file_write: inode = NULL\n");
357 if (MSDOS_SB(sb
)->cvf_format
&&
358 MSDOS_SB(sb
)->cvf_format
->cvf_file_write
)
359 return MSDOS_SB(sb
)->cvf_format
360 ->cvf_file_write(filp
,buf
,count
,ppos
);
362 /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
363 if (!S_ISREG(inode
->i_mode
) && !S_ISLNK(inode
->i_mode
)) {
364 printk("fat_file_write: mode = %07o\n",inode
->i_mode
);
367 /* system files may be immutable */
368 if (IS_IMMUTABLE(inode
))
371 * ok, append may not work when many processes are writing at the same time
372 * but so what. That way leads to madness anyway.
374 if (filp
->f_flags
& O_APPEND
)
375 *ppos
= inode
->i_size
;
379 for (start
= buf
; count
|| carry
; count
-= size
) {
380 while (!(sector
= fat_smap(inode
,*ppos
>> SECTOR_BITS
)))
381 if ((error
= fat_add_cluster(inode
)) < 0) break;
386 offset
= *ppos
& (SECTOR_SIZE
-1);
387 size
= MIN(SECTOR_SIZE
-offset
,MAX(carry
,count
));
390 && (size
== SECTOR_SIZE
391 || *ppos
+ size
>= inode
->i_size
)){
392 /* No need to read the block first since we will */
393 /* completely overwrite it */
394 /* or at least write past the end of file */
395 if (!(bh
= fat_getblk(sb
,sector
))){
399 } else if (!(bh
= fat_bread(sb
,sector
))) {
404 copy_from_user(bh
->b_data
+offset
,buf
,written
= size
);
407 written
= left
= SECTOR_SIZE
-offset
;
408 to
= (char *) bh
->b_data
+(*ppos
& (SECTOR_SIZE
-1));
414 for (size
= 0; size
< count
&& left
; size
++) {
420 if (!left
) carry
= 1;
428 update_vm_cache(inode
, *ppos
, bh
->b_data
+ (*ppos
& (SECTOR_SIZE
-1)), written
);
430 if (*ppos
> inode
->i_size
) {
431 inode
->i_size
= *ppos
;
432 mark_inode_dirty(inode
);
434 fat_set_uptodate(sb
, bh
, 1);
435 fat_mark_buffer_dirty(sb
, bh
, 0);
440 inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
441 MSDOS_I(inode
)->i_attrs
|= ATTR_ARCH
;
442 mark_inode_dirty(inode
);
446 void fat_truncate(struct inode
*inode
)
450 /* Why no return value? Surely the disk could fail... */
451 if (IS_IMMUTABLE(inode
))
453 cluster
= SECTOR_SIZE
*MSDOS_SB(inode
->i_sb
)->cluster_size
;
454 (void) fat_free(inode
,(inode
->i_size
+(cluster
-1))/cluster
);
455 MSDOS_I(inode
)->i_attrs
|= ATTR_ARCH
;
456 mark_inode_dirty(inode
);