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
13 struct buffer_head *fat_bread (
/* ![[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)
*/
14 struct super_block *sb,
15 int block)
16 {
17 struct buffer_head *ret = NULL;
18 if (sb->s_blocksize == 512){
19 /* ret = bread (sb->s_dev,block,512); */
20 ret = breada (sb->s_dev,block,512,0,18*1024);
21 }else{
22 /* struct buffer_head *real = bread (sb->s_dev,block>>1,1024); */
23 struct buffer_head *real = breada (sb->s_dev,block>>1,1024,0,18*1024);
24 if (real != NULL){
25 ret = (struct buffer_head *)kmalloc (sizeof(struct buffer_head)
26 ,GFP_KERNEL);
27 if (ret != NULL){
28 /* #Specification: msdos / strategy / special device / dummy blocks
29 Many special device (Scsi optical disk for one) use
30 larger hardware sector size. This allows for higher
31 capacity.
32
33 Most of the time, the MsDOS file system that sit
34 on this device is totally unaligned. It use logically
35 512 bytes sector size, with logical sector starting
36 in the middle of a hardware block. The bad news is
37 that a hardware sector may hold data own by two
38 different files. This means that the hardware sector
39 must be read, patch and written almost all the time.
40
41 Needless to say that it kills write performance
42 on all OS.
43
44 Internally the linux msdos fs is using 512 bytes
45 logical sector. When accessing such a device, we
46 allocate dummy buffer cache blocks, that we stuff
47 with the information of a real one (1k large).
48
49 This strategy is used to hide this difference to
50 the core of the msdos fs. The slowdown is not
51 hidden though!
52 */
53 /*
54 The memset is there only to catch errors. The msdos
55 fs is only using b_data
56 */
57 memset (ret,0,sizeof(*ret));
58 ret->b_data = real->b_data;
59 if (block & 1) ret->b_data += 512;
60 ret->b_next = real;
61 }else{
62 brelse (real);
63 }
64 }
65 }
66 return ret;
67 }
68 struct buffer_head *fat_getblk (
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
69 struct super_block *sb,
70 int block)
71 {
72 struct buffer_head *ret = NULL;
73 if (sb->s_blocksize == 512){
74 ret = getblk (sb->s_dev,block,512);
75 }else{
76 /* #Specification: msdos / special device / writing
77 A write is always preceded by a read of the complete block
78 (large hardware sector size). This defeat write performance.
79 There is a possibility to optimize this when writing large
80 chunk by making sure we are filling large block. Volunteer ?
81 */
82 ret = fat_bread (sb,block);
83 }
84 return ret;
85 }
86
87 void fat_brelse (
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
88 struct super_block *sb,
89 struct buffer_head *bh)
90 {
91 if (bh != NULL){
92 if (sb->s_blocksize == 512){
93 brelse (bh);
94 }else{
95 brelse (bh->b_next);
96 /* We can free the dummy because a new one is allocated at
97 each fat_getblk() and fat_bread().
98 */
99 kfree (bh);
100 }
101 }
102 }
103
104 void fat_mark_buffer_dirty (
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
105 struct super_block *sb,
106 struct buffer_head *bh,
107 int dirty_val)
108 {
109 if (sb->s_blocksize != 512){
110 bh = bh->b_next;
111 }
112 mark_buffer_dirty (bh,dirty_val);
113 }
114
115 void fat_set_uptodate (
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
116 struct super_block *sb,
117 struct buffer_head *bh,
118 int val)
119 {
120 if (sb->s_blocksize != 512){
121 bh = bh->b_next;
122 }
123 mark_buffer_uptodate(bh, val);
124 }
125 int fat_is_uptodate (
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
126 struct super_block *sb,
127 struct buffer_head *bh)
128 {
129 if (sb->s_blocksize != 512){
130 bh = bh->b_next;
131 }
132 return buffer_uptodate(bh);
133 }
134
135 void fat_ll_rw_block (
/* ![[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)
*/
136 struct super_block *sb,
137 int opr,
138 int nbreq,
139 struct buffer_head *bh[32])
140 {
141 if (sb->s_blocksize == 512){
142 ll_rw_block(opr,nbreq,bh);
143 }else{
144 struct buffer_head *tmp[32];
145 int i;
146 for (i=0; i<nbreq; i++){
147 tmp[i] = bh[i]->b_next;
148 }
149 ll_rw_block(opr,nbreq,tmp);
150 }
151 }
152