1 /*
2 * linux/fs/fat/buffer.c
3 *
4 *
5 */
6
7 #include <linux/mm.h>
8 #include <linux/malloc.h>
9 #include <linux/string.h>
10 #include <linux/fs.h>
11 #include <linux/msdos_fs.h>
12 #include <linux/fat_cvf.h>
13
14 #if 0
15 # define PRINTK(x) printk x
16 #else
17 # define PRINTK(x)
18 #endif
19
20 struct buffer_head *fat_bread(struct super_block *sb, int block)
21 {
22 return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block);
23 }
24 struct buffer_head *fat_getblk(struct super_block *sb, int block)
25 {
26 return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block);
27 }
28 void fat_brelse (struct super_block *sb, struct buffer_head *bh)
29 {
30 if (bh)
31 MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh);
32 }
33 void fat_mark_buffer_dirty (
34 struct super_block *sb,
35 struct buffer_head *bh)
36 {
37 MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh);
38 }
39 void fat_set_uptodate (
40 struct super_block *sb,
41 struct buffer_head *bh,
42 int val)
43 {
44 MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val);
45 }
46 int fat_is_uptodate(struct super_block *sb, struct buffer_head *bh)
47 {
48 return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh);
49 }
50 void fat_ll_rw_block (
51 struct super_block *sb,
52 int opr,
53 int nbreq,
54 struct buffer_head *bh[32])
55 {
56 MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh);
57 }
58
59 struct buffer_head *default_fat_bread(struct super_block *sb, int block)
60 {
61 return bread (sb->s_dev,block,512);
62 }
63 struct buffer_head *default_fat_getblk(struct super_block *sb, int block)
64 {
65 return getblk (sb->s_dev,block,512);
66 }
67 void default_fat_brelse(struct super_block *sb, struct buffer_head *bh)
68 {
69 brelse (bh);
70 }
71 void default_fat_mark_buffer_dirty (
72 struct super_block *sb,
73 struct buffer_head *bh)
74 {
75 mark_buffer_dirty (bh);
76 }
77 void default_fat_set_uptodate (
78 struct super_block *sb,
79 struct buffer_head *bh,
80 int val)
81 {
82 mark_buffer_uptodate(bh, val);
83 }
84 int default_fat_is_uptodate (struct super_block *sb, struct buffer_head *bh)
85 {
86 return buffer_uptodate(bh);
87 }
88 void default_fat_ll_rw_block (
89 struct super_block *sb,
90 int opr,
91 int nbreq,
92 struct buffer_head *bh[32])
93 {
94 ll_rw_block(opr,nbreq,bh);
95 }
96
97 struct buffer_head *bigblock_fat_bread (
98 struct super_block *sb,
99 int block)
100 {
101 struct buffer_head *ret = NULL;
102 struct buffer_head *real;
103 if (sb->s_blocksize == 1024){
104 real = bread (sb->s_dev,block>>1,1024);
105 } else {
106 real = bread (sb->s_dev,block>>2,2048);
107 }
108
109 if (real != NULL) {
110 ret = (struct buffer_head *)
111 kmalloc (sizeof(struct buffer_head), GFP_KERNEL);
112 if (ret != NULL) {
113 /* #Specification: msdos / strategy / special device / dummy blocks
114 * Many special device (Scsi optical disk for one) use
115 * larger hardware sector size. This allows for higher
116 * capacity.
117
118 * Most of the time, the MS-DOS filesystem that sits
119 * on this device is totally unaligned. It use logically
120 * 512 bytes sector size, with logical sector starting
121 * in the middle of a hardware block. The bad news is
122 * that a hardware sector may hold data own by two
123 * different files. This means that the hardware sector
124 * must be read, patch and written almost all the time.
125
126 * Needless to say that it kills write performance
127 * on all OS.
128
129 * Internally the linux msdos fs is using 512 bytes
130 * logical sector. When accessing such a device, we
131 * allocate dummy buffer cache blocks, that we stuff
132 * with the information of a real one (1k large).
133
134 * This strategy is used to hide this difference to
135 * the core of the msdos fs. The slowdown is not
136 * hidden though!
137 */
138 /*
139 * The memset is there only to catch errors. The msdos
140 * fs is only using b_data
141 */
142 memset (ret,0,sizeof(*ret));
143 ret->b_data = real->b_data;
144 if (sb->s_blocksize == 2048) {
145 if (block & 3) ret->b_data += (block & 3) << 9;
146 }else{
147 if (block & 1) ret->b_data += 512;
148 }
149 ret->b_next = real;
150 }else{
151 brelse (real);
152 }
153 }
154 return ret;
155 }
156
157 void bigblock_fat_brelse (
158 struct super_block *sb,
159 struct buffer_head *bh)
160 {
161 brelse (bh->b_next);
162 /*
163 * We can free the dummy because a new one is allocated at
164 * each fat_getblk() and fat_bread().
165 */
166 kfree (bh);
167 }
168
169 void bigblock_fat_mark_buffer_dirty (
170 struct super_block *sb,
171 struct buffer_head *bh)
172 {
173 mark_buffer_dirty (bh->b_next);
174 }
175
176 void bigblock_fat_set_uptodate (
177 struct super_block *sb,
178 struct buffer_head *bh,
179 int val)
180 {
181 mark_buffer_uptodate(bh->b_next, val);
182 }
183
184 int bigblock_fat_is_uptodate (
185 struct super_block *sb,
186 struct buffer_head *bh)
187 {
188 return buffer_uptodate(bh->b_next);
189 }
190
191 void bigblock_fat_ll_rw_block (
192 struct super_block *sb,
193 int opr,
194 int nbreq,
195 struct buffer_head *bh[32])
196 {
197 struct buffer_head *tmp[32];
198 int i;
199 for (i=0; i<nbreq; i++)
200 tmp[i] = bh[i]->b_next;
201 ll_rw_block(opr,nbreq,tmp);
202 }
203
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.