* [PATCH] EXT4: optimizing group serch for inode allocation @ 2015-12-18 23:32 lokesh jaliminche 2015-12-21 17:27 ` Andreas Dilger 0 siblings, 1 reply; 12+ messages in thread From: lokesh jaliminche @ 2015-12-18 23:32 UTC (permalink / raw) To: Andreas Dilger; +Cc: linux-ext4 [-- Attachment #1: Type: text/plain, Size: 2072 bytes --] >From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" and "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..588bf8e 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, struct ext4_sb_info *sbi = EXT4_SB(sb); ext4_group_t real_ngroups = ext4_get_groups_count(sb); int inodes_per_group = EXT4_INODES_PER_GROUP(sb); + unsigned int inodes_per_flex_group; + long unsigned int blocks_per_clustre; unsigned int freei, avefreei, grp_free; ext4_fsblk_t freeb, avefreec; unsigned int ndirs; @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, percpu_counter_read_positive(&sbi->s_freeclusters_counter)); avefreec = freeb; do_div(avefreec, ngroups); + inodes_per_flex_group = inodes_per_group * flex_size; + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); if (S_ISDIR(mode) && @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* the group can't get any better than empty */ + if (inodes_per_flex_group == stats.free_inodes && + blocks_per_clustre == stats.free_clusters) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 [-- Attachment #2: 0001-EXT4-optimizing-group-serch-for-inode-allocation.patch --] [-- Type: application/octet-stream, Size: 2208 bytes --] From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> Date: Sat, 19 Dec 2015 00:33:06 +0530 Subject: [PATCH] EXT4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" and "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..588bf8e 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, struct ext4_sb_info *sbi = EXT4_SB(sb); ext4_group_t real_ngroups = ext4_get_groups_count(sb); int inodes_per_group = EXT4_INODES_PER_GROUP(sb); + unsigned int inodes_per_flex_group; + long unsigned int blocks_per_clustre; unsigned int freei, avefreei, grp_free; ext4_fsblk_t freeb, avefreec; unsigned int ndirs; @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, percpu_counter_read_positive(&sbi->s_freeclusters_counter)); avefreec = freeb; do_div(avefreec, ngroups); + inodes_per_flex_group = inodes_per_group * flex_size; + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); if (S_ISDIR(mode) && @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* the group can't get any better than empty */ + if (inodes_per_flex_group == stats.free_inodes && + blocks_per_clustre == stats.free_clusters) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] EXT4: optimizing group serch for inode allocation 2015-12-18 23:32 [PATCH] EXT4: optimizing group serch for inode allocation lokesh jaliminche @ 2015-12-21 17:27 ` Andreas Dilger 2015-12-26 8:28 ` [PATCH v3] " Lokesh Jaliminche 2015-12-26 8:41 ` [PATCH v3] EXT4: optimizing group search " Lokesh Jaliminche 0 siblings, 2 replies; 12+ messages in thread From: Andreas Dilger @ 2015-12-21 17:27 UTC (permalink / raw) To: lokesh jaliminche; +Cc: linux-ext4 [-- Attachment #1: Type: text/plain, Size: 2908 bytes --] On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: > > From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> In the patch summary there is a typo - s/serch/search/ Also, it appears your email client has mangled the whitespace in the patch. Please use "git send-email" to send your patch to the list: git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 so that it arrives intact. You probably need to set it up in ~/.gitconfig: [sendemail] confirm = compose smtpdomain = {your client hostname} smtpserver = {your SMTP server hostname} Cheers, Andreas > Added a check at the start of group search loop to > avoid looping unecessarily in case of empty group. > This also allow group search to jump directly to > "found_flex_bg" with "stats" and "group" already set, > so there is no need to go through the extra steps of > setting "best_desc" and "best_group" and then break > out of the loop just to set "stats" and "group" again. > > Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> > --- > fs/ext4/ialloc.c | 8 ++++++++ > 1 files changed, 8 insertions(+), 0 deletions(-) > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > index 1b8024d..588bf8e 100644 > --- a/fs/ext4/ialloc.c > +++ b/fs/ext4/ialloc.c > @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block > *sb, struct inode *parent, > struct ext4_sb_info *sbi = EXT4_SB(sb); > ext4_group_t real_ngroups = ext4_get_groups_count(sb); > int inodes_per_group = EXT4_INODES_PER_GROUP(sb); > + unsigned int inodes_per_flex_group; > + long unsigned int blocks_per_clustre; > unsigned int freei, avefreei, grp_free; > ext4_fsblk_t freeb, avefreec; > unsigned int ndirs; > @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block > *sb, struct inode *parent, > percpu_counter_read_positive(&sbi->s_freeclusters_counter)); > avefreec = freeb; > do_div(avefreec, ngroups); > + inodes_per_flex_group = inodes_per_group * flex_size; > + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; > ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > > if (S_ISDIR(mode) && > @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block > *sb, struct inode *parent, > for (i = 0; i < ngroups; i++) { > g = (parent_group + i) % ngroups; > get_orlov_stats(sb, g, flex_size, &stats); > + /* the group can't get any better than empty */ > + if (inodes_per_flex_group == stats.free_inodes && > + blocks_per_clustre == stats.free_clusters) > + goto found_flex_bg; > if (!stats.free_inodes) > continue; > if (stats.used_dirs >= best_ndir) > -- > 1.7.1 > <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> Cheers, Andreas [-- Attachment #2: Message signed with OpenPGP using GPGMail --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3] EXT4: optimizing group serch for inode allocation 2015-12-21 17:27 ` Andreas Dilger @ 2015-12-26 8:28 ` Lokesh Jaliminche 2015-12-26 8:41 ` [PATCH v3] EXT4: optimizing group search " Lokesh Jaliminche 1 sibling, 0 replies; 12+ messages in thread From: Lokesh Jaliminche @ 2015-12-26 8:28 UTC (permalink / raw) To: Andreas Dilger, tytso; +Cc: linux-ext4 [-- Attachment #1: Type: text/plain, Size: 5521 bytes --] >From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Sat, 26 Dec 2015 13:19:36 +0530 Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" and "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..16f94db 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); if (S_ISDIR(mode) && - ((parent == d_inode(sb->s_root)) || - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { + ((parent == d_inode(sb->s_root)) || + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { + unsigned int inodes_per_flex_group; + unsigned long int clusters_per_flex_group; int best_ndir = inodes_per_group; int ret = -1; + inodes_per_flex_group = inodes_per_group * flex_size; + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* the group can't get any better than empty */ + if (inodes_per_flex_group == stats.free_inodes && + clusters_per_flex_group == stats.free_clusters) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: > On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: > > > > From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 > > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> > > In the patch summary there is a typo - s/serch/search/ > > Also, it appears your email client has mangled the whitespace in the > patch. Please use "git send-email" to send your patch to the list: > > git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 > > so that it arrives intact. You probably need to set it up in ~/.gitconfig: > > [sendemail] > confirm = compose > smtpdomain = {your client hostname} > smtpserver = {your SMTP server hostname} > > Cheers, Andreas > > > Added a check at the start of group search loop to > > avoid looping unecessarily in case of empty group. > > This also allow group search to jump directly to > > "found_flex_bg" with "stats" and "group" already set, > > so there is no need to go through the extra steps of > > setting "best_desc" and "best_group" and then break > > out of the loop just to set "stats" and "group" again. > > > > Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> > > --- > > fs/ext4/ialloc.c | 8 ++++++++ > > 1 files changed, 8 insertions(+), 0 deletions(-) > > > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > > index 1b8024d..588bf8e 100644 > > --- a/fs/ext4/ialloc.c > > +++ b/fs/ext4/ialloc.c > > @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block > > *sb, struct inode *parent, > > struct ext4_sb_info *sbi = EXT4_SB(sb); > > ext4_group_t real_ngroups = ext4_get_groups_count(sb); > > int inodes_per_group = EXT4_INODES_PER_GROUP(sb); > > + unsigned int inodes_per_flex_group; > > + long unsigned int blocks_per_clustre; > > unsigned int freei, avefreei, grp_free; > > ext4_fsblk_t freeb, avefreec; > > unsigned int ndirs; > > @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block > > *sb, struct inode *parent, > > percpu_counter_read_positive(&sbi->s_freeclusters_counter)); > > avefreec = freeb; > > do_div(avefreec, ngroups); > > + inodes_per_flex_group = inodes_per_group * flex_size; > > + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; > > ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > > > > if (S_ISDIR(mode) && > > @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block > > *sb, struct inode *parent, > > for (i = 0; i < ngroups; i++) { > > g = (parent_group + i) % ngroups; > > get_orlov_stats(sb, g, flex_size, &stats); > > + /* the group can't get any better than empty */ > > + if (inodes_per_flex_group == stats.free_inodes && > > + blocks_per_clustre == stats.free_clusters) > > + goto found_flex_bg; > > if (!stats.free_inodes) > > continue; > > if (stats.used_dirs >= best_ndir) > > -- > > 1.7.1 > > <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> > > > Cheers, Andreas > > > > > [-- Attachment #2: 0001-ext4-optimizing-group-serch-for-inode-allocation.patch --] [-- Type: text/plain, Size: 2093 bytes --] >From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Sat, 26 Dec 2015 13:19:36 +0530 Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" and "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..16f94db 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); if (S_ISDIR(mode) && - ((parent == d_inode(sb->s_root)) || - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { + ((parent == d_inode(sb->s_root)) || + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { + unsigned int inodes_per_flex_group; + unsigned long int clusters_per_flex_group; int best_ndir = inodes_per_group; int ret = -1; + inodes_per_flex_group = inodes_per_group * flex_size; + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* the group can't get any better than empty */ + if (inodes_per_flex_group == stats.free_inodes && + clusters_per_flex_group == stats.free_clusters) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3] EXT4: optimizing group search for inode allocation 2015-12-21 17:27 ` Andreas Dilger 2015-12-26 8:28 ` [PATCH v3] " Lokesh Jaliminche @ 2015-12-26 8:41 ` Lokesh Jaliminche [not found] ` <2DA2ED68-7DD4-425D-8A47-E896E9BF0F4A@dilger.ca> 1 sibling, 1 reply; 12+ messages in thread From: Lokesh Jaliminche @ 2015-12-26 8:41 UTC (permalink / raw) To: Andreas Dilger, tytso; +Cc: linux-ext4 [-- Attachment #1: Type: text/plain, Size: 5526 bytes --] >From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Sat, 26 Dec 2015 13:19:36 +0530 Subject: [PATCH v3] ext4: optimizing group search for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" and "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..16f94db 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); if (S_ISDIR(mode) && - ((parent == d_inode(sb->s_root)) || - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { + ((parent == d_inode(sb->s_root)) || + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { + unsigned int inodes_per_flex_group; + unsigned long int clusters_per_flex_group; int best_ndir = inodes_per_group; int ret = -1; + inodes_per_flex_group = inodes_per_group * flex_size; + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* the group can't get any better than empty */ + if (inodes_per_flex_group == stats.free_inodes && + clusters_per_flex_group == stats.free_clusters) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: > On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: > > > > From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 > > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> > > In the patch summary there is a typo - s/serch/search/ > > Also, it appears your email client has mangled the whitespace in the > patch. Please use "git send-email" to send your patch to the list: > > git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 > > so that it arrives intact. You probably need to set it up in ~/.gitconfig: > > [sendemail] > confirm = compose > smtpdomain = {your client hostname} > smtpserver = {your SMTP server hostname} > > Cheers, Andreas > > > Added a check at the start of group search loop to > > avoid looping unecessarily in case of empty group. > > This also allow group search to jump directly to > > "found_flex_bg" with "stats" and "group" already set, > > so there is no need to go through the extra steps of > > setting "best_desc" and "best_group" and then break > > out of the loop just to set "stats" and "group" again. > > > > Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> > > --- > > fs/ext4/ialloc.c | 8 ++++++++ > > 1 files changed, 8 insertions(+), 0 deletions(-) > > > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > > index 1b8024d..588bf8e 100644 > > --- a/fs/ext4/ialloc.c > > +++ b/fs/ext4/ialloc.c > > @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block > > *sb, struct inode *parent, > > struct ext4_sb_info *sbi = EXT4_SB(sb); > > ext4_group_t real_ngroups = ext4_get_groups_count(sb); > > int inodes_per_group = EXT4_INODES_PER_GROUP(sb); > > + unsigned int inodes_per_flex_group; > > + long unsigned int blocks_per_clustre; > > unsigned int freei, avefreei, grp_free; > > ext4_fsblk_t freeb, avefreec; > > unsigned int ndirs; > > @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block > > *sb, struct inode *parent, > > percpu_counter_read_positive(&sbi->s_freeclusters_counter)); > > avefreec = freeb; > > do_div(avefreec, ngroups); > > + inodes_per_flex_group = inodes_per_group * flex_size; > > + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; > > ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > > > > if (S_ISDIR(mode) && > > @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block > > *sb, struct inode *parent, > > for (i = 0; i < ngroups; i++) { > > g = (parent_group + i) % ngroups; > > get_orlov_stats(sb, g, flex_size, &stats); > > + /* the group can't get any better than empty */ > > + if (inodes_per_flex_group == stats.free_inodes && > > + blocks_per_clustre == stats.free_clusters) > > + goto found_flex_bg; > > if (!stats.free_inodes) > > continue; > > if (stats.used_dirs >= best_ndir) > > -- > > 1.7.1 > > <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> > > > Cheers, Andreas > > > > > [-- Attachment #2: 0001-ext4-optimizing-group-serch-for-inode-allocation.patch --] [-- Type: text/plain, Size: 2093 bytes --] >From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Sat, 26 Dec 2015 13:19:36 +0530 Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" and "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..16f94db 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); if (S_ISDIR(mode) && - ((parent == d_inode(sb->s_root)) || - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { + ((parent == d_inode(sb->s_root)) || + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { + unsigned int inodes_per_flex_group; + unsigned long int clusters_per_flex_group; int best_ndir = inodes_per_group; int ret = -1; + inodes_per_flex_group = inodes_per_group * flex_size; + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* the group can't get any better than empty */ + if (inodes_per_flex_group == stats.free_inodes && + clusters_per_flex_group == stats.free_clusters) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
[parent not found: <2DA2ED68-7DD4-425D-8A47-E896E9BF0F4A@dilger.ca>]
* [PATCH v4] EXT4: optimizing group search for inode allocation [not found] ` <2DA2ED68-7DD4-425D-8A47-E896E9BF0F4A@dilger.ca> @ 2016-01-07 0:46 ` Lokesh Jaliminche 2016-01-11 21:13 ` Andreas Dilger 0 siblings, 1 reply; 12+ messages in thread From: Lokesh Jaliminche @ 2016-01-07 0:46 UTC (permalink / raw) To: Andreas Dilger; +Cc: Theodore Ts'o, linux-ext4 [-- Attachment #1: Type: text/plain, Size: 13960 bytes --] you are right flex groups cannot be completely empty as some blocks are used for inode table and allocation bitmaps. I missed that point. I have corrected that.Also I have tested and validated this patch by putting some traces it works! Here are corresponding logs: commands: ========= mkfs.ext4 -g 10000 -G 2 /dev/sdc mount -t ext4 /dev/sdc /mnt/test_ext4/ cd /mnt/test_ext4 mkdir 1 cd 1 logs: ===== Jan 7 03:36:45 root kernel: [ 64.792939] max_usable_blocks_per_flex_group = [19692] Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_clusters = [19264] Jan 7 03:36:45 root kernel: [ 64.792939] Inodes_per_flex_group = [4864] Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_inodes = [4853] Jan 7 03:36:45 root kernel: [ 64.792950] max_usable_blocks_per_flex_group = [19692] Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_clusters = [19481] Jan 7 03:36:45 root kernel: [ 64.792950] Inodes_per_flex_group = [4864] Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_inodes = [4864] Jan 7 03:36:45 root kernel: [ 64.792958] max_usable_blocks_per_flex_group = [19692] Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_clusters = [19481] Jan 7 03:36:45 root kernel: [ 64.792958] Inodes_per_flex_group = [4864] Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_inodes = [4864] Jan 7 03:36:45 root kernel: [ 64.792965] max_usable_blocks_per_flex_group = [19692] Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_clusters = [19481] Jan 7 03:36:45 root kernel: [ 64.792965] Inodes_per_flex_group = [4864] Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_inodes = [4864] Jan 7 03:36:45 root kernel: [ 64.792972] max_usable_blocks_per_flex_group = [19692] Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_clusters = [19481] Jan 7 03:36:45 root kernel: [ 64.792972] Inodes_per_flex_group = [4864] Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_inodes = [4864] Jan 7 03:36:45 root kernel: [ 64.792979] max_usable_blocks_per_flex_group = [19692]<<<<<<<<<<< Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_clusters = [19692]<<<<<<<<<<< Jan 7 03:36:45 root kernel: [ 64.792979] Inodes_per_flex_group = [4864]<<<<<<<<<<<< Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_inodes = [4864]<<<<<<<<<<<< Jan 7 03:36:45 root kernel: [ 64.792985] found_flex_bg >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>condition satisfied [Patch v4]: ========== From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Thu, 7 Jan 2016 05:12:20 +0530 Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" , "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ext4.h | 2 ++ fs/ext4/ialloc.c | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index cc7ca4e..fc48f9a 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -326,6 +326,8 @@ struct flex_groups { #define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) #ifdef __KERNEL__ +# define EXT4_INODE_TABLE_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_itb_per_group) +# define EXT4_BLOCKS_PER_CLUSTER(s) (EXT4_SB(s)->s_cluster_ratio) # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..dc66ad8 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -463,7 +463,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, sbi->s_log_groups_per_flex; parent_group >>= sbi->s_log_groups_per_flex; } - freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); avefreei = freei / ngroups; freeb = EXT4_C2B(sbi, @@ -477,7 +476,20 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { int best_ndir = inodes_per_group; int ret = -1; - + /* blocks used for inode table and allocation bitmaps */ + unsigned int max_usable_blocks_per_flex_group; + unsigned int blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb); + unsigned int inode_table_blocks_per_group = \ + EXT4_INODE_TABLE_BLOCKS_PER_GROUP(sb); + /* Number of blocks per cluster */ + unsigned int cluster_ratio = EXT4_BLOCKS_PER_CLUSTER(sb); + unsigned int inodes_per_flex_group = inodes_per_group * \ + flex_size; + max_usable_blocks_per_flex_group = \ + ((blocks_per_group*flex_size) - \ + (inode_table_blocks_per_group * \ + flex_size + 2 * flex_size)) / \ + cluster_ratio; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; hinfo.seed = sbi->s_hash_seed; @@ -489,6 +501,11 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* can't get better group than empty group */ + if (max_usable_blocks_per_flex_group == \ + stats.free_clusters && \ + inodes_per_flex_group == stats.free_inodes) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 Regards, Lokesh On Sun, Jan 03, 2016 at 11:34:51AM -0700, Andreas Dilger wrote: > On Dec 26, 2015, at 01:41, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > > > > > > From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 > > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > > Date: Sat, 26 Dec 2015 13:19:36 +0530 > > Subject: [PATCH v3] ext4: optimizing group search for inode allocation > > > > Added a check at the start of group search loop to > > avoid looping unecessarily in case of empty group. > > This also allow group search to jump directly to > > "found_flex_bg" with "stats" and "group" already set, > > so there is no need to go through the extra steps of > > setting "best_desc" and "best_group" and then break > > out of the loop just to set "stats" and "group" again. > > > > Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > > --- > > fs/ext4/ialloc.c | 12 ++++++++++-- > > 1 files changed, 10 insertions(+), 2 deletions(-) > > > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > > index 1b8024d..16f94db 100644 > > --- a/fs/ext4/ialloc.c > > +++ b/fs/ext4/ialloc.c > > @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > > > > if (S_ISDIR(mode) && > > - ((parent == d_inode(sb->s_root)) || > > - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > > + ((parent == d_inode(sb->s_root)) || > > + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > > I don't understand why you are changing the indentation here? > > > + unsigned int inodes_per_flex_group; > > + unsigned long int clusters_per_flex_group; > > int best_ndir = inodes_per_group; > > int ret = -1; > > + inodes_per_flex_group = inodes_per_group * flex_size; > > + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; > > Have you actually tested if this code works? When I was looking at this > code I was accidentally looking at the ext2 version, which only deals with > individual groups, and not flex groups. I don't think that a flex group > can actually be completely empty, since it will always contain at least > an inode table and some bitmaps. > > This calculation needs to take this into account or it will just be > overhead and not an optimization. Something like: > > /* account for inode table and allocation bitmaps */ > clusters_per_flex_group = sbi->s_clusters_per_group * flex_size - > ((inodes_per_flex_group * EXT4_INODE_SIZE(sb) + > (flex_size << sb->s_blocksize_bits) * 2 ) >> > EXT4_SB(sb)->s_cluster_bits; > > It would be worthwhile to print this out and verify that there are actually > groups with this many free blocks in a newly formatted filesystem. > > Cheers, Andreas > > > if (qstr) { > > hinfo.hash_version = DX_HASH_HALF_MD4; > > @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > for (i = 0; i < ngroups; i++) { > > g = (parent_group + i) % ngroups; > > get_orlov_stats(sb, g, flex_size, &stats); > > + /* the group can't get any better than empty */ > > + if (inodes_per_flex_group == stats.free_inodes && > > + clusters_per_flex_group == stats.free_clusters) > > + goto found_flex_bg; > > if (!stats.free_inodes) > > continue; > > if (stats.used_dirs >= best_ndir) > > -- > > 1.7.1 > > > > > >> On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: > >>> On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: > >>> > >>> From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 > >>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> > >> > >> In the patch summary there is a typo - s/serch/search/ > >> > >> Also, it appears your email client has mangled the whitespace in the > >> patch. Please use "git send-email" to send your patch to the list: > >> > >> git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 > >> > >> so that it arrives intact. You probably need to set it up in ~/.gitconfig: > >> > >> [sendemail] > >> confirm = compose > >> smtpdomain = {your client hostname} > >> smtpserver = {your SMTP server hostname} > >> > >> Cheers, Andreas > >> > >>> Added a check at the start of group search loop to > >>> avoid looping unecessarily in case of empty group. > >>> This also allow group search to jump directly to > >>> "found_flex_bg" with "stats" and "group" already set, > >>> so there is no need to go through the extra steps of > >>> setting "best_desc" and "best_group" and then break > >>> out of the loop just to set "stats" and "group" again. > >>> > >>> Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> > >>> --- > >>> fs/ext4/ialloc.c | 8 ++++++++ > >>> 1 files changed, 8 insertions(+), 0 deletions(-) > >>> > >>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > >>> index 1b8024d..588bf8e 100644 > >>> --- a/fs/ext4/ialloc.c > >>> +++ b/fs/ext4/ialloc.c > >>> @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block > >>> *sb, struct inode *parent, > >>> struct ext4_sb_info *sbi = EXT4_SB(sb); > >>> ext4_group_t real_ngroups = ext4_get_groups_count(sb); > >>> int inodes_per_group = EXT4_INODES_PER_GROUP(sb); > >>> + unsigned int inodes_per_flex_group; > >>> + long unsigned int blocks_per_clustre; > >>> unsigned int freei, avefreei, grp_free; > >>> ext4_fsblk_t freeb, avefreec; > >>> unsigned int ndirs; > >>> @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block > >>> *sb, struct inode *parent, > >>> percpu_counter_read_positive(&sbi->s_freeclusters_counter)); > >>> avefreec = freeb; > >>> do_div(avefreec, ngroups); > >>> + inodes_per_flex_group = inodes_per_group * flex_size; > >>> + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; > >>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > >>> > >>> if (S_ISDIR(mode) && > >>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block > >>> *sb, struct inode *parent, > >>> for (i = 0; i < ngroups; i++) { > >>> g = (parent_group + i) % ngroups; > >>> get_orlov_stats(sb, g, flex_size, &stats); > >>> + /* the group can't get any better than empty */ > >>> + if (inodes_per_flex_group == stats.free_inodes && > >>> + blocks_per_clustre == stats.free_clusters) > >>> + goto found_flex_bg; > >>> if (!stats.free_inodes) > >>> continue; > >>> if (stats.used_dirs >= best_ndir) > >>> -- > >>> 1.7.1 > >>> <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> > >> > >> > >> Cheers, Andreas > > > > > > <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> [-- Attachment #2: 0001-ext4-optimizing-group-serch-for-inode-allocation.patch --] [-- Type: text/plain, Size: 3297 bytes --] >From 4734edcfb755096b1bcdd4153699ec907b072a35 Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Thu, 7 Jan 2016 05:12:20 +0530 Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" , "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ext4.h | 2 ++ fs/ext4/ialloc.c | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index cc7ca4e..fc48f9a 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -326,6 +326,8 @@ struct flex_groups { #define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) #ifdef __KERNEL__ +# define EXT4_INODE_TABLE_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_itb_per_group) +# define EXT4_BLOCKS_PER_CLUSTER(s) (EXT4_SB(s)->s_cluster_ratio) # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..dc66ad8 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -463,7 +463,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, sbi->s_log_groups_per_flex; parent_group >>= sbi->s_log_groups_per_flex; } - freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); avefreei = freei / ngroups; freeb = EXT4_C2B(sbi, @@ -477,7 +476,20 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { int best_ndir = inodes_per_group; int ret = -1; - + /* blocks used for inode table and allocation bitmaps */ + unsigned int max_usable_blocks_per_flex_group; + unsigned int blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb); + unsigned int inode_table_blocks_per_group = \ + EXT4_INODE_TABLE_BLOCKS_PER_GROUP(sb); + /* Number of blocks per cluster */ + unsigned int cluster_ratio = EXT4_BLOCKS_PER_CLUSTER(sb); + unsigned int inodes_per_flex_group = inodes_per_group * \ + flex_size; + max_usable_blocks_per_flex_group = \ + ((blocks_per_group*flex_size) - \ + (inode_table_blocks_per_group * \ + flex_size + 2 * flex_size)) / \ + cluster_ratio; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; hinfo.seed = sbi->s_hash_seed; @@ -489,6 +501,11 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* can't get better group than empty group */ + if (max_usable_blocks_per_flex_group == \ + stats.free_clusters && \ + inodes_per_flex_group == stats.free_inodes) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v4] EXT4: optimizing group search for inode allocation 2016-01-07 0:46 ` [PATCH v4] " Lokesh Jaliminche @ 2016-01-11 21:13 ` Andreas Dilger 2016-01-16 22:50 ` [PATCH v5] " Lokesh Jaliminche 2016-01-16 23:02 ` Lokesh Jaliminche 0 siblings, 2 replies; 12+ messages in thread From: Andreas Dilger @ 2016-01-11 21:13 UTC (permalink / raw) To: Lokesh Jaliminche, Theodore Ts'o; +Cc: linux-ext4 [-- Attachment #1: Type: text/plain, Size: 15766 bytes --] On Jan 6, 2016, at 5:46 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > > you are right flex groups cannot be completely empty as some > blocks are used for inode table and allocation bitmaps. I > missed that point. I have corrected that. Also I have tested > and validated this patch by putting some traces it works! Good news. Thanks for updating the patch and testing it. More comments below. > Here are corresponding logs: > commands: > ========= > mkfs.ext4 -g 10000 -G 2 /dev/sdc > mount -t ext4 /dev/sdc /mnt/test_ext4/ > cd /mnt/test_ext4 > mkdir 1 > cd 1 > > logs: > ===== > Jan 7 03:36:45 root kernel: [ 64.792939] max_usable_blocks_per_flex_group = [19692] > Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_clusters = [19264] > Jan 7 03:36:45 root kernel: [ 64.792939] Inodes_per_flex_group = [4864] > Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_inodes = [4853] > Jan 7 03:36:45 root kernel: [ 64.792950] max_usable_blocks_per_flex_group = [19692] > Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_clusters = [19481] > Jan 7 03:36:45 root kernel: [ 64.792950] Inodes_per_flex_group = [4864] > Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_inodes = [4864] > Jan 7 03:36:45 root kernel: [ 64.792958] max_usable_blocks_per_flex_group = [19692] > Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_clusters = [19481] > Jan 7 03:36:45 root kernel: [ 64.792958] Inodes_per_flex_group = [4864] > Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_inodes = [4864] > Jan 7 03:36:45 root kernel: [ 64.792965] max_usable_blocks_per_flex_group = [19692] > Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_clusters = [19481] > Jan 7 03:36:45 root kernel: [ 64.792965] Inodes_per_flex_group = [4864] > Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_inodes = [4864] > Jan 7 03:36:45 root kernel: [ 64.792972] max_usable_blocks_per_flex_group = [19692] > Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_clusters = [19481] > Jan 7 03:36:45 root kernel: [ 64.792972] Inodes_per_flex_group = [4864] > Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_inodes = [4864] > Jan 7 03:36:45 root kernel: [ 64.792979] max_usable_blocks_per_flex_group = [19692]<<<<<<<<<<< > Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_clusters = [19692]<<<<<<<<<<< > Jan 7 03:36:45 root kernel: [ 64.792979] Inodes_per_flex_group = [4864]<<<<<<<<<<<< > Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_inodes = [4864]<<<<<<<<<<<< > Jan 7 03:36:45 root kernel: [ 64.792985] found_flex_bg >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>condition satisfied > > > [Patch v4]: > ========== > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > Date: Thu, 7 Jan 2016 05:12:20 +0530 > Subject: [PATCH] ext4: optimizing group serch for inode allocation > > Added a check at the start of group search loop to > avoid looping unecessarily in case of empty group. > This also allow group search to jump directly to > "found_flex_bg" with "stats" and "group" already set, > so there is no need to go through the extra steps of > setting "best_desc" , "best_group" and then break > out of the loop just to set "stats" and "group" again. > > Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > --- > fs/ext4/ext4.h | 2 ++ > fs/ext4/ialloc.c | 21 +++++++++++++++++++-- > 2 files changed, 21 insertions(+), 2 deletions(-) > > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h > index cc7ca4e..fc48f9a 100644 > --- a/fs/ext4/ext4.h > +++ b/fs/ext4/ext4.h > @@ -326,6 +326,8 @@ struct flex_groups { > #define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE > #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) > #ifdef __KERNEL__ > +# define EXT4_INODE_TABLE_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_itb_per_group) > +# define EXT4_BLOCKS_PER_CLUSTER(s) (EXT4_SB(s)->s_cluster_ratio) I don't think there is much value to these macros. They aren't much shorter than the actual variable access, and they don't provide any improved clarity for the reader. I think they were introduced many years ago so that this header could be shared between the kernel and e2fsprogs, but that is no longer true so I don't think there is a need to add new ones. Ted, any opinion on this? > # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) > # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) > # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > index 1b8024d..dc66ad8 100644 > --- a/fs/ext4/ialloc.c > +++ b/fs/ext4/ialloc.c > @@ -463,7 +463,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > sbi->s_log_groups_per_flex; > parent_group >>= sbi->s_log_groups_per_flex; > } > - > freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); > avefreei = freei / ngroups; Not sure why this line is being deleted? > @@ -477,7 +476,20 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > int best_ndir = inodes_per_group; > int ret = -1; > - > + /* blocks used for inode table and allocation bitmaps */ > + unsigned int max_usable_blocks_per_flex_group; This could be shorter and still clear, like "max_blocks_per_flex". > + unsigned int blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb); > + unsigned int inode_table_blocks_per_group = \ > + EXT4_INODE_TABLE_BLOCKS_PER_GROUP(sb); > + /* Number of blocks per cluster */ > + unsigned int cluster_ratio = EXT4_BLOCKS_PER_CLUSTER(sb); There also isn't much value to making local variables that hold these same values again. It increases stack space for little benefit. They are only accessed once anyway. > + unsigned int inodes_per_flex_group = inodes_per_group * \ > + flex_size; > + max_usable_blocks_per_flex_group = \ > + ((blocks_per_group*flex_size) - \ Spaces around that '*'. > + (inode_table_blocks_per_group * \ > + flex_size + 2 * flex_size)) / \ This is C and not a CPP macro, so no need for linefeed escapes. > + cluster_ratio; This should be ">> EXT4_SB(sb)->s_cluster_bits" to avoid the divide. > if (qstr) { > hinfo.hash_version = DX_HASH_HALF_MD4; > hinfo.seed = sbi->s_hash_seed; > @@ -489,6 +501,11 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > for (i = 0; i < ngroups; i++) { > g = (parent_group + i) % ngroups; > get_orlov_stats(sb, g, flex_size, &stats); > + /* can't get better group than empty group */ > + if (max_usable_blocks_per_flex_group == \ > + stats.free_clusters && \ No need for linefeed escapes. > + inodes_per_flex_group == stats.free_inodes) Align continued line after '(' from the "if (" line. > + goto found_flex_bg; This is indented too much. It will work properly when you fix the previous line. > if (!stats.free_inodes) > continue; > if (stats.used_dirs >= best_ndir) > -- > 1.7.1 > > Regards, > Lokesh > > On Sun, Jan 03, 2016 at 11:34:51AM -0700, Andreas Dilger wrote: >> On Dec 26, 2015, at 01:41, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: >>> >>> >>> From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 >>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>> Date: Sat, 26 Dec 2015 13:19:36 +0530 >>> Subject: [PATCH v3] ext4: optimizing group search for inode allocation >>> >>> Added a check at the start of group search loop to >>> avoid looping unecessarily in case of empty group. >>> This also allow group search to jump directly to >>> "found_flex_bg" with "stats" and "group" already set, >>> so there is no need to go through the extra steps of >>> setting "best_desc" and "best_group" and then break >>> out of the loop just to set "stats" and "group" again. >>> >>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>> --- >>> fs/ext4/ialloc.c | 12 ++++++++++-- >>> 1 files changed, 10 insertions(+), 2 deletions(-) >>> >>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>> index 1b8024d..16f94db 100644 >>> --- a/fs/ext4/ialloc.c >>> +++ b/fs/ext4/ialloc.c >>> @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); >>> >>> if (S_ISDIR(mode) && >>> - ((parent == d_inode(sb->s_root)) || >>> - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >>> + ((parent == d_inode(sb->s_root)) || >>> + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >> >> I don't understand why you are changing the indentation here? >> >>> + unsigned int inodes_per_flex_group; >>> + unsigned long int clusters_per_flex_group; >>> int best_ndir = inodes_per_group; >>> int ret = -1; >>> + inodes_per_flex_group = inodes_per_group * flex_size; >>> + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; >> >> Have you actually tested if this code works? When I was looking at this >> code I was accidentally looking at the ext2 version, which only deals with >> individual groups, and not flex groups. I don't think that a flex group >> can actually be completely empty, since it will always contain at least >> an inode table and some bitmaps. >> >> This calculation needs to take this into account or it will just be >> overhead and not an optimization. Something like: >> >> /* account for inode table and allocation bitmaps */ >> clusters_per_flex_group = sbi->s_clusters_per_group * flex_size - >> ((inodes_per_flex_group * EXT4_INODE_SIZE(sb) + >> (flex_size << sb->s_blocksize_bits) * 2 ) >> >> EXT4_SB(sb)->s_cluster_bits; >> >> It would be worthwhile to print this out and verify that there are actually >> groups with this many free blocks in a newly formatted filesystem. >> >> Cheers, Andreas >> >>> if (qstr) { >>> hinfo.hash_version = DX_HASH_HALF_MD4; >>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>> for (i = 0; i < ngroups; i++) { >>> g = (parent_group + i) % ngroups; >>> get_orlov_stats(sb, g, flex_size, &stats); >>> + /* the group can't get any better than empty */ >>> + if (inodes_per_flex_group == stats.free_inodes && >>> + clusters_per_flex_group == stats.free_clusters) >>> + goto found_flex_bg; >>> if (!stats.free_inodes) >>> continue; >>> if (stats.used_dirs >= best_ndir) >>> -- >>> 1.7.1 >>> >>> >>>> On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: >>>>> On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: >>>>> >>>>> From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 >>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> >>>> >>>> In the patch summary there is a typo - s/serch/search/ >>>> >>>> Also, it appears your email client has mangled the whitespace in the >>>> patch. Please use "git send-email" to send your patch to the list: >>>> >>>> git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 >>>> >>>> so that it arrives intact. You probably need to set it up in ~/.gitconfig: >>>> >>>> [sendemail] >>>> confirm = compose >>>> smtpdomain = {your client hostname} >>>> smtpserver = {your SMTP server hostname} >>>> >>>> Cheers, Andreas >>>> >>>>> Added a check at the start of group search loop to >>>>> avoid looping unecessarily in case of empty group. >>>>> This also allow group search to jump directly to >>>>> "found_flex_bg" with "stats" and "group" already set, >>>>> so there is no need to go through the extra steps of >>>>> setting "best_desc" and "best_group" and then break >>>>> out of the loop just to set "stats" and "group" again. >>>>> >>>>> Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> >>>>> --- >>>>> fs/ext4/ialloc.c | 8 ++++++++ >>>>> 1 files changed, 8 insertions(+), 0 deletions(-) >>>>> >>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>>>> index 1b8024d..588bf8e 100644 >>>>> --- a/fs/ext4/ialloc.c >>>>> +++ b/fs/ext4/ialloc.c >>>>> @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block >>>>> *sb, struct inode *parent, >>>>> struct ext4_sb_info *sbi = EXT4_SB(sb); >>>>> ext4_group_t real_ngroups = ext4_get_groups_count(sb); >>>>> int inodes_per_group = EXT4_INODES_PER_GROUP(sb); >>>>> + unsigned int inodes_per_flex_group; >>>>> + long unsigned int blocks_per_clustre; >>>>> unsigned int freei, avefreei, grp_free; >>>>> ext4_fsblk_t freeb, avefreec; >>>>> unsigned int ndirs; >>>>> @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block >>>>> *sb, struct inode *parent, >>>>> percpu_counter_read_positive(&sbi->s_freeclusters_counter)); >>>>> avefreec = freeb; >>>>> do_div(avefreec, ngroups); >>>>> + inodes_per_flex_group = inodes_per_group * flex_size; >>>>> + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; >>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); >>>>> >>>>> if (S_ISDIR(mode) && >>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block >>>>> *sb, struct inode *parent, >>>>> for (i = 0; i < ngroups; i++) { >>>>> g = (parent_group + i) % ngroups; >>>>> get_orlov_stats(sb, g, flex_size, &stats); >>>>> + /* the group can't get any better than empty */ >>>>> + if (inodes_per_flex_group == stats.free_inodes && >>>>> + blocks_per_clustre == stats.free_clusters) >>>>> + goto found_flex_bg; >>>>> if (!stats.free_inodes) >>>>> continue; >>>>> if (stats.used_dirs >= best_ndir) >>>>> -- >>>>> 1.7.1 >>>>> <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> >>>> >>>> >>>> Cheers, Andreas >>> >>> >>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> > <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> Cheers, Andreas [-- Attachment #2: Message signed with OpenPGP using GPGMail --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v5] EXT4: optimizing group search for inode allocation 2016-01-11 21:13 ` Andreas Dilger @ 2016-01-16 22:50 ` Lokesh Jaliminche 2016-01-16 23:02 ` Lokesh Jaliminche 1 sibling, 0 replies; 12+ messages in thread From: Lokesh Jaliminche @ 2016-01-16 22:50 UTC (permalink / raw) To: Andreas Dilger, Theodore Ts'o; +Cc: linux-ext4 [-- Attachment #1: Type: text/plain, Size: 18010 bytes --] From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Thu, 7 Jan 2016 05:12:20 +0530 Subject: [PATCH v5] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" , "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..d2835cc 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { int best_ndir = inodes_per_group; int ret = -1; + /* Maximum usable blocks per group as some blocks are used + * for inode tables and allocation bitmaps */ + unsigned int max_blocks_per_flex = + ((sbi->s_blocks_per_group - + (sbi->s_itb_per_group + 2)) * + flex_size) >> sbi->s_cluster_bits; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* can't get better group than empty group */ + if (max_blocks_per_flex == stats.free_clusters && + (inodes_per_group * flex_size) == stats.free_inodes) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) --. 1.7.1 On Mon, Jan 11, 2016 at 02:13:46PM -0700, Andreas Dilger wrote: > On Jan 6, 2016, at 5:46 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > > > > you are right flex groups cannot be completely empty as some > > blocks are used for inode table and allocation bitmaps. I > > missed that point. I have corrected that. Also I have tested > > and validated this patch by putting some traces it works! > > Good news. Thanks for updating the patch and testing it. > More comments below. > > > Here are corresponding logs: > > commands: > > ========= > > mkfs.ext4 -g 10000 -G 2 /dev/sdc > > mount -t ext4 /dev/sdc /mnt/test_ext4/ > > cd /mnt/test_ext4 > > mkdir 1 > > cd 1 > > > > logs: > > ===== > > Jan 7 03:36:45 root kernel: [ 64.792939] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_clusters = [19264] > > Jan 7 03:36:45 root kernel: [ 64.792939] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_inodes = [4853] > > Jan 7 03:36:45 root kernel: [ 64.792950] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_clusters = [19481] > > Jan 7 03:36:45 root kernel: [ 64.792950] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_inodes = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792958] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_clusters = [19481] > > Jan 7 03:36:45 root kernel: [ 64.792958] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_inodes = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792965] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_clusters = [19481] > > Jan 7 03:36:45 root kernel: [ 64.792965] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_inodes = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792972] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_clusters = [19481] > > Jan 7 03:36:45 root kernel: [ 64.792972] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_inodes = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792979] max_usable_blocks_per_flex_group = [19692]<<<<<<<<<<< > > Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_clusters = [19692]<<<<<<<<<<< > > Jan 7 03:36:45 root kernel: [ 64.792979] Inodes_per_flex_group = [4864]<<<<<<<<<<<< > > Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_inodes = [4864]<<<<<<<<<<<< > > Jan 7 03:36:45 root kernel: [ 64.792985] found_flex_bg >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>condition satisfied > > > > > > [Patch v4]: > > ========== > > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > > Date: Thu, 7 Jan 2016 05:12:20 +0530 > > Subject: [PATCH] ext4: optimizing group serch for inode allocation > > > > Added a check at the start of group search loop to > > avoid looping unecessarily in case of empty group. > > This also allow group search to jump directly to > > "found_flex_bg" with "stats" and "group" already set, > > so there is no need to go through the extra steps of > > setting "best_desc" , "best_group" and then break > > out of the loop just to set "stats" and "group" again. > > > > Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > > --- > > fs/ext4/ext4.h | 2 ++ > > fs/ext4/ialloc.c | 21 +++++++++++++++++++-- > > 2 files changed, 21 insertions(+), 2 deletions(-) > > > > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h > > index cc7ca4e..fc48f9a 100644 > > --- a/fs/ext4/ext4.h > > +++ b/fs/ext4/ext4.h > > @@ -326,6 +326,8 @@ struct flex_groups { > > #define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE > > #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) > > #ifdef __KERNEL__ > > +# define EXT4_INODE_TABLE_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_itb_per_group) > > +# define EXT4_BLOCKS_PER_CLUSTER(s) (EXT4_SB(s)->s_cluster_ratio) > > I don't think there is much value to these macros. They aren't much > shorter than the actual variable access, and they don't provide any > improved clarity for the reader. > > I think they were introduced many years ago so that this header could > be shared between the kernel and e2fsprogs, but that is no longer true > so I don't think there is a need to add new ones. > > Ted, any opinion on this? > > > # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) > > # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) > > # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > > index 1b8024d..dc66ad8 100644 > > --- a/fs/ext4/ialloc.c > > +++ b/fs/ext4/ialloc.c > > @@ -463,7 +463,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > sbi->s_log_groups_per_flex; > > parent_group >>= sbi->s_log_groups_per_flex; > > } > > - > > freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); > > avefreei = freei / ngroups; > > Not sure why this line is being deleted? > > > @@ -477,7 +476,20 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > > int best_ndir = inodes_per_group; > > int ret = -1; > > - > > + /* blocks used for inode table and allocation bitmaps */ > > + unsigned int max_usable_blocks_per_flex_group; > > This could be shorter and still clear, like "max_blocks_per_flex". > > > + unsigned int blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb); > > + unsigned int inode_table_blocks_per_group = \ > > + EXT4_INODE_TABLE_BLOCKS_PER_GROUP(sb); > > + /* Number of blocks per cluster */ > > + unsigned int cluster_ratio = EXT4_BLOCKS_PER_CLUSTER(sb); > > There also isn't much value to making local variables that hold these > same values again. It increases stack space for little benefit. They > are only accessed once anyway. > > > + unsigned int inodes_per_flex_group = inodes_per_group * \ > > + flex_size; > > + max_usable_blocks_per_flex_group = \ > > + ((blocks_per_group*flex_size) - \ > > Spaces around that '*'. > > > + (inode_table_blocks_per_group * \ > > + flex_size + 2 * flex_size)) / \ > > This is C and not a CPP macro, so no need for linefeed escapes. > > > + cluster_ratio; > > This should be ">> EXT4_SB(sb)->s_cluster_bits" to avoid the divide. > > > if (qstr) { > > hinfo.hash_version = DX_HASH_HALF_MD4; > > hinfo.seed = sbi->s_hash_seed; > > @@ -489,6 +501,11 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > for (i = 0; i < ngroups; i++) { > > g = (parent_group + i) % ngroups; > > get_orlov_stats(sb, g, flex_size, &stats); > > + /* can't get better group than empty group */ > > + if (max_usable_blocks_per_flex_group == \ > > + stats.free_clusters && \ > > No need for linefeed escapes. > > > + inodes_per_flex_group == stats.free_inodes) > > Align continued line after '(' from the "if (" line. > > > + goto found_flex_bg; > > This is indented too much. It will work properly when you fix the > previous line. > > > if (!stats.free_inodes) > > continue; > > if (stats.used_dirs >= best_ndir) > > -- > > 1.7.1 > > > > Regards, > > Lokesh > > > > On Sun, Jan 03, 2016 at 11:34:51AM -0700, Andreas Dilger wrote: > >> On Dec 26, 2015, at 01:41, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > >>> > >>> > >>> From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 > >>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > >>> Date: Sat, 26 Dec 2015 13:19:36 +0530 > >>> Subject: [PATCH v3] ext4: optimizing group search for inode allocation > >>> > >>> Added a check at the start of group search loop to > >>> avoid looping unecessarily in case of empty group. > >>> This also allow group search to jump directly to > >>> "found_flex_bg" with "stats" and "group" already set, > >>> so there is no need to go through the extra steps of > >>> setting "best_desc" and "best_group" and then break > >>> out of the loop just to set "stats" and "group" again. > >>> > >>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > >>> --- > >>> fs/ext4/ialloc.c | 12 ++++++++++-- > >>> 1 files changed, 10 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > >>> index 1b8024d..16f94db 100644 > >>> --- a/fs/ext4/ialloc.c > >>> +++ b/fs/ext4/ialloc.c > >>> @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > >>> > >>> if (S_ISDIR(mode) && > >>> - ((parent == d_inode(sb->s_root)) || > >>> - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > >>> + ((parent == d_inode(sb->s_root)) || > >>> + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > >> > >> I don't understand why you are changing the indentation here? > >> > >>> + unsigned int inodes_per_flex_group; > >>> + unsigned long int clusters_per_flex_group; > >>> int best_ndir = inodes_per_group; > >>> int ret = -1; > >>> + inodes_per_flex_group = inodes_per_group * flex_size; > >>> + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; > >> > >> Have you actually tested if this code works? When I was looking at this > >> code I was accidentally looking at the ext2 version, which only deals with > >> individual groups, and not flex groups. I don't think that a flex group > >> can actually be completely empty, since it will always contain at least > >> an inode table and some bitmaps. > >> > >> This calculation needs to take this into account or it will just be > >> overhead and not an optimization. Something like: > >> > >> /* account for inode table and allocation bitmaps */ > >> clusters_per_flex_group = sbi->s_clusters_per_group * flex_size - > >> ((inodes_per_flex_group * EXT4_INODE_SIZE(sb) + > >> (flex_size << sb->s_blocksize_bits) * 2 ) >> > >> EXT4_SB(sb)->s_cluster_bits; > >> > >> It would be worthwhile to print this out and verify that there are actually > >> groups with this many free blocks in a newly formatted filesystem. > >> > >> Cheers, Andreas > >> > >>> if (qstr) { > >>> hinfo.hash_version = DX_HASH_HALF_MD4; > >>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>> for (i = 0; i < ngroups; i++) { > >>> g = (parent_group + i) % ngroups; > >>> get_orlov_stats(sb, g, flex_size, &stats); > >>> + /* the group can't get any better than empty */ > >>> + if (inodes_per_flex_group == stats.free_inodes && > >>> + clusters_per_flex_group == stats.free_clusters) > >>> + goto found_flex_bg; > >>> if (!stats.free_inodes) > >>> continue; > >>> if (stats.used_dirs >= best_ndir) > >>> -- > >>> 1.7.1 > >>> > >>> > >>>> On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: > >>>>> On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: > >>>>> > >>>>> From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 > >>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> > >>>> > >>>> In the patch summary there is a typo - s/serch/search/ > >>>> > >>>> Also, it appears your email client has mangled the whitespace in the > >>>> patch. Please use "git send-email" to send your patch to the list: > >>>> > >>>> git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 > >>>> > >>>> so that it arrives intact. You probably need to set it up in ~/.gitconfig: > >>>> > >>>> [sendemail] > >>>> confirm = compose > >>>> smtpdomain = {your client hostname} > >>>> smtpserver = {your SMTP server hostname} > >>>> > >>>> Cheers, Andreas > >>>> > >>>>> Added a check at the start of group search loop to > >>>>> avoid looping unecessarily in case of empty group. > >>>>> This also allow group search to jump directly to > >>>>> "found_flex_bg" with "stats" and "group" already set, > >>>>> so there is no need to go through the extra steps of > >>>>> setting "best_desc" and "best_group" and then break > >>>>> out of the loop just to set "stats" and "group" again. > >>>>> > >>>>> Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> > >>>>> --- > >>>>> fs/ext4/ialloc.c | 8 ++++++++ > >>>>> 1 files changed, 8 insertions(+), 0 deletions(-) > >>>>> > >>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > >>>>> index 1b8024d..588bf8e 100644 > >>>>> --- a/fs/ext4/ialloc.c > >>>>> +++ b/fs/ext4/ialloc.c > >>>>> @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block > >>>>> *sb, struct inode *parent, > >>>>> struct ext4_sb_info *sbi = EXT4_SB(sb); > >>>>> ext4_group_t real_ngroups = ext4_get_groups_count(sb); > >>>>> int inodes_per_group = EXT4_INODES_PER_GROUP(sb); > >>>>> + unsigned int inodes_per_flex_group; > >>>>> + long unsigned int blocks_per_clustre; > >>>>> unsigned int freei, avefreei, grp_free; > >>>>> ext4_fsblk_t freeb, avefreec; > >>>>> unsigned int ndirs; > >>>>> @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block > >>>>> *sb, struct inode *parent, > >>>>> percpu_counter_read_positive(&sbi->s_freeclusters_counter)); > >>>>> avefreec = freeb; > >>>>> do_div(avefreec, ngroups); > >>>>> + inodes_per_flex_group = inodes_per_group * flex_size; > >>>>> + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; > >>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > >>>>> > >>>>> if (S_ISDIR(mode) && > >>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block > >>>>> *sb, struct inode *parent, > >>>>> for (i = 0; i < ngroups; i++) { > >>>>> g = (parent_group + i) % ngroups; > >>>>> get_orlov_stats(sb, g, flex_size, &stats); > >>>>> + /* the group can't get any better than empty */ > >>>>> + if (inodes_per_flex_group == stats.free_inodes && > >>>>> + blocks_per_clustre == stats.free_clusters) > >>>>> + goto found_flex_bg; > >>>>> if (!stats.free_inodes) > >>>>> continue; > >>>>> if (stats.used_dirs >= best_ndir) > >>>>> -- > >>>>> 1.7.1 > >>>>> <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> > >>>> > >>>> > >>>> Cheers, Andreas > >>> > >>> > >>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> > > <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> > > > Cheers, Andreas > > > > > [-- Attachment #2: 0001-ext4-optimizing-group-serch-for-inode-allocation.patch --] [-- Type: text/plain, Size: 1917 bytes --] >From 11eeb037cbeecb82fd2ecb01056c9bfcd8d9d50f Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Thu, 7 Jan 2016 05:12:20 +0530 Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" , "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..d2835cc 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { int best_ndir = inodes_per_group; int ret = -1; + /* Maximum usable blocks per group as some blocks are used + * for inode tables and allocation bitmaps */ + unsigned int max_blocks_per_flex = + ((sbi->s_blocks_per_group - + (sbi->s_itb_per_group + 2)) * + flex_size) >> sbi->s_cluster_bits; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* can't get better group than empty group */ + if (max_blocks_per_flex == stats.free_clusters && + (inodes_per_group * flex_size) == stats.free_inodes) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v5] EXT4: optimizing group search for inode allocation 2016-01-11 21:13 ` Andreas Dilger 2016-01-16 22:50 ` [PATCH v5] " Lokesh Jaliminche @ 2016-01-16 23:02 ` Lokesh Jaliminche 2016-01-18 21:50 ` Andreas Dilger 1 sibling, 1 reply; 12+ messages in thread From: Lokesh Jaliminche @ 2016-01-16 23:02 UTC (permalink / raw) To: Andreas Dilger, Theodore Ts'o; +Cc: linux-ext4 [-- Attachment #1: Type: text/plain, Size: 18394 bytes --] From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Thu, 7 Jan 2016 05:12:20 +0530 Subject: [PATCH v5] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" , "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..d2835cc 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { int best_ndir = inodes_per_group; int ret = -1; + /* Maximum usable blocks per group as some blocks are used + * for inode tables and allocation bitmaps */ + unsigned int max_blocks_per_flex = + ((sbi->s_blocks_per_group - + (sbi->s_itb_per_group + 2)) * + flex_size) >> sbi->s_cluster_bits; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* can't get better group than empty group */ + if (max_blocks_per_flex == stats.free_clusters && + (inodes_per_group * flex_size) == stats.free_inodes) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 On Mon, Jan 11, 2016 at 02:13:46PM -0700, Andreas Dilger wrote: > On Jan 6, 2016, at 5:46 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > > > > you are right flex groups cannot be completely empty as some > > blocks are used for inode table and allocation bitmaps. I > > missed that point. I have corrected that. Also I have tested > > and validated this patch by putting some traces it works! > > Good news. Thanks for updating the patch and testing it. > More comments below. > > > Here are corresponding logs: > > commands: > > ========= > > mkfs.ext4 -g 10000 -G 2 /dev/sdc > > mount -t ext4 /dev/sdc /mnt/test_ext4/ > > cd /mnt/test_ext4 > > mkdir 1 > > cd 1 > > > > logs: > > ===== > > Jan 7 03:36:45 root kernel: [ 64.792939] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_clusters = [19264] > > Jan 7 03:36:45 root kernel: [ 64.792939] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_inodes = [4853] > > Jan 7 03:36:45 root kernel: [ 64.792950] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_clusters = [19481] > > Jan 7 03:36:45 root kernel: [ 64.792950] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_inodes = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792958] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_clusters = [19481] > > Jan 7 03:36:45 root kernel: [ 64.792958] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_inodes = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792965] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_clusters = [19481] > > Jan 7 03:36:45 root kernel: [ 64.792965] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_inodes = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792972] max_usable_blocks_per_flex_group = [19692] > > Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_clusters = [19481] > > Jan 7 03:36:45 root kernel: [ 64.792972] Inodes_per_flex_group = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_inodes = [4864] > > Jan 7 03:36:45 root kernel: [ 64.792979] max_usable_blocks_per_flex_group = [19692]<<<<<<<<<<< > > Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_clusters = [19692]<<<<<<<<<<< > > Jan 7 03:36:45 root kernel: [ 64.792979] Inodes_per_flex_group = [4864]<<<<<<<<<<<< > > Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_inodes = [4864]<<<<<<<<<<<< > > Jan 7 03:36:45 root kernel: [ 64.792985] found_flex_bg >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>condition satisfied > > > > > > [Patch v4]: > > ========== > > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > > Date: Thu, 7 Jan 2016 05:12:20 +0530 > > Subject: [PATCH] ext4: optimizing group serch for inode allocation > > > > Added a check at the start of group search loop to > > avoid looping unecessarily in case of empty group. > > This also allow group search to jump directly to > > "found_flex_bg" with "stats" and "group" already set, > > so there is no need to go through the extra steps of > > setting "best_desc" , "best_group" and then break > > out of the loop just to set "stats" and "group" again. > > > > Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > > --- > > fs/ext4/ext4.h | 2 ++ > > fs/ext4/ialloc.c | 21 +++++++++++++++++++-- > > 2 files changed, 21 insertions(+), 2 deletions(-) > > > > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h > > index cc7ca4e..fc48f9a 100644 > > --- a/fs/ext4/ext4.h > > +++ b/fs/ext4/ext4.h > > @@ -326,6 +326,8 @@ struct flex_groups { > > #define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE > > #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) > > #ifdef __KERNEL__ > > +# define EXT4_INODE_TABLE_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_itb_per_group) > > +# define EXT4_BLOCKS_PER_CLUSTER(s) (EXT4_SB(s)->s_cluster_ratio) > > I don't think there is much value to these macros. They aren't much > shorter than the actual variable access, and they don't provide any > improved clarity for the reader. > > I think they were introduced many years ago so that this header could > be shared between the kernel and e2fsprogs, but that is no longer true > so I don't think there is a need to add new ones. > > Ted, any opinion on this? > > > # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) > > # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) > > # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > > index 1b8024d..dc66ad8 100644 > > --- a/fs/ext4/ialloc.c > > +++ b/fs/ext4/ialloc.c > > @@ -463,7 +463,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > sbi->s_log_groups_per_flex; > > parent_group >>= sbi->s_log_groups_per_flex; > > } > > - > > freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); > > avefreei = freei / ngroups; > > Not sure why this line is being deleted? > > > @@ -477,7 +476,20 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > > int best_ndir = inodes_per_group; > > int ret = -1; > > - > > + /* blocks used for inode table and allocation bitmaps */ > > + unsigned int max_usable_blocks_per_flex_group; > > This could be shorter and still clear, like "max_blocks_per_flex". > > > + unsigned int blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb); > > + unsigned int inode_table_blocks_per_group = \ > > + EXT4_INODE_TABLE_BLOCKS_PER_GROUP(sb); > > + /* Number of blocks per cluster */ > > + unsigned int cluster_ratio = EXT4_BLOCKS_PER_CLUSTER(sb); > > There also isn't much value to making local variables that hold these > same values again. It increases stack space for little benefit. They > are only accessed once anyway. > > > + unsigned int inodes_per_flex_group = inodes_per_group * \ > > + flex_size; > > + max_usable_blocks_per_flex_group = \ > > + ((blocks_per_group*flex_size) - \ > > Spaces around that '*'. > > > + (inode_table_blocks_per_group * \ > > + flex_size + 2 * flex_size)) / \ > > This is C and not a CPP macro, so no need for linefeed escapes. > > > + cluster_ratio; > > This should be ">> EXT4_SB(sb)->s_cluster_bits" to avoid the divide. > > > if (qstr) { > > hinfo.hash_version = DX_HASH_HALF_MD4; > > hinfo.seed = sbi->s_hash_seed; > > @@ -489,6 +501,11 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > for (i = 0; i < ngroups; i++) { > > g = (parent_group + i) % ngroups; > > get_orlov_stats(sb, g, flex_size, &stats); > > + /* can't get better group than empty group */ > > + if (max_usable_blocks_per_flex_group == \ > > + stats.free_clusters && \ > > No need for linefeed escapes. > > > + inodes_per_flex_group == stats.free_inodes) > > Align continued line after '(' from the "if (" line. > > > + goto found_flex_bg; > > This is indented too much. It will work properly when you fix the > previous line. > > > if (!stats.free_inodes) > > continue; > > if (stats.used_dirs >= best_ndir) > > -- > > 1.7.1 > > > > Regards, > > Lokesh > > > > On Sun, Jan 03, 2016 at 11:34:51AM -0700, Andreas Dilger wrote: > >> On Dec 26, 2015, at 01:41, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > >>> > >>> > >>> From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 > >>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > >>> Date: Sat, 26 Dec 2015 13:19:36 +0530 > >>> Subject: [PATCH v3] ext4: optimizing group search for inode allocation > >>> > >>> Added a check at the start of group search loop to > >>> avoid looping unecessarily in case of empty group. > >>> This also allow group search to jump directly to > >>> "found_flex_bg" with "stats" and "group" already set, > >>> so there is no need to go through the extra steps of > >>> setting "best_desc" and "best_group" and then break > >>> out of the loop just to set "stats" and "group" again. > >>> > >>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > >>> --- > >>> fs/ext4/ialloc.c | 12 ++++++++++-- > >>> 1 files changed, 10 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > >>> index 1b8024d..16f94db 100644 > >>> --- a/fs/ext4/ialloc.c > >>> +++ b/fs/ext4/ialloc.c > >>> @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > >>> > >>> if (S_ISDIR(mode) && > >>> - ((parent == d_inode(sb->s_root)) || > >>> - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > >>> + ((parent == d_inode(sb->s_root)) || > >>> + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > >> > >> I don't understand why you are changing the indentation here? > >> > >>> + unsigned int inodes_per_flex_group; > >>> + unsigned long int clusters_per_flex_group; > >>> int best_ndir = inodes_per_group; > >>> int ret = -1; > >>> + inodes_per_flex_group = inodes_per_group * flex_size; > >>> + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; > >> > >> Have you actually tested if this code works? When I was looking at this > >> code I was accidentally looking at the ext2 version, which only deals with > >> individual groups, and not flex groups. I don't think that a flex group > >> can actually be completely empty, since it will always contain at least > >> an inode table and some bitmaps. > >> > >> This calculation needs to take this into account or it will just be > >> overhead and not an optimization. Something like: > >> > >> /* account for inode table and allocation bitmaps */ > >> clusters_per_flex_group = sbi->s_clusters_per_group * flex_size - > >> ((inodes_per_flex_group * EXT4_INODE_SIZE(sb) + > >> (flex_size << sb->s_blocksize_bits) * 2 ) >> > >> EXT4_SB(sb)->s_cluster_bits; > >> > >> It would be worthwhile to print this out and verify that there are actually > >> groups with this many free blocks in a newly formatted filesystem. > >> > >> Cheers, Andreas > >> > >>> if (qstr) { > >>> hinfo.hash_version = DX_HASH_HALF_MD4; > >>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>> for (i = 0; i < ngroups; i++) { > >>> g = (parent_group + i) % ngroups; > >>> get_orlov_stats(sb, g, flex_size, &stats); > >>> + /* the group can't get any better than empty */ > >>> + if (inodes_per_flex_group == stats.free_inodes && > >>> + clusters_per_flex_group == stats.free_clusters) > >>> + goto found_flex_bg; > >>> if (!stats.free_inodes) > >>> continue; > >>> if (stats.used_dirs >= best_ndir) > >>> -- > >>> 1.7.1 > >>> > >>> > >>>> On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: > >>>>> On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: > >>>>> > >>>>> From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 > >>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> > >>>> > >>>> In the patch summary there is a typo - s/serch/search/ > >>>> > >>>> Also, it appears your email client has mangled the whitespace in the > >>>> patch. Please use "git send-email" to send your patch to the list: > >>>> > >>>> git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 > >>>> > >>>> so that it arrives intact. You probably need to set it up in ~/.gitconfig: > >>>> > >>>> [sendemail] > >>>> confirm = compose > >>>> smtpdomain = {your client hostname} > >>>> smtpserver = {your SMTP server hostname} > >>>> > >>>> Cheers, Andreas > >>>> > >>>>> Added a check at the start of group search loop to > >>>>> avoid looping unecessarily in case of empty group. > >>>>> This also allow group search to jump directly to > >>>>> "found_flex_bg" with "stats" and "group" already set, > >>>>> so there is no need to go through the extra steps of > >>>>> setting "best_desc" and "best_group" and then break > >>>>> out of the loop just to set "stats" and "group" again. > >>>>> > >>>>> Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> > >>>>> --- > >>>>> fs/ext4/ialloc.c | 8 ++++++++ > >>>>> 1 files changed, 8 insertions(+), 0 deletions(-) > >>>>> > >>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > >>>>> index 1b8024d..588bf8e 100644 > >>>>> --- a/fs/ext4/ialloc.c > >>>>> +++ b/fs/ext4/ialloc.c > >>>>> @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block > >>>>> *sb, struct inode *parent, > >>>>> struct ext4_sb_info *sbi = EXT4_SB(sb); > >>>>> ext4_group_t real_ngroups = ext4_get_groups_count(sb); > >>>>> int inodes_per_group = EXT4_INODES_PER_GROUP(sb); > >>>>> + unsigned int inodes_per_flex_group; > >>>>> + long unsigned int blocks_per_clustre; > >>>>> unsigned int freei, avefreei, grp_free; > >>>>> ext4_fsblk_t freeb, avefreec; > >>>>> unsigned int ndirs; > >>>>> @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block > >>>>> *sb, struct inode *parent, > >>>>> percpu_counter_read_positive(&sbi->s_freeclusters_counter)); > >>>>> avefreec = freeb; > >>>>> do_div(avefreec, ngroups); > >>>>> + inodes_per_flex_group = inodes_per_group * flex_size; > >>>>> + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; > >>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > >>>>> > >>>>> if (S_ISDIR(mode) && > >>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block > >>>>> *sb, struct inode *parent, > >>>>> for (i = 0; i < ngroups; i++) { > >>>>> g = (parent_group + i) % ngroups; > >>>>> get_orlov_stats(sb, g, flex_size, &stats); > >>>>> + /* the group can't get any better than empty */ > >>>>> + if (inodes_per_flex_group == stats.free_inodes && > >>>>> + blocks_per_clustre == stats.free_clusters) > >>>>> + goto found_flex_bg; > >>>>> if (!stats.free_inodes) > >>>>> continue; > >>>>> if (stats.used_dirs >= best_ndir) > >>>>> -- > >>>>> 1.7.1 > >>>>> <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> > >>>> > >>>> > >>>> Cheers, Andreas > >>> > >>> > >>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> > > <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> > > > Cheers, Andreas > > > > > [-- Attachment #2: 0001-ext4-optimizing-group-serch-for-inode-allocation.patch --] [-- Type: text/plain, Size: 1917 bytes --] >From 11eeb037cbeecb82fd2ecb01056c9bfcd8d9d50f Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Thu, 7 Jan 2016 05:12:20 +0530 Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" , "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..d2835cc 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { int best_ndir = inodes_per_group; int ret = -1; + /* Maximum usable blocks per group as some blocks are used + * for inode tables and allocation bitmaps */ + unsigned int max_blocks_per_flex = + ((sbi->s_blocks_per_group - + (sbi->s_itb_per_group + 2)) * + flex_size) >> sbi->s_cluster_bits; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* can't get better group than empty group */ + if (max_blocks_per_flex == stats.free_clusters && + (inodes_per_group * flex_size) == stats.free_inodes) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v5] EXT4: optimizing group search for inode allocation 2016-01-16 23:02 ` Lokesh Jaliminche @ 2016-01-18 21:50 ` Andreas Dilger 2016-01-19 6:08 ` [PATCH v6] " Lokesh Jaliminche 0 siblings, 1 reply; 12+ messages in thread From: Andreas Dilger @ 2016-01-18 21:50 UTC (permalink / raw) To: Lokesh Jaliminche; +Cc: Theodore Ts'o, linux-ext4 [-- Attachment #1: Type: text/plain, Size: 19446 bytes --] On Jan 16, 2016, at 4:02 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > Date: Thu, 7 Jan 2016 05:12:20 +0530 > Subject: [PATCH v5] ext4: optimizing group serch for inode allocation > > Added a check at the start of group search loop to > avoid looping unecessarily in case of empty group. > This also allow group search to jump directly to > "found_flex_bg" with "stats" and "group" already set, > so there is no need to go through the extra steps of > setting "best_desc" , "best_group" and then break > out of the loop just to set "stats" and "group" again. This looks very good, just one minor potential issue below. > Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > --- > fs/ext4/ialloc.c | 10 ++++++++++ > 1 files changed, 10 insertions(+), 0 deletions(-) > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > index 1b8024d..d2835cc 100644 > --- a/fs/ext4/ialloc.c > +++ b/fs/ext4/ialloc.c > @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > int best_ndir = inodes_per_group; > int ret = -1; > + /* Maximum usable blocks per group as some blocks are used > + * for inode tables and allocation bitmaps */ > + unsigned int max_blocks_per_flex = This should be an unsigned long long or __u64, since the max_blocks_per_flex calculation may overflow a 32-bit value on filesystems with larger block_size and a large value for flex_size (larger than 2^13 for a 64KB blocksize). The "stats.free_clusters" is already a __u64 for this reason. > + ((sbi->s_blocks_per_group - > + (sbi->s_itb_per_group + 2)) * > + flex_size) >> sbi->s_cluster_bits; > > if (qstr) { > hinfo.hash_version = DX_HASH_HALF_MD4; > @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > for (i = 0; i < ngroups; i++) { > g = (parent_group + i) % ngroups; > get_orlov_stats(sb, g, flex_size, &stats); > + /* can't get better group than empty group */ > + if (max_blocks_per_flex == stats.free_clusters && > + (inodes_per_group * flex_size) == stats.free_inodes) > + goto found_flex_bg; > if (!stats.free_inodes) > continue; > if (stats.used_dirs >= best_ndir) > -- > 1.7.1 > > > > On Mon, Jan 11, 2016 at 02:13:46PM -0700, Andreas Dilger wrote: >> On Jan 6, 2016, at 5:46 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: >>> >>> you are right flex groups cannot be completely empty as some >>> blocks are used for inode table and allocation bitmaps. I >>> missed that point. I have corrected that. Also I have tested >>> and validated this patch by putting some traces it works! >> >> Good news. Thanks for updating the patch and testing it. >> More comments below. >> >>> Here are corresponding logs: >>> commands: >>> ========= >>> mkfs.ext4 -g 10000 -G 2 /dev/sdc >>> mount -t ext4 /dev/sdc /mnt/test_ext4/ >>> cd /mnt/test_ext4 >>> mkdir 1 >>> cd 1 >>> >>> logs: >>> ===== >>> Jan 7 03:36:45 root kernel: [ 64.792939] max_usable_blocks_per_flex_group = [19692] >>> Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_clusters = [19264] >>> Jan 7 03:36:45 root kernel: [ 64.792939] Inodes_per_flex_group = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_inodes = [4853] >>> Jan 7 03:36:45 root kernel: [ 64.792950] max_usable_blocks_per_flex_group = [19692] >>> Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_clusters = [19481] >>> Jan 7 03:36:45 root kernel: [ 64.792950] Inodes_per_flex_group = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_inodes = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792958] max_usable_blocks_per_flex_group = [19692] >>> Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_clusters = [19481] >>> Jan 7 03:36:45 root kernel: [ 64.792958] Inodes_per_flex_group = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_inodes = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792965] max_usable_blocks_per_flex_group = [19692] >>> Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_clusters = [19481] >>> Jan 7 03:36:45 root kernel: [ 64.792965] Inodes_per_flex_group = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_inodes = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792972] max_usable_blocks_per_flex_group = [19692] >>> Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_clusters = [19481] >>> Jan 7 03:36:45 root kernel: [ 64.792972] Inodes_per_flex_group = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_inodes = [4864] >>> Jan 7 03:36:45 root kernel: [ 64.792979] max_usable_blocks_per_flex_group = [19692]<<<<<<<<<<< >>> Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_clusters = [19692]<<<<<<<<<<< >>> Jan 7 03:36:45 root kernel: [ 64.792979] Inodes_per_flex_group = [4864]<<<<<<<<<<<< >>> Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_inodes = [4864]<<<<<<<<<<<< >>> Jan 7 03:36:45 root kernel: [ 64.792985] found_flex_bg >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>condition satisfied >>> >>> >>> [Patch v4]: >>> ========== >>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>> Date: Thu, 7 Jan 2016 05:12:20 +0530 >>> Subject: [PATCH] ext4: optimizing group serch for inode allocation >>> >>> Added a check at the start of group search loop to >>> avoid looping unecessarily in case of empty group. >>> This also allow group search to jump directly to >>> "found_flex_bg" with "stats" and "group" already set, >>> so there is no need to go through the extra steps of >>> setting "best_desc" , "best_group" and then break >>> out of the loop just to set "stats" and "group" again. >>> >>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>> --- >>> fs/ext4/ext4.h | 2 ++ >>> fs/ext4/ialloc.c | 21 +++++++++++++++++++-- >>> 2 files changed, 21 insertions(+), 2 deletions(-) >>> >>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h >>> index cc7ca4e..fc48f9a 100644 >>> --- a/fs/ext4/ext4.h >>> +++ b/fs/ext4/ext4.h >>> @@ -326,6 +326,8 @@ struct flex_groups { >>> #define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE >>> #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) >>> #ifdef __KERNEL__ >>> +# define EXT4_INODE_TABLE_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_itb_per_group) >>> +# define EXT4_BLOCKS_PER_CLUSTER(s) (EXT4_SB(s)->s_cluster_ratio) >> >> I don't think there is much value to these macros. They aren't much >> shorter than the actual variable access, and they don't provide any >> improved clarity for the reader. >> >> I think they were introduced many years ago so that this header could >> be shared between the kernel and e2fsprogs, but that is no longer true >> so I don't think there is a need to add new ones. >> >> Ted, any opinion on this? >> >>> # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) >>> # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) >>> # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) >>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>> index 1b8024d..dc66ad8 100644 >>> --- a/fs/ext4/ialloc.c >>> +++ b/fs/ext4/ialloc.c >>> @@ -463,7 +463,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>> sbi->s_log_groups_per_flex; >>> parent_group >>= sbi->s_log_groups_per_flex; >>> } >>> - >>> freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); >>> avefreei = freei / ngroups; >> >> Not sure why this line is being deleted? >> >>> @@ -477,7 +476,20 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>> (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >>> int best_ndir = inodes_per_group; >>> int ret = -1; >>> - >>> + /* blocks used for inode table and allocation bitmaps */ >>> + unsigned int max_usable_blocks_per_flex_group; >> >> This could be shorter and still clear, like "max_blocks_per_flex". >> >>> + unsigned int blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb); >>> + unsigned int inode_table_blocks_per_group = \ >>> + EXT4_INODE_TABLE_BLOCKS_PER_GROUP(sb); >>> + /* Number of blocks per cluster */ >>> + unsigned int cluster_ratio = EXT4_BLOCKS_PER_CLUSTER(sb); >> >> There also isn't much value to making local variables that hold these >> same values again. It increases stack space for little benefit. They >> are only accessed once anyway. >> >>> + unsigned int inodes_per_flex_group = inodes_per_group * \ >>> + flex_size; >>> + max_usable_blocks_per_flex_group = \ >>> + ((blocks_per_group*flex_size) - \ >> >> Spaces around that '*'. >> >>> + (inode_table_blocks_per_group * \ >>> + flex_size + 2 * flex_size)) / \ >> >> This is C and not a CPP macro, so no need for linefeed escapes. >> >>> + cluster_ratio; >> >> This should be ">> EXT4_SB(sb)->s_cluster_bits" to avoid the divide. >> >>> if (qstr) { >>> hinfo.hash_version = DX_HASH_HALF_MD4; >>> hinfo.seed = sbi->s_hash_seed; >>> @@ -489,6 +501,11 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>> for (i = 0; i < ngroups; i++) { >>> g = (parent_group + i) % ngroups; >>> get_orlov_stats(sb, g, flex_size, &stats); >>> + /* can't get better group than empty group */ >>> + if (max_usable_blocks_per_flex_group == \ >>> + stats.free_clusters && \ >> >> No need for linefeed escapes. >> >>> + inodes_per_flex_group == stats.free_inodes) >> >> Align continued line after '(' from the "if (" line. >> >>> + goto found_flex_bg; >> >> This is indented too much. It will work properly when you fix the >> previous line. >> >>> if (!stats.free_inodes) >>> continue; >>> if (stats.used_dirs >= best_ndir) >>> -- >>> 1.7.1 >>> >>> Regards, >>> Lokesh >>> >>> On Sun, Jan 03, 2016 at 11:34:51AM -0700, Andreas Dilger wrote: >>>> On Dec 26, 2015, at 01:41, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: >>>>> >>>>> >>>>> From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 >>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>>>> Date: Sat, 26 Dec 2015 13:19:36 +0530 >>>>> Subject: [PATCH v3] ext4: optimizing group search for inode allocation >>>>> >>>>> Added a check at the start of group search loop to >>>>> avoid looping unecessarily in case of empty group. >>>>> This also allow group search to jump directly to >>>>> "found_flex_bg" with "stats" and "group" already set, >>>>> so there is no need to go through the extra steps of >>>>> setting "best_desc" and "best_group" and then break >>>>> out of the loop just to set "stats" and "group" again. >>>>> >>>>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>>>> --- >>>>> fs/ext4/ialloc.c | 12 ++++++++++-- >>>>> 1 files changed, 10 insertions(+), 2 deletions(-) >>>>> >>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>>>> index 1b8024d..16f94db 100644 >>>>> --- a/fs/ext4/ialloc.c >>>>> +++ b/fs/ext4/ialloc.c >>>>> @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); >>>>> >>>>> if (S_ISDIR(mode) && >>>>> - ((parent == d_inode(sb->s_root)) || >>>>> - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >>>>> + ((parent == d_inode(sb->s_root)) || >>>>> + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >>>> >>>> I don't understand why you are changing the indentation here? >>>> >>>>> + unsigned int inodes_per_flex_group; >>>>> + unsigned long int clusters_per_flex_group; >>>>> int best_ndir = inodes_per_group; >>>>> int ret = -1; >>>>> + inodes_per_flex_group = inodes_per_group * flex_size; >>>>> + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; >>>> >>>> Have you actually tested if this code works? When I was looking at this >>>> code I was accidentally looking at the ext2 version, which only deals with >>>> individual groups, and not flex groups. I don't think that a flex group >>>> can actually be completely empty, since it will always contain at least >>>> an inode table and some bitmaps. >>>> >>>> This calculation needs to take this into account or it will just be >>>> overhead and not an optimization. Something like: >>>> >>>> /* account for inode table and allocation bitmaps */ >>>> clusters_per_flex_group = sbi->s_clusters_per_group * flex_size - >>>> ((inodes_per_flex_group * EXT4_INODE_SIZE(sb) + >>>> (flex_size << sb->s_blocksize_bits) * 2 ) >> >>>> EXT4_SB(sb)->s_cluster_bits; >>>> >>>> It would be worthwhile to print this out and verify that there are actually >>>> groups with this many free blocks in a newly formatted filesystem. >>>> >>>> Cheers, Andreas >>>> >>>>> if (qstr) { >>>>> hinfo.hash_version = DX_HASH_HALF_MD4; >>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>>>> for (i = 0; i < ngroups; i++) { >>>>> g = (parent_group + i) % ngroups; >>>>> get_orlov_stats(sb, g, flex_size, &stats); >>>>> + /* the group can't get any better than empty */ >>>>> + if (inodes_per_flex_group == stats.free_inodes && >>>>> + clusters_per_flex_group == stats.free_clusters) >>>>> + goto found_flex_bg; >>>>> if (!stats.free_inodes) >>>>> continue; >>>>> if (stats.used_dirs >= best_ndir) >>>>> -- >>>>> 1.7.1 >>>>> >>>>> >>>>>> On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: >>>>>>> On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: >>>>>>> >>>>>>> From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 >>>>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> >>>>>> >>>>>> In the patch summary there is a typo - s/serch/search/ >>>>>> >>>>>> Also, it appears your email client has mangled the whitespace in the >>>>>> patch. Please use "git send-email" to send your patch to the list: >>>>>> >>>>>> git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 >>>>>> >>>>>> so that it arrives intact. You probably need to set it up in ~/.gitconfig: >>>>>> >>>>>> [sendemail] >>>>>> confirm = compose >>>>>> smtpdomain = {your client hostname} >>>>>> smtpserver = {your SMTP server hostname} >>>>>> >>>>>> Cheers, Andreas >>>>>> >>>>>>> Added a check at the start of group search loop to >>>>>>> avoid looping unecessarily in case of empty group. >>>>>>> This also allow group search to jump directly to >>>>>>> "found_flex_bg" with "stats" and "group" already set, >>>>>>> so there is no need to go through the extra steps of >>>>>>> setting "best_desc" and "best_group" and then break >>>>>>> out of the loop just to set "stats" and "group" again. >>>>>>> >>>>>>> Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> >>>>>>> --- >>>>>>> fs/ext4/ialloc.c | 8 ++++++++ >>>>>>> 1 files changed, 8 insertions(+), 0 deletions(-) >>>>>>> >>>>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>>>>>> index 1b8024d..588bf8e 100644 >>>>>>> --- a/fs/ext4/ialloc.c >>>>>>> +++ b/fs/ext4/ialloc.c >>>>>>> @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block >>>>>>> *sb, struct inode *parent, >>>>>>> struct ext4_sb_info *sbi = EXT4_SB(sb); >>>>>>> ext4_group_t real_ngroups = ext4_get_groups_count(sb); >>>>>>> int inodes_per_group = EXT4_INODES_PER_GROUP(sb); >>>>>>> + unsigned int inodes_per_flex_group; >>>>>>> + long unsigned int blocks_per_clustre; >>>>>>> unsigned int freei, avefreei, grp_free; >>>>>>> ext4_fsblk_t freeb, avefreec; >>>>>>> unsigned int ndirs; >>>>>>> @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block >>>>>>> *sb, struct inode *parent, >>>>>>> percpu_counter_read_positive(&sbi->s_freeclusters_counter)); >>>>>>> avefreec = freeb; >>>>>>> do_div(avefreec, ngroups); >>>>>>> + inodes_per_flex_group = inodes_per_group * flex_size; >>>>>>> + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; >>>>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); >>>>>>> >>>>>>> if (S_ISDIR(mode) && >>>>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block >>>>>>> *sb, struct inode *parent, >>>>>>> for (i = 0; i < ngroups; i++) { >>>>>>> g = (parent_group + i) % ngroups; >>>>>>> get_orlov_stats(sb, g, flex_size, &stats); >>>>>>> + /* the group can't get any better than empty */ >>>>>>> + if (inodes_per_flex_group == stats.free_inodes && >>>>>>> + blocks_per_clustre == stats.free_clusters) >>>>>>> + goto found_flex_bg; >>>>>>> if (!stats.free_inodes) >>>>>>> continue; >>>>>>> if (stats.used_dirs >= best_ndir) >>>>>>> -- >>>>>>> 1.7.1 >>>>>>> <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> >>>>>> >>>>>> >>>>>> Cheers, Andreas >>>>> >>>>> >>>>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> >>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> >> >> >> Cheers, Andreas >> >> >> >> >> > > > <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> Cheers, Andreas [-- Attachment #2: Message signed with OpenPGP using GPGMail --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6] EXT4: optimizing group search for inode allocation 2016-01-18 21:50 ` Andreas Dilger @ 2016-01-19 6:08 ` Lokesh Jaliminche 2016-01-19 7:24 ` Andreas Dilger 2016-02-23 4:04 ` Theodore Ts'o 0 siblings, 2 replies; 12+ messages in thread From: Lokesh Jaliminche @ 2016-01-19 6:08 UTC (permalink / raw) To: Andreas Dilger, Theodore Ts'o; +Cc: linux-ext4 [-- Attachment #1: Type: text/plain, Size: 22115 bytes --] From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" , "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..3463d30 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { int best_ndir = inodes_per_group; int ret = -1; + /* Maximum usable blocks per group as some blocks are used + * for inode tables and allocation bitmaps */ + unsigned long long max_blocks_per_flex = + ((sbi->s_blocks_per_group - + (sbi->s_itb_per_group + 2)) * + flex_size) >> sbi->s_cluster_bits; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* can't get better group than empty group */ + if (max_blocks_per_flex == stats.free_clusters && + (inodes_per_group * flex_size) == stats.free_inodes) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 On Mon, Jan 18, 2016 at 02:50:48PM -0700, Andreas Dilger wrote: > On Jan 16, 2016, at 4:02 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > > > > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > > Date: Thu, 7 Jan 2016 05:12:20 +0530 > > Subject: [PATCH v5] ext4: optimizing group serch for inode allocation > > > > Added a check at the start of group search loop to > > avoid looping unecessarily in case of empty group. > > This also allow group search to jump directly to > > "found_flex_bg" with "stats" and "group" already set, > > so there is no need to go through the extra steps of > > setting "best_desc" , "best_group" and then break > > out of the loop just to set "stats" and "group" again. > > This looks very good, just one minor potential issue below. > > > Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > > --- > > fs/ext4/ialloc.c | 10 ++++++++++ > > 1 files changed, 10 insertions(+), 0 deletions(-) > > > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > > index 1b8024d..d2835cc 100644 > > --- a/fs/ext4/ialloc.c > > +++ b/fs/ext4/ialloc.c > > @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > > int best_ndir = inodes_per_group; > > int ret = -1; > > + /* Maximum usable blocks per group as some blocks are used > > + * for inode tables and allocation bitmaps */ > > + unsigned int max_blocks_per_flex = > > This should be an unsigned long long or __u64, since the max_blocks_per_flex > calculation may overflow a 32-bit value on filesystems with larger block_size > and a large value for flex_size (larger than 2^13 for a 64KB blocksize). > > The "stats.free_clusters" is already a __u64 for this reason. > > > + ((sbi->s_blocks_per_group - > > + (sbi->s_itb_per_group + 2)) * > > + flex_size) >> sbi->s_cluster_bits; > > > > if (qstr) { > > hinfo.hash_version = DX_HASH_HALF_MD4; > > @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > > for (i = 0; i < ngroups; i++) { > > g = (parent_group + i) % ngroups; > > get_orlov_stats(sb, g, flex_size, &stats); > > + /* can't get better group than empty group */ > > + if (max_blocks_per_flex == stats.free_clusters && > > + (inodes_per_group * flex_size) == stats.free_inodes) > > + goto found_flex_bg; > > if (!stats.free_inodes) > > continue; > > if (stats.used_dirs >= best_ndir) > > -- > > 1.7.1 > > > > > > > > On Mon, Jan 11, 2016 at 02:13:46PM -0700, Andreas Dilger wrote: > >> On Jan 6, 2016, at 5:46 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > >>> > >>> you are right flex groups cannot be completely empty as some > >>> blocks are used for inode table and allocation bitmaps. I > >>> missed that point. I have corrected that. Also I have tested > >>> and validated this patch by putting some traces it works! > >> > >> Good news. Thanks for updating the patch and testing it. > >> More comments below. > >> > >>> Here are corresponding logs: > >>> commands: > >>> ========= > >>> mkfs.ext4 -g 10000 -G 2 /dev/sdc > >>> mount -t ext4 /dev/sdc /mnt/test_ext4/ > >>> cd /mnt/test_ext4 > >>> mkdir 1 > >>> cd 1 > >>> > >>> logs: > >>> ===== > >>> Jan 7 03:36:45 root kernel: [ 64.792939] max_usable_blocks_per_flex_group = [19692] > >>> Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_clusters = [19264] > >>> Jan 7 03:36:45 root kernel: [ 64.792939] Inodes_per_flex_group = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_inodes = [4853] > >>> Jan 7 03:36:45 root kernel: [ 64.792950] max_usable_blocks_per_flex_group = [19692] > >>> Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_clusters = [19481] > >>> Jan 7 03:36:45 root kernel: [ 64.792950] Inodes_per_flex_group = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_inodes = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792958] max_usable_blocks_per_flex_group = [19692] > >>> Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_clusters = [19481] > >>> Jan 7 03:36:45 root kernel: [ 64.792958] Inodes_per_flex_group = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_inodes = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792965] max_usable_blocks_per_flex_group = [19692] > >>> Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_clusters = [19481] > >>> Jan 7 03:36:45 root kernel: [ 64.792965] Inodes_per_flex_group = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_inodes = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792972] max_usable_blocks_per_flex_group = [19692] > >>> Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_clusters = [19481] > >>> Jan 7 03:36:45 root kernel: [ 64.792972] Inodes_per_flex_group = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_inodes = [4864] > >>> Jan 7 03:36:45 root kernel: [ 64.792979] max_usable_blocks_per_flex_group = [19692]<<<<<<<<<<< > >>> Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_clusters = [19692]<<<<<<<<<<< > >>> Jan 7 03:36:45 root kernel: [ 64.792979] Inodes_per_flex_group = [4864]<<<<<<<<<<<< > >>> Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_inodes = [4864]<<<<<<<<<<<< > >>> Jan 7 03:36:45 root kernel: [ 64.792985] found_flex_bg >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>condition satisfied > >>> > >>> > >>> [Patch v4]: > >>> ========== > >>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > >>> Date: Thu, 7 Jan 2016 05:12:20 +0530 > >>> Subject: [PATCH] ext4: optimizing group serch for inode allocation > >>> > >>> Added a check at the start of group search loop to > >>> avoid looping unecessarily in case of empty group. > >>> This also allow group search to jump directly to > >>> "found_flex_bg" with "stats" and "group" already set, > >>> so there is no need to go through the extra steps of > >>> setting "best_desc" , "best_group" and then break > >>> out of the loop just to set "stats" and "group" again. > >>> > >>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > >>> --- > >>> fs/ext4/ext4.h | 2 ++ > >>> fs/ext4/ialloc.c | 21 +++++++++++++++++++-- > >>> 2 files changed, 21 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h > >>> index cc7ca4e..fc48f9a 100644 > >>> --- a/fs/ext4/ext4.h > >>> +++ b/fs/ext4/ext4.h > >>> @@ -326,6 +326,8 @@ struct flex_groups { > >>> #define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE > >>> #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) > >>> #ifdef __KERNEL__ > >>> +# define EXT4_INODE_TABLE_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_itb_per_group) > >>> +# define EXT4_BLOCKS_PER_CLUSTER(s) (EXT4_SB(s)->s_cluster_ratio) > >> > >> I don't think there is much value to these macros. They aren't much > >> shorter than the actual variable access, and they don't provide any > >> improved clarity for the reader. > >> > >> I think they were introduced many years ago so that this header could > >> be shared between the kernel and e2fsprogs, but that is no longer true > >> so I don't think there is a need to add new ones. > >> > >> Ted, any opinion on this? > >> > >>> # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) > >>> # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) > >>> # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) > >>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > >>> index 1b8024d..dc66ad8 100644 > >>> --- a/fs/ext4/ialloc.c > >>> +++ b/fs/ext4/ialloc.c > >>> @@ -463,7 +463,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>> sbi->s_log_groups_per_flex; > >>> parent_group >>= sbi->s_log_groups_per_flex; > >>> } > >>> - > >>> freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); > >>> avefreei = freei / ngroups; > >> > >> Not sure why this line is being deleted? > >> > >>> @@ -477,7 +476,20 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>> (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > >>> int best_ndir = inodes_per_group; > >>> int ret = -1; > >>> - > >>> + /* blocks used for inode table and allocation bitmaps */ > >>> + unsigned int max_usable_blocks_per_flex_group; > >> > >> This could be shorter and still clear, like "max_blocks_per_flex". > >> > >>> + unsigned int blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb); > >>> + unsigned int inode_table_blocks_per_group = \ > >>> + EXT4_INODE_TABLE_BLOCKS_PER_GROUP(sb); > >>> + /* Number of blocks per cluster */ > >>> + unsigned int cluster_ratio = EXT4_BLOCKS_PER_CLUSTER(sb); > >> > >> There also isn't much value to making local variables that hold these > >> same values again. It increases stack space for little benefit. They > >> are only accessed once anyway. > >> > >>> + unsigned int inodes_per_flex_group = inodes_per_group * \ > >>> + flex_size; > >>> + max_usable_blocks_per_flex_group = \ > >>> + ((blocks_per_group*flex_size) - \ > >> > >> Spaces around that '*'. > >> > >>> + (inode_table_blocks_per_group * \ > >>> + flex_size + 2 * flex_size)) / \ > >> > >> This is C and not a CPP macro, so no need for linefeed escapes. > >> > >>> + cluster_ratio; > >> > >> This should be ">> EXT4_SB(sb)->s_cluster_bits" to avoid the divide. > >> > >>> if (qstr) { > >>> hinfo.hash_version = DX_HASH_HALF_MD4; > >>> hinfo.seed = sbi->s_hash_seed; > >>> @@ -489,6 +501,11 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>> for (i = 0; i < ngroups; i++) { > >>> g = (parent_group + i) % ngroups; > >>> get_orlov_stats(sb, g, flex_size, &stats); > >>> + /* can't get better group than empty group */ > >>> + if (max_usable_blocks_per_flex_group == \ > >>> + stats.free_clusters && \ > >> > >> No need for linefeed escapes. > >> > >>> + inodes_per_flex_group == stats.free_inodes) > >> > >> Align continued line after '(' from the "if (" line. > >> > >>> + goto found_flex_bg; > >> > >> This is indented too much. It will work properly when you fix the > >> previous line. > >> > >>> if (!stats.free_inodes) > >>> continue; > >>> if (stats.used_dirs >= best_ndir) > >>> -- > >>> 1.7.1 > >>> > >>> Regards, > >>> Lokesh > >>> > >>> On Sun, Jan 03, 2016 at 11:34:51AM -0700, Andreas Dilger wrote: > >>>> On Dec 26, 2015, at 01:41, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > >>>>> > >>>>> > >>>>> From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 > >>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > >>>>> Date: Sat, 26 Dec 2015 13:19:36 +0530 > >>>>> Subject: [PATCH v3] ext4: optimizing group search for inode allocation > >>>>> > >>>>> Added a check at the start of group search loop to > >>>>> avoid looping unecessarily in case of empty group. > >>>>> This also allow group search to jump directly to > >>>>> "found_flex_bg" with "stats" and "group" already set, > >>>>> so there is no need to go through the extra steps of > >>>>> setting "best_desc" and "best_group" and then break > >>>>> out of the loop just to set "stats" and "group" again. > >>>>> > >>>>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > >>>>> --- > >>>>> fs/ext4/ialloc.c | 12 ++++++++++-- > >>>>> 1 files changed, 10 insertions(+), 2 deletions(-) > >>>>> > >>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > >>>>> index 1b8024d..16f94db 100644 > >>>>> --- a/fs/ext4/ialloc.c > >>>>> +++ b/fs/ext4/ialloc.c > >>>>> @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > >>>>> > >>>>> if (S_ISDIR(mode) && > >>>>> - ((parent == d_inode(sb->s_root)) || > >>>>> - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > >>>>> + ((parent == d_inode(sb->s_root)) || > >>>>> + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > >>>> > >>>> I don't understand why you are changing the indentation here? > >>>> > >>>>> + unsigned int inodes_per_flex_group; > >>>>> + unsigned long int clusters_per_flex_group; > >>>>> int best_ndir = inodes_per_group; > >>>>> int ret = -1; > >>>>> + inodes_per_flex_group = inodes_per_group * flex_size; > >>>>> + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; > >>>> > >>>> Have you actually tested if this code works? When I was looking at this > >>>> code I was accidentally looking at the ext2 version, which only deals with > >>>> individual groups, and not flex groups. I don't think that a flex group > >>>> can actually be completely empty, since it will always contain at least > >>>> an inode table and some bitmaps. > >>>> > >>>> This calculation needs to take this into account or it will just be > >>>> overhead and not an optimization. Something like: > >>>> > >>>> /* account for inode table and allocation bitmaps */ > >>>> clusters_per_flex_group = sbi->s_clusters_per_group * flex_size - > >>>> ((inodes_per_flex_group * EXT4_INODE_SIZE(sb) + > >>>> (flex_size << sb->s_blocksize_bits) * 2 ) >> > >>>> EXT4_SB(sb)->s_cluster_bits; > >>>> > >>>> It would be worthwhile to print this out and verify that there are actually > >>>> groups with this many free blocks in a newly formatted filesystem. > >>>> > >>>> Cheers, Andreas > >>>> > >>>>> if (qstr) { > >>>>> hinfo.hash_version = DX_HASH_HALF_MD4; > >>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > >>>>> for (i = 0; i < ngroups; i++) { > >>>>> g = (parent_group + i) % ngroups; > >>>>> get_orlov_stats(sb, g, flex_size, &stats); > >>>>> + /* the group can't get any better than empty */ > >>>>> + if (inodes_per_flex_group == stats.free_inodes && > >>>>> + clusters_per_flex_group == stats.free_clusters) > >>>>> + goto found_flex_bg; > >>>>> if (!stats.free_inodes) > >>>>> continue; > >>>>> if (stats.used_dirs >= best_ndir) > >>>>> -- > >>>>> 1.7.1 > >>>>> > >>>>> > >>>>>> On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: > >>>>>>> On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: > >>>>>>> > >>>>>>> From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 > >>>>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> > >>>>>> > >>>>>> In the patch summary there is a typo - s/serch/search/ > >>>>>> > >>>>>> Also, it appears your email client has mangled the whitespace in the > >>>>>> patch. Please use "git send-email" to send your patch to the list: > >>>>>> > >>>>>> git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 > >>>>>> > >>>>>> so that it arrives intact. You probably need to set it up in ~/.gitconfig: > >>>>>> > >>>>>> [sendemail] > >>>>>> confirm = compose > >>>>>> smtpdomain = {your client hostname} > >>>>>> smtpserver = {your SMTP server hostname} > >>>>>> > >>>>>> Cheers, Andreas > >>>>>> > >>>>>>> Added a check at the start of group search loop to > >>>>>>> avoid looping unecessarily in case of empty group. > >>>>>>> This also allow group search to jump directly to > >>>>>>> "found_flex_bg" with "stats" and "group" already set, > >>>>>>> so there is no need to go through the extra steps of > >>>>>>> setting "best_desc" and "best_group" and then break > >>>>>>> out of the loop just to set "stats" and "group" again. > >>>>>>> > >>>>>>> Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> > >>>>>>> --- > >>>>>>> fs/ext4/ialloc.c | 8 ++++++++ > >>>>>>> 1 files changed, 8 insertions(+), 0 deletions(-) > >>>>>>> > >>>>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > >>>>>>> index 1b8024d..588bf8e 100644 > >>>>>>> --- a/fs/ext4/ialloc.c > >>>>>>> +++ b/fs/ext4/ialloc.c > >>>>>>> @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block > >>>>>>> *sb, struct inode *parent, > >>>>>>> struct ext4_sb_info *sbi = EXT4_SB(sb); > >>>>>>> ext4_group_t real_ngroups = ext4_get_groups_count(sb); > >>>>>>> int inodes_per_group = EXT4_INODES_PER_GROUP(sb); > >>>>>>> + unsigned int inodes_per_flex_group; > >>>>>>> + long unsigned int blocks_per_clustre; > >>>>>>> unsigned int freei, avefreei, grp_free; > >>>>>>> ext4_fsblk_t freeb, avefreec; > >>>>>>> unsigned int ndirs; > >>>>>>> @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block > >>>>>>> *sb, struct inode *parent, > >>>>>>> percpu_counter_read_positive(&sbi->s_freeclusters_counter)); > >>>>>>> avefreec = freeb; > >>>>>>> do_div(avefreec, ngroups); > >>>>>>> + inodes_per_flex_group = inodes_per_group * flex_size; > >>>>>>> + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; > >>>>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); > >>>>>>> > >>>>>>> if (S_ISDIR(mode) && > >>>>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block > >>>>>>> *sb, struct inode *parent, > >>>>>>> for (i = 0; i < ngroups; i++) { > >>>>>>> g = (parent_group + i) % ngroups; > >>>>>>> get_orlov_stats(sb, g, flex_size, &stats); > >>>>>>> + /* the group can't get any better than empty */ > >>>>>>> + if (inodes_per_flex_group == stats.free_inodes && > >>>>>>> + blocks_per_clustre == stats.free_clusters) > >>>>>>> + goto found_flex_bg; > >>>>>>> if (!stats.free_inodes) > >>>>>>> continue; > >>>>>>> if (stats.used_dirs >= best_ndir) > >>>>>>> -- > >>>>>>> 1.7.1 > >>>>>>> <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> > >>>>>> > >>>>>> > >>>>>> Cheers, Andreas > >>>>> > >>>>> > >>>>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> > >>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> > >> > >> > >> Cheers, Andreas > >> > >> > >> > >> > >> > > > > > > <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> > > > Cheers, Andreas > > > > > [-- Attachment #2: 0001-ext4-optimizing-group-serch-for-inode-allocation.patch --] [-- Type: text/plain, Size: 1924 bytes --] >From 13530650a7dd1a0937c72e6a6acbb1bab59c3bbd Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Date: Thu, 7 Jan 2016 05:12:20 +0530 Subject: [PATCH] ext4: optimizing group serch for inode allocation Added a check at the start of group search loop to avoid looping unecessarily in case of empty group. This also allow group search to jump directly to "found_flex_bg" with "stats" and "group" already set, so there is no need to go through the extra steps of setting "best_desc" , "best_group" and then break out of the loop just to set "stats" and "group" again. Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> --- fs/ext4/ialloc.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1b8024d..3463d30 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { int best_ndir = inodes_per_group; int ret = -1; + /* Maximum usable blocks per group as some blocks are used + * for inode tables and allocation bitmaps */ + unsigned long long max_blocks_per_flex = + ((sbi->s_blocks_per_group - + (sbi->s_itb_per_group + 2)) * + flex_size) >> sbi->s_cluster_bits; if (qstr) { hinfo.hash_version = DX_HASH_HALF_MD4; @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { g = (parent_group + i) % ngroups; get_orlov_stats(sb, g, flex_size, &stats); + /* can't get better group than empty group */ + if (max_blocks_per_flex == stats.free_clusters && + (inodes_per_group * flex_size) == stats.free_inodes) + goto found_flex_bg; if (!stats.free_inodes) continue; if (stats.used_dirs >= best_ndir) -- 1.7.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v6] EXT4: optimizing group search for inode allocation 2016-01-19 6:08 ` [PATCH v6] " Lokesh Jaliminche @ 2016-01-19 7:24 ` Andreas Dilger 2016-02-23 4:04 ` Theodore Ts'o 1 sibling, 0 replies; 12+ messages in thread From: Andreas Dilger @ 2016-01-19 7:24 UTC (permalink / raw) To: Lokesh Jaliminche; +Cc: Theodore Ts'o, linux-ext4 [-- Attachment #1: Type: text/plain, Size: 22948 bytes --] > On Jan 18, 2016, at 11:08 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: > > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > Subject: [PATCH] ext4: optimizing group serch for inode allocation > > Added a check at the start of group search loop to > avoid looping unecessarily in case of empty group. > This also allow group search to jump directly to > "found_flex_bg" with "stats" and "group" already set, > so there is no need to go through the extra steps of > setting "best_desc" , "best_group" and then break > out of the loop just to set "stats" and "group" again. > > Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Thanks for sticking with the patch. This one looks good. Reviewed-by: Andreas Dilger <adilger@dilger.ca> > --- > fs/ext4/ialloc.c | 10 ++++++++++ > 1 files changed, 10 insertions(+), 0 deletions(-) > > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c > index 1b8024d..3463d30 100644 > --- a/fs/ext4/ialloc.c > +++ b/fs/ext4/ialloc.c > @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { > int best_ndir = inodes_per_group; > int ret = -1; > + /* Maximum usable blocks per group as some blocks are used > + * for inode tables and allocation bitmaps */ > + unsigned long long max_blocks_per_flex = > + ((sbi->s_blocks_per_group - > + (sbi->s_itb_per_group + 2)) * > + flex_size) >> sbi->s_cluster_bits; > > if (qstr) { > hinfo.hash_version = DX_HASH_HALF_MD4; > @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, > for (i = 0; i < ngroups; i++) { > g = (parent_group + i) % ngroups; > get_orlov_stats(sb, g, flex_size, &stats); > + /* can't get better group than empty group */ > + if (max_blocks_per_flex == stats.free_clusters && > + (inodes_per_group * flex_size) == stats.free_inodes) > + goto found_flex_bg; > if (!stats.free_inodes) > continue; > if (stats.used_dirs >= best_ndir) > -- > 1.7.1 > > > > On Mon, Jan 18, 2016 at 02:50:48PM -0700, Andreas Dilger wrote: >> On Jan 16, 2016, at 4:02 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: >>> >>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>> Date: Thu, 7 Jan 2016 05:12:20 +0530 >>> Subject: [PATCH v5] ext4: optimizing group serch for inode allocation >>> >>> Added a check at the start of group search loop to >>> avoid looping unecessarily in case of empty group. >>> This also allow group search to jump directly to >>> "found_flex_bg" with "stats" and "group" already set, >>> so there is no need to go through the extra steps of >>> setting "best_desc" , "best_group" and then break >>> out of the loop just to set "stats" and "group" again. >> >> This looks very good, just one minor potential issue below. >> >>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>> --- >>> fs/ext4/ialloc.c | 10 ++++++++++ >>> 1 files changed, 10 insertions(+), 0 deletions(-) >>> >>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>> index 1b8024d..d2835cc 100644 >>> --- a/fs/ext4/ialloc.c >>> +++ b/fs/ext4/ialloc.c >>> @@ -477,6 +477,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>> (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >>> int best_ndir = inodes_per_group; >>> int ret = -1; >>> + /* Maximum usable blocks per group as some blocks are used >>> + * for inode tables and allocation bitmaps */ >>> + unsigned int max_blocks_per_flex = >> >> This should be an unsigned long long or __u64, since the max_blocks_per_flex >> calculation may overflow a 32-bit value on filesystems with larger block_size >> and a large value for flex_size (larger than 2^13 for a 64KB blocksize). >> >> The "stats.free_clusters" is already a __u64 for this reason. >> >>> + ((sbi->s_blocks_per_group - >>> + (sbi->s_itb_per_group + 2)) * >>> + flex_size) >> sbi->s_cluster_bits; >>> >>> if (qstr) { >>> hinfo.hash_version = DX_HASH_HALF_MD4; >>> @@ -489,6 +495,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>> for (i = 0; i < ngroups; i++) { >>> g = (parent_group + i) % ngroups; >>> get_orlov_stats(sb, g, flex_size, &stats); >>> + /* can't get better group than empty group */ >>> + if (max_blocks_per_flex == stats.free_clusters && >>> + (inodes_per_group * flex_size) == stats.free_inodes) >>> + goto found_flex_bg; >>> if (!stats.free_inodes) >>> continue; >>> if (stats.used_dirs >= best_ndir) >>> -- >>> 1.7.1 >>> >>> >>> >>> On Mon, Jan 11, 2016 at 02:13:46PM -0700, Andreas Dilger wrote: >>>> On Jan 6, 2016, at 5:46 PM, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: >>>>> >>>>> you are right flex groups cannot be completely empty as some >>>>> blocks are used for inode table and allocation bitmaps. I >>>>> missed that point. I have corrected that. Also I have tested >>>>> and validated this patch by putting some traces it works! >>>> >>>> Good news. Thanks for updating the patch and testing it. >>>> More comments below. >>>> >>>>> Here are corresponding logs: >>>>> commands: >>>>> ========= >>>>> mkfs.ext4 -g 10000 -G 2 /dev/sdc >>>>> mount -t ext4 /dev/sdc /mnt/test_ext4/ >>>>> cd /mnt/test_ext4 >>>>> mkdir 1 >>>>> cd 1 >>>>> >>>>> logs: >>>>> ===== >>>>> Jan 7 03:36:45 root kernel: [ 64.792939] max_usable_blocks_per_flex_group = [19692] >>>>> Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_clusters = [19264] >>>>> Jan 7 03:36:45 root kernel: [ 64.792939] Inodes_per_flex_group = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792939] stats.free_inodes = [4853] >>>>> Jan 7 03:36:45 root kernel: [ 64.792950] max_usable_blocks_per_flex_group = [19692] >>>>> Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_clusters = [19481] >>>>> Jan 7 03:36:45 root kernel: [ 64.792950] Inodes_per_flex_group = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792950] stats.free_inodes = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792958] max_usable_blocks_per_flex_group = [19692] >>>>> Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_clusters = [19481] >>>>> Jan 7 03:36:45 root kernel: [ 64.792958] Inodes_per_flex_group = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792958] stats.free_inodes = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792965] max_usable_blocks_per_flex_group = [19692] >>>>> Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_clusters = [19481] >>>>> Jan 7 03:36:45 root kernel: [ 64.792965] Inodes_per_flex_group = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792965] stats.free_inodes = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792972] max_usable_blocks_per_flex_group = [19692] >>>>> Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_clusters = [19481] >>>>> Jan 7 03:36:45 root kernel: [ 64.792972] Inodes_per_flex_group = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792972] stats.free_inodes = [4864] >>>>> Jan 7 03:36:45 root kernel: [ 64.792979] max_usable_blocks_per_flex_group = [19692]<<<<<<<<<<< >>>>> Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_clusters = [19692]<<<<<<<<<<< >>>>> Jan 7 03:36:45 root kernel: [ 64.792979] Inodes_per_flex_group = [4864]<<<<<<<<<<<< >>>>> Jan 7 03:36:45 root kernel: [ 64.792979] stats.free_inodes = [4864]<<<<<<<<<<<< >>>>> Jan 7 03:36:45 root kernel: [ 64.792985] found_flex_bg >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>condition satisfied >>>>> >>>>> >>>>> [Patch v4]: >>>>> ========== >>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>>>> Date: Thu, 7 Jan 2016 05:12:20 +0530 >>>>> Subject: [PATCH] ext4: optimizing group serch for inode allocation >>>>> >>>>> Added a check at the start of group search loop to >>>>> avoid looping unecessarily in case of empty group. >>>>> This also allow group search to jump directly to >>>>> "found_flex_bg" with "stats" and "group" already set, >>>>> so there is no need to go through the extra steps of >>>>> setting "best_desc" , "best_group" and then break >>>>> out of the loop just to set "stats" and "group" again. >>>>> >>>>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>>>> --- >>>>> fs/ext4/ext4.h | 2 ++ >>>>> fs/ext4/ialloc.c | 21 +++++++++++++++++++-- >>>>> 2 files changed, 21 insertions(+), 2 deletions(-) >>>>> >>>>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h >>>>> index cc7ca4e..fc48f9a 100644 >>>>> --- a/fs/ext4/ext4.h >>>>> +++ b/fs/ext4/ext4.h >>>>> @@ -326,6 +326,8 @@ struct flex_groups { >>>>> #define EXT4_MAX_DESC_SIZE EXT4_MIN_BLOCK_SIZE >>>>> #define EXT4_DESC_SIZE(s) (EXT4_SB(s)->s_desc_size) >>>>> #ifdef __KERNEL__ >>>>> +# define EXT4_INODE_TABLE_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_itb_per_group) >>>>> +# define EXT4_BLOCKS_PER_CLUSTER(s) (EXT4_SB(s)->s_cluster_ratio) >>>> >>>> I don't think there is much value to these macros. They aren't much >>>> shorter than the actual variable access, and they don't provide any >>>> improved clarity for the reader. >>>> >>>> I think they were introduced many years ago so that this header could >>>> be shared between the kernel and e2fsprogs, but that is no longer true >>>> so I don't think there is a need to add new ones. >>>> >>>> Ted, any opinion on this? >>>> >>>>> # define EXT4_BLOCKS_PER_GROUP(s) (EXT4_SB(s)->s_blocks_per_group) >>>>> # define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group) >>>>> # define EXT4_DESC_PER_BLOCK(s) (EXT4_SB(s)->s_desc_per_block) >>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>>>> index 1b8024d..dc66ad8 100644 >>>>> --- a/fs/ext4/ialloc.c >>>>> +++ b/fs/ext4/ialloc.c >>>>> @@ -463,7 +463,6 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>>>> sbi->s_log_groups_per_flex; >>>>> parent_group >>= sbi->s_log_groups_per_flex; >>>>> } >>>>> - >>>>> freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); >>>>> avefreei = freei / ngroups; >>>> >>>> Not sure why this line is being deleted? >>>> >>>>> @@ -477,7 +476,20 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>>>> (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >>>>> int best_ndir = inodes_per_group; >>>>> int ret = -1; >>>>> - >>>>> + /* blocks used for inode table and allocation bitmaps */ >>>>> + unsigned int max_usable_blocks_per_flex_group; >>>> >>>> This could be shorter and still clear, like "max_blocks_per_flex". >>>> >>>>> + unsigned int blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb); >>>>> + unsigned int inode_table_blocks_per_group = \ >>>>> + EXT4_INODE_TABLE_BLOCKS_PER_GROUP(sb); >>>>> + /* Number of blocks per cluster */ >>>>> + unsigned int cluster_ratio = EXT4_BLOCKS_PER_CLUSTER(sb); >>>> >>>> There also isn't much value to making local variables that hold these >>>> same values again. It increases stack space for little benefit. They >>>> are only accessed once anyway. >>>> >>>>> + unsigned int inodes_per_flex_group = inodes_per_group * \ >>>>> + flex_size; >>>>> + max_usable_blocks_per_flex_group = \ >>>>> + ((blocks_per_group*flex_size) - \ >>>> >>>> Spaces around that '*'. >>>> >>>>> + (inode_table_blocks_per_group * \ >>>>> + flex_size + 2 * flex_size)) / \ >>>> >>>> This is C and not a CPP macro, so no need for linefeed escapes. >>>> >>>>> + cluster_ratio; >>>> >>>> This should be ">> EXT4_SB(sb)->s_cluster_bits" to avoid the divide. >>>> >>>>> if (qstr) { >>>>> hinfo.hash_version = DX_HASH_HALF_MD4; >>>>> hinfo.seed = sbi->s_hash_seed; >>>>> @@ -489,6 +501,11 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>>>> for (i = 0; i < ngroups; i++) { >>>>> g = (parent_group + i) % ngroups; >>>>> get_orlov_stats(sb, g, flex_size, &stats); >>>>> + /* can't get better group than empty group */ >>>>> + if (max_usable_blocks_per_flex_group == \ >>>>> + stats.free_clusters && \ >>>> >>>> No need for linefeed escapes. >>>> >>>>> + inodes_per_flex_group == stats.free_inodes) >>>> >>>> Align continued line after '(' from the "if (" line. >>>> >>>>> + goto found_flex_bg; >>>> >>>> This is indented too much. It will work properly when you fix the >>>> previous line. >>>> >>>>> if (!stats.free_inodes) >>>>> continue; >>>>> if (stats.used_dirs >= best_ndir) >>>>> -- >>>>> 1.7.1 >>>>> >>>>> Regards, >>>>> Lokesh >>>>> >>>>> On Sun, Jan 03, 2016 at 11:34:51AM -0700, Andreas Dilger wrote: >>>>>> On Dec 26, 2015, at 01:41, Lokesh Jaliminche <lokesh.jaliminche@gmail.com> wrote: >>>>>>> >>>>>>> >>>>>>> From 5199982d29ff291b181c25af63a22d6f2d6d3f7b Mon Sep 17 00:00:00 2001 >>>>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>>>>>> Date: Sat, 26 Dec 2015 13:19:36 +0530 >>>>>>> Subject: [PATCH v3] ext4: optimizing group search for inode allocation >>>>>>> >>>>>>> Added a check at the start of group search loop to >>>>>>> avoid looping unecessarily in case of empty group. >>>>>>> This also allow group search to jump directly to >>>>>>> "found_flex_bg" with "stats" and "group" already set, >>>>>>> so there is no need to go through the extra steps of >>>>>>> setting "best_desc" and "best_group" and then break >>>>>>> out of the loop just to set "stats" and "group" again. >>>>>>> >>>>>>> Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> >>>>>>> --- >>>>>>> fs/ext4/ialloc.c | 12 ++++++++++-- >>>>>>> 1 files changed, 10 insertions(+), 2 deletions(-) >>>>>>> >>>>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>>>>>> index 1b8024d..16f94db 100644 >>>>>>> --- a/fs/ext4/ialloc.c >>>>>>> +++ b/fs/ext4/ialloc.c >>>>>>> @@ -473,10 +473,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>>>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); >>>>>>> >>>>>>> if (S_ISDIR(mode) && >>>>>>> - ((parent == d_inode(sb->s_root)) || >>>>>>> - (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >>>>>>> + ((parent == d_inode(sb->s_root)) || >>>>>>> + (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) { >>>>>> >>>>>> I don't understand why you are changing the indentation here? >>>>>> >>>>>>> + unsigned int inodes_per_flex_group; >>>>>>> + unsigned long int clusters_per_flex_group; >>>>>>> int best_ndir = inodes_per_group; >>>>>>> int ret = -1; >>>>>>> + inodes_per_flex_group = inodes_per_group * flex_size; >>>>>>> + clusters_per_flex_group = sbi->s_clusters_per_group * flex_size; >>>>>> >>>>>> Have you actually tested if this code works? When I was looking at this >>>>>> code I was accidentally looking at the ext2 version, which only deals with >>>>>> individual groups, and not flex groups. I don't think that a flex group >>>>>> can actually be completely empty, since it will always contain at least >>>>>> an inode table and some bitmaps. >>>>>> >>>>>> This calculation needs to take this into account or it will just be >>>>>> overhead and not an optimization. Something like: >>>>>> >>>>>> /* account for inode table and allocation bitmaps */ >>>>>> clusters_per_flex_group = sbi->s_clusters_per_group * flex_size - >>>>>> ((inodes_per_flex_group * EXT4_INODE_SIZE(sb) + >>>>>> (flex_size << sb->s_blocksize_bits) * 2 ) >> >>>>>> EXT4_SB(sb)->s_cluster_bits; >>>>>> >>>>>> It would be worthwhile to print this out and verify that there are actually >>>>>> groups with this many free blocks in a newly formatted filesystem. >>>>>> >>>>>> Cheers, Andreas >>>>>> >>>>>>> if (qstr) { >>>>>>> hinfo.hash_version = DX_HASH_HALF_MD4; >>>>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, >>>>>>> for (i = 0; i < ngroups; i++) { >>>>>>> g = (parent_group + i) % ngroups; >>>>>>> get_orlov_stats(sb, g, flex_size, &stats); >>>>>>> + /* the group can't get any better than empty */ >>>>>>> + if (inodes_per_flex_group == stats.free_inodes && >>>>>>> + clusters_per_flex_group == stats.free_clusters) >>>>>>> + goto found_flex_bg; >>>>>>> if (!stats.free_inodes) >>>>>>> continue; >>>>>>> if (stats.used_dirs >= best_ndir) >>>>>>> -- >>>>>>> 1.7.1 >>>>>>> >>>>>>> >>>>>>>> On Mon, Dec 21, 2015 at 10:27:37AM -0700, Andreas Dilger wrote: >>>>>>>>> On Dec 18, 2015, at 4:32 PM, lokesh jaliminche <lokesh.jaliminche@gmail.com> wrote: >>>>>>>>> >>>>>>>>> From 9e09fef78b2fa552c883bf8124af873abfde0805 Mon Sep 17 00:00:00 2001 >>>>>>>>> From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> >>>>>>>> >>>>>>>> In the patch summary there is a typo - s/serch/search/ >>>>>>>> >>>>>>>> Also, it appears your email client has mangled the whitespace in the >>>>>>>> patch. Please use "git send-email" to send your patch to the list: >>>>>>>> >>>>>>>> git send-email --to tytso@mit.edu --cc linux-ext4@vger.kernel.org HEAD~1 >>>>>>>> >>>>>>>> so that it arrives intact. You probably need to set it up in ~/.gitconfig: >>>>>>>> >>>>>>>> [sendemail] >>>>>>>> confirm = compose >>>>>>>> smtpdomain = {your client hostname} >>>>>>>> smtpserver = {your SMTP server hostname} >>>>>>>> >>>>>>>> Cheers, Andreas >>>>>>>> >>>>>>>>> Added a check at the start of group search loop to >>>>>>>>> avoid looping unecessarily in case of empty group. >>>>>>>>> This also allow group search to jump directly to >>>>>>>>> "found_flex_bg" with "stats" and "group" already set, >>>>>>>>> so there is no need to go through the extra steps of >>>>>>>>> setting "best_desc" and "best_group" and then break >>>>>>>>> out of the loop just to set "stats" and "group" again. >>>>>>>>> >>>>>>>>> Signed-off-by: Lokesh N Jaliminche <lokesh.jaliminche@gmail.com> >>>>>>>>> --- >>>>>>>>> fs/ext4/ialloc.c | 8 ++++++++ >>>>>>>>> 1 files changed, 8 insertions(+), 0 deletions(-) >>>>>>>>> >>>>>>>>> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c >>>>>>>>> index 1b8024d..588bf8e 100644 >>>>>>>>> --- a/fs/ext4/ialloc.c >>>>>>>>> +++ b/fs/ext4/ialloc.c >>>>>>>>> @@ -446,6 +446,8 @@ static int find_group_orlov(struct super_block >>>>>>>>> *sb, struct inode *parent, >>>>>>>>> struct ext4_sb_info *sbi = EXT4_SB(sb); >>>>>>>>> ext4_group_t real_ngroups = ext4_get_groups_count(sb); >>>>>>>>> int inodes_per_group = EXT4_INODES_PER_GROUP(sb); >>>>>>>>> + unsigned int inodes_per_flex_group; >>>>>>>>> + long unsigned int blocks_per_clustre; >>>>>>>>> unsigned int freei, avefreei, grp_free; >>>>>>>>> ext4_fsblk_t freeb, avefreec; >>>>>>>>> unsigned int ndirs; >>>>>>>>> @@ -470,6 +472,8 @@ static int find_group_orlov(struct super_block >>>>>>>>> *sb, struct inode *parent, >>>>>>>>> percpu_counter_read_positive(&sbi->s_freeclusters_counter)); >>>>>>>>> avefreec = freeb; >>>>>>>>> do_div(avefreec, ngroups); >>>>>>>>> + inodes_per_flex_group = inodes_per_group * flex_size; >>>>>>>>> + blocks_per_clustre = sbi->s_blocks_per_group * flex_size; >>>>>>>>> ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); >>>>>>>>> >>>>>>>>> if (S_ISDIR(mode) && >>>>>>>>> @@ -489,6 +493,10 @@ static int find_group_orlov(struct super_block >>>>>>>>> *sb, struct inode *parent, >>>>>>>>> for (i = 0; i < ngroups; i++) { >>>>>>>>> g = (parent_group + i) % ngroups; >>>>>>>>> get_orlov_stats(sb, g, flex_size, &stats); >>>>>>>>> + /* the group can't get any better than empty */ >>>>>>>>> + if (inodes_per_flex_group == stats.free_inodes && >>>>>>>>> + blocks_per_clustre == stats.free_clusters) >>>>>>>>> + goto found_flex_bg; >>>>>>>>> if (!stats.free_inodes) >>>>>>>>> continue; >>>>>>>>> if (stats.used_dirs >= best_ndir) >>>>>>>>> -- >>>>>>>>> 1.7.1 >>>>>>>>> <0001-EXT4-optimizing-group-serch-for-inode-allocation.patch> >>>>>>>> >>>>>>>> >>>>>>>> Cheers, Andreas >>>>>>> >>>>>>> >>>>>>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> >>>>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> >>>> >>>> >>>> Cheers, Andreas >>>> >>>> >>>> >>>> >>>> >>> >>> >>> <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> >> >> >> Cheers, Andreas >> >> >> >> >> > > > <0001-ext4-optimizing-group-serch-for-inode-allocation.patch> Cheers, Andreas [-- Attachment #2: Message signed with OpenPGP using GPGMail --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6] EXT4: optimizing group search for inode allocation 2016-01-19 6:08 ` [PATCH v6] " Lokesh Jaliminche 2016-01-19 7:24 ` Andreas Dilger @ 2016-02-23 4:04 ` Theodore Ts'o 1 sibling, 0 replies; 12+ messages in thread From: Theodore Ts'o @ 2016-02-23 4:04 UTC (permalink / raw) To: Lokesh Jaliminche; +Cc: Andreas Dilger, linux-ext4 On Tue, Jan 19, 2016 at 11:38:12AM +0530, Lokesh Jaliminche wrote: > From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> > Subject: [PATCH] ext4: optimizing group serch for inode allocation > > Added a check at the start of group search loop to > avoid looping unecessarily in case of empty group. > This also allow group search to jump directly to > "found_flex_bg" with "stats" and "group" already set, > so there is no need to go through the extra steps of > setting "best_desc" , "best_group" and then break > out of the loop just to set "stats" and "group" again. > > Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@gmail.com> Thanks, applied. - Ted ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2016-02-23 4:04 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-12-18 23:32 [PATCH] EXT4: optimizing group serch for inode allocation lokesh jaliminche 2015-12-21 17:27 ` Andreas Dilger 2015-12-26 8:28 ` [PATCH v3] " Lokesh Jaliminche 2015-12-26 8:41 ` [PATCH v3] EXT4: optimizing group search " Lokesh Jaliminche [not found] ` <2DA2ED68-7DD4-425D-8A47-E896E9BF0F4A@dilger.ca> 2016-01-07 0:46 ` [PATCH v4] " Lokesh Jaliminche 2016-01-11 21:13 ` Andreas Dilger 2016-01-16 22:50 ` [PATCH v5] " Lokesh Jaliminche 2016-01-16 23:02 ` Lokesh Jaliminche 2016-01-18 21:50 ` Andreas Dilger 2016-01-19 6:08 ` [PATCH v6] " Lokesh Jaliminche 2016-01-19 7:24 ` Andreas Dilger 2016-02-23 4:04 ` Theodore Ts'o
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.