|
@@ -20,6 +20,7 @@
|
|
|
#include <linux/string.h>
|
|
|
#include <linux/fs.h>
|
|
|
#include <linux/time.h>
|
|
|
+#include <linux/vmalloc.h>
|
|
|
#include <linux/jbd2.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/init.h>
|
|
@@ -45,16 +46,20 @@
|
|
|
#include "ext4_jbd2.h"
|
|
|
#include "xattr.h"
|
|
|
#include "acl.h"
|
|
|
-#include "namei.h"
|
|
|
-#include "group.h"
|
|
|
+
|
|
|
+static int default_mb_history_length = 1000;
|
|
|
+
|
|
|
+module_param_named(default_mb_history_length, default_mb_history_length,
|
|
|
+ int, 0644);
|
|
|
+MODULE_PARM_DESC(default_mb_history_length,
|
|
|
+ "Default number of entries saved for mb_history");
|
|
|
|
|
|
struct proc_dir_entry *ext4_proc_root;
|
|
|
static struct kset *ext4_kset;
|
|
|
|
|
|
static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
|
|
|
unsigned long journal_devnum);
|
|
|
-static int ext4_commit_super(struct super_block *sb,
|
|
|
- struct ext4_super_block *es, int sync);
|
|
|
+static int ext4_commit_super(struct super_block *sb, int sync);
|
|
|
static void ext4_mark_recovery_complete(struct super_block *sb,
|
|
|
struct ext4_super_block *es);
|
|
|
static void ext4_clear_journal_err(struct super_block *sb,
|
|
@@ -74,7 +79,7 @@ ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
|
|
|
{
|
|
|
return le32_to_cpu(bg->bg_block_bitmap_lo) |
|
|
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
|
|
- (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
|
|
|
+ (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
|
|
|
}
|
|
|
|
|
|
ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
|
|
@@ -82,7 +87,7 @@ ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
|
|
|
{
|
|
|
return le32_to_cpu(bg->bg_inode_bitmap_lo) |
|
|
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
|
|
- (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
|
|
|
+ (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
|
|
|
}
|
|
|
|
|
|
ext4_fsblk_t ext4_inode_table(struct super_block *sb,
|
|
@@ -90,7 +95,7 @@ ext4_fsblk_t ext4_inode_table(struct super_block *sb,
|
|
|
{
|
|
|
return le32_to_cpu(bg->bg_inode_table_lo) |
|
|
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
|
|
- (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
|
|
|
+ (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
|
|
|
}
|
|
|
|
|
|
__u32 ext4_free_blks_count(struct super_block *sb,
|
|
@@ -98,7 +103,7 @@ __u32 ext4_free_blks_count(struct super_block *sb,
|
|
|
{
|
|
|
return le16_to_cpu(bg->bg_free_blocks_count_lo) |
|
|
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
|
|
- (__u32)le16_to_cpu(bg->bg_free_blocks_count_hi) << 16 : 0);
|
|
|
+ (__u32)le16_to_cpu(bg->bg_free_blocks_count_hi) << 16 : 0);
|
|
|
}
|
|
|
|
|
|
__u32 ext4_free_inodes_count(struct super_block *sb,
|
|
@@ -106,7 +111,7 @@ __u32 ext4_free_inodes_count(struct super_block *sb,
|
|
|
{
|
|
|
return le16_to_cpu(bg->bg_free_inodes_count_lo) |
|
|
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
|
|
- (__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0);
|
|
|
+ (__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0);
|
|
|
}
|
|
|
|
|
|
__u32 ext4_used_dirs_count(struct super_block *sb,
|
|
@@ -114,7 +119,7 @@ __u32 ext4_used_dirs_count(struct super_block *sb,
|
|
|
{
|
|
|
return le16_to_cpu(bg->bg_used_dirs_count_lo) |
|
|
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
|
|
- (__u32)le16_to_cpu(bg->bg_used_dirs_count_hi) << 16 : 0);
|
|
|
+ (__u32)le16_to_cpu(bg->bg_used_dirs_count_hi) << 16 : 0);
|
|
|
}
|
|
|
|
|
|
__u32 ext4_itable_unused_count(struct super_block *sb,
|
|
@@ -122,7 +127,7 @@ __u32 ext4_itable_unused_count(struct super_block *sb,
|
|
|
{
|
|
|
return le16_to_cpu(bg->bg_itable_unused_lo) |
|
|
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
|
|
- (__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0);
|
|
|
+ (__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0);
|
|
|
}
|
|
|
|
|
|
void ext4_block_bitmap_set(struct super_block *sb,
|
|
@@ -202,8 +207,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
|
|
|
journal = EXT4_SB(sb)->s_journal;
|
|
|
if (journal) {
|
|
|
if (is_journal_aborted(journal)) {
|
|
|
- ext4_abort(sb, __func__,
|
|
|
- "Detected aborted journal");
|
|
|
+ ext4_abort(sb, __func__, "Detected aborted journal");
|
|
|
return ERR_PTR(-EROFS);
|
|
|
}
|
|
|
return jbd2_journal_start(journal, nblocks);
|
|
@@ -302,10 +306,10 @@ static void ext4_handle_error(struct super_block *sb)
|
|
|
jbd2_journal_abort(journal, -EIO);
|
|
|
}
|
|
|
if (test_opt(sb, ERRORS_RO)) {
|
|
|
- printk(KERN_CRIT "Remounting filesystem read-only\n");
|
|
|
+ ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
|
|
|
sb->s_flags |= MS_RDONLY;
|
|
|
}
|
|
|
- ext4_commit_super(sb, es, 1);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
if (test_opt(sb, ERRORS_PANIC))
|
|
|
panic("EXT4-fs (device %s): panic forced after error\n",
|
|
|
sb->s_id);
|
|
@@ -395,8 +399,6 @@ void ext4_abort(struct super_block *sb, const char *function,
|
|
|
{
|
|
|
va_list args;
|
|
|
|
|
|
- printk(KERN_CRIT "ext4_abort called.\n");
|
|
|
-
|
|
|
va_start(args, fmt);
|
|
|
printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function);
|
|
|
vprintk(fmt, args);
|
|
@@ -409,7 +411,7 @@ void ext4_abort(struct super_block *sb, const char *function,
|
|
|
if (sb->s_flags & MS_RDONLY)
|
|
|
return;
|
|
|
|
|
|
- printk(KERN_CRIT "Remounting filesystem read-only\n");
|
|
|
+ ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
|
|
|
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
|
|
|
sb->s_flags |= MS_RDONLY;
|
|
|
EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;
|
|
@@ -417,6 +419,18 @@ void ext4_abort(struct super_block *sb, const char *function,
|
|
|
jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
|
|
|
}
|
|
|
|
|
|
+void ext4_msg (struct super_block * sb, const char *prefix,
|
|
|
+ const char *fmt, ...)
|
|
|
+{
|
|
|
+ va_list args;
|
|
|
+
|
|
|
+ va_start(args, fmt);
|
|
|
+ printk("%sEXT4-fs (%s): ", prefix, sb->s_id);
|
|
|
+ vprintk(fmt, args);
|
|
|
+ printk("\n");
|
|
|
+ va_end(args);
|
|
|
+}
|
|
|
+
|
|
|
void ext4_warning(struct super_block *sb, const char *function,
|
|
|
const char *fmt, ...)
|
|
|
{
|
|
@@ -431,7 +445,7 @@ void ext4_warning(struct super_block *sb, const char *function,
|
|
|
}
|
|
|
|
|
|
void ext4_grp_locked_error(struct super_block *sb, ext4_group_t grp,
|
|
|
- const char *function, const char *fmt, ...)
|
|
|
+ const char *function, const char *fmt, ...)
|
|
|
__releases(bitlock)
|
|
|
__acquires(bitlock)
|
|
|
{
|
|
@@ -447,7 +461,7 @@ __acquires(bitlock)
|
|
|
if (test_opt(sb, ERRORS_CONT)) {
|
|
|
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
|
|
|
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
|
|
|
- ext4_commit_super(sb, es, 0);
|
|
|
+ ext4_commit_super(sb, 0);
|
|
|
return;
|
|
|
}
|
|
|
ext4_unlock_group(sb, grp);
|
|
@@ -467,7 +481,6 @@ __acquires(bitlock)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
void ext4_update_dynamic_rev(struct super_block *sb)
|
|
|
{
|
|
|
struct ext4_super_block *es = EXT4_SB(sb)->s_es;
|
|
@@ -496,7 +509,7 @@ void ext4_update_dynamic_rev(struct super_block *sb)
|
|
|
/*
|
|
|
* Open the external journal device
|
|
|
*/
|
|
|
-static struct block_device *ext4_blkdev_get(dev_t dev)
|
|
|
+static struct block_device *ext4_blkdev_get(dev_t dev, struct super_block *sb)
|
|
|
{
|
|
|
struct block_device *bdev;
|
|
|
char b[BDEVNAME_SIZE];
|
|
@@ -507,7 +520,7 @@ static struct block_device *ext4_blkdev_get(dev_t dev)
|
|
|
return bdev;
|
|
|
|
|
|
fail:
|
|
|
- printk(KERN_ERR "EXT4-fs: failed to open journal device %s: %ld\n",
|
|
|
+ ext4_msg(sb, KERN_ERR, "failed to open journal device %s: %ld",
|
|
|
__bdevname(dev, b), PTR_ERR(bdev));
|
|
|
return NULL;
|
|
|
}
|
|
@@ -543,8 +556,8 @@ static void dump_orphan_list(struct super_block *sb, struct ext4_sb_info *sbi)
|
|
|
{
|
|
|
struct list_head *l;
|
|
|
|
|
|
- printk(KERN_ERR "sb orphan head is %d\n",
|
|
|
- le32_to_cpu(sbi->s_es->s_last_orphan));
|
|
|
+ ext4_msg(sb, KERN_ERR, "sb orphan head is %d",
|
|
|
+ le32_to_cpu(sbi->s_es->s_last_orphan));
|
|
|
|
|
|
printk(KERN_ERR "sb_info orphan list:\n");
|
|
|
list_for_each(l, &sbi->s_orphan) {
|
|
@@ -563,6 +576,7 @@ static void ext4_put_super(struct super_block *sb)
|
|
|
struct ext4_super_block *es = sbi->s_es;
|
|
|
int i, err;
|
|
|
|
|
|
+ ext4_release_system_zone(sb);
|
|
|
ext4_mb_release(sb);
|
|
|
ext4_ext_release(sb);
|
|
|
ext4_xattr_put_super(sb);
|
|
@@ -576,7 +590,7 @@ static void ext4_put_super(struct super_block *sb)
|
|
|
if (!(sb->s_flags & MS_RDONLY)) {
|
|
|
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
|
es->s_state = cpu_to_le16(sbi->s_mount_state);
|
|
|
- ext4_commit_super(sb, es, 1);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
}
|
|
|
if (sbi->s_proc) {
|
|
|
remove_proc_entry(sb->s_id, ext4_proc_root);
|
|
@@ -586,7 +600,10 @@ static void ext4_put_super(struct super_block *sb)
|
|
|
for (i = 0; i < sbi->s_gdb_count; i++)
|
|
|
brelse(sbi->s_group_desc[i]);
|
|
|
kfree(sbi->s_group_desc);
|
|
|
- kfree(sbi->s_flex_groups);
|
|
|
+ if (is_vmalloc_addr(sbi->s_flex_groups))
|
|
|
+ vfree(sbi->s_flex_groups);
|
|
|
+ else
|
|
|
+ kfree(sbi->s_flex_groups);
|
|
|
percpu_counter_destroy(&sbi->s_freeblocks_counter);
|
|
|
percpu_counter_destroy(&sbi->s_freeinodes_counter);
|
|
|
percpu_counter_destroy(&sbi->s_dirs_counter);
|
|
@@ -629,7 +646,6 @@ static void ext4_put_super(struct super_block *sb)
|
|
|
lock_kernel();
|
|
|
kfree(sbi->s_blockgroup_lock);
|
|
|
kfree(sbi);
|
|
|
- return;
|
|
|
}
|
|
|
|
|
|
static struct kmem_cache *ext4_inode_cachep;
|
|
@@ -644,6 +660,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
|
|
|
ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS);
|
|
|
if (!ei)
|
|
|
return NULL;
|
|
|
+
|
|
|
#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
|
|
ei->i_acl = EXT4_ACL_NOT_CACHED;
|
|
|
ei->i_default_acl = EXT4_ACL_NOT_CACHED;
|
|
@@ -664,14 +681,16 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
|
|
|
ei->i_allocated_meta_blocks = 0;
|
|
|
ei->i_delalloc_reserved_flag = 0;
|
|
|
spin_lock_init(&(ei->i_block_reservation_lock));
|
|
|
+
|
|
|
return &ei->vfs_inode;
|
|
|
}
|
|
|
|
|
|
static void ext4_destroy_inode(struct inode *inode)
|
|
|
{
|
|
|
if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
|
|
|
- printk("EXT4 Inode %p: orphan list check failed!\n",
|
|
|
- EXT4_I(inode));
|
|
|
+ ext4_msg(inode->i_sb, KERN_ERR,
|
|
|
+ "Inode %lu (%p): orphan list check failed!",
|
|
|
+ inode->i_ino, EXT4_I(inode));
|
|
|
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
|
EXT4_I(inode), sizeof(struct ext4_inode_info),
|
|
|
true);
|
|
@@ -870,12 +889,12 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
|
|
seq_puts(seq, ",noauto_da_alloc");
|
|
|
|
|
|
ext4_show_quota_options(seq, sb);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
static struct inode *ext4_nfs_get_inode(struct super_block *sb,
|
|
|
- u64 ino, u32 generation)
|
|
|
+ u64 ino, u32 generation)
|
|
|
{
|
|
|
struct inode *inode;
|
|
|
|
|
@@ -904,14 +923,14 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb,
|
|
|
}
|
|
|
|
|
|
static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid,
|
|
|
- int fh_len, int fh_type)
|
|
|
+ int fh_len, int fh_type)
|
|
|
{
|
|
|
return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
|
|
|
ext4_nfs_get_inode);
|
|
|
}
|
|
|
|
|
|
static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|
|
- int fh_len, int fh_type)
|
|
|
+ int fh_len, int fh_type)
|
|
|
{
|
|
|
return generic_fh_to_parent(sb, fid, fh_len, fh_type,
|
|
|
ext4_nfs_get_inode);
|
|
@@ -923,7 +942,8 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|
|
* which would prevent try_to_free_buffers() from freeing them, we must use
|
|
|
* jbd2 layer's try_to_free_buffers() function to release them.
|
|
|
*/
|
|
|
-static int bdev_try_to_free_page(struct super_block *sb, struct page *page, gfp_t wait)
|
|
|
+static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
|
|
|
+ gfp_t wait)
|
|
|
{
|
|
|
journal_t *journal = EXT4_SB(sb)->s_journal;
|
|
|
|
|
@@ -992,7 +1012,6 @@ static const struct super_operations ext4_sops = {
|
|
|
.dirty_inode = ext4_dirty_inode,
|
|
|
.delete_inode = ext4_delete_inode,
|
|
|
.put_super = ext4_put_super,
|
|
|
- .write_super = ext4_write_super,
|
|
|
.sync_fs = ext4_sync_fs,
|
|
|
.freeze_fs = ext4_freeze,
|
|
|
.unfreeze_fs = ext4_unfreeze,
|
|
@@ -1007,6 +1026,25 @@ static const struct super_operations ext4_sops = {
|
|
|
.bdev_try_to_free_page = bdev_try_to_free_page,
|
|
|
};
|
|
|
|
|
|
+static const struct super_operations ext4_nojournal_sops = {
|
|
|
+ .alloc_inode = ext4_alloc_inode,
|
|
|
+ .destroy_inode = ext4_destroy_inode,
|
|
|
+ .write_inode = ext4_write_inode,
|
|
|
+ .dirty_inode = ext4_dirty_inode,
|
|
|
+ .delete_inode = ext4_delete_inode,
|
|
|
+ .write_super = ext4_write_super,
|
|
|
+ .put_super = ext4_put_super,
|
|
|
+ .statfs = ext4_statfs,
|
|
|
+ .remount_fs = ext4_remount,
|
|
|
+ .clear_inode = ext4_clear_inode,
|
|
|
+ .show_options = ext4_show_options,
|
|
|
+#ifdef CONFIG_QUOTA
|
|
|
+ .quota_read = ext4_quota_read,
|
|
|
+ .quota_write = ext4_quota_write,
|
|
|
+#endif
|
|
|
+ .bdev_try_to_free_page = bdev_try_to_free_page,
|
|
|
+};
|
|
|
+
|
|
|
static const struct export_operations ext4_export_ops = {
|
|
|
.fh_to_dentry = ext4_fh_to_dentry,
|
|
|
.fh_to_parent = ext4_fh_to_parent,
|
|
@@ -1023,12 +1061,13 @@ enum {
|
|
|
Opt_journal_update, Opt_journal_dev,
|
|
|
Opt_journal_checksum, Opt_journal_async_commit,
|
|
|
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
|
|
|
- Opt_data_err_abort, Opt_data_err_ignore,
|
|
|
+ Opt_data_err_abort, Opt_data_err_ignore, Opt_mb_history_length,
|
|
|
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
|
|
|
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
|
|
|
Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
|
|
|
Opt_usrquota, Opt_grpquota, Opt_i_version,
|
|
|
Opt_stripe, Opt_delalloc, Opt_nodelalloc,
|
|
|
+ Opt_block_validity, Opt_noblock_validity,
|
|
|
Opt_inode_readahead_blks, Opt_journal_ioprio
|
|
|
};
|
|
|
|
|
@@ -1069,6 +1108,7 @@ static const match_table_t tokens = {
|
|
|
{Opt_data_writeback, "data=writeback"},
|
|
|
{Opt_data_err_abort, "data_err=abort"},
|
|
|
{Opt_data_err_ignore, "data_err=ignore"},
|
|
|
+ {Opt_mb_history_length, "mb_history_length=%u"},
|
|
|
{Opt_offusrjquota, "usrjquota="},
|
|
|
{Opt_usrjquota, "usrjquota=%s"},
|
|
|
{Opt_offgrpjquota, "grpjquota="},
|
|
@@ -1087,6 +1127,8 @@ static const match_table_t tokens = {
|
|
|
{Opt_resize, "resize"},
|
|
|
{Opt_delalloc, "delalloc"},
|
|
|
{Opt_nodelalloc, "nodelalloc"},
|
|
|
+ {Opt_block_validity, "block_validity"},
|
|
|
+ {Opt_noblock_validity, "noblock_validity"},
|
|
|
{Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
|
|
|
{Opt_journal_ioprio, "journal_ioprio=%u"},
|
|
|
{Opt_auto_da_alloc, "auto_da_alloc=%u"},
|
|
@@ -1102,8 +1144,9 @@ static ext4_fsblk_t get_sb_block(void **data)
|
|
|
|
|
|
if (!options || strncmp(options, "sb=", 3) != 0)
|
|
|
return 1; /* Default location */
|
|
|
+
|
|
|
options += 3;
|
|
|
- /*todo: use simple_strtoll with >32bit ext4 */
|
|
|
+ /* TODO: use simple_strtoll with >32bit ext4 */
|
|
|
sb_block = simple_strtoul(options, &options, 0);
|
|
|
if (*options && *options != ',') {
|
|
|
printk(KERN_ERR "EXT4-fs: Invalid sb specification: %s\n",
|
|
@@ -1113,6 +1156,7 @@ static ext4_fsblk_t get_sb_block(void **data)
|
|
|
if (*options == ',')
|
|
|
options++;
|
|
|
*data = (void *) options;
|
|
|
+
|
|
|
return sb_block;
|
|
|
}
|
|
|
|
|
@@ -1206,8 +1250,7 @@ static int parse_options(char *options, struct super_block *sb,
|
|
|
#else
|
|
|
case Opt_user_xattr:
|
|
|
case Opt_nouser_xattr:
|
|
|
- printk(KERN_ERR "EXT4 (no)user_xattr options "
|
|
|
- "not supported\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "(no)user_xattr options not supported");
|
|
|
break;
|
|
|
#endif
|
|
|
#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
|
@@ -1220,8 +1263,7 @@ static int parse_options(char *options, struct super_block *sb,
|
|
|
#else
|
|
|
case Opt_acl:
|
|
|
case Opt_noacl:
|
|
|
- printk(KERN_ERR "EXT4 (no)acl options "
|
|
|
- "not supported\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "(no)acl options not supported");
|
|
|
break;
|
|
|
#endif
|
|
|
case Opt_journal_update:
|
|
@@ -1231,16 +1273,16 @@ static int parse_options(char *options, struct super_block *sb,
|
|
|
user to specify an existing inode to be the
|
|
|
journal file. */
|
|
|
if (is_remount) {
|
|
|
- printk(KERN_ERR "EXT4-fs: cannot specify "
|
|
|
- "journal on remount\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Cannot specify journal on remount");
|
|
|
return 0;
|
|
|
}
|
|
|
set_opt(sbi->s_mount_opt, UPDATE_JOURNAL);
|
|
|
break;
|
|
|
case Opt_journal_dev:
|
|
|
if (is_remount) {
|
|
|
- printk(KERN_ERR "EXT4-fs: cannot specify "
|
|
|
- "journal on remount\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Cannot specify journal on remount");
|
|
|
return 0;
|
|
|
}
|
|
|
if (match_int(&args[0], &option))
|
|
@@ -1294,9 +1336,8 @@ static int parse_options(char *options, struct super_block *sb,
|
|
|
if (is_remount) {
|
|
|
if ((sbi->s_mount_opt & EXT4_MOUNT_DATA_FLAGS)
|
|
|
!= data_opt) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: cannot change data "
|
|
|
- "mode on remount\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Cannot change data mode on remount");
|
|
|
return 0;
|
|
|
}
|
|
|
} else {
|
|
@@ -1310,6 +1351,13 @@ static int parse_options(char *options, struct super_block *sb,
|
|
|
case Opt_data_err_ignore:
|
|
|
clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
|
|
|
break;
|
|
|
+ case Opt_mb_history_length:
|
|
|
+ if (match_int(&args[0], &option))
|
|
|
+ return 0;
|
|
|
+ if (option < 0)
|
|
|
+ return 0;
|
|
|
+ sbi->s_mb_history_max = option;
|
|
|
+ break;
|
|
|
#ifdef CONFIG_QUOTA
|
|
|
case Opt_usrjquota:
|
|
|
qtype = USRQUOTA;
|
|
@@ -1319,31 +1367,31 @@ static int parse_options(char *options, struct super_block *sb,
|
|
|
set_qf_name:
|
|
|
if (sb_any_quota_loaded(sb) &&
|
|
|
!sbi->s_qf_names[qtype]) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: Cannot change journaled "
|
|
|
- "quota options when quota turned on.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Cannot change journaled "
|
|
|
+ "quota options when quota turned on");
|
|
|
return 0;
|
|
|
}
|
|
|
qname = match_strdup(&args[0]);
|
|
|
if (!qname) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: not enough memory for "
|
|
|
- "storing quotafile name.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Not enough memory for "
|
|
|
+ "storing quotafile name");
|
|
|
return 0;
|
|
|
}
|
|
|
if (sbi->s_qf_names[qtype] &&
|
|
|
strcmp(sbi->s_qf_names[qtype], qname)) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: %s quota file already "
|
|
|
- "specified.\n", QTYPE2NAME(qtype));
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "%s quota file already "
|
|
|
+ "specified", QTYPE2NAME(qtype));
|
|
|
kfree(qname);
|
|
|
return 0;
|
|
|
}
|
|
|
sbi->s_qf_names[qtype] = qname;
|
|
|
if (strchr(sbi->s_qf_names[qtype], '/')) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: quotafile must be on "
|
|
|
- "filesystem root.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "quotafile must be on "
|
|
|
+ "filesystem root");
|
|
|
kfree(sbi->s_qf_names[qtype]);
|
|
|
sbi->s_qf_names[qtype] = NULL;
|
|
|
return 0;
|
|
@@ -1358,9 +1406,9 @@ set_qf_name:
|
|
|
clear_qf_name:
|
|
|
if (sb_any_quota_loaded(sb) &&
|
|
|
sbi->s_qf_names[qtype]) {
|
|
|
- printk(KERN_ERR "EXT4-fs: Cannot change "
|
|
|
+ ext4_msg(sb, KERN_ERR, "Cannot change "
|
|
|
"journaled quota options when "
|
|
|
- "quota turned on.\n");
|
|
|
+ "quota turned on");
|
|
|
return 0;
|
|
|
}
|
|
|
/*
|
|
@@ -1377,9 +1425,9 @@ clear_qf_name:
|
|
|
set_qf_format:
|
|
|
if (sb_any_quota_loaded(sb) &&
|
|
|
sbi->s_jquota_fmt != qfmt) {
|
|
|
- printk(KERN_ERR "EXT4-fs: Cannot change "
|
|
|
+ ext4_msg(sb, KERN_ERR, "Cannot change "
|
|
|
"journaled quota options when "
|
|
|
- "quota turned on.\n");
|
|
|
+ "quota turned on");
|
|
|
return 0;
|
|
|
}
|
|
|
sbi->s_jquota_fmt = qfmt;
|
|
@@ -1395,8 +1443,8 @@ set_qf_format:
|
|
|
break;
|
|
|
case Opt_noquota:
|
|
|
if (sb_any_quota_loaded(sb)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: Cannot change quota "
|
|
|
- "options when quota turned on.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "Cannot change quota "
|
|
|
+ "options when quota turned on");
|
|
|
return 0;
|
|
|
}
|
|
|
clear_opt(sbi->s_mount_opt, QUOTA);
|
|
@@ -1407,8 +1455,8 @@ set_qf_format:
|
|
|
case Opt_quota:
|
|
|
case Opt_usrquota:
|
|
|
case Opt_grpquota:
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: quota options not supported.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "quota options not supported");
|
|
|
break;
|
|
|
case Opt_usrjquota:
|
|
|
case Opt_grpjquota:
|
|
@@ -1416,9 +1464,8 @@ set_qf_format:
|
|
|
case Opt_offgrpjquota:
|
|
|
case Opt_jqfmt_vfsold:
|
|
|
case Opt_jqfmt_vfsv0:
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: journaled quota options not "
|
|
|
- "supported.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "journaled quota options not supported");
|
|
|
break;
|
|
|
case Opt_noquota:
|
|
|
break;
|
|
@@ -1443,8 +1490,9 @@ set_qf_format:
|
|
|
break;
|
|
|
case Opt_resize:
|
|
|
if (!is_remount) {
|
|
|
- printk("EXT4-fs: resize option only available "
|
|
|
- "for remount\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "resize option only available "
|
|
|
+ "for remount");
|
|
|
return 0;
|
|
|
}
|
|
|
if (match_int(&args[0], &option) != 0)
|
|
@@ -1474,14 +1522,21 @@ set_qf_format:
|
|
|
case Opt_delalloc:
|
|
|
set_opt(sbi->s_mount_opt, DELALLOC);
|
|
|
break;
|
|
|
+ case Opt_block_validity:
|
|
|
+ set_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
|
|
|
+ break;
|
|
|
+ case Opt_noblock_validity:
|
|
|
+ clear_opt(sbi->s_mount_opt, BLOCK_VALIDITY);
|
|
|
+ break;
|
|
|
case Opt_inode_readahead_blks:
|
|
|
if (match_int(&args[0], &option))
|
|
|
return 0;
|
|
|
if (option < 0 || option > (1 << 30))
|
|
|
return 0;
|
|
|
- if (option & (option - 1)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: inode_readahead_blks"
|
|
|
- " must be a power of 2\n");
|
|
|
+ if (!is_power_of_2(option)) {
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "EXT4-fs: inode_readahead_blks"
|
|
|
+ " must be a power of 2");
|
|
|
return 0;
|
|
|
}
|
|
|
sbi->s_inode_readahead_blks = option;
|
|
@@ -1508,9 +1563,9 @@ set_qf_format:
|
|
|
set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
|
|
|
break;
|
|
|
default:
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: Unrecognized mount option \"%s\" "
|
|
|
- "or missing value\n", p);
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Unrecognized mount option \"%s\" "
|
|
|
+ "or missing value", p);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
@@ -1528,21 +1583,21 @@ set_qf_format:
|
|
|
(sbi->s_mount_opt & EXT4_MOUNT_GRPQUOTA)) ||
|
|
|
(sbi->s_qf_names[GRPQUOTA] &&
|
|
|
(sbi->s_mount_opt & EXT4_MOUNT_USRQUOTA))) {
|
|
|
- printk(KERN_ERR "EXT4-fs: old and new quota "
|
|
|
- "format mixing.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "old and new quota "
|
|
|
+ "format mixing");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
if (!sbi->s_jquota_fmt) {
|
|
|
- printk(KERN_ERR "EXT4-fs: journaled quota format "
|
|
|
- "not specified.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "journaled quota format "
|
|
|
+ "not specified");
|
|
|
return 0;
|
|
|
}
|
|
|
} else {
|
|
|
if (sbi->s_jquota_fmt) {
|
|
|
- printk(KERN_ERR "EXT4-fs: journaled quota format "
|
|
|
+ ext4_msg(sb, KERN_ERR, "journaled quota format "
|
|
|
"specified with no journaling "
|
|
|
- "enabled.\n");
|
|
|
+ "enabled");
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
@@ -1557,32 +1612,32 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
|
|
|
int res = 0;
|
|
|
|
|
|
if (le32_to_cpu(es->s_rev_level) > EXT4_MAX_SUPP_REV) {
|
|
|
- printk(KERN_ERR "EXT4-fs warning: revision level too high, "
|
|
|
- "forcing read-only mode\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "revision level too high, "
|
|
|
+ "forcing read-only mode");
|
|
|
res = MS_RDONLY;
|
|
|
}
|
|
|
if (read_only)
|
|
|
return res;
|
|
|
if (!(sbi->s_mount_state & EXT4_VALID_FS))
|
|
|
- printk(KERN_WARNING "EXT4-fs warning: mounting unchecked fs, "
|
|
|
- "running e2fsck is recommended\n");
|
|
|
+ ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, "
|
|
|
+ "running e2fsck is recommended");
|
|
|
else if ((sbi->s_mount_state & EXT4_ERROR_FS))
|
|
|
- printk(KERN_WARNING
|
|
|
- "EXT4-fs warning: mounting fs with errors, "
|
|
|
- "running e2fsck is recommended\n");
|
|
|
+ ext4_msg(sb, KERN_WARNING,
|
|
|
+ "warning: mounting fs with errors, "
|
|
|
+ "running e2fsck is recommended");
|
|
|
else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
|
|
|
le16_to_cpu(es->s_mnt_count) >=
|
|
|
(unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
|
|
|
- printk(KERN_WARNING
|
|
|
- "EXT4-fs warning: maximal mount count reached, "
|
|
|
- "running e2fsck is recommended\n");
|
|
|
+ ext4_msg(sb, KERN_WARNING,
|
|
|
+ "warning: maximal mount count reached, "
|
|
|
+ "running e2fsck is recommended");
|
|
|
else if (le32_to_cpu(es->s_checkinterval) &&
|
|
|
(le32_to_cpu(es->s_lastcheck) +
|
|
|
le32_to_cpu(es->s_checkinterval) <= get_seconds()))
|
|
|
- printk(KERN_WARNING
|
|
|
- "EXT4-fs warning: checktime reached, "
|
|
|
- "running e2fsck is recommended\n");
|
|
|
- if (!sbi->s_journal)
|
|
|
+ ext4_msg(sb, KERN_WARNING,
|
|
|
+ "warning: checktime reached, "
|
|
|
+ "running e2fsck is recommended");
|
|
|
+ if (!sbi->s_journal)
|
|
|
es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
|
|
|
if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
|
|
|
es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
|
|
@@ -1592,7 +1647,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
|
|
|
if (sbi->s_journal)
|
|
|
EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
|
|
|
|
- ext4_commit_super(sb, es, 1);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
if (test_opt(sb, DEBUG))
|
|
|
printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
|
|
|
"bpg=%lu, ipg=%lu, mo=%04lx]\n",
|
|
@@ -1603,11 +1658,11 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
|
|
|
sbi->s_mount_opt);
|
|
|
|
|
|
if (EXT4_SB(sb)->s_journal) {
|
|
|
- printk(KERN_INFO "EXT4 FS on %s, %s journal on %s\n",
|
|
|
- sb->s_id, EXT4_SB(sb)->s_journal->j_inode ? "internal" :
|
|
|
+ ext4_msg(sb, KERN_INFO, "%s journal on %s",
|
|
|
+ EXT4_SB(sb)->s_journal->j_inode ? "internal" :
|
|
|
"external", EXT4_SB(sb)->s_journal->j_devname);
|
|
|
} else {
|
|
|
- printk(KERN_INFO "EXT4 FS on %s, no journal\n", sb->s_id);
|
|
|
+ ext4_msg(sb, KERN_INFO, "no journal");
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
@@ -1616,10 +1671,10 @@ static int ext4_fill_flex_info(struct super_block *sb)
|
|
|
{
|
|
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
|
|
struct ext4_group_desc *gdp = NULL;
|
|
|
- struct buffer_head *bh;
|
|
|
ext4_group_t flex_group_count;
|
|
|
ext4_group_t flex_group;
|
|
|
int groups_per_flex = 0;
|
|
|
+ size_t size;
|
|
|
int i;
|
|
|
|
|
|
if (!sbi->s_es->s_log_groups_per_flex) {
|
|
@@ -1634,16 +1689,21 @@ static int ext4_fill_flex_info(struct super_block *sb)
|
|
|
flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
|
|
|
((le16_to_cpu(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 *
|
|
|
- sizeof(struct flex_groups), GFP_KERNEL);
|
|
|
+ size = flex_group_count * sizeof(struct flex_groups);
|
|
|
+ sbi->s_flex_groups = kzalloc(size, GFP_KERNEL);
|
|
|
+ if (sbi->s_flex_groups == NULL) {
|
|
|
+ sbi->s_flex_groups = vmalloc(size);
|
|
|
+ if (sbi->s_flex_groups)
|
|
|
+ memset(sbi->s_flex_groups, 0, size);
|
|
|
+ }
|
|
|
if (sbi->s_flex_groups == NULL) {
|
|
|
- printk(KERN_ERR "EXT4-fs: not enough memory for "
|
|
|
- "%u flex groups\n", flex_group_count);
|
|
|
+ ext4_msg(sb, KERN_ERR, "not enough memory for "
|
|
|
+ "%u flex groups", flex_group_count);
|
|
|
goto failed;
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < sbi->s_groups_count; i++) {
|
|
|
- gdp = ext4_get_group_desc(sb, i, &bh);
|
|
|
+ gdp = ext4_get_group_desc(sb, i, NULL);
|
|
|
|
|
|
flex_group = ext4_flex_group(sbi, i);
|
|
|
atomic_set(&sbi->s_flex_groups[flex_group].free_inodes,
|
|
@@ -1724,44 +1784,44 @@ static int ext4_check_descriptors(struct super_block *sb)
|
|
|
|
|
|
block_bitmap = ext4_block_bitmap(sb, gdp);
|
|
|
if (block_bitmap < first_block || block_bitmap > last_block) {
|
|
|
- printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
|
|
+ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
|
|
|
"Block bitmap for group %u not in group "
|
|
|
- "(block %llu)!\n", i, block_bitmap);
|
|
|
+ "(block %llu)!", i, block_bitmap);
|
|
|
return 0;
|
|
|
}
|
|
|
inode_bitmap = ext4_inode_bitmap(sb, gdp);
|
|
|
if (inode_bitmap < first_block || inode_bitmap > last_block) {
|
|
|
- printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
|
|
+ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
|
|
|
"Inode bitmap for group %u not in group "
|
|
|
- "(block %llu)!\n", i, inode_bitmap);
|
|
|
+ "(block %llu)!", i, inode_bitmap);
|
|
|
return 0;
|
|
|
}
|
|
|
inode_table = ext4_inode_table(sb, gdp);
|
|
|
if (inode_table < first_block ||
|
|
|
inode_table + sbi->s_itb_per_group - 1 > last_block) {
|
|
|
- printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
|
|
+ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
|
|
|
"Inode table for group %u not in group "
|
|
|
- "(block %llu)!\n", i, inode_table);
|
|
|
+ "(block %llu)!", i, inode_table);
|
|
|
return 0;
|
|
|
}
|
|
|
- spin_lock(sb_bgl_lock(sbi, i));
|
|
|
+ ext4_lock_group(sb, i);
|
|
|
if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
|
|
- "Checksum for group %u failed (%u!=%u)\n",
|
|
|
- i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
|
|
- gdp)), le16_to_cpu(gdp->bg_checksum));
|
|
|
+ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
|
|
|
+ "Checksum for group %u failed (%u!=%u)",
|
|
|
+ i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
|
|
+ gdp)), le16_to_cpu(gdp->bg_checksum));
|
|
|
if (!(sb->s_flags & MS_RDONLY)) {
|
|
|
- spin_unlock(sb_bgl_lock(sbi, i));
|
|
|
+ ext4_unlock_group(sb, i);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
- spin_unlock(sb_bgl_lock(sbi, i));
|
|
|
+ ext4_unlock_group(sb, i);
|
|
|
if (!flexbg_flag)
|
|
|
first_block += EXT4_BLOCKS_PER_GROUP(sb);
|
|
|
}
|
|
|
|
|
|
ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
|
|
|
- sbi->s_es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
|
|
|
+ sbi->s_es->s_free_inodes_count =cpu_to_le32(ext4_count_free_inodes(sb));
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
@@ -1796,8 +1856,8 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
|
|
}
|
|
|
|
|
|
if (bdev_read_only(sb->s_bdev)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: write access "
|
|
|
- "unavailable, skipping orphan cleanup.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "write access "
|
|
|
+ "unavailable, skipping orphan cleanup");
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -1811,8 +1871,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
|
|
}
|
|
|
|
|
|
if (s_flags & MS_RDONLY) {
|
|
|
- printk(KERN_INFO "EXT4-fs: %s: orphan cleanup on readonly fs\n",
|
|
|
- sb->s_id);
|
|
|
+ ext4_msg(sb, KERN_INFO, "orphan cleanup on readonly fs");
|
|
|
sb->s_flags &= ~MS_RDONLY;
|
|
|
}
|
|
|
#ifdef CONFIG_QUOTA
|
|
@@ -1823,9 +1882,9 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
|
|
if (EXT4_SB(sb)->s_qf_names[i]) {
|
|
|
int ret = ext4_quota_on_mount(sb, i);
|
|
|
if (ret < 0)
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: Cannot turn on journaled "
|
|
|
- "quota: error %d\n", ret);
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Cannot turn on journaled "
|
|
|
+ "quota: error %d", ret);
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
@@ -1842,16 +1901,16 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
|
|
list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
|
|
|
vfs_dq_init(inode);
|
|
|
if (inode->i_nlink) {
|
|
|
- printk(KERN_DEBUG
|
|
|
- "%s: truncating inode %lu to %lld bytes\n",
|
|
|
+ ext4_msg(sb, KERN_DEBUG,
|
|
|
+ "%s: truncating inode %lu to %lld bytes",
|
|
|
__func__, inode->i_ino, inode->i_size);
|
|
|
jbd_debug(2, "truncating inode %lu to %lld bytes\n",
|
|
|
inode->i_ino, inode->i_size);
|
|
|
ext4_truncate(inode);
|
|
|
nr_truncates++;
|
|
|
} else {
|
|
|
- printk(KERN_DEBUG
|
|
|
- "%s: deleting unreferenced inode %lu\n",
|
|
|
+ ext4_msg(sb, KERN_DEBUG,
|
|
|
+ "%s: deleting unreferenced inode %lu",
|
|
|
__func__, inode->i_ino);
|
|
|
jbd_debug(2, "deleting unreferenced inode %lu\n",
|
|
|
inode->i_ino);
|
|
@@ -1863,11 +1922,11 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
|
|
#define PLURAL(x) (x), ((x) == 1) ? "" : "s"
|
|
|
|
|
|
if (nr_orphans)
|
|
|
- printk(KERN_INFO "EXT4-fs: %s: %d orphan inode%s deleted\n",
|
|
|
- sb->s_id, PLURAL(nr_orphans));
|
|
|
+ ext4_msg(sb, KERN_INFO, "%d orphan inode%s deleted",
|
|
|
+ PLURAL(nr_orphans));
|
|
|
if (nr_truncates)
|
|
|
- printk(KERN_INFO "EXT4-fs: %s: %d truncate%s cleaned up\n",
|
|
|
- sb->s_id, PLURAL(nr_truncates));
|
|
|
+ ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
|
|
|
+ PLURAL(nr_truncates));
|
|
|
#ifdef CONFIG_QUOTA
|
|
|
/* Turn quotas off */
|
|
|
for (i = 0; i < MAXQUOTAS; i++) {
|
|
@@ -1877,6 +1936,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
|
|
#endif
|
|
|
sb->s_flags = s_flags; /* Restore MS_RDONLY status */
|
|
|
}
|
|
|
+
|
|
|
/*
|
|
|
* Maximal extent format file size.
|
|
|
* Resulting logical blkno at s_maxbytes must fit in our on-disk
|
|
@@ -1927,19 +1987,19 @@ static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
|
|
|
loff_t res = EXT4_NDIR_BLOCKS;
|
|
|
int meta_blocks;
|
|
|
loff_t upper_limit;
|
|
|
- /* This is calculated to be the largest file size for a
|
|
|
- * dense, bitmapped file such that the total number of
|
|
|
- * sectors in the file, including data and all indirect blocks,
|
|
|
- * does not exceed 2^48 -1
|
|
|
- * __u32 i_blocks_lo and _u16 i_blocks_high representing the
|
|
|
- * total number of 512 bytes blocks of the file
|
|
|
+ /* This is calculated to be the largest file size for a dense, block
|
|
|
+ * mapped file such that the file's total number of 512-byte sectors,
|
|
|
+ * including data and all indirect blocks, does not exceed (2^48 - 1).
|
|
|
+ *
|
|
|
+ * __u32 i_blocks_lo and _u16 i_blocks_high represent the total
|
|
|
+ * number of 512-byte sectors of the file.
|
|
|
*/
|
|
|
|
|
|
if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
|
|
|
/*
|
|
|
- * !has_huge_files or CONFIG_LBD is not enabled
|
|
|
- * implies the inode i_block represent total blocks in
|
|
|
- * 512 bytes 32 == size of vfs inode i_blocks * 8
|
|
|
+ * !has_huge_files or CONFIG_LBD not enabled implies that
|
|
|
+ * the inode i_block field represents total file blocks in
|
|
|
+ * 2^32 512-byte sectors == size of vfs inode i_blocks * 8
|
|
|
*/
|
|
|
upper_limit = (1LL << 32) - 1;
|
|
|
|
|
@@ -1981,7 +2041,7 @@ static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
|
|
|
}
|
|
|
|
|
|
static ext4_fsblk_t descriptor_loc(struct super_block *sb,
|
|
|
- ext4_fsblk_t logical_sb_block, int nr)
|
|
|
+ ext4_fsblk_t logical_sb_block, int nr)
|
|
|
{
|
|
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
|
|
ext4_group_t bg, first_meta_bg;
|
|
@@ -1995,6 +2055,7 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb,
|
|
|
bg = sbi->s_desc_per_block * nr;
|
|
|
if (ext4_bg_has_super(sb, bg))
|
|
|
has_super = 1;
|
|
|
+
|
|
|
return (has_super + ext4_group_first_block_no(sb, bg));
|
|
|
}
|
|
|
|
|
@@ -2091,8 +2152,7 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
|
|
|
if (parse_strtoul(buf, 0x40000000, &t))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- /* inode_readahead_blks must be a power of 2 */
|
|
|
- if (t & (t-1))
|
|
|
+ if (!is_power_of_2(t))
|
|
|
return -EINVAL;
|
|
|
|
|
|
sbi->s_inode_readahead_blks = t;
|
|
@@ -2100,7 +2160,7 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
|
|
|
}
|
|
|
|
|
|
static ssize_t sbi_ui_show(struct ext4_attr *a,
|
|
|
- struct ext4_sb_info *sbi, char *buf)
|
|
|
+ struct ext4_sb_info *sbi, char *buf)
|
|
|
{
|
|
|
unsigned int *ui = (unsigned int *) (((char *) sbi) + a->offset);
|
|
|
|
|
@@ -2205,7 +2265,6 @@ static struct kobj_type ext4_ktype = {
|
|
|
static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
__releases(kernel_lock)
|
|
|
__acquires(kernel_lock)
|
|
|
-
|
|
|
{
|
|
|
struct buffer_head *bh;
|
|
|
struct ext4_super_block *es = NULL;
|
|
@@ -2256,7 +2315,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
|
|
|
blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE);
|
|
|
if (!blocksize) {
|
|
|
- printk(KERN_ERR "EXT4-fs: unable to set blocksize\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "unable to set blocksize");
|
|
|
goto out_fail;
|
|
|
}
|
|
|
|
|
@@ -2272,7 +2331,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
}
|
|
|
|
|
|
if (!(bh = sb_bread(sb, logical_sb_block))) {
|
|
|
- printk(KERN_ERR "EXT4-fs: unable to read superblock\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "unable to read superblock");
|
|
|
goto out_fail;
|
|
|
}
|
|
|
/*
|
|
@@ -2321,6 +2380,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ;
|
|
|
sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
|
|
|
sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
|
|
|
+ sbi->s_mb_history_max = default_mb_history_length;
|
|
|
|
|
|
set_opt(sbi->s_mount_opt, BARRIER);
|
|
|
|
|
@@ -2330,7 +2390,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
*/
|
|
|
set_opt(sbi->s_mount_opt, DELALLOC);
|
|
|
|
|
|
-
|
|
|
if (!parse_options((char *) data, sb, &journal_devnum,
|
|
|
&journal_ioprio, NULL, 0))
|
|
|
goto failed_mount;
|
|
@@ -2342,9 +2401,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
(EXT4_HAS_COMPAT_FEATURE(sb, ~0U) ||
|
|
|
EXT4_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
|
|
|
EXT4_HAS_INCOMPAT_FEATURE(sb, ~0U)))
|
|
|
- printk(KERN_WARNING
|
|
|
- "EXT4-fs warning: feature flags set on rev 0 fs, "
|
|
|
- "running e2fsck is recommended\n");
|
|
|
+ ext4_msg(sb, KERN_WARNING,
|
|
|
+ "feature flags set on rev 0 fs, "
|
|
|
+ "running e2fsck is recommended");
|
|
|
|
|
|
/*
|
|
|
* Check feature flags regardless of the revision level, since we
|
|
@@ -2353,16 +2412,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
*/
|
|
|
features = EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT4_FEATURE_INCOMPAT_SUPP);
|
|
|
if (features) {
|
|
|
- printk(KERN_ERR "EXT4-fs: %s: couldn't mount because of "
|
|
|
- "unsupported optional features (%x).\n", sb->s_id,
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Couldn't mount because of "
|
|
|
+ "unsupported optional features (%x)",
|
|
|
(le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_incompat) &
|
|
|
~EXT4_FEATURE_INCOMPAT_SUPP));
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
features = EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP);
|
|
|
if (!(sb->s_flags & MS_RDONLY) && features) {
|
|
|
- printk(KERN_ERR "EXT4-fs: %s: couldn't mount RDWR because of "
|
|
|
- "unsupported optional features (%x).\n", sb->s_id,
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Couldn't mount RDWR because of "
|
|
|
+ "unsupported optional features (%x)",
|
|
|
(le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_ro_compat) &
|
|
|
~EXT4_FEATURE_RO_COMPAT_SUPP));
|
|
|
goto failed_mount;
|
|
@@ -2376,9 +2437,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
*/
|
|
|
if (sizeof(root->i_blocks) < sizeof(u64) &&
|
|
|
!(sb->s_flags & MS_RDONLY)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: %s: Filesystem with huge "
|
|
|
+ ext4_msg(sb, KERN_ERR, "Filesystem with huge "
|
|
|
"files cannot be mounted read-write "
|
|
|
- "without CONFIG_LBD.\n", sb->s_id);
|
|
|
+ "without CONFIG_LBD");
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
}
|
|
@@ -2386,17 +2447,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
|
|
|
if (blocksize < EXT4_MIN_BLOCK_SIZE ||
|
|
|
blocksize > EXT4_MAX_BLOCK_SIZE) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: Unsupported filesystem blocksize %d on %s.\n",
|
|
|
- blocksize, sb->s_id);
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Unsupported filesystem blocksize %d", blocksize);
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
|
|
|
if (sb->s_blocksize != blocksize) {
|
|
|
-
|
|
|
/* Validate the filesystem blocksize */
|
|
|
if (!sb_set_blocksize(sb, blocksize)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: bad block size %d.\n",
|
|
|
+ ext4_msg(sb, KERN_ERR, "bad block size %d",
|
|
|
blocksize);
|
|
|
goto failed_mount;
|
|
|
}
|
|
@@ -2406,15 +2465,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
offset = do_div(logical_sb_block, blocksize);
|
|
|
bh = sb_bread(sb, logical_sb_block);
|
|
|
if (!bh) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: Can't read superblock on 2nd try.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Can't read superblock on 2nd try");
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
es = (struct ext4_super_block *)(((char *)bh->b_data) + offset);
|
|
|
sbi->s_es = es;
|
|
|
if (es->s_magic != cpu_to_le16(EXT4_SUPER_MAGIC)) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: Magic mismatch, very weird !\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "Magic mismatch, very weird!");
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
}
|
|
@@ -2432,30 +2491,33 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
|
|
|
(!is_power_of_2(sbi->s_inode_size)) ||
|
|
|
(sbi->s_inode_size > blocksize)) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: unsupported inode size: %d\n",
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "unsupported inode size: %d",
|
|
|
sbi->s_inode_size);
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)
|
|
|
sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2);
|
|
|
}
|
|
|
+
|
|
|
sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
|
|
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
|
|
|
if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
|
|
|
sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
|
|
|
!is_power_of_2(sbi->s_desc_size)) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: unsupported descriptor size %lu\n",
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "unsupported descriptor size %lu",
|
|
|
sbi->s_desc_size);
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
} else
|
|
|
sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
|
|
|
+
|
|
|
sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
|
|
|
sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
|
|
|
if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0)
|
|
|
goto cantfind_ext4;
|
|
|
+
|
|
|
sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
|
|
|
if (sbi->s_inodes_per_block == 0)
|
|
|
goto cantfind_ext4;
|
|
@@ -2466,6 +2528,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
sbi->s_mount_state = le16_to_cpu(es->s_state);
|
|
|
sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
|
|
|
sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
|
|
|
+
|
|
|
for (i = 0; i < 4; i++)
|
|
|
sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
|
|
|
sbi->s_def_hash_version = es->s_def_hash_version;
|
|
@@ -2483,25 +2546,24 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
}
|
|
|
|
|
|
if (sbi->s_blocks_per_group > blocksize * 8) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: #blocks per group too big: %lu\n",
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "#blocks per group too big: %lu",
|
|
|
sbi->s_blocks_per_group);
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
if (sbi->s_inodes_per_group > blocksize * 8) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: #inodes per group too big: %lu\n",
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "#inodes per group too big: %lu",
|
|
|
sbi->s_inodes_per_group);
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
|
|
|
if (ext4_blocks_count(es) >
|
|
|
(sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: filesystem on %s:"
|
|
|
- " too large to mount safely\n", sb->s_id);
|
|
|
+ ext4_msg(sb, KERN_ERR, "filesystem"
|
|
|
+ " too large to mount safely");
|
|
|
if (sizeof(sector_t) < 8)
|
|
|
- printk(KERN_WARNING "EXT4-fs: CONFIG_LBD not "
|
|
|
- "enabled\n");
|
|
|
+ ext4_msg(sb, KERN_WARNING, "CONFIG_LBD not enabled");
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
|
|
@@ -2511,21 +2573,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
/* check blocks count against device size */
|
|
|
blocks_count = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
|
|
|
if (blocks_count && ext4_blocks_count(es) > blocks_count) {
|
|
|
- printk(KERN_WARNING "EXT4-fs: bad geometry: block count %llu "
|
|
|
- "exceeds size of device (%llu blocks)\n",
|
|
|
+ ext4_msg(sb, KERN_WARNING, "bad geometry: block count %llu "
|
|
|
+ "exceeds size of device (%llu blocks)",
|
|
|
ext4_blocks_count(es), blocks_count);
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * It makes no sense for the first data block to be beyond the end
|
|
|
- * of the filesystem.
|
|
|
- */
|
|
|
- if (le32_to_cpu(es->s_first_data_block) >= ext4_blocks_count(es)) {
|
|
|
- printk(KERN_WARNING "EXT4-fs: bad geometry: first data"
|
|
|
- "block %u is beyond end of filesystem (%llu)\n",
|
|
|
- le32_to_cpu(es->s_first_data_block),
|
|
|
- ext4_blocks_count(es));
|
|
|
+ /*
|
|
|
+ * It makes no sense for the first data block to be beyond the end
|
|
|
+ * of the filesystem.
|
|
|
+ */
|
|
|
+ if (le32_to_cpu(es->s_first_data_block) >= ext4_blocks_count(es)) {
|
|
|
+ ext4_msg(sb, KERN_WARNING, "bad geometry: first data"
|
|
|
+ "block %u is beyond end of filesystem (%llu)",
|
|
|
+ le32_to_cpu(es->s_first_data_block),
|
|
|
+ ext4_blocks_count(es));
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
blocks_count = (ext4_blocks_count(es) -
|
|
@@ -2533,9 +2595,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
EXT4_BLOCKS_PER_GROUP(sb) - 1);
|
|
|
do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb));
|
|
|
if (blocks_count > ((uint64_t)1<<32) - EXT4_DESC_PER_BLOCK(sb)) {
|
|
|
- printk(KERN_WARNING "EXT4-fs: groups count too large: %u "
|
|
|
+ ext4_msg(sb, KERN_WARNING, "groups count too large: %u "
|
|
|
"(block count %llu, first data block %u, "
|
|
|
- "blocks per group %lu)\n", sbi->s_groups_count,
|
|
|
+ "blocks per group %lu)", sbi->s_groups_count,
|
|
|
ext4_blocks_count(es),
|
|
|
le32_to_cpu(es->s_first_data_block),
|
|
|
EXT4_BLOCKS_PER_GROUP(sb));
|
|
@@ -2547,7 +2609,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
sbi->s_group_desc = kmalloc(db_count * sizeof(struct buffer_head *),
|
|
|
GFP_KERNEL);
|
|
|
if (sbi->s_group_desc == NULL) {
|
|
|
- printk(KERN_ERR "EXT4-fs: not enough memory\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "not enough memory");
|
|
|
goto failed_mount;
|
|
|
}
|
|
|
|
|
@@ -2562,21 +2624,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
block = descriptor_loc(sb, logical_sb_block, i);
|
|
|
sbi->s_group_desc[i] = sb_bread(sb, block);
|
|
|
if (!sbi->s_group_desc[i]) {
|
|
|
- printk(KERN_ERR "EXT4-fs: "
|
|
|
- "can't read group descriptor %d\n", i);
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "can't read group descriptor %d", i);
|
|
|
db_count = i;
|
|
|
goto failed_mount2;
|
|
|
}
|
|
|
}
|
|
|
if (!ext4_check_descriptors(sb)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: group descriptors corrupted!\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
|
|
|
goto failed_mount2;
|
|
|
}
|
|
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
|
|
|
if (!ext4_fill_flex_info(sb)) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: unable to initialize "
|
|
|
- "flex_bg meta info!\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "unable to initialize "
|
|
|
+ "flex_bg meta info!");
|
|
|
goto failed_mount2;
|
|
|
}
|
|
|
|
|
@@ -2598,7 +2660,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
|
|
|
}
|
|
|
if (err) {
|
|
|
- printk(KERN_ERR "EXT4-fs: insufficient memory\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "insufficient memory");
|
|
|
goto failed_mount3;
|
|
|
}
|
|
|
|
|
@@ -2607,7 +2669,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
/*
|
|
|
* set up enough so that it can read an inode
|
|
|
*/
|
|
|
- sb->s_op = &ext4_sops;
|
|
|
+ if (!test_opt(sb, NOLOAD) &&
|
|
|
+ EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
|
|
|
+ sb->s_op = &ext4_sops;
|
|
|
+ else
|
|
|
+ sb->s_op = &ext4_nojournal_sops;
|
|
|
sb->s_export_op = &ext4_export_ops;
|
|
|
sb->s_xattr = ext4_xattr_handlers;
|
|
|
#ifdef CONFIG_QUOTA
|
|
@@ -2615,6 +2681,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
sb->dq_op = &ext4_quota_operations;
|
|
|
#endif
|
|
|
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
|
|
|
+ mutex_init(&sbi->s_orphan_lock);
|
|
|
+ mutex_init(&sbi->s_resize_lock);
|
|
|
|
|
|
sb->s_root = NULL;
|
|
|
|
|
@@ -2632,13 +2700,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
goto failed_mount3;
|
|
|
if (!(sb->s_flags & MS_RDONLY) &&
|
|
|
EXT4_SB(sb)->s_journal->j_failed_commit) {
|
|
|
- printk(KERN_CRIT "EXT4-fs error (device %s): "
|
|
|
+ ext4_msg(sb, KERN_CRIT, "error: "
|
|
|
"ext4_fill_super: Journal transaction "
|
|
|
- "%u is corrupt\n", sb->s_id,
|
|
|
+ "%u is corrupt",
|
|
|
EXT4_SB(sb)->s_journal->j_failed_commit);
|
|
|
if (test_opt(sb, ERRORS_RO)) {
|
|
|
- printk(KERN_CRIT
|
|
|
- "Mounting filesystem read-only\n");
|
|
|
+ ext4_msg(sb, KERN_CRIT,
|
|
|
+ "Mounting filesystem read-only");
|
|
|
sb->s_flags |= MS_RDONLY;
|
|
|
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
|
|
|
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
|
|
@@ -2646,14 +2714,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
if (test_opt(sb, ERRORS_PANIC)) {
|
|
|
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
|
|
|
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
|
|
|
- ext4_commit_super(sb, es, 1);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
goto failed_mount4;
|
|
|
}
|
|
|
}
|
|
|
} else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
|
|
|
EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: required journal recovery "
|
|
|
- "suppressed and not mounted read-only\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "required journal recovery "
|
|
|
+ "suppressed and not mounted read-only");
|
|
|
goto failed_mount4;
|
|
|
} else {
|
|
|
clear_opt(sbi->s_mount_opt, DATA_FLAGS);
|
|
@@ -2666,7 +2734,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
if (ext4_blocks_count(es) > 0xffffffffULL &&
|
|
|
!jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
|
|
|
JBD2_FEATURE_INCOMPAT_64BIT)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: Failed to set 64-bit journal feature\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature");
|
|
|
goto failed_mount4;
|
|
|
}
|
|
|
|
|
@@ -2704,8 +2772,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
case EXT4_MOUNT_WRITEBACK_DATA:
|
|
|
if (!jbd2_journal_check_available_features
|
|
|
(sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: Journal does not support "
|
|
|
- "requested data journaling mode\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "Journal does not support "
|
|
|
+ "requested data journaling mode");
|
|
|
goto failed_mount4;
|
|
|
}
|
|
|
default:
|
|
@@ -2717,8 +2785,8 @@ no_journal:
|
|
|
|
|
|
if (test_opt(sb, NOBH)) {
|
|
|
if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) {
|
|
|
- printk(KERN_WARNING "EXT4-fs: Ignoring nobh option - "
|
|
|
- "its supported only with writeback mode\n");
|
|
|
+ ext4_msg(sb, KERN_WARNING, "Ignoring nobh option - "
|
|
|
+ "its supported only with writeback mode");
|
|
|
clear_opt(sbi->s_mount_opt, NOBH);
|
|
|
}
|
|
|
}
|
|
@@ -2729,18 +2797,18 @@ no_journal:
|
|
|
|
|
|
root = ext4_iget(sb, EXT4_ROOT_INO);
|
|
|
if (IS_ERR(root)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: get root inode failed\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "get root inode failed");
|
|
|
ret = PTR_ERR(root);
|
|
|
goto failed_mount4;
|
|
|
}
|
|
|
if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
|
|
|
iput(root);
|
|
|
- printk(KERN_ERR "EXT4-fs: corrupt root inode, run e2fsck\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck");
|
|
|
goto failed_mount4;
|
|
|
}
|
|
|
sb->s_root = d_alloc_root(root);
|
|
|
if (!sb->s_root) {
|
|
|
- printk(KERN_ERR "EXT4-fs: get root dentry failed\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "get root dentry failed");
|
|
|
iput(root);
|
|
|
ret = -ENOMEM;
|
|
|
goto failed_mount4;
|
|
@@ -2769,22 +2837,29 @@ no_journal:
|
|
|
sbi->s_inode_size) {
|
|
|
sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
|
|
|
EXT4_GOOD_OLD_INODE_SIZE;
|
|
|
- printk(KERN_INFO "EXT4-fs: required extra inode space not"
|
|
|
- "available.\n");
|
|
|
+ ext4_msg(sb, KERN_INFO, "required extra inode space not"
|
|
|
+ "available");
|
|
|
}
|
|
|
|
|
|
if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
|
|
|
- printk(KERN_WARNING "EXT4-fs: Ignoring delalloc option - "
|
|
|
- "requested data journaling mode\n");
|
|
|
+ ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - "
|
|
|
+ "requested data journaling mode");
|
|
|
clear_opt(sbi->s_mount_opt, DELALLOC);
|
|
|
} else if (test_opt(sb, DELALLOC))
|
|
|
- printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
|
|
|
+ ext4_msg(sb, KERN_INFO, "delayed allocation enabled");
|
|
|
+
|
|
|
+ err = ext4_setup_system_zone(sb);
|
|
|
+ if (err) {
|
|
|
+ ext4_msg(sb, KERN_ERR, "failed to initialize system "
|
|
|
+ "zone (%d)\n", err);
|
|
|
+ goto failed_mount4;
|
|
|
+ }
|
|
|
|
|
|
ext4_ext_init(sb);
|
|
|
err = ext4_mb_init(sb, needs_recovery);
|
|
|
if (err) {
|
|
|
- printk(KERN_ERR "EXT4-fs: failed to initalize mballoc (%d)\n",
|
|
|
- err);
|
|
|
+ ext4_msg(sb, KERN_ERR, "failed to initalize mballoc (%d)",
|
|
|
+ err);
|
|
|
goto failed_mount4;
|
|
|
}
|
|
|
|
|
@@ -2798,19 +2873,11 @@ no_journal:
|
|
|
goto failed_mount4;
|
|
|
};
|
|
|
|
|
|
- /*
|
|
|
- * akpm: core read_super() calls in here with the superblock locked.
|
|
|
- * That deadlocks, because orphan cleanup needs to lock the superblock
|
|
|
- * in numerous places. Here we just pop the lock - it's relatively
|
|
|
- * harmless, because we are now ready to accept write_super() requests,
|
|
|
- * and aviro says that's the only reason for hanging onto the
|
|
|
- * superblock lock.
|
|
|
- */
|
|
|
EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS;
|
|
|
ext4_orphan_cleanup(sb, es);
|
|
|
EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS;
|
|
|
if (needs_recovery) {
|
|
|
- printk(KERN_INFO "EXT4-fs: recovery complete.\n");
|
|
|
+ ext4_msg(sb, KERN_INFO, "recovery complete");
|
|
|
ext4_mark_recovery_complete(sb, es);
|
|
|
}
|
|
|
if (EXT4_SB(sb)->s_journal) {
|
|
@@ -2823,25 +2890,30 @@ no_journal:
|
|
|
} else
|
|
|
descr = "out journal";
|
|
|
|
|
|
- printk(KERN_INFO "EXT4-fs: mounted filesystem %s with%s\n",
|
|
|
- sb->s_id, descr);
|
|
|
+ ext4_msg(sb, KERN_INFO, "mounted filesystem with%s", descr);
|
|
|
|
|
|
lock_kernel();
|
|
|
return 0;
|
|
|
|
|
|
cantfind_ext4:
|
|
|
if (!silent)
|
|
|
- printk(KERN_ERR "VFS: Can't find ext4 filesystem on dev %s.\n",
|
|
|
- sb->s_id);
|
|
|
+ ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
|
|
|
goto failed_mount;
|
|
|
|
|
|
failed_mount4:
|
|
|
- printk(KERN_ERR "EXT4-fs (device %s): mount failed\n", sb->s_id);
|
|
|
+ ext4_msg(sb, KERN_ERR, "mount failed");
|
|
|
+ ext4_release_system_zone(sb);
|
|
|
if (sbi->s_journal) {
|
|
|
jbd2_journal_destroy(sbi->s_journal);
|
|
|
sbi->s_journal = NULL;
|
|
|
}
|
|
|
failed_mount3:
|
|
|
+ if (sbi->s_flex_groups) {
|
|
|
+ if (is_vmalloc_addr(sbi->s_flex_groups))
|
|
|
+ vfree(sbi->s_flex_groups);
|
|
|
+ else
|
|
|
+ kfree(sbi->s_flex_groups);
|
|
|
+ }
|
|
|
percpu_counter_destroy(&sbi->s_freeblocks_counter);
|
|
|
percpu_counter_destroy(&sbi->s_freeinodes_counter);
|
|
|
percpu_counter_destroy(&sbi->s_dirs_counter);
|
|
@@ -2862,6 +2934,7 @@ failed_mount:
|
|
|
brelse(bh);
|
|
|
out_fail:
|
|
|
sb->s_fs_info = NULL;
|
|
|
+ kfree(sbi->s_blockgroup_lock);
|
|
|
kfree(sbi);
|
|
|
lock_kernel();
|
|
|
return ret;
|
|
@@ -2906,27 +2979,27 @@ static journal_t *ext4_get_journal(struct super_block *sb,
|
|
|
|
|
|
journal_inode = ext4_iget(sb, journal_inum);
|
|
|
if (IS_ERR(journal_inode)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: no journal found.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "no journal found");
|
|
|
return NULL;
|
|
|
}
|
|
|
if (!journal_inode->i_nlink) {
|
|
|
make_bad_inode(journal_inode);
|
|
|
iput(journal_inode);
|
|
|
- printk(KERN_ERR "EXT4-fs: journal inode is deleted.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "journal inode is deleted");
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
jbd_debug(2, "Journal inode found at %p: %lld bytes\n",
|
|
|
journal_inode, journal_inode->i_size);
|
|
|
if (!S_ISREG(journal_inode->i_mode)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: invalid journal inode.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "invalid journal inode");
|
|
|
iput(journal_inode);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
journal = jbd2_journal_init_inode(journal_inode);
|
|
|
if (!journal) {
|
|
|
- printk(KERN_ERR "EXT4-fs: Could not load journal inode\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "Could not load journal inode");
|
|
|
iput(journal_inode);
|
|
|
return NULL;
|
|
|
}
|
|
@@ -2950,13 +3023,13 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
|
|
|
|
|
|
BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL));
|
|
|
|
|
|
- bdev = ext4_blkdev_get(j_dev);
|
|
|
+ bdev = ext4_blkdev_get(j_dev, sb);
|
|
|
if (bdev == NULL)
|
|
|
return NULL;
|
|
|
|
|
|
if (bd_claim(bdev, sb)) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: failed to claim external journal device.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "failed to claim external journal device");
|
|
|
blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
|
|
|
return NULL;
|
|
|
}
|
|
@@ -2964,8 +3037,8 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
|
|
|
blocksize = sb->s_blocksize;
|
|
|
hblock = bdev_hardsect_size(bdev);
|
|
|
if (blocksize < hblock) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: blocksize too small for journal device.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "blocksize too small for journal device");
|
|
|
goto out_bdev;
|
|
|
}
|
|
|
|
|
@@ -2973,8 +3046,8 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
|
|
|
offset = EXT4_MIN_BLOCK_SIZE % blocksize;
|
|
|
set_blocksize(bdev, blocksize);
|
|
|
if (!(bh = __bread(bdev, sb_block, blocksize))) {
|
|
|
- printk(KERN_ERR "EXT4-fs: couldn't read superblock of "
|
|
|
- "external journal\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "couldn't read superblock of "
|
|
|
+ "external journal");
|
|
|
goto out_bdev;
|
|
|
}
|
|
|
|
|
@@ -2982,14 +3055,14 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
|
|
|
if ((le16_to_cpu(es->s_magic) != EXT4_SUPER_MAGIC) ||
|
|
|
!(le32_to_cpu(es->s_feature_incompat) &
|
|
|
EXT4_FEATURE_INCOMPAT_JOURNAL_DEV)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: external journal has "
|
|
|
- "bad superblock\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "external journal has "
|
|
|
+ "bad superblock");
|
|
|
brelse(bh);
|
|
|
goto out_bdev;
|
|
|
}
|
|
|
|
|
|
if (memcmp(EXT4_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: journal UUID does not match\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "journal UUID does not match");
|
|
|
brelse(bh);
|
|
|
goto out_bdev;
|
|
|
}
|
|
@@ -3001,25 +3074,26 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
|
|
|
journal = jbd2_journal_init_dev(bdev, sb->s_bdev,
|
|
|
start, len, blocksize);
|
|
|
if (!journal) {
|
|
|
- printk(KERN_ERR "EXT4-fs: failed to create device journal\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "failed to create device journal");
|
|
|
goto out_bdev;
|
|
|
}
|
|
|
journal->j_private = sb;
|
|
|
ll_rw_block(READ, 1, &journal->j_sb_buffer);
|
|
|
wait_on_buffer(journal->j_sb_buffer);
|
|
|
if (!buffer_uptodate(journal->j_sb_buffer)) {
|
|
|
- printk(KERN_ERR "EXT4-fs: I/O error on journal device\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "I/O error on journal device");
|
|
|
goto out_journal;
|
|
|
}
|
|
|
if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
|
|
|
- printk(KERN_ERR "EXT4-fs: External journal has more than one "
|
|
|
- "user (unsupported) - %d\n",
|
|
|
+ ext4_msg(sb, KERN_ERR, "External journal has more than one "
|
|
|
+ "user (unsupported) - %d",
|
|
|
be32_to_cpu(journal->j_superblock->s_nr_users));
|
|
|
goto out_journal;
|
|
|
}
|
|
|
EXT4_SB(sb)->journal_bdev = bdev;
|
|
|
ext4_init_journal_params(sb, journal);
|
|
|
return journal;
|
|
|
+
|
|
|
out_journal:
|
|
|
jbd2_journal_destroy(journal);
|
|
|
out_bdev:
|
|
@@ -3041,8 +3115,8 @@ static int ext4_load_journal(struct super_block *sb,
|
|
|
|
|
|
if (journal_devnum &&
|
|
|
journal_devnum != le32_to_cpu(es->s_journal_dev)) {
|
|
|
- printk(KERN_INFO "EXT4-fs: external journal device major/minor "
|
|
|
- "numbers have changed\n");
|
|
|
+ ext4_msg(sb, KERN_INFO, "external journal device major/minor "
|
|
|
+ "numbers have changed");
|
|
|
journal_dev = new_decode_dev(journal_devnum);
|
|
|
} else
|
|
|
journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
|
|
@@ -3054,24 +3128,23 @@ static int ext4_load_journal(struct super_block *sb,
|
|
|
* crash? For recovery, we need to check in advance whether we
|
|
|
* can get read-write access to the device.
|
|
|
*/
|
|
|
-
|
|
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
|
|
|
if (sb->s_flags & MS_RDONLY) {
|
|
|
- printk(KERN_INFO "EXT4-fs: INFO: recovery "
|
|
|
- "required on readonly filesystem.\n");
|
|
|
+ ext4_msg(sb, KERN_INFO, "INFO: recovery "
|
|
|
+ "required on readonly filesystem");
|
|
|
if (really_read_only) {
|
|
|
- printk(KERN_ERR "EXT4-fs: write access "
|
|
|
- "unavailable, cannot proceed.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "write access "
|
|
|
+ "unavailable, cannot proceed");
|
|
|
return -EROFS;
|
|
|
}
|
|
|
- printk(KERN_INFO "EXT4-fs: write access will "
|
|
|
- "be enabled during recovery.\n");
|
|
|
+ ext4_msg(sb, KERN_INFO, "write access will "
|
|
|
+ "be enabled during recovery");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (journal_inum && journal_dev) {
|
|
|
- printk(KERN_ERR "EXT4-fs: filesystem has both journal "
|
|
|
- "and inode journals!\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "filesystem has both journal "
|
|
|
+ "and inode journals!");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
@@ -3084,14 +3157,14 @@ static int ext4_load_journal(struct super_block *sb,
|
|
|
}
|
|
|
|
|
|
if (journal->j_flags & JBD2_BARRIER)
|
|
|
- printk(KERN_INFO "EXT4-fs: barriers enabled\n");
|
|
|
+ ext4_msg(sb, KERN_INFO, "barriers enabled");
|
|
|
else
|
|
|
- printk(KERN_INFO "EXT4-fs: barriers disabled\n");
|
|
|
+ ext4_msg(sb, KERN_INFO, "barriers disabled");
|
|
|
|
|
|
if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
|
|
|
err = jbd2_journal_update_format(journal);
|
|
|
if (err) {
|
|
|
- printk(KERN_ERR "EXT4-fs: error updating journal.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "error updating journal");
|
|
|
jbd2_journal_destroy(journal);
|
|
|
return err;
|
|
|
}
|
|
@@ -3103,7 +3176,7 @@ static int ext4_load_journal(struct super_block *sb,
|
|
|
err = jbd2_journal_load(journal);
|
|
|
|
|
|
if (err) {
|
|
|
- printk(KERN_ERR "EXT4-fs: error loading journal.\n");
|
|
|
+ ext4_msg(sb, KERN_ERR, "error loading journal");
|
|
|
jbd2_journal_destroy(journal);
|
|
|
return err;
|
|
|
}
|
|
@@ -3114,18 +3187,17 @@ static int ext4_load_journal(struct super_block *sb,
|
|
|
if (journal_devnum &&
|
|
|
journal_devnum != le32_to_cpu(es->s_journal_dev)) {
|
|
|
es->s_journal_dev = cpu_to_le32(journal_devnum);
|
|
|
- sb->s_dirt = 1;
|
|
|
|
|
|
/* Make sure we flush the recovery flag to disk. */
|
|
|
- ext4_commit_super(sb, es, 1);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int ext4_commit_super(struct super_block *sb,
|
|
|
- struct ext4_super_block *es, int sync)
|
|
|
+static int ext4_commit_super(struct super_block *sb, int sync)
|
|
|
{
|
|
|
+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;
|
|
|
struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
|
|
|
int error = 0;
|
|
|
|
|
@@ -3140,8 +3212,8 @@ static int ext4_commit_super(struct super_block *sb,
|
|
|
* be remapped. Nothing we can do but to retry the
|
|
|
* write and hope for the best.
|
|
|
*/
|
|
|
- printk(KERN_ERR "EXT4-fs: previous I/O error to "
|
|
|
- "superblock detected for %s.\n", sb->s_id);
|
|
|
+ ext4_msg(sb, KERN_ERR, "previous I/O error to "
|
|
|
+ "superblock detected");
|
|
|
clear_buffer_write_io_error(sbh);
|
|
|
set_buffer_uptodate(sbh);
|
|
|
}
|
|
@@ -3154,7 +3226,7 @@ static int ext4_commit_super(struct super_block *sb,
|
|
|
&EXT4_SB(sb)->s_freeblocks_counter));
|
|
|
es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive(
|
|
|
&EXT4_SB(sb)->s_freeinodes_counter));
|
|
|
-
|
|
|
+ sb->s_dirt = 0;
|
|
|
BUFFER_TRACE(sbh, "marking dirty");
|
|
|
mark_buffer_dirty(sbh);
|
|
|
if (sync) {
|
|
@@ -3164,8 +3236,8 @@ static int ext4_commit_super(struct super_block *sb,
|
|
|
|
|
|
error = buffer_write_io_error(sbh);
|
|
|
if (error) {
|
|
|
- printk(KERN_ERR "EXT4-fs: I/O error while writing "
|
|
|
- "superblock for %s.\n", sb->s_id);
|
|
|
+ ext4_msg(sb, KERN_ERR, "I/O error while writing "
|
|
|
+ "superblock");
|
|
|
clear_buffer_write_io_error(sbh);
|
|
|
set_buffer_uptodate(sbh);
|
|
|
}
|
|
@@ -3173,7 +3245,6 @@ static int ext4_commit_super(struct super_block *sb,
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/*
|
|
|
* Have we just finished recovery? If so, and if we are mounting (or
|
|
|
* remounting) the filesystem readonly, then we will end up with a
|
|
@@ -3192,14 +3263,11 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
|
|
|
if (jbd2_journal_flush(journal) < 0)
|
|
|
goto out;
|
|
|
|
|
|
- lock_super(sb);
|
|
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
|
|
|
sb->s_flags & MS_RDONLY) {
|
|
|
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
|
- sb->s_dirt = 0;
|
|
|
- ext4_commit_super(sb, es, 1);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
}
|
|
|
- unlock_super(sb);
|
|
|
|
|
|
out:
|
|
|
jbd2_journal_unlock_updates(journal);
|
|
@@ -3238,7 +3306,7 @@ static void ext4_clear_journal_err(struct super_block *sb,
|
|
|
|
|
|
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
|
|
|
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
|
|
|
- ext4_commit_super(sb, es, 1);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
|
|
|
jbd2_journal_clear_err(journal);
|
|
|
}
|
|
@@ -3257,29 +3325,15 @@ int ext4_force_commit(struct super_block *sb)
|
|
|
return 0;
|
|
|
|
|
|
journal = EXT4_SB(sb)->s_journal;
|
|
|
- if (journal) {
|
|
|
- sb->s_dirt = 0;
|
|
|
+ if (journal)
|
|
|
ret = ext4_journal_force_commit(journal);
|
|
|
- }
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Ext4 always journals updates to the superblock itself, so we don't
|
|
|
- * have to propagate any other updates to the superblock on disk at this
|
|
|
- * point. (We can probably nuke this function altogether, and remove
|
|
|
- * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...)
|
|
|
- */
|
|
|
static void ext4_write_super(struct super_block *sb)
|
|
|
{
|
|
|
- if (EXT4_SB(sb)->s_journal) {
|
|
|
- if (mutex_trylock(&sb->s_lock) != 0)
|
|
|
- BUG();
|
|
|
- sb->s_dirt = 0;
|
|
|
- } else {
|
|
|
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
|
|
|
- }
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
}
|
|
|
|
|
|
static int ext4_sync_fs(struct super_block *sb, int wait)
|
|
@@ -3288,16 +3342,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
|
|
|
tid_t target;
|
|
|
|
|
|
trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
|
|
|
- sb->s_dirt = 0;
|
|
|
- if (EXT4_SB(sb)->s_journal) {
|
|
|
- if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal,
|
|
|
- &target)) {
|
|
|
- if (wait)
|
|
|
- jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
|
|
|
- target);
|
|
|
- }
|
|
|
- } else {
|
|
|
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, wait);
|
|
|
+ if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
|
|
|
+ if (wait)
|
|
|
+ jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
|
|
|
}
|
|
|
return ret;
|
|
|
}
|
|
@@ -3310,34 +3357,32 @@ static int ext4_freeze(struct super_block *sb)
|
|
|
{
|
|
|
int error = 0;
|
|
|
journal_t *journal;
|
|
|
- sb->s_dirt = 0;
|
|
|
|
|
|
- if (!(sb->s_flags & MS_RDONLY)) {
|
|
|
- journal = EXT4_SB(sb)->s_journal;
|
|
|
+ if (sb->s_flags & MS_RDONLY)
|
|
|
+ return 0;
|
|
|
|
|
|
- if (journal) {
|
|
|
- /* Now we set up the journal barrier. */
|
|
|
- jbd2_journal_lock_updates(journal);
|
|
|
+ journal = EXT4_SB(sb)->s_journal;
|
|
|
|
|
|
- /*
|
|
|
- * We don't want to clear needs_recovery flag when we
|
|
|
- * failed to flush the journal.
|
|
|
- */
|
|
|
- error = jbd2_journal_flush(journal);
|
|
|
- if (error < 0)
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ /* Now we set up the journal barrier. */
|
|
|
+ jbd2_journal_lock_updates(journal);
|
|
|
|
|
|
- /* Journal blocked and flushed, clear needs_recovery flag. */
|
|
|
- EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
|
- error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
|
|
|
- if (error)
|
|
|
- goto out;
|
|
|
+ /*
|
|
|
+ * Don't clear the needs_recovery flag if we failed to flush
|
|
|
+ * the journal.
|
|
|
+ */
|
|
|
+ error = jbd2_journal_flush(journal);
|
|
|
+ if (error < 0) {
|
|
|
+ out:
|
|
|
+ jbd2_journal_unlock_updates(journal);
|
|
|
+ return error;
|
|
|
}
|
|
|
+
|
|
|
+ /* Journal blocked and flushed, clear needs_recovery flag. */
|
|
|
+ EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
|
+ error = ext4_commit_super(sb, 1);
|
|
|
+ if (error)
|
|
|
+ goto out;
|
|
|
return 0;
|
|
|
-out:
|
|
|
- jbd2_journal_unlock_updates(journal);
|
|
|
- return error;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -3346,14 +3391,15 @@ out:
|
|
|
*/
|
|
|
static int ext4_unfreeze(struct super_block *sb)
|
|
|
{
|
|
|
- if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) {
|
|
|
- lock_super(sb);
|
|
|
- /* Reser the needs_recovery flag before the fs is unlocked. */
|
|
|
- EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
|
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
|
|
|
- unlock_super(sb);
|
|
|
- jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
|
|
|
- }
|
|
|
+ if (sb->s_flags & MS_RDONLY)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ lock_super(sb);
|
|
|
+ /* Reset the needs_recovery flag before the fs is unlocked. */
|
|
|
+ EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
+ unlock_super(sb);
|
|
|
+ jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -3432,22 +3478,15 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
|
|
|
(sbi->s_mount_state & EXT4_VALID_FS))
|
|
|
es->s_state = cpu_to_le16(sbi->s_mount_state);
|
|
|
|
|
|
- /*
|
|
|
- * We have to unlock super so that we can wait for
|
|
|
- * transactions.
|
|
|
- */
|
|
|
- if (sbi->s_journal) {
|
|
|
- unlock_super(sb);
|
|
|
+ if (sbi->s_journal)
|
|
|
ext4_mark_recovery_complete(sb, es);
|
|
|
- lock_super(sb);
|
|
|
- }
|
|
|
} else {
|
|
|
int ret;
|
|
|
if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb,
|
|
|
~EXT4_FEATURE_RO_COMPAT_SUPP))) {
|
|
|
- printk(KERN_WARNING "EXT4-fs: %s: couldn't "
|
|
|
+ ext4_msg(sb, KERN_WARNING, "couldn't "
|
|
|
"remount RDWR because of unsupported "
|
|
|
- "optional features (%x).\n", sb->s_id,
|
|
|
+ "optional features (%x)",
|
|
|
(le32_to_cpu(sbi->s_es->s_feature_ro_compat) &
|
|
|
~EXT4_FEATURE_RO_COMPAT_SUPP));
|
|
|
err = -EROFS;
|
|
@@ -3456,17 +3495,15 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
|
|
|
|
|
|
/*
|
|
|
* Make sure the group descriptor checksums
|
|
|
- * are sane. If they aren't, refuse to
|
|
|
- * remount r/w.
|
|
|
+ * are sane. If they aren't, refuse to remount r/w.
|
|
|
*/
|
|
|
for (g = 0; g < sbi->s_groups_count; g++) {
|
|
|
struct ext4_group_desc *gdp =
|
|
|
ext4_get_group_desc(sb, g, NULL);
|
|
|
|
|
|
if (!ext4_group_desc_csum_verify(sbi, g, gdp)) {
|
|
|
- printk(KERN_ERR
|
|
|
- "EXT4-fs: ext4_remount: "
|
|
|
- "Checksum for group %u failed (%u!=%u)\n",
|
|
|
+ ext4_msg(sb, KERN_ERR,
|
|
|
+ "ext4_remount: Checksum for group %u failed (%u!=%u)",
|
|
|
g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)),
|
|
|
le16_to_cpu(gdp->bg_checksum));
|
|
|
err = -EINVAL;
|
|
@@ -3480,11 +3517,10 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
|
|
|
* require a full umount/remount for now.
|
|
|
*/
|
|
|
if (es->s_last_orphan) {
|
|
|
- printk(KERN_WARNING "EXT4-fs: %s: couldn't "
|
|
|
+ ext4_msg(sb, KERN_WARNING, "Couldn't "
|
|
|
"remount RDWR because of unprocessed "
|
|
|
"orphan inode list. Please "
|
|
|
- "umount/remount instead.\n",
|
|
|
- sb->s_id);
|
|
|
+ "umount/remount instead");
|
|
|
err = -EINVAL;
|
|
|
goto restore_opts;
|
|
|
}
|
|
@@ -3504,8 +3540,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
|
|
|
sb->s_flags &= ~MS_RDONLY;
|
|
|
}
|
|
|
}
|
|
|
+ ext4_setup_system_zone(sb);
|
|
|
if (sbi->s_journal == NULL)
|
|
|
- ext4_commit_super(sb, es, 1);
|
|
|
+ ext4_commit_super(sb, 1);
|
|
|
|
|
|
#ifdef CONFIG_QUOTA
|
|
|
/* Release old quota file names */
|
|
@@ -3515,6 +3552,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
|
|
|
kfree(old_opts.s_qf_names[i]);
|
|
|
#endif
|
|
|
return 0;
|
|
|
+
|
|
|
restore_opts:
|
|
|
sb->s_flags = old_sb_flags;
|
|
|
sbi->s_mount_opt = old_opts.s_mount_opt;
|
|
@@ -3545,9 +3583,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|
|
if (test_opt(sb, MINIX_DF)) {
|
|
|
sbi->s_overhead_last = 0;
|
|
|
} else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
|
|
|
- ext4_group_t ngroups = sbi->s_groups_count, i;
|
|
|
+ ext4_group_t i, ngroups = ext4_get_groups_count(sb);
|
|
|
ext4_fsblk_t overhead = 0;
|
|
|
- smp_rmb();
|
|
|
|
|
|
/*
|
|
|
* Compute the overhead (FS structures). This is constant
|
|
@@ -3599,11 +3636,12 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|
|
le64_to_cpup((void *)es->s_uuid + sizeof(u64));
|
|
|
buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
|
|
|
buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* Helper function for writing quotas on sync - we need to start transaction before quota file
|
|
|
- * is locked for write. Otherwise the are possible deadlocks:
|
|
|
+/* Helper function for writing quotas on sync - we need to start transaction
|
|
|
+ * before quota file is locked for write. Otherwise the are possible deadlocks:
|
|
|
* Process 1 Process 2
|
|
|
* ext4_create() quota_sync()
|
|
|
* jbd2_journal_start() write_dquot()
|
|
@@ -3627,7 +3665,7 @@ static int ext4_write_dquot(struct dquot *dquot)
|
|
|
|
|
|
inode = dquot_to_inode(dquot);
|
|
|
handle = ext4_journal_start(inode,
|
|
|
- EXT4_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
|
|
+ EXT4_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
|
|
if (IS_ERR(handle))
|
|
|
return PTR_ERR(handle);
|
|
|
ret = dquot_commit(dquot);
|
|
@@ -3643,7 +3681,7 @@ static int ext4_acquire_dquot(struct dquot *dquot)
|
|
|
handle_t *handle;
|
|
|
|
|
|
handle = ext4_journal_start(dquot_to_inode(dquot),
|
|
|
- EXT4_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
|
|
+ EXT4_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
|
|
if (IS_ERR(handle))
|
|
|
return PTR_ERR(handle);
|
|
|
ret = dquot_acquire(dquot);
|
|
@@ -3659,7 +3697,7 @@ static int ext4_release_dquot(struct dquot *dquot)
|
|
|
handle_t *handle;
|
|
|
|
|
|
handle = ext4_journal_start(dquot_to_inode(dquot),
|
|
|
- EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
|
|
+ EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
|
|
if (IS_ERR(handle)) {
|
|
|
/* Release dquot anyway to avoid endless cycle in dqput() */
|
|
|
dquot_release(dquot);
|
|
@@ -3707,7 +3745,7 @@ static int ext4_write_info(struct super_block *sb, int type)
|
|
|
static int ext4_quota_on_mount(struct super_block *sb, int type)
|
|
|
{
|
|
|
return vfs_quota_on_mount(sb, EXT4_SB(sb)->s_qf_names[type],
|
|
|
- EXT4_SB(sb)->s_jquota_fmt, type);
|
|
|
+ EXT4_SB(sb)->s_jquota_fmt, type);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -3738,9 +3776,9 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
|
|
|
if (EXT4_SB(sb)->s_qf_names[type]) {
|
|
|
/* Quotafile not in fs root? */
|
|
|
if (path.dentry->d_parent != sb->s_root)
|
|
|
- printk(KERN_WARNING
|
|
|
- "EXT4-fs: Quota file not on filesystem root. "
|
|
|
- "Journaled quota will not work.\n");
|
|
|
+ ext4_msg(sb, KERN_WARNING,
|
|
|
+ "Quota file not on filesystem root. "
|
|
|
+ "Journaled quota will not work");
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -3823,8 +3861,8 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
|
|
|
handle_t *handle = journal_current_handle();
|
|
|
|
|
|
if (EXT4_SB(sb)->s_journal && !handle) {
|
|
|
- printk(KERN_WARNING "EXT4-fs: Quota write (off=%llu, len=%llu)"
|
|
|
- " cancelled because transaction is not started.\n",
|
|
|
+ ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
|
|
|
+ " cancelled because transaction is not started",
|
|
|
(unsigned long long)off, (unsigned long long)len);
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -3878,10 +3916,10 @@ out:
|
|
|
|
|
|
#endif
|
|
|
|
|
|
-static int ext4_get_sb(struct file_system_type *fs_type,
|
|
|
- int flags, const char *dev_name, void *data, struct vfsmount *mnt)
|
|
|
+static int ext4_get_sb(struct file_system_type *fs_type, int flags,
|
|
|
+ const char *dev_name, void *data, struct vfsmount *mnt)
|
|
|
{
|
|
|
- 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);
|
|
|
}
|
|
|
|
|
|
static struct file_system_type ext4_fs_type = {
|
|
@@ -3893,14 +3931,14 @@ static struct file_system_type ext4_fs_type = {
|
|
|
};
|
|
|
|
|
|
#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)
|
|
|
+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);
|
|
|
+ printk(KERN_WARNING "EXT4-fs (%s): Update your userspace programs "
|
|
|
+ "to mount using ext4\n", dev_name);
|
|
|
+ printk(KERN_WARNING "EXT4-fs (%s): ext4dev backwards compatibility "
|
|
|
+ "will go away by 2.6.31\n", dev_name);
|
|
|
+ return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt);
|
|
|
}
|
|
|
|
|
|
static struct file_system_type ext4dev_fs_type = {
|
|
@@ -3917,13 +3955,16 @@ static int __init init_ext4_fs(void)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
|
+ err = init_ext4_system_zone();
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
|
|
|
if (!ext4_kset)
|
|
|
- return -ENOMEM;
|
|
|
+ goto out4;
|
|
|
ext4_proc_root = proc_mkdir("fs/ext4", NULL);
|
|
|
err = init_ext4_mballoc();
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ goto out3;
|
|
|
|
|
|
err = init_ext4_xattr();
|
|
|
if (err)
|
|
@@ -3948,6 +3989,11 @@ out1:
|
|
|
exit_ext4_xattr();
|
|
|
out2:
|
|
|
exit_ext4_mballoc();
|
|
|
+out3:
|
|
|
+ remove_proc_entry("fs/ext4", NULL);
|
|
|
+ kset_unregister(ext4_kset);
|
|
|
+out4:
|
|
|
+ exit_ext4_system_zone();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -3962,6 +4008,7 @@ static void __exit exit_ext4_fs(void)
|
|
|
exit_ext4_mballoc();
|
|
|
remove_proc_entry("fs/ext4", NULL);
|
|
|
kset_unregister(ext4_kset);
|
|
|
+ exit_ext4_system_zone();
|
|
|
}
|
|
|
|
|
|
MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
|