@@ -962,6 +962,7 @@ struct ext4_inode_info {
#define EXT4_MOUNT2_EXPLICIT_DELALLOC 0x00000001 /* User explicitly
specified delalloc */
+#define EXT4_MOUNT2_NO_ORLOV 0x00000002 /* Disable orlov */
#define clear_opt(sb, opt) EXT4_SB(sb)->s_mount_opt &= \
~EXT4_MOUNT_##opt
@@ -517,6 +517,9 @@ static int find_group_other(struct super
struct ext4_group_desc *desc;
int flex_size = ext4_flex_bg_size(EXT4_SB(sb));
+ if (test_opt2(sb, NO_ORLOV))
+ goto do_linear;
+
/*
* Try to place the inode is the same flex group as its
* parent. If we can't find space, use the Orlov algorithm to
@@ -589,6 +592,7 @@ static int find_group_other(struct super
return 0;
}
+do_linear:
/*
* That failed: try linear search for a free inode, even if that group
* has no free blocks.
@@ -655,7 +659,7 @@ struct inode *ext4_new_inode(handle_t *h
goto got_group;
}
- if (S_ISDIR(mode))
+ if (!test_opt2(sb, NO_ORLOV) && S_ISDIR(mode))
ret2 = find_group_orlov(sb, dir, &group, mode, qstr);
else
ret2 = find_group_other(sb, dir, &group, mode);
@@ -1191,6 +1201,7 @@ enum {
Opt_inode_readahead_blks, Opt_journal_ioprio,
Opt_dioread_nolock, Opt_dioread_lock,
Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
+ Opt_noorlov
};
static const match_table_t tokens = {
@@ -1210,6 +1221,7 @@ static const match_table_t tokens = {
{Opt_debug, "debug"},
{Opt_removed, "oldalloc"},
{Opt_removed, "orlov"},
+ {Opt_noorlov, "noorlov"},
{Opt_user_xattr, "user_xattr"},
{Opt_nouser_xattr, "nouser_xattr"},
{Opt_acl, "acl"},
@@ -1376,6 +1388,7 @@ static const struct mount_opts {
int token;
int mount_opt;
int flags;
+ int mount_opt2;
} ext4_mount_opts[] = {
{Opt_minix_df, EXT4_MOUNT_MINIX_DF, MOPT_SET},
{Opt_bsd_df, EXT4_MOUNT_MINIX_DF, MOPT_CLEAR},
@@ -1444,6 +1457,7 @@ static const struct mount_opts {
{Opt_jqfmt_vfsold, QFMT_VFS_OLD, MOPT_QFMT},
{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
+ {Opt_noorlov, 0, MOPT_SET, EXT4_MOUNT2_NO_ORLOV},
{Opt_err, 0, 0}
};
@@ -1562,6 +1576,7 @@ static int handle_mount_opt(struct super
} else {
clear_opt(sb, DATA_FLAGS);
sbi->s_mount_opt |= m->mount_opt;
+ sbi->s_mount_opt2 |= m->mount_opt2;
}
#ifdef CONFIG_QUOTA
} else if (m->flags & MOPT_QFMT) {
@@ -1585,10 +1600,13 @@ static int handle_mount_opt(struct super
WARN_ON(1);
return -1;
}
- if (arg != 0)
+ if (arg != 0) {
sbi->s_mount_opt |= m->mount_opt;
- else
+ sbi->s_mount_opt2 |= m->mount_opt2;
+ } else {
sbi->s_mount_opt &= ~m->mount_opt;
+ sbi->s_mount_opt2 &= ~m->mount_opt2;
+ }
}
return 1;
}
@@ -1736,11 +1754,15 @@ static int _ext4_show_options(struct seq
if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
(m->flags & MOPT_CLEAR_ERR))
continue;
- if (!(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
+ if (!(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)) &&
+ !(m->mount_opt2 & sbi->s_mount_opt2))
continue; /* skip if same as the default */
- if ((want_set &&
- (sbi->s_mount_opt & m->mount_opt) != m->mount_opt) ||
- (!want_set && (sbi->s_mount_opt & m->mount_opt)))
+ if (want_set &&
+ (((sbi->s_mount_opt & m->mount_opt) != m->mount_opt) ||
+ ((sbi->s_mount_opt2 & m->mount_opt2) != m->mount_opt2)))
+ continue; /* select Opt_noFoo vs Opt_Foo */
+ if (!want_set && ((sbi->s_mount_opt & m->mount_opt) ||
+ (sbi->s_mount_opt2 & m->mount_opt2)))
continue; /* select Opt_noFoo vs Opt_Foo */
SEQ_OPTS_PRINT("%s", token2str(m->token));
}