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.

GFS2: Use kmalloc when possible for ->readdir()

If we don't need a huge amount of memory in ->readdir() then
we can use kmalloc rather than vmalloc to allocate it. This
should cut down on the greater overheads associated with
vmalloc for smaller directories.

We may be able to eliminate vmalloc entirely at some stage,
but this is easy to do right away.

Also using GFP_NOFS to avoid any issues wrt to deleting inodes
while under a glock, and suggestion from Linus to factor out
the alloc/dealloc.

I've given this a test with a variety of different sized
directories and it seems to work ok.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Steven Whitehouse and committed by
Linus Torvalds
d2a97a4e fc0f5ac8

+25 -6
+25 -6
fs/gfs2/dir.c
··· 1231 1231 return 0; 1232 1232 } 1233 1233 1234 + static void *gfs2_alloc_sort_buffer(unsigned size) 1235 + { 1236 + void *ptr = NULL; 1237 + 1238 + if (size < KMALLOC_MAX_SIZE) 1239 + ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN); 1240 + if (!ptr) 1241 + ptr = __vmalloc(size, GFP_NOFS, PAGE_KERNEL); 1242 + return ptr; 1243 + } 1244 + 1245 + static void gfs2_free_sort_buffer(void *ptr) 1246 + { 1247 + if (is_vmalloc_addr(ptr)) 1248 + vfree(ptr); 1249 + else 1250 + kfree(ptr); 1251 + } 1252 + 1234 1253 static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, 1235 1254 filldir_t filldir, int *copied, unsigned *depth, 1236 1255 u64 leaf_no) ··· 1290 1271 * 99 is the maximum number of entries that can fit in a single 1291 1272 * leaf block. 1292 1273 */ 1293 - larr = vmalloc((leaves + entries + 99) * sizeof(void *)); 1274 + larr = gfs2_alloc_sort_buffer((leaves + entries + 99) * sizeof(void *)); 1294 1275 if (!larr) 1295 1276 goto out; 1296 1277 darr = (const struct gfs2_dirent **)(larr + leaves); ··· 1301 1282 do { 1302 1283 error = get_leaf(ip, lfn, &bh); 1303 1284 if (error) 1304 - goto out_kfree; 1285 + goto out_free; 1305 1286 lf = (struct gfs2_leaf *)bh->b_data; 1306 1287 lfn = be64_to_cpu(lf->lf_next); 1307 1288 if (lf->lf_entries) { ··· 1310 1291 gfs2_dirent_gather, NULL, &g); 1311 1292 error = PTR_ERR(dent); 1312 1293 if (IS_ERR(dent)) 1313 - goto out_kfree; 1294 + goto out_free; 1314 1295 if (entries2 != g.offset) { 1315 1296 fs_warn(sdp, "Number of entries corrupt in dir " 1316 1297 "leaf %llu, entries2 (%u) != " ··· 1319 1300 entries2, g.offset); 1320 1301 1321 1302 error = -EIO; 1322 - goto out_kfree; 1303 + goto out_free; 1323 1304 } 1324 1305 error = 0; 1325 1306 larr[leaf++] = bh; ··· 1331 1312 BUG_ON(entries2 != entries); 1332 1313 error = do_filldir_main(ip, offset, opaque, filldir, darr, 1333 1314 entries, copied); 1334 - out_kfree: 1315 + out_free: 1335 1316 for(i = 0; i < leaf; i++) 1336 1317 brelse(larr[i]); 1337 - vfree(larr); 1318 + gfs2_free_sort_buffer(larr); 1338 1319 out: 1339 1320 return error; 1340 1321 }