Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Mikulas Patocka and committed by
Linus Torvalds
1c0b8a7a 2cbe5c76

+50 -46
+50 -46
fs/hpfs/buffer.c
··· 86 86 void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh, 87 87 int ahead) 88 88 { 89 - struct buffer_head *bh; 90 89 char *data; 91 90 92 91 hpfs_lock_assert(s); ··· 99 100 100 101 hpfs_prefetch_sectors(s, secno, 4 + ahead); 101 102 103 + if (!(qbh->bh[0] = sb_bread(s, secno + 0))) goto bail0; 104 + if (!(qbh->bh[1] = sb_bread(s, secno + 1))) goto bail1; 105 + if (!(qbh->bh[2] = sb_bread(s, secno + 2))) goto bail2; 106 + if (!(qbh->bh[3] = sb_bread(s, secno + 3))) goto bail3; 107 + 108 + if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && 109 + likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && 110 + likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) { 111 + return qbh->data = qbh->bh[0]->b_data; 112 + } 113 + 102 114 qbh->data = data = kmalloc(2048, GFP_NOFS); 103 115 if (!data) { 104 116 printk("HPFS: hpfs_map_4sectors: out of memory\n"); 105 - goto bail; 117 + goto bail4; 106 118 } 107 119 108 - qbh->bh[0] = bh = sb_bread(s, secno); 109 - if (!bh) 110 - goto bail0; 111 - memcpy(data, bh->b_data, 512); 112 - 113 - qbh->bh[1] = bh = sb_bread(s, secno + 1); 114 - if (!bh) 115 - goto bail1; 116 - memcpy(data + 512, bh->b_data, 512); 117 - 118 - qbh->bh[2] = bh = sb_bread(s, secno + 2); 119 - if (!bh) 120 - goto bail2; 121 - memcpy(data + 2 * 512, bh->b_data, 512); 122 - 123 - qbh->bh[3] = bh = sb_bread(s, secno + 3); 124 - if (!bh) 125 - goto bail3; 126 - memcpy(data + 3 * 512, bh->b_data, 512); 120 + memcpy(data + 0 * 512, qbh->bh[0]->b_data, 512); 121 + memcpy(data + 1 * 512, qbh->bh[1]->b_data, 512); 122 + memcpy(data + 2 * 512, qbh->bh[2]->b_data, 512); 123 + memcpy(data + 3 * 512, qbh->bh[3]->b_data, 512); 127 124 128 125 return data; 129 126 127 + bail4: 128 + brelse(qbh->bh[3]); 130 129 bail3: 131 130 brelse(qbh->bh[2]); 132 131 bail2: ··· 132 135 bail1: 133 136 brelse(qbh->bh[0]); 134 137 bail0: 135 - kfree(data); 136 - printk("HPFS: hpfs_map_4sectors: read error\n"); 137 - bail: 138 138 return NULL; 139 139 } 140 140 ··· 149 155 return NULL; 150 156 } 151 157 152 - /*return hpfs_map_4sectors(s, secno, qbh, 0);*/ 158 + if (!hpfs_get_sector(s, secno + 0, &qbh->bh[0])) goto bail0; 159 + if (!hpfs_get_sector(s, secno + 1, &qbh->bh[1])) goto bail1; 160 + if (!hpfs_get_sector(s, secno + 2, &qbh->bh[2])) goto bail2; 161 + if (!hpfs_get_sector(s, secno + 3, &qbh->bh[3])) goto bail3; 162 + 163 + if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && 164 + likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && 165 + likely(qbh->bh[3]->b_data == qbh->bh[0]->b_data + 3 * 512)) { 166 + return qbh->data = qbh->bh[0]->b_data; 167 + } 168 + 153 169 if (!(qbh->data = kmalloc(2048, GFP_NOFS))) { 154 170 printk("HPFS: hpfs_get_4sectors: out of memory\n"); 155 - return NULL; 171 + goto bail4; 156 172 } 157 - if (!(hpfs_get_sector(s, secno, &qbh->bh[0]))) goto bail0; 158 - if (!(hpfs_get_sector(s, secno + 1, &qbh->bh[1]))) goto bail1; 159 - if (!(hpfs_get_sector(s, secno + 2, &qbh->bh[2]))) goto bail2; 160 - if (!(hpfs_get_sector(s, secno + 3, &qbh->bh[3]))) goto bail3; 161 - memcpy(qbh->data, qbh->bh[0]->b_data, 512); 162 - memcpy(qbh->data + 512, qbh->bh[1]->b_data, 512); 163 - memcpy(qbh->data + 2*512, qbh->bh[2]->b_data, 512); 164 - memcpy(qbh->data + 3*512, qbh->bh[3]->b_data, 512); 165 173 return qbh->data; 166 174 167 - bail3: brelse(qbh->bh[2]); 168 - bail2: brelse(qbh->bh[1]); 169 - bail1: brelse(qbh->bh[0]); 170 - bail0: 175 + bail4: 176 + brelse(qbh->bh[3]); 177 + bail3: 178 + brelse(qbh->bh[2]); 179 + bail2: 180 + brelse(qbh->bh[1]); 181 + bail1: 182 + brelse(qbh->bh[0]); 183 + bail0: 171 184 return NULL; 172 185 } 173 186 174 187 175 188 void hpfs_brelse4(struct quad_buffer_head *qbh) 176 189 { 177 - brelse(qbh->bh[3]); 178 - brelse(qbh->bh[2]); 179 - brelse(qbh->bh[1]); 190 + if (unlikely(qbh->data != qbh->bh[0]->b_data)) 191 + kfree(qbh->data); 180 192 brelse(qbh->bh[0]); 181 - kfree(qbh->data); 193 + brelse(qbh->bh[1]); 194 + brelse(qbh->bh[2]); 195 + brelse(qbh->bh[3]); 182 196 } 183 197 184 198 void hpfs_mark_4buffers_dirty(struct quad_buffer_head *qbh) 185 199 { 186 - memcpy(qbh->bh[0]->b_data, qbh->data, 512); 187 - memcpy(qbh->bh[1]->b_data, qbh->data + 512, 512); 188 - memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512); 189 - memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512); 200 + if (unlikely(qbh->data != qbh->bh[0]->b_data)) { 201 + memcpy(qbh->bh[0]->b_data, qbh->data + 0 * 512, 512); 202 + memcpy(qbh->bh[1]->b_data, qbh->data + 1 * 512, 512); 203 + memcpy(qbh->bh[2]->b_data, qbh->data + 2 * 512, 512); 204 + memcpy(qbh->bh[3]->b_data, qbh->data + 3 * 512, 512); 205 + } 190 206 mark_buffer_dirty(qbh->bh[0]); 191 207 mark_buffer_dirty(qbh->bh[1]); 192 208 mark_buffer_dirty(qbh->bh[2]);