|
@@ -34,6 +34,8 @@
|
|
#include <linux/namei.h>
|
|
#include <linux/namei.h>
|
|
#include <linux/quotaops.h>
|
|
#include <linux/quotaops.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/seq_file.h>
|
|
|
|
+#include <linux/proc_fs.h>
|
|
|
|
+#include <linux/marker.h>
|
|
#include <linux/log2.h>
|
|
#include <linux/log2.h>
|
|
#include <linux/crc16.h>
|
|
#include <linux/crc16.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/uaccess.h>
|
|
@@ -45,6 +47,8 @@
|
|
#include "namei.h"
|
|
#include "namei.h"
|
|
#include "group.h"
|
|
#include "group.h"
|
|
|
|
|
|
|
|
+struct proc_dir_entry *ext4_proc_root;
|
|
|
|
+
|
|
static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
|
|
static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
|
|
unsigned long journal_devnum);
|
|
unsigned long journal_devnum);
|
|
static int ext4_create_journal(struct super_block *, struct ext4_super_block *,
|
|
static int ext4_create_journal(struct super_block *, struct ext4_super_block *,
|
|
@@ -508,10 +512,12 @@ static void ext4_put_super(struct super_block *sb)
|
|
if (!(sb->s_flags & MS_RDONLY)) {
|
|
if (!(sb->s_flags & MS_RDONLY)) {
|
|
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
es->s_state = cpu_to_le16(sbi->s_mount_state);
|
|
es->s_state = cpu_to_le16(sbi->s_mount_state);
|
|
- BUFFER_TRACE(sbi->s_sbh, "marking dirty");
|
|
|
|
- mark_buffer_dirty(sbi->s_sbh);
|
|
|
|
ext4_commit_super(sb, es, 1);
|
|
ext4_commit_super(sb, es, 1);
|
|
}
|
|
}
|
|
|
|
+ if (sbi->s_proc) {
|
|
|
|
+ remove_proc_entry("inode_readahead_blks", sbi->s_proc);
|
|
|
|
+ remove_proc_entry(sb->s_id, ext4_proc_root);
|
|
|
|
+ }
|
|
|
|
|
|
for (i = 0; i < sbi->s_gdb_count; i++)
|
|
for (i = 0; i < sbi->s_gdb_count; i++)
|
|
brelse(sbi->s_group_desc[i]);
|
|
brelse(sbi->s_group_desc[i]);
|
|
@@ -520,6 +526,7 @@ static void ext4_put_super(struct super_block *sb)
|
|
percpu_counter_destroy(&sbi->s_freeblocks_counter);
|
|
percpu_counter_destroy(&sbi->s_freeblocks_counter);
|
|
percpu_counter_destroy(&sbi->s_freeinodes_counter);
|
|
percpu_counter_destroy(&sbi->s_freeinodes_counter);
|
|
percpu_counter_destroy(&sbi->s_dirs_counter);
|
|
percpu_counter_destroy(&sbi->s_dirs_counter);
|
|
|
|
+ percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
|
|
brelse(sbi->s_sbh);
|
|
brelse(sbi->s_sbh);
|
|
#ifdef CONFIG_QUOTA
|
|
#ifdef CONFIG_QUOTA
|
|
for (i = 0; i < MAXQUOTAS; i++)
|
|
for (i = 0; i < MAXQUOTAS; i++)
|
|
@@ -562,11 +569,10 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
|
|
ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS);
|
|
ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS);
|
|
if (!ei)
|
|
if (!ei)
|
|
return NULL;
|
|
return NULL;
|
|
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
|
ei->i_acl = EXT4_ACL_NOT_CACHED;
|
|
ei->i_acl = EXT4_ACL_NOT_CACHED;
|
|
ei->i_default_acl = EXT4_ACL_NOT_CACHED;
|
|
ei->i_default_acl = EXT4_ACL_NOT_CACHED;
|
|
#endif
|
|
#endif
|
|
- ei->i_block_alloc_info = NULL;
|
|
|
|
ei->vfs_inode.i_version = 1;
|
|
ei->vfs_inode.i_version = 1;
|
|
ei->vfs_inode.i_data.writeback_index = 0;
|
|
ei->vfs_inode.i_data.writeback_index = 0;
|
|
memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
|
|
memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
|
|
@@ -599,7 +605,7 @@ static void init_once(void *foo)
|
|
struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
|
|
struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
|
|
|
|
|
|
INIT_LIST_HEAD(&ei->i_orphan);
|
|
INIT_LIST_HEAD(&ei->i_orphan);
|
|
-#ifdef CONFIG_EXT4DEV_FS_XATTR
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_XATTR
|
|
init_rwsem(&ei->xattr_sem);
|
|
init_rwsem(&ei->xattr_sem);
|
|
#endif
|
|
#endif
|
|
init_rwsem(&ei->i_data_sem);
|
|
init_rwsem(&ei->i_data_sem);
|
|
@@ -625,8 +631,7 @@ static void destroy_inodecache(void)
|
|
|
|
|
|
static void ext4_clear_inode(struct inode *inode)
|
|
static void ext4_clear_inode(struct inode *inode)
|
|
{
|
|
{
|
|
- struct ext4_block_alloc_info *rsv = EXT4_I(inode)->i_block_alloc_info;
|
|
|
|
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
|
if (EXT4_I(inode)->i_acl &&
|
|
if (EXT4_I(inode)->i_acl &&
|
|
EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) {
|
|
EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) {
|
|
posix_acl_release(EXT4_I(inode)->i_acl);
|
|
posix_acl_release(EXT4_I(inode)->i_acl);
|
|
@@ -638,10 +643,7 @@ static void ext4_clear_inode(struct inode *inode)
|
|
EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED;
|
|
EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
- ext4_discard_reservation(inode);
|
|
|
|
- EXT4_I(inode)->i_block_alloc_info = NULL;
|
|
|
|
- if (unlikely(rsv))
|
|
|
|
- kfree(rsv);
|
|
|
|
|
|
+ ext4_discard_preallocations(inode);
|
|
jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal,
|
|
jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal,
|
|
&EXT4_I(inode)->jinode);
|
|
&EXT4_I(inode)->jinode);
|
|
}
|
|
}
|
|
@@ -654,7 +656,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
|
|
|
|
|
|
if (sbi->s_jquota_fmt)
|
|
if (sbi->s_jquota_fmt)
|
|
seq_printf(seq, ",jqfmt=%s",
|
|
seq_printf(seq, ",jqfmt=%s",
|
|
- (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
|
|
|
|
|
|
+ (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0");
|
|
|
|
|
|
if (sbi->s_qf_names[USRQUOTA])
|
|
if (sbi->s_qf_names[USRQUOTA])
|
|
seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
|
|
seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
|
|
@@ -718,7 +720,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
|
seq_puts(seq, ",debug");
|
|
seq_puts(seq, ",debug");
|
|
if (test_opt(sb, OLDALLOC))
|
|
if (test_opt(sb, OLDALLOC))
|
|
seq_puts(seq, ",oldalloc");
|
|
seq_puts(seq, ",oldalloc");
|
|
-#ifdef CONFIG_EXT4DEV_FS_XATTR
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_XATTR
|
|
if (test_opt(sb, XATTR_USER) &&
|
|
if (test_opt(sb, XATTR_USER) &&
|
|
!(def_mount_opts & EXT4_DEFM_XATTR_USER))
|
|
!(def_mount_opts & EXT4_DEFM_XATTR_USER))
|
|
seq_puts(seq, ",user_xattr");
|
|
seq_puts(seq, ",user_xattr");
|
|
@@ -727,7 +729,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
|
seq_puts(seq, ",nouser_xattr");
|
|
seq_puts(seq, ",nouser_xattr");
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
|
if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL))
|
|
if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL))
|
|
seq_puts(seq, ",acl");
|
|
seq_puts(seq, ",acl");
|
|
if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
|
|
if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL))
|
|
@@ -752,8 +754,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
|
seq_puts(seq, ",nobh");
|
|
seq_puts(seq, ",nobh");
|
|
if (!test_opt(sb, EXTENTS))
|
|
if (!test_opt(sb, EXTENTS))
|
|
seq_puts(seq, ",noextents");
|
|
seq_puts(seq, ",noextents");
|
|
- if (!test_opt(sb, MBALLOC))
|
|
|
|
- seq_puts(seq, ",nomballoc");
|
|
|
|
if (test_opt(sb, I_VERSION))
|
|
if (test_opt(sb, I_VERSION))
|
|
seq_puts(seq, ",i_version");
|
|
seq_puts(seq, ",i_version");
|
|
if (!test_opt(sb, DELALLOC))
|
|
if (!test_opt(sb, DELALLOC))
|
|
@@ -773,6 +773,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
|
else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
|
|
else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
|
|
seq_puts(seq, ",data=writeback");
|
|
seq_puts(seq, ",data=writeback");
|
|
|
|
|
|
|
|
+ if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
|
|
|
|
+ seq_printf(seq, ",inode_readahead_blks=%u",
|
|
|
|
+ sbi->s_inode_readahead_blks);
|
|
|
|
+
|
|
ext4_show_quota_options(seq, sb);
|
|
ext4_show_quota_options(seq, sb);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -822,7 +826,7 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_QUOTA
|
|
#ifdef CONFIG_QUOTA
|
|
-#define QTYPE2NAME(t) ((t) == USRQUOTA?"user":"group")
|
|
|
|
|
|
+#define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
|
|
#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
|
|
#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
|
|
|
|
|
|
static int ext4_dquot_initialize(struct inode *inode, int type);
|
|
static int ext4_dquot_initialize(struct inode *inode, int type);
|
|
@@ -907,6 +911,7 @@ enum {
|
|
Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
|
|
Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
|
|
Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
|
|
Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
|
|
Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc,
|
|
Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc,
|
|
|
|
+ Opt_inode_readahead_blks
|
|
};
|
|
};
|
|
|
|
|
|
static match_table_t tokens = {
|
|
static match_table_t tokens = {
|
|
@@ -967,6 +972,7 @@ static match_table_t tokens = {
|
|
{Opt_resize, "resize"},
|
|
{Opt_resize, "resize"},
|
|
{Opt_delalloc, "delalloc"},
|
|
{Opt_delalloc, "delalloc"},
|
|
{Opt_nodelalloc, "nodelalloc"},
|
|
{Opt_nodelalloc, "nodelalloc"},
|
|
|
|
+ {Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
|
|
{Opt_err, NULL},
|
|
{Opt_err, NULL},
|
|
};
|
|
};
|
|
|
|
|
|
@@ -981,7 +987,7 @@ static ext4_fsblk_t get_sb_block(void **data)
|
|
/*todo: use simple_strtoll with >32bit ext4 */
|
|
/*todo: use simple_strtoll with >32bit ext4 */
|
|
sb_block = simple_strtoul(options, &options, 0);
|
|
sb_block = simple_strtoul(options, &options, 0);
|
|
if (*options && *options != ',') {
|
|
if (*options && *options != ',') {
|
|
- printk("EXT4-fs: Invalid sb specification: %s\n",
|
|
|
|
|
|
+ printk(KERN_ERR "EXT4-fs: Invalid sb specification: %s\n",
|
|
(char *) *data);
|
|
(char *) *data);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -1072,7 +1078,7 @@ static int parse_options(char *options, struct super_block *sb,
|
|
case Opt_orlov:
|
|
case Opt_orlov:
|
|
clear_opt(sbi->s_mount_opt, OLDALLOC);
|
|
clear_opt(sbi->s_mount_opt, OLDALLOC);
|
|
break;
|
|
break;
|
|
-#ifdef CONFIG_EXT4DEV_FS_XATTR
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_XATTR
|
|
case Opt_user_xattr:
|
|
case Opt_user_xattr:
|
|
set_opt(sbi->s_mount_opt, XATTR_USER);
|
|
set_opt(sbi->s_mount_opt, XATTR_USER);
|
|
break;
|
|
break;
|
|
@@ -1082,10 +1088,11 @@ static int parse_options(char *options, struct super_block *sb,
|
|
#else
|
|
#else
|
|
case Opt_user_xattr:
|
|
case Opt_user_xattr:
|
|
case Opt_nouser_xattr:
|
|
case Opt_nouser_xattr:
|
|
- printk("EXT4 (no)user_xattr options not supported\n");
|
|
|
|
|
|
+ printk(KERN_ERR "EXT4 (no)user_xattr options "
|
|
|
|
+ "not supported\n");
|
|
break;
|
|
break;
|
|
#endif
|
|
#endif
|
|
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
|
case Opt_acl:
|
|
case Opt_acl:
|
|
set_opt(sbi->s_mount_opt, POSIX_ACL);
|
|
set_opt(sbi->s_mount_opt, POSIX_ACL);
|
|
break;
|
|
break;
|
|
@@ -1095,7 +1102,8 @@ static int parse_options(char *options, struct super_block *sb,
|
|
#else
|
|
#else
|
|
case Opt_acl:
|
|
case Opt_acl:
|
|
case Opt_noacl:
|
|
case Opt_noacl:
|
|
- printk("EXT4 (no)acl options not supported\n");
|
|
|
|
|
|
+ printk(KERN_ERR "EXT4 (no)acl options "
|
|
|
|
+ "not supported\n");
|
|
break;
|
|
break;
|
|
#endif
|
|
#endif
|
|
case Opt_reservation:
|
|
case Opt_reservation:
|
|
@@ -1189,8 +1197,8 @@ set_qf_name:
|
|
sb_any_quota_suspended(sb)) &&
|
|
sb_any_quota_suspended(sb)) &&
|
|
!sbi->s_qf_names[qtype]) {
|
|
!sbi->s_qf_names[qtype]) {
|
|
printk(KERN_ERR
|
|
printk(KERN_ERR
|
|
- "EXT4-fs: Cannot change journaled "
|
|
|
|
- "quota options when quota turned on.\n");
|
|
|
|
|
|
+ "EXT4-fs: Cannot change journaled "
|
|
|
|
+ "quota options when quota turned on.\n");
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
qname = match_strdup(&args[0]);
|
|
qname = match_strdup(&args[0]);
|
|
@@ -1357,12 +1365,6 @@ set_qf_format:
|
|
case Opt_nodelalloc:
|
|
case Opt_nodelalloc:
|
|
clear_opt(sbi->s_mount_opt, DELALLOC);
|
|
clear_opt(sbi->s_mount_opt, DELALLOC);
|
|
break;
|
|
break;
|
|
- case Opt_mballoc:
|
|
|
|
- set_opt(sbi->s_mount_opt, MBALLOC);
|
|
|
|
- break;
|
|
|
|
- case Opt_nomballoc:
|
|
|
|
- clear_opt(sbi->s_mount_opt, MBALLOC);
|
|
|
|
- break;
|
|
|
|
case Opt_stripe:
|
|
case Opt_stripe:
|
|
if (match_int(&args[0], &option))
|
|
if (match_int(&args[0], &option))
|
|
return 0;
|
|
return 0;
|
|
@@ -1373,6 +1375,13 @@ set_qf_format:
|
|
case Opt_delalloc:
|
|
case Opt_delalloc:
|
|
set_opt(sbi->s_mount_opt, DELALLOC);
|
|
set_opt(sbi->s_mount_opt, DELALLOC);
|
|
break;
|
|
break;
|
|
|
|
+ case Opt_inode_readahead_blks:
|
|
|
|
+ if (match_int(&args[0], &option))
|
|
|
|
+ return 0;
|
|
|
|
+ if (option < 0 || option > (1 << 30))
|
|
|
|
+ return 0;
|
|
|
|
+ sbi->s_inode_readahead_blks = option;
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
printk(KERN_ERR
|
|
printk(KERN_ERR
|
|
"EXT4-fs: Unrecognized mount option \"%s\" "
|
|
"EXT4-fs: Unrecognized mount option \"%s\" "
|
|
@@ -1473,15 +1482,9 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
|
|
EXT4_INODES_PER_GROUP(sb),
|
|
EXT4_INODES_PER_GROUP(sb),
|
|
sbi->s_mount_opt);
|
|
sbi->s_mount_opt);
|
|
|
|
|
|
- printk(KERN_INFO "EXT4 FS on %s, ", sb->s_id);
|
|
|
|
- if (EXT4_SB(sb)->s_journal->j_inode == NULL) {
|
|
|
|
- char b[BDEVNAME_SIZE];
|
|
|
|
-
|
|
|
|
- printk("external journal on %s\n",
|
|
|
|
- bdevname(EXT4_SB(sb)->s_journal->j_dev, b));
|
|
|
|
- } else {
|
|
|
|
- printk("internal journal\n");
|
|
|
|
- }
|
|
|
|
|
|
+ printk(KERN_INFO "EXT4 FS on %s, %s journal on %s\n",
|
|
|
|
+ sb->s_id, EXT4_SB(sb)->s_journal->j_inode ? "internal" :
|
|
|
|
+ "external", EXT4_SB(sb)->s_journal->j_devname);
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1504,8 +1507,11 @@ static int ext4_fill_flex_info(struct super_block *sb)
|
|
sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
|
|
sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
|
|
groups_per_flex = 1 << sbi->s_log_groups_per_flex;
|
|
groups_per_flex = 1 << sbi->s_log_groups_per_flex;
|
|
|
|
|
|
- flex_group_count = (sbi->s_groups_count + groups_per_flex - 1) /
|
|
|
|
- groups_per_flex;
|
|
|
|
|
|
+ /* We allocate both existing and potentially added groups */
|
|
|
|
+ flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
|
|
|
|
+ ((sbi->s_es->s_reserved_gdt_blocks +1 ) <<
|
|
|
|
+ EXT4_DESC_PER_BLOCK_BITS(sb))) /
|
|
|
|
+ groups_per_flex;
|
|
sbi->s_flex_groups = kzalloc(flex_group_count *
|
|
sbi->s_flex_groups = kzalloc(flex_group_count *
|
|
sizeof(struct flex_groups), GFP_KERNEL);
|
|
sizeof(struct flex_groups), GFP_KERNEL);
|
|
if (sbi->s_flex_groups == NULL) {
|
|
if (sbi->s_flex_groups == NULL) {
|
|
@@ -1584,7 +1590,7 @@ static int ext4_check_descriptors(struct super_block *sb)
|
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
|
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
|
|
flexbg_flag = 1;
|
|
flexbg_flag = 1;
|
|
|
|
|
|
- ext4_debug ("Checking group descriptors");
|
|
|
|
|
|
+ ext4_debug("Checking group descriptors");
|
|
|
|
|
|
for (i = 0; i < sbi->s_groups_count; i++) {
|
|
for (i = 0; i < sbi->s_groups_count; i++) {
|
|
struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
|
|
struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
|
|
@@ -1623,8 +1629,10 @@ static int ext4_check_descriptors(struct super_block *sb)
|
|
"Checksum for group %lu failed (%u!=%u)\n",
|
|
"Checksum for group %lu failed (%u!=%u)\n",
|
|
i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
|
i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
|
gdp)), le16_to_cpu(gdp->bg_checksum));
|
|
gdp)), le16_to_cpu(gdp->bg_checksum));
|
|
- if (!(sb->s_flags & MS_RDONLY))
|
|
|
|
|
|
+ if (!(sb->s_flags & MS_RDONLY)) {
|
|
|
|
+ spin_unlock(sb_bgl_lock(sbi, i));
|
|
return 0;
|
|
return 0;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
spin_unlock(sb_bgl_lock(sbi, i));
|
|
spin_unlock(sb_bgl_lock(sbi, i));
|
|
if (!flexbg_flag)
|
|
if (!flexbg_flag)
|
|
@@ -1714,9 +1722,9 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
|
DQUOT_INIT(inode);
|
|
DQUOT_INIT(inode);
|
|
if (inode->i_nlink) {
|
|
if (inode->i_nlink) {
|
|
printk(KERN_DEBUG
|
|
printk(KERN_DEBUG
|
|
- "%s: truncating inode %lu to %Ld bytes\n",
|
|
|
|
|
|
+ "%s: truncating inode %lu to %lld bytes\n",
|
|
__func__, inode->i_ino, inode->i_size);
|
|
__func__, inode->i_ino, inode->i_size);
|
|
- jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
|
|
|
|
|
|
+ jbd_debug(2, "truncating inode %lu to %lld bytes\n",
|
|
inode->i_ino, inode->i_size);
|
|
inode->i_ino, inode->i_size);
|
|
ext4_truncate(inode);
|
|
ext4_truncate(inode);
|
|
nr_truncates++;
|
|
nr_truncates++;
|
|
@@ -1914,6 +1922,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
unsigned long journal_devnum = 0;
|
|
unsigned long journal_devnum = 0;
|
|
unsigned long def_mount_opts;
|
|
unsigned long def_mount_opts;
|
|
struct inode *root;
|
|
struct inode *root;
|
|
|
|
+ char *cp;
|
|
int ret = -EINVAL;
|
|
int ret = -EINVAL;
|
|
int blocksize;
|
|
int blocksize;
|
|
int db_count;
|
|
int db_count;
|
|
@@ -1930,10 +1939,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
sbi->s_mount_opt = 0;
|
|
sbi->s_mount_opt = 0;
|
|
sbi->s_resuid = EXT4_DEF_RESUID;
|
|
sbi->s_resuid = EXT4_DEF_RESUID;
|
|
sbi->s_resgid = EXT4_DEF_RESGID;
|
|
sbi->s_resgid = EXT4_DEF_RESGID;
|
|
|
|
+ sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
|
|
sbi->s_sb_block = sb_block;
|
|
sbi->s_sb_block = sb_block;
|
|
|
|
|
|
unlock_kernel();
|
|
unlock_kernel();
|
|
|
|
|
|
|
|
+ /* Cleanup superblock name */
|
|
|
|
+ for (cp = sb->s_id; (cp = strchr(cp, '/'));)
|
|
|
|
+ *cp = '!';
|
|
|
|
+
|
|
blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE);
|
|
blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE);
|
|
if (!blocksize) {
|
|
if (!blocksize) {
|
|
printk(KERN_ERR "EXT4-fs: unable to set blocksize\n");
|
|
printk(KERN_ERR "EXT4-fs: unable to set blocksize\n");
|
|
@@ -1973,11 +1987,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
set_opt(sbi->s_mount_opt, GRPID);
|
|
set_opt(sbi->s_mount_opt, GRPID);
|
|
if (def_mount_opts & EXT4_DEFM_UID16)
|
|
if (def_mount_opts & EXT4_DEFM_UID16)
|
|
set_opt(sbi->s_mount_opt, NO_UID32);
|
|
set_opt(sbi->s_mount_opt, NO_UID32);
|
|
-#ifdef CONFIG_EXT4DEV_FS_XATTR
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_XATTR
|
|
if (def_mount_opts & EXT4_DEFM_XATTR_USER)
|
|
if (def_mount_opts & EXT4_DEFM_XATTR_USER)
|
|
set_opt(sbi->s_mount_opt, XATTR_USER);
|
|
set_opt(sbi->s_mount_opt, XATTR_USER);
|
|
#endif
|
|
#endif
|
|
-#ifdef CONFIG_EXT4DEV_FS_POSIX_ACL
|
|
|
|
|
|
+#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
|
if (def_mount_opts & EXT4_DEFM_ACL)
|
|
if (def_mount_opts & EXT4_DEFM_ACL)
|
|
set_opt(sbi->s_mount_opt, POSIX_ACL);
|
|
set_opt(sbi->s_mount_opt, POSIX_ACL);
|
|
#endif
|
|
#endif
|
|
@@ -2012,11 +2026,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
ext4_warning(sb, __func__,
|
|
ext4_warning(sb, __func__,
|
|
"extents feature not enabled on this filesystem, "
|
|
"extents feature not enabled on this filesystem, "
|
|
"use tune2fs.\n");
|
|
"use tune2fs.\n");
|
|
- /*
|
|
|
|
- * turn on mballoc code by default in ext4 filesystem
|
|
|
|
- * Use -o nomballoc to turn it off
|
|
|
|
- */
|
|
|
|
- set_opt(sbi->s_mount_opt, MBALLOC);
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* enable delayed allocation by default
|
|
* enable delayed allocation by default
|
|
@@ -2040,16 +2049,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
"EXT4-fs warning: feature flags set on rev 0 fs, "
|
|
"EXT4-fs warning: feature flags set on rev 0 fs, "
|
|
"running e2fsck is recommended\n");
|
|
"running e2fsck is recommended\n");
|
|
|
|
|
|
- /*
|
|
|
|
- * Since ext4 is still considered development code, we require
|
|
|
|
- * that the TEST_FILESYS flag in s->flags be set.
|
|
|
|
- */
|
|
|
|
- if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) {
|
|
|
|
- printk(KERN_WARNING "EXT4-fs: %s: not marked "
|
|
|
|
- "OK to use with test code.\n", sb->s_id);
|
|
|
|
- goto failed_mount;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Check feature flags regardless of the revision level, since we
|
|
* Check feature flags regardless of the revision level, since we
|
|
* previously didn't change the revision level when setting the flags,
|
|
* previously didn't change the revision level when setting the flags,
|
|
@@ -2219,6 +2218,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
goto failed_mount;
|
|
goto failed_mount;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (ext4_proc_root)
|
|
|
|
+ sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
|
|
|
|
+
|
|
|
|
+ if (sbi->s_proc)
|
|
|
|
+ proc_create_data("inode_readahead_blks", 0644, sbi->s_proc,
|
|
|
|
+ &ext4_ui_proc_fops,
|
|
|
|
+ &sbi->s_inode_readahead_blks);
|
|
|
|
+
|
|
bgl_lock_init(&sbi->s_blockgroup_lock);
|
|
bgl_lock_init(&sbi->s_blockgroup_lock);
|
|
|
|
|
|
for (i = 0; i < db_count; i++) {
|
|
for (i = 0; i < db_count; i++) {
|
|
@@ -2257,24 +2264,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
err = percpu_counter_init(&sbi->s_dirs_counter,
|
|
err = percpu_counter_init(&sbi->s_dirs_counter,
|
|
ext4_count_dirs(sb));
|
|
ext4_count_dirs(sb));
|
|
}
|
|
}
|
|
|
|
+ if (!err) {
|
|
|
|
+ err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
|
|
|
|
+ }
|
|
if (err) {
|
|
if (err) {
|
|
printk(KERN_ERR "EXT4-fs: insufficient memory\n");
|
|
printk(KERN_ERR "EXT4-fs: insufficient memory\n");
|
|
goto failed_mount3;
|
|
goto failed_mount3;
|
|
}
|
|
}
|
|
|
|
|
|
- /* per fileystem reservation list head & lock */
|
|
|
|
- spin_lock_init(&sbi->s_rsv_window_lock);
|
|
|
|
- sbi->s_rsv_window_root = RB_ROOT;
|
|
|
|
- /* Add a single, static dummy reservation to the start of the
|
|
|
|
- * reservation window list --- it gives us a placeholder for
|
|
|
|
- * append-at-start-of-list which makes the allocation logic
|
|
|
|
- * _much_ simpler. */
|
|
|
|
- sbi->s_rsv_window_head.rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
|
|
|
|
- sbi->s_rsv_window_head.rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED;
|
|
|
|
- sbi->s_rsv_window_head.rsv_alloc_hit = 0;
|
|
|
|
- sbi->s_rsv_window_head.rsv_goal_size = 0;
|
|
|
|
- ext4_rsv_window_add(sb, &sbi->s_rsv_window_head);
|
|
|
|
-
|
|
|
|
sbi->s_stripe = ext4_get_stripe_size(sbi);
|
|
sbi->s_stripe = ext4_get_stripe_size(sbi);
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2471,7 +2468,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
|
|
printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
|
|
|
|
|
|
ext4_ext_init(sb);
|
|
ext4_ext_init(sb);
|
|
- ext4_mb_init(sb, needs_recovery);
|
|
|
|
|
|
+ err = ext4_mb_init(sb, needs_recovery);
|
|
|
|
+ if (err) {
|
|
|
|
+ printk(KERN_ERR "EXT4-fs: failed to initalize mballoc (%d)\n",
|
|
|
|
+ err);
|
|
|
|
+ goto failed_mount4;
|
|
|
|
+ }
|
|
|
|
|
|
lock_kernel();
|
|
lock_kernel();
|
|
return 0;
|
|
return 0;
|
|
@@ -2489,11 +2491,16 @@ failed_mount3:
|
|
percpu_counter_destroy(&sbi->s_freeblocks_counter);
|
|
percpu_counter_destroy(&sbi->s_freeblocks_counter);
|
|
percpu_counter_destroy(&sbi->s_freeinodes_counter);
|
|
percpu_counter_destroy(&sbi->s_freeinodes_counter);
|
|
percpu_counter_destroy(&sbi->s_dirs_counter);
|
|
percpu_counter_destroy(&sbi->s_dirs_counter);
|
|
|
|
+ percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
|
|
failed_mount2:
|
|
failed_mount2:
|
|
for (i = 0; i < db_count; i++)
|
|
for (i = 0; i < db_count; i++)
|
|
brelse(sbi->s_group_desc[i]);
|
|
brelse(sbi->s_group_desc[i]);
|
|
kfree(sbi->s_group_desc);
|
|
kfree(sbi->s_group_desc);
|
|
failed_mount:
|
|
failed_mount:
|
|
|
|
+ if (sbi->s_proc) {
|
|
|
|
+ remove_proc_entry("inode_readahead_blks", sbi->s_proc);
|
|
|
|
+ remove_proc_entry(sb->s_id, ext4_proc_root);
|
|
|
|
+ }
|
|
#ifdef CONFIG_QUOTA
|
|
#ifdef CONFIG_QUOTA
|
|
for (i = 0; i < MAXQUOTAS; i++)
|
|
for (i = 0; i < MAXQUOTAS; i++)
|
|
kfree(sbi->s_qf_names[i]);
|
|
kfree(sbi->s_qf_names[i]);
|
|
@@ -2552,7 +2559,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
- jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",
|
|
|
|
|
|
+ jbd_debug(2, "Journal inode found at %p: %lld bytes\n",
|
|
journal_inode, journal_inode->i_size);
|
|
journal_inode, journal_inode->i_size);
|
|
if (!S_ISREG(journal_inode->i_mode)) {
|
|
if (!S_ISREG(journal_inode->i_mode)) {
|
|
printk(KERN_ERR "EXT4-fs: invalid journal inode.\n");
|
|
printk(KERN_ERR "EXT4-fs: invalid journal inode.\n");
|
|
@@ -2715,6 +2722,11 @@ static int ext4_load_journal(struct super_block *sb,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (journal->j_flags & JBD2_BARRIER)
|
|
|
|
+ printk(KERN_INFO "EXT4-fs: barriers enabled\n");
|
|
|
|
+ else
|
|
|
|
+ printk(KERN_INFO "EXT4-fs: barriers disabled\n");
|
|
|
|
+
|
|
if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
|
|
if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
|
|
err = jbd2_journal_update_format(journal);
|
|
err = jbd2_journal_update_format(journal);
|
|
if (err) {
|
|
if (err) {
|
|
@@ -2799,13 +2811,34 @@ static void ext4_commit_super(struct super_block *sb,
|
|
|
|
|
|
if (!sbh)
|
|
if (!sbh)
|
|
return;
|
|
return;
|
|
|
|
+ if (buffer_write_io_error(sbh)) {
|
|
|
|
+ /*
|
|
|
|
+ * Oh, dear. A previous attempt to write the
|
|
|
|
+ * superblock failed. This could happen because the
|
|
|
|
+ * USB device was yanked out. Or it could happen to
|
|
|
|
+ * be a transient write error and maybe the block will
|
|
|
|
+ * be remapped. Nothing we can do but to retry the
|
|
|
|
+ * write and hope for the best.
|
|
|
|
+ */
|
|
|
|
+ printk(KERN_ERR "ext4: previous I/O error to "
|
|
|
|
+ "superblock detected for %s.\n", sb->s_id);
|
|
|
|
+ clear_buffer_write_io_error(sbh);
|
|
|
|
+ set_buffer_uptodate(sbh);
|
|
|
|
+ }
|
|
es->s_wtime = cpu_to_le32(get_seconds());
|
|
es->s_wtime = cpu_to_le32(get_seconds());
|
|
ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb));
|
|
ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb));
|
|
es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
|
|
es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
|
|
BUFFER_TRACE(sbh, "marking dirty");
|
|
BUFFER_TRACE(sbh, "marking dirty");
|
|
mark_buffer_dirty(sbh);
|
|
mark_buffer_dirty(sbh);
|
|
- if (sync)
|
|
|
|
|
|
+ if (sync) {
|
|
sync_dirty_buffer(sbh);
|
|
sync_dirty_buffer(sbh);
|
|
|
|
+ if (buffer_write_io_error(sbh)) {
|
|
|
|
+ printk(KERN_ERR "ext4: I/O error while writing "
|
|
|
|
+ "superblock for %s.\n", sb->s_id);
|
|
|
|
+ clear_buffer_write_io_error(sbh);
|
|
|
|
+ set_buffer_uptodate(sbh);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2907,6 +2940,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
|
|
{
|
|
{
|
|
tid_t target;
|
|
tid_t target;
|
|
|
|
|
|
|
|
+ trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
|
|
sb->s_dirt = 0;
|
|
sb->s_dirt = 0;
|
|
if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
|
|
if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
|
|
if (wait)
|
|
if (wait)
|
|
@@ -3162,7 +3196,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|
buf->f_type = EXT4_SUPER_MAGIC;
|
|
buf->f_type = EXT4_SUPER_MAGIC;
|
|
buf->f_bsize = sb->s_blocksize;
|
|
buf->f_bsize = sb->s_blocksize;
|
|
buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
|
|
buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
|
|
- buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
|
|
|
|
|
|
+ buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) -
|
|
|
|
+ percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter);
|
|
ext4_free_blocks_count_set(es, buf->f_bfree);
|
|
ext4_free_blocks_count_set(es, buf->f_bfree);
|
|
buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
|
|
buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
|
|
if (buf->f_bfree < ext4_r_blocks_count(es))
|
|
if (buf->f_bfree < ext4_r_blocks_count(es))
|
|
@@ -3432,7 +3467,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
|
|
handle_t *handle = journal_current_handle();
|
|
handle_t *handle = journal_current_handle();
|
|
|
|
|
|
if (!handle) {
|
|
if (!handle) {
|
|
- printk(KERN_WARNING "EXT4-fs: Quota write (off=%Lu, len=%Lu)"
|
|
|
|
|
|
+ printk(KERN_WARNING "EXT4-fs: Quota write (off=%llu, len=%llu)"
|
|
" cancelled because transaction is not started.\n",
|
|
" cancelled because transaction is not started.\n",
|
|
(unsigned long long)off, (unsigned long long)len);
|
|
(unsigned long long)off, (unsigned long long)len);
|
|
return -EIO;
|
|
return -EIO;
|
|
@@ -3493,18 +3528,82 @@ static int ext4_get_sb(struct file_system_type *fs_type,
|
|
return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt);
|
|
return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef CONFIG_PROC_FS
|
|
|
|
+static int ext4_ui_proc_show(struct seq_file *m, void *v)
|
|
|
|
+{
|
|
|
|
+ unsigned int *p = m->private;
|
|
|
|
+
|
|
|
|
+ seq_printf(m, "%u\n", *p);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int ext4_ui_proc_open(struct inode *inode, struct file *file)
|
|
|
|
+{
|
|
|
|
+ return single_open(file, ext4_ui_proc_show, PDE(inode)->data);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ssize_t ext4_ui_proc_write(struct file *file, const char __user *buf,
|
|
|
|
+ size_t cnt, loff_t *ppos)
|
|
|
|
+{
|
|
|
|
+ unsigned int *p = PDE(file->f_path.dentry->d_inode)->data;
|
|
|
|
+ char str[32];
|
|
|
|
+ unsigned long value;
|
|
|
|
+
|
|
|
|
+ if (cnt >= sizeof(str))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ if (copy_from_user(str, buf, cnt))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+ value = simple_strtol(str, NULL, 0);
|
|
|
|
+ if (value < 0)
|
|
|
|
+ return -ERANGE;
|
|
|
|
+ *p = value;
|
|
|
|
+ return cnt;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const struct file_operations ext4_ui_proc_fops = {
|
|
|
|
+ .owner = THIS_MODULE,
|
|
|
|
+ .open = ext4_ui_proc_open,
|
|
|
|
+ .read = seq_read,
|
|
|
|
+ .llseek = seq_lseek,
|
|
|
|
+ .release = single_release,
|
|
|
|
+ .write = ext4_ui_proc_write,
|
|
|
|
+};
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+static struct file_system_type ext4_fs_type = {
|
|
|
|
+ .owner = THIS_MODULE,
|
|
|
|
+ .name = "ext4",
|
|
|
|
+ .get_sb = ext4_get_sb,
|
|
|
|
+ .kill_sb = kill_block_super,
|
|
|
|
+ .fs_flags = FS_REQUIRES_DEV,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_EXT4DEV_COMPAT
|
|
|
|
+static int ext4dev_get_sb(struct file_system_type *fs_type,
|
|
|
|
+ int flags, const char *dev_name, void *data, struct vfsmount *mnt)
|
|
|
|
+{
|
|
|
|
+ printk(KERN_WARNING "EXT4-fs: Update your userspace programs "
|
|
|
|
+ "to mount using ext4\n");
|
|
|
|
+ printk(KERN_WARNING "EXT4-fs: ext4dev backwards compatibility "
|
|
|
|
+ "will go away by 2.6.31\n");
|
|
|
|
+ return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt);
|
|
|
|
+}
|
|
|
|
+
|
|
static struct file_system_type ext4dev_fs_type = {
|
|
static struct file_system_type ext4dev_fs_type = {
|
|
.owner = THIS_MODULE,
|
|
.owner = THIS_MODULE,
|
|
.name = "ext4dev",
|
|
.name = "ext4dev",
|
|
- .get_sb = ext4_get_sb,
|
|
|
|
|
|
+ .get_sb = ext4dev_get_sb,
|
|
.kill_sb = kill_block_super,
|
|
.kill_sb = kill_block_super,
|
|
.fs_flags = FS_REQUIRES_DEV,
|
|
.fs_flags = FS_REQUIRES_DEV,
|
|
};
|
|
};
|
|
|
|
+MODULE_ALIAS("ext4dev");
|
|
|
|
+#endif
|
|
|
|
|
|
static int __init init_ext4_fs(void)
|
|
static int __init init_ext4_fs(void)
|
|
{
|
|
{
|
|
int err;
|
|
int err;
|
|
|
|
|
|
|
|
+ ext4_proc_root = proc_mkdir("fs/ext4", NULL);
|
|
err = init_ext4_mballoc();
|
|
err = init_ext4_mballoc();
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
@@ -3515,9 +3614,16 @@ static int __init init_ext4_fs(void)
|
|
err = init_inodecache();
|
|
err = init_inodecache();
|
|
if (err)
|
|
if (err)
|
|
goto out1;
|
|
goto out1;
|
|
- err = register_filesystem(&ext4dev_fs_type);
|
|
|
|
|
|
+ err = register_filesystem(&ext4_fs_type);
|
|
if (err)
|
|
if (err)
|
|
goto out;
|
|
goto out;
|
|
|
|
+#ifdef CONFIG_EXT4DEV_COMPAT
|
|
|
|
+ err = register_filesystem(&ext4dev_fs_type);
|
|
|
|
+ if (err) {
|
|
|
|
+ unregister_filesystem(&ext4_fs_type);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
return 0;
|
|
return 0;
|
|
out:
|
|
out:
|
|
destroy_inodecache();
|
|
destroy_inodecache();
|
|
@@ -3530,10 +3636,14 @@ out2:
|
|
|
|
|
|
static void __exit exit_ext4_fs(void)
|
|
static void __exit exit_ext4_fs(void)
|
|
{
|
|
{
|
|
|
|
+ unregister_filesystem(&ext4_fs_type);
|
|
|
|
+#ifdef CONFIG_EXT4DEV_COMPAT
|
|
unregister_filesystem(&ext4dev_fs_type);
|
|
unregister_filesystem(&ext4dev_fs_type);
|
|
|
|
+#endif
|
|
destroy_inodecache();
|
|
destroy_inodecache();
|
|
exit_ext4_xattr();
|
|
exit_ext4_xattr();
|
|
exit_ext4_mballoc();
|
|
exit_ext4_mballoc();
|
|
|
|
+ remove_proc_entry("fs/ext4", NULL);
|
|
}
|
|
}
|
|
|
|
|
|
MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
|
|
MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
|