ext4: Use a hash of the topdir directory name for the Orlov parent group
Instead of using a random number to determine the goal parent grop for the Orlov top directories, use a hash of the directory name. This allows for repeatable results when trying to benchmark filesystem layout algorithms. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
8a8a2050c8
commit
f157a4aa98
|
@ -1315,7 +1315,8 @@ extern int ext4fs_dirhash(const char *name, int len, struct
|
||||||
dx_hash_info *hinfo);
|
dx_hash_info *hinfo);
|
||||||
|
|
||||||
/* ialloc.c */
|
/* ialloc.c */
|
||||||
extern struct inode * ext4_new_inode(handle_t *, struct inode *, int);
|
extern struct inode *ext4_new_inode(handle_t *, struct inode *, int,
|
||||||
|
const struct qstr *qstr);
|
||||||
extern void ext4_free_inode(handle_t *, struct inode *);
|
extern void ext4_free_inode(handle_t *, struct inode *);
|
||||||
extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
|
extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
|
||||||
extern unsigned long ext4_count_free_inodes(struct super_block *);
|
extern unsigned long ext4_count_free_inodes(struct super_block *);
|
||||||
|
|
|
@ -470,7 +470,8 @@ void get_orlov_stats(struct super_block *sb, ext4_group_t g,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
||||||
ext4_group_t *group, int mode)
|
ext4_group_t *group, int mode,
|
||||||
|
const struct qstr *qstr)
|
||||||
{
|
{
|
||||||
ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
|
ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
|
||||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
@ -485,6 +486,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
||||||
struct ext4_group_desc *desc;
|
struct ext4_group_desc *desc;
|
||||||
struct orlov_stats stats;
|
struct orlov_stats stats;
|
||||||
int flex_size = ext4_flex_bg_size(sbi);
|
int flex_size = ext4_flex_bg_size(sbi);
|
||||||
|
struct dx_hash_info hinfo;
|
||||||
|
|
||||||
ngroups = real_ngroups;
|
ngroups = real_ngroups;
|
||||||
if (flex_size > 1) {
|
if (flex_size > 1) {
|
||||||
|
@ -506,7 +508,13 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
||||||
int best_ndir = inodes_per_group;
|
int best_ndir = inodes_per_group;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
get_random_bytes(&grp, sizeof(grp));
|
if (qstr) {
|
||||||
|
hinfo.hash_version = DX_HASH_HALF_MD4;
|
||||||
|
hinfo.seed = sbi->s_hash_seed;
|
||||||
|
ext4fs_dirhash(qstr->name, qstr->len, &hinfo);
|
||||||
|
grp = hinfo.hash;
|
||||||
|
} else
|
||||||
|
get_random_bytes(&grp, sizeof(grp));
|
||||||
parent_group = (unsigned)grp % ngroups;
|
parent_group = (unsigned)grp % ngroups;
|
||||||
for (i = 0; i < ngroups; i++) {
|
for (i = 0; i < ngroups; i++) {
|
||||||
g = (parent_group + i) % ngroups;
|
g = (parent_group + i) % ngroups;
|
||||||
|
@ -649,7 +657,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
|
||||||
*group = parent_group + flex_size;
|
*group = parent_group + flex_size;
|
||||||
if (*group > ngroups)
|
if (*group > ngroups)
|
||||||
*group = 0;
|
*group = 0;
|
||||||
return find_group_orlov(sb, parent, group, mode);
|
return find_group_orlov(sb, parent, group, mode, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -790,7 +798,8 @@ err_ret:
|
||||||
* For other inodes, search forward from the parent directory's block
|
* For other inodes, search forward from the parent directory's block
|
||||||
* group to find a free inode.
|
* group to find a free inode.
|
||||||
*/
|
*/
|
||||||
struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
|
struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
|
||||||
|
const struct qstr *qstr)
|
||||||
{
|
{
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
struct buffer_head *inode_bitmap_bh = NULL;
|
struct buffer_head *inode_bitmap_bh = NULL;
|
||||||
|
@ -839,7 +848,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
|
||||||
if (test_opt(sb, OLDALLOC))
|
if (test_opt(sb, OLDALLOC))
|
||||||
ret2 = find_group_dir(sb, dir, &group);
|
ret2 = find_group_dir(sb, dir, &group);
|
||||||
else
|
else
|
||||||
ret2 = find_group_orlov(sb, dir, &group, mode);
|
ret2 = find_group_orlov(sb, dir, &group, mode, qstr);
|
||||||
} else
|
} else
|
||||||
ret2 = find_group_other(sb, dir, &group, mode);
|
ret2 = find_group_other(sb, dir, &group, mode);
|
||||||
|
|
||||||
|
|
|
@ -483,9 +483,8 @@ int ext4_ext_migrate(struct inode *inode)
|
||||||
retval = PTR_ERR(handle);
|
retval = PTR_ERR(handle);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
tmp_inode = ext4_new_inode(handle,
|
tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
|
||||||
inode->i_sb->s_root->d_inode,
|
S_IFREG, 0);
|
||||||
S_IFREG);
|
|
||||||
if (IS_ERR(tmp_inode)) {
|
if (IS_ERR(tmp_inode)) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
ext4_journal_stop(handle);
|
ext4_journal_stop(handle);
|
||||||
|
|
|
@ -1782,7 +1782,7 @@ retry:
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
inode = ext4_new_inode (handle, dir, mode);
|
inode = ext4_new_inode(handle, dir, mode, &dentry->d_name);
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
if (!IS_ERR(inode)) {
|
if (!IS_ERR(inode)) {
|
||||||
inode->i_op = &ext4_file_inode_operations;
|
inode->i_op = &ext4_file_inode_operations;
|
||||||
|
@ -1816,7 +1816,7 @@ retry:
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
inode = ext4_new_inode(handle, dir, mode);
|
inode = ext4_new_inode(handle, dir, mode, &dentry->d_name);
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
if (!IS_ERR(inode)) {
|
if (!IS_ERR(inode)) {
|
||||||
init_special_inode(inode, inode->i_mode, rdev);
|
init_special_inode(inode, inode->i_mode, rdev);
|
||||||
|
@ -1853,7 +1853,7 @@ retry:
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
inode = ext4_new_inode(handle, dir, S_IFDIR | mode);
|
inode = ext4_new_inode(handle, dir, S_IFDIR | mode, &dentry->d_name);
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
if (IS_ERR(inode))
|
if (IS_ERR(inode))
|
||||||
goto out_stop;
|
goto out_stop;
|
||||||
|
@ -2264,7 +2264,7 @@ retry:
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO);
|
inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO, &dentry->d_name);
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
if (IS_ERR(inode))
|
if (IS_ERR(inode))
|
||||||
goto out_stop;
|
goto out_stop;
|
||||||
|
|
Loading…
Reference in New Issue