aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>2014-01-28 18:11:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-02-02 19:24:07 -0500
commit1c0b8a7a62c3d3ebf53a8e40cc6da22f5e192d63 (patch)
tree3ecae7ff3391cfcd628c2d78acee83a78e9de66e /fs
parent2cbe5c76fc5e38e9af4b709593146e4b8272b69e (diff)
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 <mikulas@artax.karlin.mff.cuni.cz> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/hpfs/buffer.c96
1 files changed, 50 insertions, 46 deletions
diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c
index 4d0a1afa058c..139ef1684d07 100644
--- a/fs/hpfs/buffer.c
+++ b/fs/hpfs/buffer.c
@@ -86,7 +86,6 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head
86void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh, 86void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh,
87 int ahead) 87 int ahead)
88{ 88{
89 struct buffer_head *bh;
90 char *data; 89 char *data;
91 90
92 hpfs_lock_assert(s); 91 hpfs_lock_assert(s);
@@ -100,34 +99,32 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
100 99
101 hpfs_prefetch_sectors(s, secno, 4 + ahead); 100 hpfs_prefetch_sectors(s, secno, 4 + ahead);
102 101
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
103 qbh->data = data = kmalloc(2048, GFP_NOFS); 113 qbh->data = data = kmalloc(2048, GFP_NOFS);
104 if (!data) { 114 if (!data) {
105 printk("HPFS: hpfs_map_4sectors: out of memory\n"); 115 printk("HPFS: hpfs_map_4sectors: out of memory\n");
106 goto bail; 116 goto bail4;
107 } 117 }
108 118
109 qbh->bh[0] = bh = sb_bread(s, secno); 119 memcpy(data + 0 * 512, qbh->bh[0]->b_data, 512);
110 if (!bh) 120 memcpy(data + 1 * 512, qbh->bh[1]->b_data, 512);
111 goto bail0; 121 memcpy(data + 2 * 512, qbh->bh[2]->b_data, 512);
112 memcpy(data, bh->b_data, 512); 122 memcpy(data + 3 * 512, qbh->bh[3]->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);
128 123
129 return data; 124 return data;
130 125
126 bail4:
127 brelse(qbh->bh[3]);
131 bail3: 128 bail3:
132 brelse(qbh->bh[2]); 129 brelse(qbh->bh[2]);
133 bail2: 130 bail2:
@@ -135,9 +132,6 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
135 bail1: 132 bail1:
136 brelse(qbh->bh[0]); 133 brelse(qbh->bh[0]);
137 bail0: 134 bail0:
138 kfree(data);
139 printk("HPFS: hpfs_map_4sectors: read error\n");
140 bail:
141 return NULL; 135 return NULL;
142} 136}
143 137
@@ -155,44 +149,54 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
155 return NULL; 149 return NULL;
156 } 150 }
157 151
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
159 if (!(qbh->data = kmalloc(2048, GFP_NOFS))) { 163 if (!(qbh->data = kmalloc(2048, GFP_NOFS))) {
160 printk("HPFS: hpfs_get_4sectors: out of memory\n"); 164 printk("HPFS: hpfs_get_4sectors: out of memory\n");
161 return NULL; 165 goto bail4;
162 } 166 }
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);
171 return qbh->data; 167 return qbh->data;
172 168
173 bail3: brelse(qbh->bh[2]); 169bail4:
174 bail2: brelse(qbh->bh[1]); 170 brelse(qbh->bh[3]);
175 bail1: brelse(qbh->bh[0]); 171bail3:
176 bail0: 172 brelse(qbh->bh[2]);
173bail2:
174 brelse(qbh->bh[1]);
175bail1:
176 brelse(qbh->bh[0]);
177bail0:
177 return NULL; 178 return NULL;
178} 179}
179 180
180 181
181void hpfs_brelse4(struct quad_buffer_head *qbh) 182void hpfs_brelse4(struct quad_buffer_head *qbh)
182{ 183{
183 brelse(qbh->bh[3]); 184 if (unlikely(qbh->data != qbh->bh[0]->b_data))
184 brelse(qbh->bh[2]); 185 kfree(qbh->data);
185 brelse(qbh->bh[1]);
186 brelse(qbh->bh[0]); 186 brelse(qbh->bh[0]);
187 kfree(qbh->data); 187 brelse(qbh->bh[1]);
188 brelse(qbh->bh[2]);
189 brelse(qbh->bh[3]);
188} 190}
189 191
190void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh) 192void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh)
191{ 193{
192 memcpy(qbh->bh[0]->b_data, qbh->data, 512); 194 if (unlikely(qbh->data != qbh->bh[0]->b_data)) {
193 memcpy(qbh->bh[1]->b_data, qbh->data + 512, 512); 195 memcpy(qbh->bh[0]->b_data, qbh->data + 0 * 512, 512);
194 memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512); 196 memcpy(qbh->bh[1]->b_data, qbh->data + 1 * 512, 512);
195 memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 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 }
196 mark_buffer_dirty(qbh->bh[0]); 200 mark_buffer_dirty(qbh->bh[0]);
197 mark_buffer_dirty(qbh->bh[1]); 201 mark_buffer_dirty(qbh->bh[1]);
198 mark_buffer_dirty(qbh->bh[2]); 202 mark_buffer_dirty(qbh->bh[2]);