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