2 * linux/fs/fat/buffer.c
8 #include <linux/malloc.h>
9 #include <linux/string.h>
11 #include <linux/msdos_fs.h>
12 #include <linux/fat_cvf.h>
15 # define PRINTK(x) printk x
20 struct buffer_head
*fat_bread (
21 struct super_block
*sb
,
24 struct buffer_head
*ret
= NULL
;
26 PRINTK(("fat_bread: block=0x%x\n", block
));
28 * Note that the blocksize is 512, 1024 or 2048, but the first read
29 * is always of size 1024 (or 2048). Doing readahead may be
30 * counterproductive or just plain wrong.
33 if(MSDOS_SB(sb
)->cvf_format
&&
34 MSDOS_SB(sb
)->cvf_format
->cvf_bread
)
35 return MSDOS_SB(sb
)->cvf_format
->cvf_bread(sb
,block
);
37 if (sb
->s_blocksize
== 512) {
38 ret
= bread (sb
->s_dev
,block
,512);
40 struct buffer_head
*real
;
41 if (sb
->s_blocksize
== 1024){
42 real
= bread (sb
->s_dev
,block
>>1,1024);
44 real
= bread (sb
->s_dev
,block
>>2,2048);
48 ret
= (struct buffer_head
*)
49 kmalloc (sizeof(struct buffer_head
), GFP_KERNEL
);
51 /* #Specification: msdos / strategy / special device / dummy blocks
52 * Many special device (Scsi optical disk for one) use
53 * larger hardware sector size. This allows for higher
56 * Most of the time, the MsDOS file system that sit
57 * on this device is totally unaligned. It use logically
58 * 512 bytes sector size, with logical sector starting
59 * in the middle of a hardware block. The bad news is
60 * that a hardware sector may hold data own by two
61 * different files. This means that the hardware sector
62 * must be read, patch and written almost all the time.
64 * Needless to say that it kills write performance
67 * Internally the linux msdos fs is using 512 bytes
68 * logical sector. When accessing such a device, we
69 * allocate dummy buffer cache blocks, that we stuff
70 * with the information of a real one (1k large).
72 * This strategy is used to hide this difference to
73 * the core of the msdos fs. The slowdown is not
77 * The memset is there only to catch errors. The msdos
78 * fs is only using b_data
80 memset (ret
,0,sizeof(*ret
));
81 ret
->b_data
= real
->b_data
;
82 if (sb
->s_blocksize
== 2048) {
83 if (block
& 3) ret
->b_data
+= (block
& 3) << 9;
85 if (block
& 1) ret
->b_data
+= 512;
96 struct buffer_head
*fat_getblk(struct super_block
*sb
, int block
)
98 struct buffer_head
*ret
= NULL
;
99 PRINTK(("fat_getblk: block=0x%x\n", block
));
101 if (MSDOS_SB(sb
)->cvf_format
&&
102 MSDOS_SB(sb
)->cvf_format
->cvf_getblk
)
103 return MSDOS_SB(sb
)->cvf_format
->cvf_getblk(sb
,block
);
105 if (sb
->s_blocksize
== 512){
106 ret
= getblk (sb
->s_dev
,block
,512);
109 * #Specification: msdos / special device / writing
110 * A write is always preceded by a read of the complete block
111 * (large hardware sector size). This defeat write performance.
112 * There is a possibility to optimize this when writing large
113 * chunk by making sure we are filling large block. Volunteer ?
115 ret
= fat_bread (sb
,block
);
121 struct super_block
*sb
,
122 struct buffer_head
*bh
)
125 if (MSDOS_SB(sb
)->cvf_format
&&
126 MSDOS_SB(sb
)->cvf_format
->cvf_brelse
)
127 return MSDOS_SB(sb
)->cvf_format
->cvf_brelse(sb
,bh
);
129 if (sb
->s_blocksize
== 512){
133 /* We can free the dummy because a new one is allocated at
134 each fat_getblk() and fat_bread().
141 void fat_mark_buffer_dirty (
142 struct super_block
*sb
,
143 struct buffer_head
*bh
,
146 if (MSDOS_SB(sb
)->cvf_format
&&
147 MSDOS_SB(sb
)->cvf_format
->cvf_mark_buffer_dirty
) {
148 MSDOS_SB(sb
)->cvf_format
->cvf_mark_buffer_dirty(sb
,bh
,dirty
);
152 if (sb
->s_blocksize
!= 512){
155 mark_buffer_dirty (bh
,dirty
);
158 void fat_set_uptodate (
159 struct super_block
*sb
,
160 struct buffer_head
*bh
,
163 if (MSDOS_SB(sb
)->cvf_format
&&
164 MSDOS_SB(sb
)->cvf_format
->cvf_set_uptodate
) {
165 MSDOS_SB(sb
)->cvf_format
->cvf_set_uptodate(sb
,bh
,val
);
169 if (sb
->s_blocksize
!= 512){
172 mark_buffer_uptodate(bh
, val
);
174 int fat_is_uptodate (
175 struct super_block
*sb
,
176 struct buffer_head
*bh
)
178 if(MSDOS_SB(sb
)->cvf_format
&&
179 MSDOS_SB(sb
)->cvf_format
->cvf_is_uptodate
)
180 return MSDOS_SB(sb
)->cvf_format
->cvf_is_uptodate(sb
,bh
);
182 if (sb
->s_blocksize
!= 512){
185 return buffer_uptodate(bh
);
188 void fat_ll_rw_block (
189 struct super_block
*sb
,
192 struct buffer_head
*bh
[32])
194 if (MSDOS_SB(sb
)->cvf_format
&&
195 MSDOS_SB(sb
)->cvf_format
->cvf_ll_rw_block
) {
196 MSDOS_SB(sb
)->cvf_format
->cvf_ll_rw_block(sb
,opr
,nbreq
,bh
);
200 if (sb
->s_blocksize
== 512){
201 ll_rw_block(opr
,nbreq
,bh
);
203 struct buffer_head
*tmp
[32];
205 for (i
=0; i
<nbreq
; i
++){
206 tmp
[i
] = bh
[i
]->b_next
;
208 ll_rw_block(opr
,nbreq
,tmp
);