Skip to content

Commit 1c0b8a7

Browse files
Mikulas Patockatorvalds
Mikulas Patocka
authored andcommitted
hpfs: optimize quad buffer loading
HPFS needs to load 4 consecutive 512-byte sectors when accessing the directory nodes or bitmaps. We can't switch to 2048-byte block size because files are allocated in the units of 512-byte sectors. Previously, the driver would allocate a 2048-byte area using kmalloc, copy the data from four buffers to this area and eventually copy them back if they were modified. In the current implementation of the buffer cache, buffers are allocated in the pagecache. That means that 4 consecutive 512-byte buffers are stored in consecutive areas in the kernel address space. So, we don't need to allocate extra memory and copy the content of the buffers there. This patch optimizes the code to avoid copying the buffers. It checks if the four buffers are stored in contiguous memory - if they are not, it falls back to allocating a 2048-byte area and copying data there. Signed-off-by: Mikulas Patocka <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 2cbe5c7 commit 1c0b8a7

File tree

1 file changed

+50
-46
lines changed

1 file changed

+50
-46
lines changed

fs/hpfs/buffer.c

+50-46
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head
8686
void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh,
8787
int ahead)
8888
{
89-
struct buffer_head *bh;
9089
char *data;
9190

9291
hpfs_lock_assert(s);
@@ -100,44 +99,39 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
10099

101100
hpfs_prefetch_sectors(s, secno, 4 + ahead);
102101

102+
if (!(qbh->bh[0] = sb_bread(s, secno + 0))) goto bail0;
103+
if (!(qbh->bh[1] = sb_bread(s, secno + 1))) goto bail1;
104+
if (!(qbh->bh[2] = sb_bread(s, secno + 2))) goto bail2;
105+
if (!(qbh->bh[3] = sb_bread(s, secno + 3))) goto bail3;
106+
107+
if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) &&
108+
likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) &&
109+
likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) {
110+
return qbh->data = qbh->bh[0]->b_data;
111+
}
112+
103113
qbh->data = data = kmalloc(2048, GFP_NOFS);
104114
if (!data) {
105115
printk("HPFS: hpfs_map_4sectors: out of memory\n");
106-
goto bail;
116+
goto bail4;
107117
}
108118

109-
qbh->bh[0] = bh = sb_bread(s, secno);
110-
if (!bh)
111-
goto bail0;
112-
memcpy(data, bh->b_data, 512);
113-
114-
qbh->bh[1] = bh = sb_bread(s, secno + 1);
115-
if (!bh)
116-
goto bail1;
117-
memcpy(data + 512, bh->b_data, 512);
118-
119-
qbh->bh[2] = bh = sb_bread(s, secno + 2);
120-
if (!bh)
121-
goto bail2;
122-
memcpy(data + 2 * 512, bh->b_data, 512);
123-
124-
qbh->bh[3] = bh = sb_bread(s, secno + 3);
125-
if (!bh)
126-
goto bail3;
127-
memcpy(data + 3 * 512, bh->b_data, 512);
119+
memcpy(data + 0 * 512, qbh->bh[0]->b_data, 512);
120+
memcpy(data + 1 * 512, qbh->bh[1]->b_data, 512);
121+
memcpy(data + 2 * 512, qbh->bh[2]->b_data, 512);
122+
memcpy(data + 3 * 512, qbh->bh[3]->b_data, 512);
128123

129124
return data;
130125

126+
bail4:
127+
brelse(qbh->bh[3]);
131128
bail3:
132129
brelse(qbh->bh[2]);
133130
bail2:
134131
brelse(qbh->bh[1]);
135132
bail1:
136133
brelse(qbh->bh[0]);
137134
bail0:
138-
kfree(data);
139-
printk("HPFS: hpfs_map_4sectors: read error\n");
140-
bail:
141135
return NULL;
142136
}
143137

@@ -155,44 +149,54 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
155149
return NULL;
156150
}
157151

158-
/*return hpfs_map_4sectors(s, secno, qbh, 0);*/
152+
if (!hpfs_get_sector(s, secno + 0, &qbh->bh[0])) goto bail0;
153+
if (!hpfs_get_sector(s, secno + 1, &qbh->bh[1])) goto bail1;
154+
if (!hpfs_get_sector(s, secno + 2, &qbh->bh[2])) goto bail2;
155+
if (!hpfs_get_sector(s, secno + 3, &qbh->bh[3])) goto bail3;
156+
157+
if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) &&
158+
likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) &&
159+
likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) {
160+
return qbh->data = qbh->bh[0]->b_data;
161+
}
162+
159163
if (!(qbh->data = kmalloc(2048, GFP_NOFS))) {
160164
printk("HPFS: hpfs_get_4sectors: out of memory\n");
161-
return NULL;
165+
goto bail4;
162166
}
163-
if (!(hpfs_get_sector(s, secno, &qbh->bh[0]))) goto bail0;
164-
if (!(hpfs_get_sector(s, secno + 1, &qbh->bh[1]))) goto bail1;
165-
if (!(hpfs_get_sector(s, secno + 2, &qbh->bh[2]))) goto bail2;
166-
if (!(hpfs_get_sector(s, secno + 3, &qbh->bh[3]))) goto bail3;
167-
memcpy(qbh->data, qbh->bh[0]->b_data, 512);
168-
memcpy(qbh->data + 512, qbh->bh[1]->b_data, 512);
169-
memcpy(qbh->data + 2*512, qbh->bh[2]->b_data, 512);
170-
memcpy(qbh->data + 3*512, qbh->bh[3]->b_data, 512);
171167
return qbh->data;
172168

173-
bail3: brelse(qbh->bh[2]);
174-
bail2: brelse(qbh->bh[1]);
175-
bail1: brelse(qbh->bh[0]);
176-
bail0:
169+
bail4:
170+
brelse(qbh->bh[3]);
171+
bail3:
172+
brelse(qbh->bh[2]);
173+
bail2:
174+
brelse(qbh->bh[1]);
175+
bail1:
176+
brelse(qbh->bh[0]);
177+
bail0:
177178
return NULL;
178179
}
179180

180181

181182
void hpfs_brelse4(struct quad_buffer_head *qbh)
182183
{
183-
brelse(qbh->bh[3]);
184-
brelse(qbh->bh[2]);
185-
brelse(qbh->bh[1]);
184+
if (unlikely(qbh->data != qbh->bh[0]->b_data))
185+
kfree(qbh->data);
186186
brelse(qbh->bh[0]);
187-
kfree(qbh->data);
187+
brelse(qbh->bh[1]);
188+
brelse(qbh->bh[2]);
189+
brelse(qbh->bh[3]);
188190
}
189191

190192
void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh)
191193
{
192-
memcpy(qbh->bh[0]->b_data, qbh->data, 512);
193-
memcpy(qbh->bh[1]->b_data, qbh->data + 512, 512);
194-
memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512);
195-
memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512);
194+
if (unlikely(qbh->data != qbh->bh[0]->b_data)) {
195+
memcpy(qbh->bh[0]->b_data, qbh->data + 0 * 512, 512);
196+
memcpy(qbh->bh[1]->b_data, qbh->data + 1 * 512, 512);
197+
memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512);
198+
memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512);
199+
}
196200
mark_buffer_dirty(qbh->bh[0]);
197201
mark_buffer_dirty(qbh->bh[1]);
198202
mark_buffer_dirty(qbh->bh[2]);

0 commit comments

Comments
 (0)