diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-18 17:07:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-18 17:07:46 -0400 |
| commit | 0732f87761dbe417cb6e084b712d07e879e876ef (patch) | |
| tree | afed6ca0368fd3e121fd4f43b11e32aa1e5139c0 /fs/ext4/ialloc.c | |
| parent | 15fc204afc6feb915c400159546f646eca8ba1d9 (diff) | |
| parent | 536fc240e7147858255bdb08e7a999a3351a9fb4 (diff) | |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
jbd2: clean up jbd2_journal_try_to_free_buffers()
ext4: Don't update ctime for non-extent-mapped inodes
ext4: Fix up whitespace issues in fs/ext4/inode.c
ext4: Fix 64-bit block type problem on 32-bit platforms
ext4: teach the inode allocator to use a goal inode number
ext4: Use a hash of the topdir directory name for the Orlov parent group
ext4: document the "abort" mount option
ext4: move the abort flag from s_mount_opts to s_mount_flags
ext4: update the s_last_mounted field in the superblock
ext4: change s_mount_opt to be an unsigned int
ext4: online defrag -- Add EXT4_IOC_MOVE_EXT ioctl
ext4: avoid unnecessary spinlock in critical POSIX ACL path
ext3: avoid unnecessary spinlock in critical POSIX ACL path
ext4: convert instrumentation from markers to tracepoints
jbd2: convert instrumentation from markers to tracepoints
Diffstat (limited to 'fs/ext4/ialloc.c')
| -rw-r--r-- | fs/ext4/ialloc.c | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 3743bd849bce..2f645732e3b7 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -23,11 +23,14 @@ | |||
| 23 | #include <linux/bitops.h> | 23 | #include <linux/bitops.h> |
| 24 | #include <linux/blkdev.h> | 24 | #include <linux/blkdev.h> |
| 25 | #include <asm/byteorder.h> | 25 | #include <asm/byteorder.h> |
| 26 | |||
| 26 | #include "ext4.h" | 27 | #include "ext4.h" |
| 27 | #include "ext4_jbd2.h" | 28 | #include "ext4_jbd2.h" |
| 28 | #include "xattr.h" | 29 | #include "xattr.h" |
| 29 | #include "acl.h" | 30 | #include "acl.h" |
| 30 | 31 | ||
| 32 | #include <trace/events/ext4.h> | ||
| 33 | |||
| 31 | /* | 34 | /* |
| 32 | * ialloc.c contains the inodes allocation and deallocation routines | 35 | * ialloc.c contains the inodes allocation and deallocation routines |
| 33 | */ | 36 | */ |
| @@ -208,11 +211,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) | |||
| 208 | 211 | ||
| 209 | ino = inode->i_ino; | 212 | ino = inode->i_ino; |
| 210 | ext4_debug("freeing inode %lu\n", ino); | 213 | ext4_debug("freeing inode %lu\n", ino); |
| 211 | trace_mark(ext4_free_inode, | 214 | trace_ext4_free_inode(inode); |
| 212 | "dev %s ino %lu mode %d uid %lu gid %lu bocks %llu", | ||
| 213 | sb->s_id, inode->i_ino, inode->i_mode, | ||
| 214 | (unsigned long) inode->i_uid, (unsigned long) inode->i_gid, | ||
| 215 | (unsigned long long) inode->i_blocks); | ||
| 216 | 215 | ||
| 217 | /* | 216 | /* |
| 218 | * Note: we must free any quota before locking the superblock, | 217 | * Note: we must free any quota before locking the superblock, |
| @@ -471,7 +470,8 @@ void get_orlov_stats(struct super_block *sb, ext4_group_t g, | |||
| 471 | */ | 470 | */ |
| 472 | 471 | ||
| 473 | static int find_group_orlov(struct super_block *sb, struct inode *parent, | 472 | static int find_group_orlov(struct super_block *sb, struct inode *parent, |
| 474 | ext4_group_t *group, int mode) | 473 | ext4_group_t *group, int mode, |
| 474 | const struct qstr *qstr) | ||
| 475 | { | 475 | { |
| 476 | ext4_group_t parent_group = EXT4_I(parent)->i_block_group; | 476 | ext4_group_t parent_group = EXT4_I(parent)->i_block_group; |
| 477 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 477 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| @@ -486,6 +486,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, | |||
| 486 | struct ext4_group_desc *desc; | 486 | struct ext4_group_desc *desc; |
| 487 | struct orlov_stats stats; | 487 | struct orlov_stats stats; |
| 488 | int flex_size = ext4_flex_bg_size(sbi); | 488 | int flex_size = ext4_flex_bg_size(sbi); |
| 489 | struct dx_hash_info hinfo; | ||
| 489 | 490 | ||
| 490 | ngroups = real_ngroups; | 491 | ngroups = real_ngroups; |
| 491 | if (flex_size > 1) { | 492 | if (flex_size > 1) { |
| @@ -507,7 +508,13 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, | |||
| 507 | int best_ndir = inodes_per_group; | 508 | int best_ndir = inodes_per_group; |
| 508 | int ret = -1; | 509 | int ret = -1; |
| 509 | 510 | ||
| 510 | get_random_bytes(&grp, sizeof(grp)); | 511 | if (qstr) { |
| 512 | hinfo.hash_version = DX_HASH_HALF_MD4; | ||
| 513 | hinfo.seed = sbi->s_hash_seed; | ||
| 514 | ext4fs_dirhash(qstr->name, qstr->len, &hinfo); | ||
| 515 | grp = hinfo.hash; | ||
| 516 | } else | ||
| 517 | get_random_bytes(&grp, sizeof(grp)); | ||
| 511 | parent_group = (unsigned)grp % ngroups; | 518 | parent_group = (unsigned)grp % ngroups; |
| 512 | for (i = 0; i < ngroups; i++) { | 519 | for (i = 0; i < ngroups; i++) { |
| 513 | g = (parent_group + i) % ngroups; | 520 | g = (parent_group + i) % ngroups; |
| @@ -650,7 +657,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent, | |||
| 650 | *group = parent_group + flex_size; | 657 | *group = parent_group + flex_size; |
| 651 | if (*group > ngroups) | 658 | if (*group > ngroups) |
| 652 | *group = 0; | 659 | *group = 0; |
| 653 | return find_group_orlov(sb, parent, group, mode); | 660 | return find_group_orlov(sb, parent, group, mode, 0); |
| 654 | } | 661 | } |
| 655 | 662 | ||
| 656 | /* | 663 | /* |
| @@ -791,7 +798,8 @@ err_ret: | |||
| 791 | * For other inodes, search forward from the parent directory's block | 798 | * For other inodes, search forward from the parent directory's block |
| 792 | * group to find a free inode. | 799 | * group to find a free inode. |
| 793 | */ | 800 | */ |
| 794 | struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) | 801 | struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode, |
| 802 | const struct qstr *qstr, __u32 goal) | ||
| 795 | { | 803 | { |
| 796 | struct super_block *sb; | 804 | struct super_block *sb; |
| 797 | struct buffer_head *inode_bitmap_bh = NULL; | 805 | struct buffer_head *inode_bitmap_bh = NULL; |
| @@ -815,14 +823,23 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) | |||
| 815 | 823 | ||
| 816 | sb = dir->i_sb; | 824 | sb = dir->i_sb; |
| 817 | ngroups = ext4_get_groups_count(sb); | 825 | ngroups = ext4_get_groups_count(sb); |
| 818 | trace_mark(ext4_request_inode, "dev %s dir %lu mode %d", sb->s_id, | 826 | trace_ext4_request_inode(dir, mode); |
| 819 | dir->i_ino, mode); | ||
| 820 | inode = new_inode(sb); | 827 | inode = new_inode(sb); |
| 821 | if (!inode) | 828 | if (!inode) |
| 822 | return ERR_PTR(-ENOMEM); | 829 | return ERR_PTR(-ENOMEM); |
| 823 | ei = EXT4_I(inode); | 830 | ei = EXT4_I(inode); |
| 824 | sbi = EXT4_SB(sb); | 831 | sbi = EXT4_SB(sb); |
| 825 | 832 | ||
| 833 | if (!goal) | ||
| 834 | goal = sbi->s_inode_goal; | ||
| 835 | |||
| 836 | if (goal && goal < le32_to_cpu(sbi->s_es->s_inodes_count)) { | ||
| 837 | group = (goal - 1) / EXT4_INODES_PER_GROUP(sb); | ||
| 838 | ino = (goal - 1) % EXT4_INODES_PER_GROUP(sb); | ||
| 839 | ret2 = 0; | ||
| 840 | goto got_group; | ||
| 841 | } | ||
| 842 | |||
| 826 | if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) { | 843 | if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) { |
| 827 | ret2 = find_group_flex(sb, dir, &group); | 844 | ret2 = find_group_flex(sb, dir, &group); |
| 828 | if (ret2 == -1) { | 845 | if (ret2 == -1) { |
| @@ -841,7 +858,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) | |||
| 841 | if (test_opt(sb, OLDALLOC)) | 858 | if (test_opt(sb, OLDALLOC)) |
| 842 | ret2 = find_group_dir(sb, dir, &group); | 859 | ret2 = find_group_dir(sb, dir, &group); |
| 843 | else | 860 | else |
| 844 | ret2 = find_group_orlov(sb, dir, &group, mode); | 861 | ret2 = find_group_orlov(sb, dir, &group, mode, qstr); |
| 845 | } else | 862 | } else |
| 846 | ret2 = find_group_other(sb, dir, &group, mode); | 863 | ret2 = find_group_other(sb, dir, &group, mode); |
| 847 | 864 | ||
| @@ -851,7 +868,7 @@ got_group: | |||
| 851 | if (ret2 == -1) | 868 | if (ret2 == -1) |
| 852 | goto out; | 869 | goto out; |
| 853 | 870 | ||
| 854 | for (i = 0; i < ngroups; i++) { | 871 | for (i = 0; i < ngroups; i++, ino = 0) { |
| 855 | err = -EIO; | 872 | err = -EIO; |
| 856 | 873 | ||
| 857 | gdp = ext4_get_group_desc(sb, group, &group_desc_bh); | 874 | gdp = ext4_get_group_desc(sb, group, &group_desc_bh); |
| @@ -863,8 +880,6 @@ got_group: | |||
| 863 | if (!inode_bitmap_bh) | 880 | if (!inode_bitmap_bh) |
| 864 | goto fail; | 881 | goto fail; |
| 865 | 882 | ||
| 866 | ino = 0; | ||
| 867 | |||
| 868 | repeat_in_this_group: | 883 | repeat_in_this_group: |
| 869 | ino = ext4_find_next_zero_bit((unsigned long *) | 884 | ino = ext4_find_next_zero_bit((unsigned long *) |
| 870 | inode_bitmap_bh->b_data, | 885 | inode_bitmap_bh->b_data, |
| @@ -1047,8 +1062,7 @@ got: | |||
| 1047 | } | 1062 | } |
| 1048 | 1063 | ||
| 1049 | ext4_debug("allocating inode %lu\n", inode->i_ino); | 1064 | ext4_debug("allocating inode %lu\n", inode->i_ino); |
| 1050 | trace_mark(ext4_allocate_inode, "dev %s ino %lu dir %lu mode %d", | 1065 | trace_ext4_allocate_inode(inode, dir, mode); |
| 1051 | sb->s_id, inode->i_ino, dir->i_ino, mode); | ||
| 1052 | goto really_out; | 1066 | goto really_out; |
| 1053 | fail: | 1067 | fail: |
| 1054 | ext4_std_error(sb, err); | 1068 | ext4_std_error(sb, err); |
