aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/ialloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/ialloc.c')
-rw-r--r--fs/ext4/ialloc.c138
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 */
306static 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
337static 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
357find_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
395found_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;
406out:
407 return 0;
408}
409
410struct orlov_stats { 296struct 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
870got_group: 738got_group: