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