Blame view

fs/hpfs/buffer.c 5.28 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   *  linux/fs/hpfs/buffer.c
   *
   *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
   *
   *  general buffer i/o
   */
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
8
  #include <linux/sched.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
9
  #include <linux/slab.h>
275f495db   Mikulas Patocka   hpfs: implement p...
10
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
  #include "hpfs_fn.h"
a64eefaac   Mikulas Patocka   hpfs: support hot...
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  secno hpfs_search_hotfix_map(struct super_block *s, secno sec)
  {
  	unsigned i;
  	struct hpfs_sb_info *sbi = hpfs_sb(s);
  	for (i = 0; unlikely(i < sbi->n_hotfixes); i++) {
  		if (sbi->hotfix_from[i] == sec) {
  			return sbi->hotfix_to[i];
  		}
  	}
  	return sec;
  }
  
  unsigned hpfs_search_hotfix_map_for_range(struct super_block *s, secno sec, unsigned n)
  {
  	unsigned i;
  	struct hpfs_sb_info *sbi = hpfs_sb(s);
  	for (i = 0; unlikely(i < sbi->n_hotfixes); i++) {
  		if (sbi->hotfix_from[i] >= sec && sbi->hotfix_from[i] < sec + n) {
  			n = sbi->hotfix_from[i] - sec;
  		}
  	}
  	return n;
  }
275f495db   Mikulas Patocka   hpfs: implement p...
35
36
37
38
39
40
41
  void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)
  {
  	struct buffer_head *bh;
  	struct blk_plug plug;
  
  	if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size))
  		return;
a64eefaac   Mikulas Patocka   hpfs: support hot...
42
43
  	if (unlikely(hpfs_search_hotfix_map_for_range(s, secno, n) != n))
  		return;
275f495db   Mikulas Patocka   hpfs: implement p...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  	bh = sb_find_get_block(s, secno);
  	if (bh) {
  		if (buffer_uptodate(bh)) {
  			brelse(bh);
  			return;
  		}
  		brelse(bh);
  	};
  
  	blk_start_plug(&plug);
  	while (n > 0) {
  		if (unlikely(secno >= hpfs_sb(s)->sb_fs_size))
  			break;
  		sb_breadahead(s, secno);
  		secno++;
  		n--;
  	}
  	blk_finish_plug(&plug);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
68
  /* Map a sector into a buffer and return pointers to it and to the buffer. */
  
  void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp,
  		 int ahead)
  {
  	struct buffer_head *bh;
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
69
  	hpfs_lock_assert(s);
275f495db   Mikulas Patocka   hpfs: implement p...
70
  	hpfs_prefetch_sectors(s, secno, ahead);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  	cond_resched();
a64eefaac   Mikulas Patocka   hpfs: support hot...
72
  	*bhp = bh = sb_bread(s, hpfs_search_hotfix_map(s, secno));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
  	if (bh != NULL)
  		return bh->b_data;
  	else {
a19189e55   Fabian Frederick   fs/hpfs: increase...
76
77
  		pr_err("%s(): read error
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
82
83
84
85
86
87
  		return NULL;
  	}
  }
  
  /* Like hpfs_map_sector but don't read anything */
  
  void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp)
  {
  	struct buffer_head *bh;
  	/*return hpfs_map_sector(s, secno, bhp, 0);*/
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
88
  	hpfs_lock_assert(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  	cond_resched();
a64eefaac   Mikulas Patocka   hpfs: support hot...
90
  	if ((*bhp = bh = sb_getblk(s, hpfs_search_hotfix_map(s, secno))) != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
  		if (!buffer_uptodate(bh)) wait_on_buffer(bh);
  		set_buffer_uptodate(bh);
  		return bh->b_data;
  	} else {
a19189e55   Fabian Frederick   fs/hpfs: increase...
95
96
  		pr_err("%s(): getblk failed
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
100
101
102
103
104
105
  		return NULL;
  	}
  }
  
  /* Map 4 sectors into a 4buffer and return pointers to it and to the buffer. */
  
  void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh,
  		   int ahead)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
  	char *data;
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
107
  	hpfs_lock_assert(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
  	cond_resched();
  
  	if (secno & 3) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
111
112
  		pr_err("%s(): unaligned read
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
  		return NULL;
  	}
275f495db   Mikulas Patocka   hpfs: implement p...
115
  	hpfs_prefetch_sectors(s, secno, 4 + ahead);
a64eefaac   Mikulas Patocka   hpfs: support hot...
116
117
118
119
  	if (!hpfs_map_sector(s, secno + 0, &qbh->bh[0], 0)) goto bail0;
  	if (!hpfs_map_sector(s, secno + 1, &qbh->bh[1], 0)) goto bail1;
  	if (!hpfs_map_sector(s, secno + 2, &qbh->bh[2], 0)) goto bail2;
  	if (!hpfs_map_sector(s, secno + 3, &qbh->bh[3], 0)) goto bail3;
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
120
121
122
123
124
125
  
  	if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) &&
  	    likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) &&
  	    likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) {
  		return qbh->data = qbh->bh[0]->b_data;
  	}
