diff options
Diffstat (limited to 'fs/ext4/ialloc.c')
-rw-r--r-- | fs/ext4/ialloc.c | 138 |
1 files changed, 3 insertions, 135 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index d50a7d5e4726..04219988e75f 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -293,120 +293,6 @@ error_return: | |||
293 | ext4_std_error(sb, fatal); | 293 | ext4_std_error(sb, fatal); |
294 | } | 294 | } |
295 | 295 | ||
296 | /* | ||
297 | * There are two policies for allocating an inode. If the new inode is | ||
298 | * a directory, then a forward search is made for a block group with both | ||
299 | * free space and a low directory-to-inode ratio; if that fails, then of | ||
300 | * the groups with above-average free space, that group with the fewest | ||
301 | * directories already is chosen. | ||
302 | * | ||
303 | * For other inodes, search forward from the parent directory\'s block | ||
304 | * group to find a free inode. | ||
305 | */ | ||
306 | static int find_group_dir(struct super_block *sb, struct inode *parent, | ||
307 | ext4_group_t *best_group) | ||
308 | { | ||
309 | ext4_group_t ngroups = ext4_get_groups_count(sb); | ||
310 | unsigned int freei, avefreei; | ||
311 | struct ext4_group_desc *desc, *best_desc = NULL; | ||
312 | ext4_group_t group; | ||
313 | int ret = -1; | ||
314 | |||
315 | freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter); | ||
316 | avefreei = freei / ngroups; | ||
317 | |||
318 | for (group = 0; group < ngroups; group++) { | ||
319 | desc = ext4_get_group_desc(sb, group, NULL); | ||
320 | if (!desc || !ext4_free_inodes_count(sb, desc)) | ||
321 | continue; | ||
322 | if (ext4_free_inodes_count(sb, desc) < avefreei) | ||
323 | continue; | ||
324 | if (!best_desc || | ||
325 | (ext4_free_group_clusters(sb, desc) > | ||
326 | ext4_free_group_clusters(sb, best_desc))) { | ||
327 | *best_group = group; | ||
328 | best_desc = desc; | ||
329 | ret = 0; | ||
330 | } | ||
331 | } | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | #define free_block_ratio 10 | ||
336 | |||
337 | static int find_group_flex(struct super_block *sb, struct inode *parent, | ||
338 | ext4_group_t *best_group) | ||
339 | { | ||
340 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
341 | struct ext4_group_desc *desc; | ||
342 | struct flex_groups *flex_group = sbi->s_flex_groups; | ||
343 | ext4_group_t parent_group = EXT4_I(parent)->i_block_group; | ||
344 | ext4_group_t parent_fbg_group = ext4_flex_group(sbi, parent_group); | ||
345 | ext4_group_t ngroups = ext4_get_groups_count(sb); | ||
346 | int flex_size = ext4_flex_bg_size(sbi); | ||
347 | ext4_group_t best_flex = parent_fbg_group; | ||
348 | int blocks_per_flex = sbi->s_blocks_per_group * flex_size; | ||
349 | int flexbg_free_clusters; | ||
350 | int flex_freeb_ratio; | ||
351 | ext4_group_t n_fbg_groups; | ||
352 | ext4_group_t i; | ||
353 | |||
354 | n_fbg_groups = (ngroups + flex_size - 1) >> | ||
355 | sbi->s_log_groups_per_flex; | ||
356 | |||
357 | find_close_to_parent: | ||
358 | flexbg_free_clusters = atomic_read(&flex_group[best_flex].free_clusters); | ||
359 | flex_freeb_ratio = EXT4_C2B(sbi, flexbg_free_clusters) * 100 / | ||
360 | blocks_per_flex; | ||
361 | if (atomic_read(&flex_group[best_flex].free_inodes) && | ||
362 | flex_freeb_ratio > free_block_ratio) | ||
363 | goto found_flexbg; | ||
364 | |||
365 | if (best_flex && best_flex == parent_fbg_group) { | ||
366 | best_flex--; | ||
367 | goto find_close_to_parent; | ||
368 | } | ||
369 | |||
370 | for (i = 0; i < n_fbg_groups; i++) { | ||
371 | if (i == parent_fbg_group || i == parent_fbg_group - 1) | ||
372 | continue; | ||
373 | |||
374 | flexbg_free_clusters = atomic_read(&flex_group[i].free_clusters); | ||
375 | flex_freeb_ratio = EXT4_C2B(sbi, flexbg_free_clusters) * 100 / | ||
376 | blocks_per_flex; | ||
377 | |||
378 | if (flex_freeb_ratio > free_block_ratio && | ||
379 | (atomic_read(&flex_group[i].free_inodes))) { | ||
380 | best_flex = i; | ||
381 | goto found_flexbg; | ||
382 | } | ||
383 | |||
384 | if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) || | ||
385 | ((atomic_read(&flex_group[i].free_clusters) > | ||
386 | atomic_read(&flex_group[best_flex].free_clusters)) && | ||
387 | atomic_read(&flex_group[i].free_inodes))) | ||
388 | best_flex = i; | ||
389 | } | ||
390 | |||
391 | if (!atomic_read(&flex_group[best_flex].free_inodes) || | ||
392 | !atomic_read(&flex_group[best_flex].free_clusters)) | ||
393 | return -1; | ||
394 | |||
395 | found_flexbg: | ||
396 | for (i = best_flex * flex_size; i < ngroups && | ||
397 | i < (best_flex + 1) * flex_size; i++) { | ||
398 | desc = ext4_get_group_desc(sb, i, NULL); | ||
399 | if (ext4_free_inodes_count(sb, desc)) { | ||
400 | *best_group = i; | ||
401 | goto out; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | return -1; | ||
406 | out: | ||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | struct orlov_stats { | 296 | struct orlov_stats { |
411 | __u32 free_inodes; | 297 | __u32 free_inodes; |
412 | __u32 free_clusters; | 298 | __u32 free_clusters; |
@@ -819,7 +705,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode, | |||
819 | int ret2, err = 0; | 705 | int ret2, err = 0; |
820 | struct inode *ret; | 706 | struct inode *ret; |
821 | ext4_group_t i; | 707 | ext4_group_t i; |
822 | static int once = 1; | ||
823 | ext4_group_t flex_group; | 708 | ext4_group_t flex_group; |
824 | 709 | ||
825 | /* Cannot create files in a deleted directory */ | 710 | /* Cannot create files in a deleted directory */ |
@@ -845,26 +730,9 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode, | |||
845 | goto got_group; | 730 | goto got_group; |
846 | } | 731 | } |
847 | 732 | ||
848 | if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) { | 733 | if (S_ISDIR(mode)) |
849 | ret2 = find_group_flex(sb, dir, &group); | 734 | ret2 = find_group_orlov(sb, dir, &group, mode, qstr); |
850 | if (ret2 == -1) { | 735 | else |
851 | ret2 = find_group_other(sb, dir, &group, mode); | ||
852 | if (ret2 == 0 && once) { | ||
853 | once = 0; | ||
854 | printk(KERN_NOTICE "ext4: find_group_flex " | ||
855 | "failed, fallback succeeded dir %lu\n", | ||
856 | dir->i_ino); | ||
857 | } | ||
858 | } | ||
859 | goto got_group; | ||
860 | } | ||
861 | |||
862 | if (S_ISDIR(mode)) { | ||
863 | if (test_opt(sb, OLDALLOC)) | ||
864 | ret2 = find_group_dir(sb, dir, &group); | ||
865 | else | ||
866 | ret2 = find_group_orlov(sb, dir, &group, mode, qstr); | ||
867 | } else | ||
868 | ret2 = find_group_other(sb, dir, &group, mode); | 736 | ret2 = find_group_other(sb, dir, &group, mode); |
869 | 737 | ||
870 | got_group: | 738 | got_group: |