f52720ca5   Panagiotis Issaris   [PATCH] fs: Remov...
126
  	qbh->data = data = kmalloc(2048, GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  	if (!data) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
128
129
  		pr_err("%s(): out of memory
  ", __func__);
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
130
  		goto bail4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  	}
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
132
133
134
135
  	memcpy(data + 0 * 512, qbh->bh[0]->b_data, 512);
  	memcpy(data + 1 * 512, qbh->bh[1]->b_data, 512);
  	memcpy(data + 2 * 512, qbh->bh[2]->b_data, 512);
  	memcpy(data + 3 * 512, qbh->bh[3]->b_data, 512);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  
  	return data;
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
138
139
   bail4:
  	brelse(qbh->bh[3]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
   bail3:
  	brelse(qbh->bh[2]);
   bail2:
  	brelse(qbh->bh[1]);
   bail1:
  	brelse(qbh->bh[0]);
   bail0:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
153
154
155
  	return NULL;
  }
  
  /* Don't read sectors */
  
  void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
                            struct quad_buffer_head *qbh)
  {
  	cond_resched();
7dd29d8d8   Mikulas Patocka   HPFS: Introduce a...
156
  	hpfs_lock_assert(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  	if (secno & 3) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
158
159
  		pr_err("%s(): unaligned read
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  		return NULL;
  	}
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
162
163
164
165
166
167
168
169
170
171
  	if (!hpfs_get_sector(s, secno + 0, &qbh->bh[0])) goto bail0;
  	if (!hpfs_get_sector(s, secno + 1, &qbh->bh[1])) goto bail1;
  	if (!hpfs_get_sector(s, secno + 2, &qbh->bh[2])) goto bail2;
  	if (!hpfs_get_sector(s, secno + 3, &qbh->bh[3])) goto bail3;
  
  	if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) &&
  	    likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) &&
  	    likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) {
  		return qbh->data = qbh->bh[0]->b_data;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  	if (!(qbh->data = kmalloc(2048, GFP_NOFS))) {
a19189e55   Fabian Frederick   fs/hpfs: increase...
173
174
  		pr_err("%s(): out of memory
  ", __func__);
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
175
  		goto bail4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  	return qbh->data;
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
178
179
180
181
182
183
184
185
186
  bail4:
  	brelse(qbh->bh[3]);
  bail3:
  	brelse(qbh->bh[2]);
  bail2:
  	brelse(qbh->bh[1]);
  bail1:
  	brelse(qbh->bh[0]);
  bail0:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
191
192
  	return NULL;
  }
  	
  
  void hpfs_brelse4(struct quad_buffer_head *qbh)
  {
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
193
194
  	if (unlikely(qbh->data != qbh->bh[0]->b_data))
  		kfree(qbh->data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  	brelse(qbh->bh[0]);
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
196
197
198
  	brelse(qbh->bh[1]);
  	brelse(qbh->bh[2]);
  	brelse(qbh->bh[3]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
  }	
  
  void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh)
  {
1c0b8a7a6   Mikulas Patocka   hpfs: optimize qu...
203
204
205
206
207
208
  	if (unlikely(qbh->data != qbh->bh[0]->b_data)) {
  		memcpy(qbh->bh[0]->b_data, qbh->data + 0 * 512, 512);
  		memcpy(qbh->bh[1]->b_data, qbh->data + 1 * 512, 512);
  		memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512);
  		memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
  	mark_buffer_dirty(qbh->bh[0]);
  	mark_buffer_dirty(qbh->bh[1]);
  	mark_buffer_dirty(qbh->bh[2]);
  	mark_buffer_dirty(qbh->bh[3]);
  }