1ac27a0ecSDave Kleikamp /* 2617ba13bSMingming Cao * linux/fs/ext4/super.c 3ac27a0ecSDave Kleikamp * 4ac27a0ecSDave Kleikamp * Copyright (C) 1992, 1993, 1994, 1995 5ac27a0ecSDave Kleikamp * Remy Card (card@masi.ibp.fr) 6ac27a0ecSDave Kleikamp * Laboratoire MASI - Institut Blaise Pascal 7ac27a0ecSDave Kleikamp * Universite Pierre et Marie Curie (Paris VI) 8ac27a0ecSDave Kleikamp * 9ac27a0ecSDave Kleikamp * from 10ac27a0ecSDave Kleikamp * 11ac27a0ecSDave Kleikamp * linux/fs/minix/inode.c 12ac27a0ecSDave Kleikamp * 13ac27a0ecSDave Kleikamp * Copyright (C) 1991, 1992 Linus Torvalds 14ac27a0ecSDave Kleikamp * 15ac27a0ecSDave Kleikamp * Big-endian to little-endian byte-swapping/bitmaps by 16ac27a0ecSDave Kleikamp * David S. Miller (davem@caip.rutgers.edu), 1995 17ac27a0ecSDave Kleikamp */ 18ac27a0ecSDave Kleikamp 19ac27a0ecSDave Kleikamp #include <linux/module.h> 20ac27a0ecSDave Kleikamp #include <linux/string.h> 21ac27a0ecSDave Kleikamp #include <linux/fs.h> 22ac27a0ecSDave Kleikamp #include <linux/time.h> 23c5ca7c76STheodore Ts'o #include <linux/vmalloc.h> 24dab291afSMingming Cao #include <linux/jbd2.h> 25ac27a0ecSDave Kleikamp #include <linux/slab.h> 26ac27a0ecSDave Kleikamp #include <linux/init.h> 27ac27a0ecSDave Kleikamp #include <linux/blkdev.h> 28ac27a0ecSDave Kleikamp #include <linux/parser.h> 29ac27a0ecSDave Kleikamp #include <linux/buffer_head.h> 30a5694255SChristoph Hellwig #include <linux/exportfs.h> 31ac27a0ecSDave Kleikamp #include <linux/vfs.h> 32ac27a0ecSDave Kleikamp #include <linux/random.h> 33ac27a0ecSDave Kleikamp #include <linux/mount.h> 34ac27a0ecSDave Kleikamp #include <linux/namei.h> 35ac27a0ecSDave Kleikamp #include <linux/quotaops.h> 36ac27a0ecSDave Kleikamp #include <linux/seq_file.h> 379f6200bbSTheodore Ts'o #include <linux/proc_fs.h> 383197ebdbSTheodore Ts'o #include <linux/ctype.h> 391330593eSVignesh Babu #include <linux/log2.h> 40717d50e4SAndreas Dilger #include <linux/crc16.h> 417abc52c2SDan Magenheimer #include <linux/cleancache.h> 42ac27a0ecSDave Kleikamp #include <asm/uaccess.h> 43ac27a0ecSDave Kleikamp 44bfff6873SLukas Czerner #include <linux/kthread.h> 45bfff6873SLukas Czerner #include <linux/freezer.h> 46bfff6873SLukas Czerner 473dcf5451SChristoph Hellwig #include "ext4.h" 483dcf5451SChristoph Hellwig #include "ext4_jbd2.h" 49ac27a0ecSDave Kleikamp #include "xattr.h" 50ac27a0ecSDave Kleikamp #include "acl.h" 513661d286STheodore Ts'o #include "mballoc.h" 52ac27a0ecSDave Kleikamp 539bffad1eSTheodore Ts'o #define CREATE_TRACE_POINTS 549bffad1eSTheodore Ts'o #include <trace/events/ext4.h> 559bffad1eSTheodore Ts'o 561f109d5aSTheodore Ts'o static struct proc_dir_entry *ext4_proc_root; 573197ebdbSTheodore Ts'o static struct kset *ext4_kset; 580b75a840SLukas Czerner static struct ext4_lazy_init *ext4_li_info; 590b75a840SLukas Czerner static struct mutex ext4_li_mtx; 600b75a840SLukas Czerner static struct ext4_features *ext4_feat; 619f6200bbSTheodore Ts'o 62617ba13bSMingming Cao static int ext4_load_journal(struct super_block *, struct ext4_super_block *, 63ac27a0ecSDave Kleikamp unsigned long journal_devnum); 64e2d67052STheodore Ts'o static int ext4_commit_super(struct super_block *sb, int sync); 65617ba13bSMingming Cao static void ext4_mark_recovery_complete(struct super_block *sb, 66617ba13bSMingming Cao struct ext4_super_block *es); 67617ba13bSMingming Cao static void ext4_clear_journal_err(struct super_block *sb, 68617ba13bSMingming Cao struct ext4_super_block *es); 69617ba13bSMingming Cao static int ext4_sync_fs(struct super_block *sb, int wait); 70617ba13bSMingming Cao static const char *ext4_decode_error(struct super_block *sb, int errno, 71ac27a0ecSDave Kleikamp char nbuf[16]); 72617ba13bSMingming Cao static int ext4_remount(struct super_block *sb, int *flags, char *data); 73617ba13bSMingming Cao static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf); 74c4be0c1dSTakashi Sato static int ext4_unfreeze(struct super_block *sb); 75617ba13bSMingming Cao static void ext4_write_super(struct super_block *sb); 76c4be0c1dSTakashi Sato static int ext4_freeze(struct super_block *sb); 77152a0836SAl Viro static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, 78152a0836SAl Viro const char *dev_name, void *data); 792035e776STheodore Ts'o static inline int ext2_feature_set_ok(struct super_block *sb); 802035e776STheodore Ts'o static inline int ext3_feature_set_ok(struct super_block *sb); 81d39195c3SAmir Goldstein static int ext4_feature_set_ok(struct super_block *sb, int readonly); 82bfff6873SLukas Czerner static void ext4_destroy_lazyinit_thread(void); 83bfff6873SLukas Czerner static void ext4_unregister_li_request(struct super_block *sb); 848f1f7453SEric Sandeen static void ext4_clear_request_list(void); 85ac27a0ecSDave Kleikamp 862035e776STheodore Ts'o #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) 872035e776STheodore Ts'o static struct file_system_type ext2_fs_type = { 882035e776STheodore Ts'o .owner = THIS_MODULE, 892035e776STheodore Ts'o .name = "ext2", 902035e776STheodore Ts'o .mount = ext4_mount, 912035e776STheodore Ts'o .kill_sb = kill_block_super, 922035e776STheodore Ts'o .fs_flags = FS_REQUIRES_DEV, 932035e776STheodore Ts'o }; 942035e776STheodore Ts'o #define IS_EXT2_SB(sb) ((sb)->s_bdev->bd_holder == &ext2_fs_type) 952035e776STheodore Ts'o #else 962035e776STheodore Ts'o #define IS_EXT2_SB(sb) (0) 972035e776STheodore Ts'o #endif 982035e776STheodore Ts'o 992035e776STheodore Ts'o 100ba69f9abSJan Kara #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) 101ba69f9abSJan Kara static struct file_system_type ext3_fs_type = { 102ba69f9abSJan Kara .owner = THIS_MODULE, 103ba69f9abSJan Kara .name = "ext3", 104152a0836SAl Viro .mount = ext4_mount, 105ba69f9abSJan Kara .kill_sb = kill_block_super, 106ba69f9abSJan Kara .fs_flags = FS_REQUIRES_DEV, 107ba69f9abSJan Kara }; 108ba69f9abSJan Kara #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type) 109ba69f9abSJan Kara #else 110ba69f9abSJan Kara #define IS_EXT3_SB(sb) (0) 111ba69f9abSJan Kara #endif 112bd81d8eeSLaurent Vivier 1138fadc143SAlexandre Ratchov ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, 1148fadc143SAlexandre Ratchov struct ext4_group_desc *bg) 115bd81d8eeSLaurent Vivier { 1163a14589cSAneesh Kumar K.V return le32_to_cpu(bg->bg_block_bitmap_lo) | 1178fadc143SAlexandre Ratchov (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 1188fadc143SAlexandre Ratchov (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0); 119bd81d8eeSLaurent Vivier } 120bd81d8eeSLaurent Vivier 1218fadc143SAlexandre Ratchov ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb, 1228fadc143SAlexandre Ratchov struct ext4_group_desc *bg) 123bd81d8eeSLaurent Vivier { 1245272f837SAneesh Kumar K.V return le32_to_cpu(bg->bg_inode_bitmap_lo) | 1258fadc143SAlexandre Ratchov (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 1268fadc143SAlexandre Ratchov (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0); 127bd81d8eeSLaurent Vivier } 128bd81d8eeSLaurent Vivier 1298fadc143SAlexandre Ratchov ext4_fsblk_t ext4_inode_table(struct super_block *sb, 1308fadc143SAlexandre Ratchov struct ext4_group_desc *bg) 131bd81d8eeSLaurent Vivier { 1325272f837SAneesh Kumar K.V return le32_to_cpu(bg->bg_inode_table_lo) | 1338fadc143SAlexandre Ratchov (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 1348fadc143SAlexandre Ratchov (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0); 135bd81d8eeSLaurent Vivier } 136bd81d8eeSLaurent Vivier 137560671a0SAneesh Kumar K.V __u32 ext4_free_blks_count(struct super_block *sb, 138560671a0SAneesh Kumar K.V struct ext4_group_desc *bg) 139560671a0SAneesh Kumar K.V { 140560671a0SAneesh Kumar K.V return le16_to_cpu(bg->bg_free_blocks_count_lo) | 141560671a0SAneesh Kumar K.V (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 142560671a0SAneesh Kumar K.V (__u32)le16_to_cpu(bg->bg_free_blocks_count_hi) << 16 : 0); 143560671a0SAneesh Kumar K.V } 144560671a0SAneesh Kumar K.V 145560671a0SAneesh Kumar K.V __u32 ext4_free_inodes_count(struct super_block *sb, 146560671a0SAneesh Kumar K.V struct ext4_group_desc *bg) 147560671a0SAneesh Kumar K.V { 148560671a0SAneesh Kumar K.V return le16_to_cpu(bg->bg_free_inodes_count_lo) | 149560671a0SAneesh Kumar K.V (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 150560671a0SAneesh Kumar K.V (__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0); 151560671a0SAneesh Kumar K.V } 152560671a0SAneesh Kumar K.V 153560671a0SAneesh Kumar K.V __u32 ext4_used_dirs_count(struct super_block *sb, 154560671a0SAneesh Kumar K.V struct ext4_group_desc *bg) 155560671a0SAneesh Kumar K.V { 156560671a0SAneesh Kumar K.V return le16_to_cpu(bg->bg_used_dirs_count_lo) | 157560671a0SAneesh Kumar K.V (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 158560671a0SAneesh Kumar K.V (__u32)le16_to_cpu(bg->bg_used_dirs_count_hi) << 16 : 0); 159560671a0SAneesh Kumar K.V } 160560671a0SAneesh Kumar K.V 161560671a0SAneesh Kumar K.V __u32 ext4_itable_unused_count(struct super_block *sb, 162560671a0SAneesh Kumar K.V struct ext4_group_desc *bg) 163560671a0SAneesh Kumar K.V { 164560671a0SAneesh Kumar K.V return le16_to_cpu(bg->bg_itable_unused_lo) | 165560671a0SAneesh Kumar K.V (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ? 166560671a0SAneesh Kumar K.V (__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0); 167560671a0SAneesh Kumar K.V } 168560671a0SAneesh Kumar K.V 1698fadc143SAlexandre Ratchov void ext4_block_bitmap_set(struct super_block *sb, 1708fadc143SAlexandre Ratchov struct ext4_group_desc *bg, ext4_fsblk_t blk) 171bd81d8eeSLaurent Vivier { 1723a14589cSAneesh Kumar K.V bg->bg_block_bitmap_lo = cpu_to_le32((u32)blk); 1738fadc143SAlexandre Ratchov if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 1748fadc143SAlexandre Ratchov bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32); 175bd81d8eeSLaurent Vivier } 176bd81d8eeSLaurent Vivier 1778fadc143SAlexandre Ratchov void ext4_inode_bitmap_set(struct super_block *sb, 1788fadc143SAlexandre Ratchov struct ext4_group_desc *bg, ext4_fsblk_t blk) 179bd81d8eeSLaurent Vivier { 1805272f837SAneesh Kumar K.V bg->bg_inode_bitmap_lo = cpu_to_le32((u32)blk); 1818fadc143SAlexandre Ratchov if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 1828fadc143SAlexandre Ratchov bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32); 183bd81d8eeSLaurent Vivier } 184bd81d8eeSLaurent Vivier 1858fadc143SAlexandre Ratchov void ext4_inode_table_set(struct super_block *sb, 1868fadc143SAlexandre Ratchov struct ext4_group_desc *bg, ext4_fsblk_t blk) 187bd81d8eeSLaurent Vivier { 1885272f837SAneesh Kumar K.V bg->bg_inode_table_lo = cpu_to_le32((u32)blk); 1898fadc143SAlexandre Ratchov if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 1908fadc143SAlexandre Ratchov bg->bg_inode_table_hi = cpu_to_le32(blk >> 32); 191bd81d8eeSLaurent Vivier } 192bd81d8eeSLaurent Vivier 193560671a0SAneesh Kumar K.V void ext4_free_blks_set(struct super_block *sb, 194560671a0SAneesh Kumar K.V struct ext4_group_desc *bg, __u32 count) 195560671a0SAneesh Kumar K.V { 196560671a0SAneesh Kumar K.V bg->bg_free_blocks_count_lo = cpu_to_le16((__u16)count); 197560671a0SAneesh Kumar K.V if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 198560671a0SAneesh Kumar K.V bg->bg_free_blocks_count_hi = cpu_to_le16(count >> 16); 199560671a0SAneesh Kumar K.V } 200560671a0SAneesh Kumar K.V 201560671a0SAneesh Kumar K.V void ext4_free_inodes_set(struct super_block *sb, 202560671a0SAneesh Kumar K.V struct ext4_group_desc *bg, __u32 count) 203560671a0SAneesh Kumar K.V { 204560671a0SAneesh Kumar K.V bg->bg_free_inodes_count_lo = cpu_to_le16((__u16)count); 205560671a0SAneesh Kumar K.V if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 206560671a0SAneesh Kumar K.V bg->bg_free_inodes_count_hi = cpu_to_le16(count >> 16); 207560671a0SAneesh Kumar K.V } 208560671a0SAneesh Kumar K.V 209560671a0SAneesh Kumar K.V void ext4_used_dirs_set(struct super_block *sb, 210560671a0SAneesh Kumar K.V struct ext4_group_desc *bg, __u32 count) 211560671a0SAneesh Kumar K.V { 212560671a0SAneesh Kumar K.V bg->bg_used_dirs_count_lo = cpu_to_le16((__u16)count); 213560671a0SAneesh Kumar K.V if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 214560671a0SAneesh Kumar K.V bg->bg_used_dirs_count_hi = cpu_to_le16(count >> 16); 215560671a0SAneesh Kumar K.V } 216560671a0SAneesh Kumar K.V 217560671a0SAneesh Kumar K.V void ext4_itable_unused_set(struct super_block *sb, 218560671a0SAneesh Kumar K.V struct ext4_group_desc *bg, __u32 count) 219560671a0SAneesh Kumar K.V { 220560671a0SAneesh Kumar K.V bg->bg_itable_unused_lo = cpu_to_le16((__u16)count); 221560671a0SAneesh Kumar K.V if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT) 222560671a0SAneesh Kumar K.V bg->bg_itable_unused_hi = cpu_to_le16(count >> 16); 223560671a0SAneesh Kumar K.V } 224560671a0SAneesh Kumar K.V 225d3d1faf6SCurt Wohlgemuth 226d3d1faf6SCurt Wohlgemuth /* Just increment the non-pointer handle value */ 227d3d1faf6SCurt Wohlgemuth static handle_t *ext4_get_nojournal(void) 228d3d1faf6SCurt Wohlgemuth { 229d3d1faf6SCurt Wohlgemuth handle_t *handle = current->journal_info; 230d3d1faf6SCurt Wohlgemuth unsigned long ref_cnt = (unsigned long)handle; 231d3d1faf6SCurt Wohlgemuth 232d3d1faf6SCurt Wohlgemuth BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT); 233d3d1faf6SCurt Wohlgemuth 234d3d1faf6SCurt Wohlgemuth ref_cnt++; 235d3d1faf6SCurt Wohlgemuth handle = (handle_t *)ref_cnt; 236d3d1faf6SCurt Wohlgemuth 237d3d1faf6SCurt Wohlgemuth current->journal_info = handle; 238d3d1faf6SCurt Wohlgemuth return handle; 239d3d1faf6SCurt Wohlgemuth } 240d3d1faf6SCurt Wohlgemuth 241d3d1faf6SCurt Wohlgemuth 242d3d1faf6SCurt Wohlgemuth /* Decrement the non-pointer handle value */ 243d3d1faf6SCurt Wohlgemuth static void ext4_put_nojournal(handle_t *handle) 244d3d1faf6SCurt Wohlgemuth { 245d3d1faf6SCurt Wohlgemuth unsigned long ref_cnt = (unsigned long)handle; 246d3d1faf6SCurt Wohlgemuth 247d3d1faf6SCurt Wohlgemuth BUG_ON(ref_cnt == 0); 248d3d1faf6SCurt Wohlgemuth 249d3d1faf6SCurt Wohlgemuth ref_cnt--; 250d3d1faf6SCurt Wohlgemuth handle = (handle_t *)ref_cnt; 251d3d1faf6SCurt Wohlgemuth 252d3d1faf6SCurt Wohlgemuth current->journal_info = handle; 253d3d1faf6SCurt Wohlgemuth } 254d3d1faf6SCurt Wohlgemuth 255ac27a0ecSDave Kleikamp /* 256dab291afSMingming Cao * Wrappers for jbd2_journal_start/end. 257ac27a0ecSDave Kleikamp * 258ac27a0ecSDave Kleikamp * The only special thing we need to do here is to make sure that all 259ac27a0ecSDave Kleikamp * journal_end calls result in the superblock being marked dirty, so 260ac27a0ecSDave Kleikamp * that sync() will call the filesystem's write_super callback if 261ac27a0ecSDave Kleikamp * appropriate. 262be4f27d3SYongqiang Yang * 263be4f27d3SYongqiang Yang * To avoid j_barrier hold in userspace when a user calls freeze(), 264be4f27d3SYongqiang Yang * ext4 prevents a new handle from being started by s_frozen, which 265be4f27d3SYongqiang Yang * is in an upper layer. 266ac27a0ecSDave Kleikamp */ 267617ba13bSMingming Cao handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) 268ac27a0ecSDave Kleikamp { 269ac27a0ecSDave Kleikamp journal_t *journal; 270be4f27d3SYongqiang Yang handle_t *handle; 271ac27a0ecSDave Kleikamp 272ac27a0ecSDave Kleikamp if (sb->s_flags & MS_RDONLY) 273ac27a0ecSDave Kleikamp return ERR_PTR(-EROFS); 274ac27a0ecSDave Kleikamp 275617ba13bSMingming Cao journal = EXT4_SB(sb)->s_journal; 276be4f27d3SYongqiang Yang handle = ext4_journal_current_handle(); 277be4f27d3SYongqiang Yang 278be4f27d3SYongqiang Yang /* 279be4f27d3SYongqiang Yang * If a handle has been started, it should be allowed to 280be4f27d3SYongqiang Yang * finish, otherwise deadlock could happen between freeze 281be4f27d3SYongqiang Yang * and others(e.g. truncate) due to the restart of the 282be4f27d3SYongqiang Yang * journal handle if the filesystem is forzen and active 283be4f27d3SYongqiang Yang * handles are not stopped. 284be4f27d3SYongqiang Yang */ 285be4f27d3SYongqiang Yang if (!handle) 286be4f27d3SYongqiang Yang vfs_check_frozen(sb, SB_FREEZE_TRANS); 287be4f27d3SYongqiang Yang 288be4f27d3SYongqiang Yang if (!journal) 289be4f27d3SYongqiang Yang return ext4_get_nojournal(); 290be4f27d3SYongqiang Yang /* 291be4f27d3SYongqiang Yang * Special case here: if the journal has aborted behind our 292be4f27d3SYongqiang Yang * backs (eg. EIO in the commit thread), then we still need to 293be4f27d3SYongqiang Yang * take the FS itself readonly cleanly. 294be4f27d3SYongqiang Yang */ 295ac27a0ecSDave Kleikamp if (is_journal_aborted(journal)) { 296c67d859eSTheodore Ts'o ext4_abort(sb, "Detected aborted journal"); 297ac27a0ecSDave Kleikamp return ERR_PTR(-EROFS); 298ac27a0ecSDave Kleikamp } 299dab291afSMingming Cao return jbd2_journal_start(journal, nblocks); 300ac27a0ecSDave Kleikamp } 301ac27a0ecSDave Kleikamp 302ac27a0ecSDave Kleikamp /* 303ac27a0ecSDave Kleikamp * The only special thing we need to do here is to make sure that all 304dab291afSMingming Cao * jbd2_journal_stop calls result in the superblock being marked dirty, so 305ac27a0ecSDave Kleikamp * that sync() will call the filesystem's write_super callback if 306ac27a0ecSDave Kleikamp * appropriate. 307ac27a0ecSDave Kleikamp */ 308c398eda0STheodore Ts'o int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) 309ac27a0ecSDave Kleikamp { 310ac27a0ecSDave Kleikamp struct super_block *sb; 311ac27a0ecSDave Kleikamp int err; 312ac27a0ecSDave Kleikamp int rc; 313ac27a0ecSDave Kleikamp 3140390131bSFrank Mayhar if (!ext4_handle_valid(handle)) { 315d3d1faf6SCurt Wohlgemuth ext4_put_nojournal(handle); 3160390131bSFrank Mayhar return 0; 3170390131bSFrank Mayhar } 318ac27a0ecSDave Kleikamp sb = handle->h_transaction->t_journal->j_private; 319ac27a0ecSDave Kleikamp err = handle->h_err; 320dab291afSMingming Cao rc = jbd2_journal_stop(handle); 321ac27a0ecSDave Kleikamp 322ac27a0ecSDave Kleikamp if (!err) 323ac27a0ecSDave Kleikamp err = rc; 324ac27a0ecSDave Kleikamp if (err) 325c398eda0STheodore Ts'o __ext4_std_error(sb, where, line, err); 326ac27a0ecSDave Kleikamp return err; 327ac27a0ecSDave Kleikamp } 328ac27a0ecSDave Kleikamp 32990c7201bSTheodore Ts'o void ext4_journal_abort_handle(const char *caller, unsigned int line, 33090c7201bSTheodore Ts'o const char *err_fn, struct buffer_head *bh, 33190c7201bSTheodore Ts'o handle_t *handle, int err) 332ac27a0ecSDave Kleikamp { 333ac27a0ecSDave Kleikamp char nbuf[16]; 334617ba13bSMingming Cao const char *errstr = ext4_decode_error(NULL, err, nbuf); 335ac27a0ecSDave Kleikamp 3360390131bSFrank Mayhar BUG_ON(!ext4_handle_valid(handle)); 3370390131bSFrank Mayhar 338ac27a0ecSDave Kleikamp if (bh) 339ac27a0ecSDave Kleikamp BUFFER_TRACE(bh, "abort"); 340ac27a0ecSDave Kleikamp 341ac27a0ecSDave Kleikamp if (!handle->h_err) 342ac27a0ecSDave Kleikamp handle->h_err = err; 343ac27a0ecSDave Kleikamp 344ac27a0ecSDave Kleikamp if (is_handle_aborted(handle)) 345ac27a0ecSDave Kleikamp return; 346ac27a0ecSDave Kleikamp 34790c7201bSTheodore Ts'o printk(KERN_ERR "%s:%d: aborting transaction: %s in %s\n", 34890c7201bSTheodore Ts'o caller, line, errstr, err_fn); 349ac27a0ecSDave Kleikamp 350dab291afSMingming Cao jbd2_journal_abort_handle(handle); 351ac27a0ecSDave Kleikamp } 352ac27a0ecSDave Kleikamp 3531c13d5c0STheodore Ts'o static void __save_error_info(struct super_block *sb, const char *func, 3541c13d5c0STheodore Ts'o unsigned int line) 3551c13d5c0STheodore Ts'o { 3561c13d5c0STheodore Ts'o struct ext4_super_block *es = EXT4_SB(sb)->s_es; 3571c13d5c0STheodore Ts'o 3581c13d5c0STheodore Ts'o EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; 3591c13d5c0STheodore Ts'o es->s_state |= cpu_to_le16(EXT4_ERROR_FS); 3601c13d5c0STheodore Ts'o es->s_last_error_time = cpu_to_le32(get_seconds()); 3611c13d5c0STheodore Ts'o strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func)); 3621c13d5c0STheodore Ts'o es->s_last_error_line = cpu_to_le32(line); 3631c13d5c0STheodore Ts'o if (!es->s_first_error_time) { 3641c13d5c0STheodore Ts'o es->s_first_error_time = es->s_last_error_time; 3651c13d5c0STheodore Ts'o strncpy(es->s_first_error_func, func, 3661c13d5c0STheodore Ts'o sizeof(es->s_first_error_func)); 3671c13d5c0STheodore Ts'o es->s_first_error_line = cpu_to_le32(line); 3681c13d5c0STheodore Ts'o es->s_first_error_ino = es->s_last_error_ino; 3691c13d5c0STheodore Ts'o es->s_first_error_block = es->s_last_error_block; 3701c13d5c0STheodore Ts'o } 37166e61a9eSTheodore Ts'o /* 37266e61a9eSTheodore Ts'o * Start the daily error reporting function if it hasn't been 37366e61a9eSTheodore Ts'o * started already 37466e61a9eSTheodore Ts'o */ 37566e61a9eSTheodore Ts'o if (!es->s_error_count) 37666e61a9eSTheodore Ts'o mod_timer(&EXT4_SB(sb)->s_err_report, jiffies + 24*60*60*HZ); 3771c13d5c0STheodore Ts'o es->s_error_count = cpu_to_le32(le32_to_cpu(es->s_error_count) + 1); 3781c13d5c0STheodore Ts'o } 3791c13d5c0STheodore Ts'o 3801c13d5c0STheodore Ts'o static void save_error_info(struct super_block *sb, const char *func, 3811c13d5c0STheodore Ts'o unsigned int line) 3821c13d5c0STheodore Ts'o { 3831c13d5c0STheodore Ts'o __save_error_info(sb, func, line); 3841c13d5c0STheodore Ts'o ext4_commit_super(sb, 1); 3851c13d5c0STheodore Ts'o } 3861c13d5c0STheodore Ts'o 3871c13d5c0STheodore Ts'o 388ac27a0ecSDave Kleikamp /* Deal with the reporting of failure conditions on a filesystem such as 389ac27a0ecSDave Kleikamp * inconsistencies detected or read IO failures. 390ac27a0ecSDave Kleikamp * 391ac27a0ecSDave Kleikamp * On ext2, we can store the error state of the filesystem in the 392617ba13bSMingming Cao * superblock. That is not possible on ext4, because we may have other 393ac27a0ecSDave Kleikamp * write ordering constraints on the superblock which prevent us from 394ac27a0ecSDave Kleikamp * writing it out straight away; and given that the journal is about to 395ac27a0ecSDave Kleikamp * be aborted, we can't rely on the current, or future, transactions to 396ac27a0ecSDave Kleikamp * write out the superblock safely. 397ac27a0ecSDave Kleikamp * 398dab291afSMingming Cao * We'll just use the jbd2_journal_abort() error code to record an error in 399d6b198bcSThadeu Lima de Souza Cascardo * the journal instead. On recovery, the journal will complain about 400ac27a0ecSDave Kleikamp * that error until we've noted it down and cleared it. 401ac27a0ecSDave Kleikamp */ 402ac27a0ecSDave Kleikamp 403617ba13bSMingming Cao static void ext4_handle_error(struct super_block *sb) 404ac27a0ecSDave Kleikamp { 405ac27a0ecSDave Kleikamp if (sb->s_flags & MS_RDONLY) 406ac27a0ecSDave Kleikamp return; 407ac27a0ecSDave Kleikamp 408ac27a0ecSDave Kleikamp if (!test_opt(sb, ERRORS_CONT)) { 409617ba13bSMingming Cao journal_t *journal = EXT4_SB(sb)->s_journal; 410ac27a0ecSDave Kleikamp 4114ab2f15bSTheodore Ts'o EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; 412ac27a0ecSDave Kleikamp if (journal) 413dab291afSMingming Cao jbd2_journal_abort(journal, -EIO); 414ac27a0ecSDave Kleikamp } 415ac27a0ecSDave Kleikamp if (test_opt(sb, ERRORS_RO)) { 416b31e1552SEric Sandeen ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); 417ac27a0ecSDave Kleikamp sb->s_flags |= MS_RDONLY; 418ac27a0ecSDave Kleikamp } 419ac27a0ecSDave Kleikamp if (test_opt(sb, ERRORS_PANIC)) 420617ba13bSMingming Cao panic("EXT4-fs (device %s): panic forced after error\n", 421ac27a0ecSDave Kleikamp sb->s_id); 422ac27a0ecSDave Kleikamp } 423ac27a0ecSDave Kleikamp 42412062dddSEric Sandeen void __ext4_error(struct super_block *sb, const char *function, 425c398eda0STheodore Ts'o unsigned int line, const char *fmt, ...) 426ac27a0ecSDave Kleikamp { 4270ff2ea7dSJoe Perches struct va_format vaf; 428ac27a0ecSDave Kleikamp va_list args; 429ac27a0ecSDave Kleikamp 430ac27a0ecSDave Kleikamp va_start(args, fmt); 4310ff2ea7dSJoe Perches vaf.fmt = fmt; 4320ff2ea7dSJoe Perches vaf.va = &args; 4330ff2ea7dSJoe Perches printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n", 4340ff2ea7dSJoe Perches sb->s_id, function, line, current->comm, &vaf); 435ac27a0ecSDave Kleikamp va_end(args); 436ac27a0ecSDave Kleikamp 437617ba13bSMingming Cao ext4_handle_error(sb); 438ac27a0ecSDave Kleikamp } 439ac27a0ecSDave Kleikamp 440c398eda0STheodore Ts'o void ext4_error_inode(struct inode *inode, const char *function, 441c398eda0STheodore Ts'o unsigned int line, ext4_fsblk_t block, 442273df556SFrank Mayhar const char *fmt, ...) 443273df556SFrank Mayhar { 444273df556SFrank Mayhar va_list args; 445f7c21177STheodore Ts'o struct va_format vaf; 4461c13d5c0STheodore Ts'o struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; 447273df556SFrank Mayhar 4481c13d5c0STheodore Ts'o es->s_last_error_ino = cpu_to_le32(inode->i_ino); 4491c13d5c0STheodore Ts'o es->s_last_error_block = cpu_to_le64(block); 4501c13d5c0STheodore Ts'o save_error_info(inode->i_sb, function, line); 451273df556SFrank Mayhar va_start(args, fmt); 452f7c21177STheodore Ts'o vaf.fmt = fmt; 453f7c21177STheodore Ts'o vaf.va = &args; 454c398eda0STheodore Ts'o printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ", 455c398eda0STheodore Ts'o inode->i_sb->s_id, function, line, inode->i_ino); 456c398eda0STheodore Ts'o if (block) 457f7c21177STheodore Ts'o printk(KERN_CONT "block %llu: ", block); 458f7c21177STheodore Ts'o printk(KERN_CONT "comm %s: %pV\n", current->comm, &vaf); 459273df556SFrank Mayhar va_end(args); 460273df556SFrank Mayhar 461273df556SFrank Mayhar ext4_handle_error(inode->i_sb); 462273df556SFrank Mayhar } 463273df556SFrank Mayhar 464c398eda0STheodore Ts'o void ext4_error_file(struct file *file, const char *function, 465f7c21177STheodore Ts'o unsigned int line, ext4_fsblk_t block, 466f7c21177STheodore Ts'o const char *fmt, ...) 467273df556SFrank Mayhar { 468273df556SFrank Mayhar va_list args; 469f7c21177STheodore Ts'o struct va_format vaf; 4701c13d5c0STheodore Ts'o struct ext4_super_block *es; 471273df556SFrank Mayhar struct inode *inode = file->f_dentry->d_inode; 472273df556SFrank Mayhar char pathname[80], *path; 473273df556SFrank Mayhar 4741c13d5c0STheodore Ts'o es = EXT4_SB(inode->i_sb)->s_es; 4751c13d5c0STheodore Ts'o es->s_last_error_ino = cpu_to_le32(inode->i_ino); 4761c13d5c0STheodore Ts'o save_error_info(inode->i_sb, function, line); 477273df556SFrank Mayhar path = d_path(&(file->f_path), pathname, sizeof(pathname)); 478f9a62d09SDan Carpenter if (IS_ERR(path)) 479273df556SFrank Mayhar path = "(unknown)"; 480273df556SFrank Mayhar printk(KERN_CRIT 481f7c21177STheodore Ts'o "EXT4-fs error (device %s): %s:%d: inode #%lu: ", 482f7c21177STheodore Ts'o inode->i_sb->s_id, function, line, inode->i_ino); 483f7c21177STheodore Ts'o if (block) 484f7c21177STheodore Ts'o printk(KERN_CONT "block %llu: ", block); 485f7c21177STheodore Ts'o va_start(args, fmt); 486f7c21177STheodore Ts'o vaf.fmt = fmt; 487f7c21177STheodore Ts'o vaf.va = &args; 488f7c21177STheodore Ts'o printk(KERN_CONT "comm %s: path %s: %pV\n", current->comm, path, &vaf); 489273df556SFrank Mayhar va_end(args); 490273df556SFrank Mayhar 491273df556SFrank Mayhar ext4_handle_error(inode->i_sb); 492273df556SFrank Mayhar } 493273df556SFrank Mayhar 494617ba13bSMingming Cao static const char *ext4_decode_error(struct super_block *sb, int errno, 495ac27a0ecSDave Kleikamp char nbuf[16]) 496ac27a0ecSDave Kleikamp { 497ac27a0ecSDave Kleikamp char *errstr = NULL; 498ac27a0ecSDave Kleikamp 499ac27a0ecSDave Kleikamp switch (errno) { 500ac27a0ecSDave Kleikamp case -EIO: 501ac27a0ecSDave Kleikamp errstr = "IO failure"; 502ac27a0ecSDave Kleikamp break; 503ac27a0ecSDave Kleikamp case -ENOMEM: 504ac27a0ecSDave Kleikamp errstr = "Out of memory"; 505ac27a0ecSDave Kleikamp break; 506ac27a0ecSDave Kleikamp case -EROFS: 50778f1ddbbSTheodore Ts'o if (!sb || (EXT4_SB(sb)->s_journal && 50878f1ddbbSTheodore Ts'o EXT4_SB(sb)->s_journal->j_flags & JBD2_ABORT)) 509ac27a0ecSDave Kleikamp errstr = "Journal has aborted"; 510ac27a0ecSDave Kleikamp else 511ac27a0ecSDave Kleikamp errstr = "Readonly filesystem"; 512ac27a0ecSDave Kleikamp break; 513ac27a0ecSDave Kleikamp default: 514ac27a0ecSDave Kleikamp /* If the caller passed in an extra buffer for unknown 515ac27a0ecSDave Kleikamp * errors, textualise them now. Else we just return 516ac27a0ecSDave Kleikamp * NULL. */ 517ac27a0ecSDave Kleikamp if (nbuf) { 518ac27a0ecSDave Kleikamp /* Check for truncated error codes... */ 519ac27a0ecSDave Kleikamp if (snprintf(nbuf, 16, "error %d", -errno) >= 0) 520ac27a0ecSDave Kleikamp errstr = nbuf; 521ac27a0ecSDave Kleikamp } 522ac27a0ecSDave Kleikamp break; 523ac27a0ecSDave Kleikamp } 524ac27a0ecSDave Kleikamp 525ac27a0ecSDave Kleikamp return errstr; 526ac27a0ecSDave Kleikamp } 527ac27a0ecSDave Kleikamp 528617ba13bSMingming Cao /* __ext4_std_error decodes expected errors from journaling functions 529ac27a0ecSDave Kleikamp * automatically and invokes the appropriate error response. */ 530ac27a0ecSDave Kleikamp 531c398eda0STheodore Ts'o void __ext4_std_error(struct super_block *sb, const char *function, 532c398eda0STheodore Ts'o unsigned int line, int errno) 533ac27a0ecSDave Kleikamp { 534ac27a0ecSDave Kleikamp char nbuf[16]; 535ac27a0ecSDave Kleikamp const char *errstr; 536ac27a0ecSDave Kleikamp 537ac27a0ecSDave Kleikamp /* Special case: if the error is EROFS, and we're not already 538ac27a0ecSDave Kleikamp * inside a transaction, then there's really no point in logging 539ac27a0ecSDave Kleikamp * an error. */ 540ac27a0ecSDave Kleikamp if (errno == -EROFS && journal_current_handle() == NULL && 541ac27a0ecSDave Kleikamp (sb->s_flags & MS_RDONLY)) 542ac27a0ecSDave Kleikamp return; 543ac27a0ecSDave Kleikamp 544617ba13bSMingming Cao errstr = ext4_decode_error(sb, errno, nbuf); 545c398eda0STheodore Ts'o printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n", 546c398eda0STheodore Ts'o sb->s_id, function, line, errstr); 5471c13d5c0STheodore Ts'o save_error_info(sb, function, line); 548ac27a0ecSDave Kleikamp 549617ba13bSMingming Cao ext4_handle_error(sb); 550ac27a0ecSDave Kleikamp } 551ac27a0ecSDave Kleikamp 552ac27a0ecSDave Kleikamp /* 553617ba13bSMingming Cao * ext4_abort is a much stronger failure handler than ext4_error. The 554ac27a0ecSDave Kleikamp * abort function may be used to deal with unrecoverable failures such 555ac27a0ecSDave Kleikamp * as journal IO errors or ENOMEM at a critical moment in log management. 556ac27a0ecSDave Kleikamp * 557ac27a0ecSDave Kleikamp * We unconditionally force the filesystem into an ABORT|READONLY state, 558ac27a0ecSDave Kleikamp * unless the error response on the fs has been set to panic in which 559ac27a0ecSDave Kleikamp * case we take the easy way out and panic immediately. 560ac27a0ecSDave Kleikamp */ 561ac27a0ecSDave Kleikamp 562c67d859eSTheodore Ts'o void __ext4_abort(struct super_block *sb, const char *function, 563c398eda0STheodore Ts'o unsigned int line, const char *fmt, ...) 564ac27a0ecSDave Kleikamp { 565ac27a0ecSDave Kleikamp va_list args; 566ac27a0ecSDave Kleikamp 5671c13d5c0STheodore Ts'o save_error_info(sb, function, line); 568ac27a0ecSDave Kleikamp va_start(args, fmt); 569c398eda0STheodore Ts'o printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: ", sb->s_id, 570c398eda0STheodore Ts'o function, line); 571ac27a0ecSDave Kleikamp vprintk(fmt, args); 572ac27a0ecSDave Kleikamp printk("\n"); 573ac27a0ecSDave Kleikamp va_end(args); 574ac27a0ecSDave Kleikamp 5751c13d5c0STheodore Ts'o if ((sb->s_flags & MS_RDONLY) == 0) { 576b31e1552SEric Sandeen ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); 577ac27a0ecSDave Kleikamp sb->s_flags |= MS_RDONLY; 5784ab2f15bSTheodore Ts'o EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; 579ef2cabf7SHidehiro Kawai if (EXT4_SB(sb)->s_journal) 580dab291afSMingming Cao jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); 5811c13d5c0STheodore Ts'o save_error_info(sb, function, line); 5821c13d5c0STheodore Ts'o } 5831c13d5c0STheodore Ts'o if (test_opt(sb, ERRORS_PANIC)) 5841c13d5c0STheodore Ts'o panic("EXT4-fs panic from previous error\n"); 585ac27a0ecSDave Kleikamp } 586ac27a0ecSDave Kleikamp 5870ff2ea7dSJoe Perches void ext4_msg(struct super_block *sb, const char *prefix, const char *fmt, ...) 588b31e1552SEric Sandeen { 5890ff2ea7dSJoe Perches struct va_format vaf; 590b31e1552SEric Sandeen va_list args; 591b31e1552SEric Sandeen 592b31e1552SEric Sandeen va_start(args, fmt); 5930ff2ea7dSJoe Perches vaf.fmt = fmt; 5940ff2ea7dSJoe Perches vaf.va = &args; 5950ff2ea7dSJoe Perches printk("%sEXT4-fs (%s): %pV\n", prefix, sb->s_id, &vaf); 596b31e1552SEric Sandeen va_end(args); 597b31e1552SEric Sandeen } 598b31e1552SEric Sandeen 59912062dddSEric Sandeen void __ext4_warning(struct super_block *sb, const char *function, 600c398eda0STheodore Ts'o unsigned int line, const char *fmt, ...) 601ac27a0ecSDave Kleikamp { 6020ff2ea7dSJoe Perches struct va_format vaf; 603ac27a0ecSDave Kleikamp va_list args; 604ac27a0ecSDave Kleikamp 605ac27a0ecSDave Kleikamp va_start(args, fmt); 6060ff2ea7dSJoe Perches vaf.fmt = fmt; 6070ff2ea7dSJoe Perches vaf.va = &args; 6080ff2ea7dSJoe Perches printk(KERN_WARNING "EXT4-fs warning (device %s): %s:%d: %pV\n", 6090ff2ea7dSJoe Perches sb->s_id, function, line, &vaf); 610ac27a0ecSDave Kleikamp va_end(args); 611ac27a0ecSDave Kleikamp } 612ac27a0ecSDave Kleikamp 613e29136f8STheodore Ts'o void __ext4_grp_locked_error(const char *function, unsigned int line, 614e29136f8STheodore Ts'o struct super_block *sb, ext4_group_t grp, 615e29136f8STheodore Ts'o unsigned long ino, ext4_fsblk_t block, 616e29136f8STheodore Ts'o const char *fmt, ...) 6175d1b1b3fSAneesh Kumar K.V __releases(bitlock) 6185d1b1b3fSAneesh Kumar K.V __acquires(bitlock) 6195d1b1b3fSAneesh Kumar K.V { 6200ff2ea7dSJoe Perches struct va_format vaf; 6215d1b1b3fSAneesh Kumar K.V va_list args; 6225d1b1b3fSAneesh Kumar K.V struct ext4_super_block *es = EXT4_SB(sb)->s_es; 6235d1b1b3fSAneesh Kumar K.V 6241c13d5c0STheodore Ts'o es->s_last_error_ino = cpu_to_le32(ino); 6251c13d5c0STheodore Ts'o es->s_last_error_block = cpu_to_le64(block); 6261c13d5c0STheodore Ts'o __save_error_info(sb, function, line); 6270ff2ea7dSJoe Perches 6285d1b1b3fSAneesh Kumar K.V va_start(args, fmt); 6290ff2ea7dSJoe Perches 6300ff2ea7dSJoe Perches vaf.fmt = fmt; 6310ff2ea7dSJoe Perches vaf.va = &args; 63221149d61SRobin Dong printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ", 633e29136f8STheodore Ts'o sb->s_id, function, line, grp); 634e29136f8STheodore Ts'o if (ino) 6350ff2ea7dSJoe Perches printk(KERN_CONT "inode %lu: ", ino); 636e29136f8STheodore Ts'o if (block) 6370ff2ea7dSJoe Perches printk(KERN_CONT "block %llu:", (unsigned long long) block); 6380ff2ea7dSJoe Perches printk(KERN_CONT "%pV\n", &vaf); 6395d1b1b3fSAneesh Kumar K.V va_end(args); 6405d1b1b3fSAneesh Kumar K.V 6415d1b1b3fSAneesh Kumar K.V if (test_opt(sb, ERRORS_CONT)) { 642e2d67052STheodore Ts'o ext4_commit_super(sb, 0); 6435d1b1b3fSAneesh Kumar K.V return; 6445d1b1b3fSAneesh Kumar K.V } 6451c13d5c0STheodore Ts'o 6465d1b1b3fSAneesh Kumar K.V ext4_unlock_group(sb, grp); 6475d1b1b3fSAneesh Kumar K.V ext4_handle_error(sb); 6485d1b1b3fSAneesh Kumar K.V /* 6495d1b1b3fSAneesh Kumar K.V * We only get here in the ERRORS_RO case; relocking the group 6505d1b1b3fSAneesh Kumar K.V * may be dangerous, but nothing bad will happen since the 6515d1b1b3fSAneesh Kumar K.V * filesystem will have already been marked read/only and the 6525d1b1b3fSAneesh Kumar K.V * journal has been aborted. We return 1 as a hint to callers 6535d1b1b3fSAneesh Kumar K.V * who might what to use the return value from 65425985edcSLucas De Marchi * ext4_grp_locked_error() to distinguish between the 6555d1b1b3fSAneesh Kumar K.V * ERRORS_CONT and ERRORS_RO case, and perhaps return more 6565d1b1b3fSAneesh Kumar K.V * aggressively from the ext4 function in question, with a 6575d1b1b3fSAneesh Kumar K.V * more appropriate error code. 6585d1b1b3fSAneesh Kumar K.V */ 6595d1b1b3fSAneesh Kumar K.V ext4_lock_group(sb, grp); 6605d1b1b3fSAneesh Kumar K.V return; 6615d1b1b3fSAneesh Kumar K.V } 6625d1b1b3fSAneesh Kumar K.V 663617ba13bSMingming Cao void ext4_update_dynamic_rev(struct super_block *sb) 664ac27a0ecSDave Kleikamp { 665617ba13bSMingming Cao struct ext4_super_block *es = EXT4_SB(sb)->s_es; 666ac27a0ecSDave Kleikamp 667617ba13bSMingming Cao if (le32_to_cpu(es->s_rev_level) > EXT4_GOOD_OLD_REV) 668ac27a0ecSDave Kleikamp return; 669ac27a0ecSDave Kleikamp 67012062dddSEric Sandeen ext4_warning(sb, 671ac27a0ecSDave Kleikamp "updating to rev %d because of new feature flag, " 672ac27a0ecSDave Kleikamp "running e2fsck is recommended", 673617ba13bSMingming Cao EXT4_DYNAMIC_REV); 674ac27a0ecSDave Kleikamp 675617ba13bSMingming Cao es->s_first_ino = cpu_to_le32(EXT4_GOOD_OLD_FIRST_INO); 676617ba13bSMingming Cao es->s_inode_size = cpu_to_le16(EXT4_GOOD_OLD_INODE_SIZE); 677617ba13bSMingming Cao es->s_rev_level = cpu_to_le32(EXT4_DYNAMIC_REV); 678ac27a0ecSDave Kleikamp /* leave es->s_feature_*compat flags alone */ 679ac27a0ecSDave Kleikamp /* es->s_uuid will be set by e2fsck if empty */ 680ac27a0ecSDave Kleikamp 681ac27a0ecSDave Kleikamp /* 682ac27a0ecSDave Kleikamp * The rest of the superblock fields should be zero, and if not it 683ac27a0ecSDave Kleikamp * means they are likely already in use, so leave them alone. We 684ac27a0ecSDave Kleikamp * can leave it up to e2fsck to clean up any inconsistencies there. 685ac27a0ecSDave Kleikamp */ 686ac27a0ecSDave Kleikamp } 687ac27a0ecSDave Kleikamp 688ac27a0ecSDave Kleikamp /* 689ac27a0ecSDave Kleikamp * Open the external journal device 690ac27a0ecSDave Kleikamp */ 691b31e1552SEric Sandeen static struct block_device *ext4_blkdev_get(dev_t dev, struct super_block *sb) 692ac27a0ecSDave Kleikamp { 693ac27a0ecSDave Kleikamp struct block_device *bdev; 694ac27a0ecSDave Kleikamp char b[BDEVNAME_SIZE]; 695ac27a0ecSDave Kleikamp 696d4d77629STejun Heo bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, sb); 697ac27a0ecSDave Kleikamp if (IS_ERR(bdev)) 698ac27a0ecSDave Kleikamp goto fail; 699ac27a0ecSDave Kleikamp return bdev; 700ac27a0ecSDave Kleikamp 701ac27a0ecSDave Kleikamp fail: 702b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "failed to open journal device %s: %ld", 703ac27a0ecSDave Kleikamp __bdevname(dev, b), PTR_ERR(bdev)); 704ac27a0ecSDave Kleikamp return NULL; 705ac27a0ecSDave Kleikamp } 706ac27a0ecSDave Kleikamp 707ac27a0ecSDave Kleikamp /* 708ac27a0ecSDave Kleikamp * Release the journal device 709ac27a0ecSDave Kleikamp */ 710617ba13bSMingming Cao static int ext4_blkdev_put(struct block_device *bdev) 711ac27a0ecSDave Kleikamp { 712e525fd89STejun Heo return blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); 713ac27a0ecSDave Kleikamp } 714ac27a0ecSDave Kleikamp 715617ba13bSMingming Cao static int ext4_blkdev_remove(struct ext4_sb_info *sbi) 716ac27a0ecSDave Kleikamp { 717ac27a0ecSDave Kleikamp struct block_device *bdev; 718ac27a0ecSDave Kleikamp int ret = -ENODEV; 719ac27a0ecSDave Kleikamp 720ac27a0ecSDave Kleikamp bdev = sbi->journal_bdev; 721ac27a0ecSDave Kleikamp if (bdev) { 722617ba13bSMingming Cao ret = ext4_blkdev_put(bdev); 723ac27a0ecSDave Kleikamp sbi->journal_bdev = NULL; 724ac27a0ecSDave Kleikamp } 725ac27a0ecSDave Kleikamp return ret; 726ac27a0ecSDave Kleikamp } 727ac27a0ecSDave Kleikamp 728ac27a0ecSDave Kleikamp static inline struct inode *orphan_list_entry(struct list_head *l) 729ac27a0ecSDave Kleikamp { 730617ba13bSMingming Cao return &list_entry(l, struct ext4_inode_info, i_orphan)->vfs_inode; 731ac27a0ecSDave Kleikamp } 732ac27a0ecSDave Kleikamp 733617ba13bSMingming Cao static void dump_orphan_list(struct super_block *sb, struct ext4_sb_info *sbi) 734ac27a0ecSDave Kleikamp { 735ac27a0ecSDave Kleikamp struct list_head *l; 736ac27a0ecSDave Kleikamp 737b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "sb orphan head is %d", 738ac27a0ecSDave Kleikamp le32_to_cpu(sbi->s_es->s_last_orphan)); 739ac27a0ecSDave Kleikamp 740ac27a0ecSDave Kleikamp printk(KERN_ERR "sb_info orphan list:\n"); 741ac27a0ecSDave Kleikamp list_for_each(l, &sbi->s_orphan) { 742ac27a0ecSDave Kleikamp struct inode *inode = orphan_list_entry(l); 743ac27a0ecSDave Kleikamp printk(KERN_ERR " " 744ac27a0ecSDave Kleikamp "inode %s:%lu at %p: mode %o, nlink %d, next %d\n", 745ac27a0ecSDave Kleikamp inode->i_sb->s_id, inode->i_ino, inode, 746ac27a0ecSDave Kleikamp inode->i_mode, inode->i_nlink, 747ac27a0ecSDave Kleikamp NEXT_ORPHAN(inode)); 748ac27a0ecSDave Kleikamp } 749ac27a0ecSDave Kleikamp } 750ac27a0ecSDave Kleikamp 751617ba13bSMingming Cao static void ext4_put_super(struct super_block *sb) 752ac27a0ecSDave Kleikamp { 753617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 754617ba13bSMingming Cao struct ext4_super_block *es = sbi->s_es; 755ef2cabf7SHidehiro Kawai int i, err; 756ac27a0ecSDave Kleikamp 757857ac889SLukas Czerner ext4_unregister_li_request(sb); 758e0ccfd95SChristoph Hellwig dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); 759e0ccfd95SChristoph Hellwig 7604c0425ffSMingming Cao flush_workqueue(sbi->dio_unwritten_wq); 7614c0425ffSMingming Cao destroy_workqueue(sbi->dio_unwritten_wq); 7624c0425ffSMingming Cao 763a9e220f8SAl Viro lock_super(sb); 7648c85e125SChristoph Hellwig if (sb->s_dirt) 765ebc1ac16SChristoph Hellwig ext4_commit_super(sb, 1); 7668c85e125SChristoph Hellwig 7670390131bSFrank Mayhar if (sbi->s_journal) { 768ef2cabf7SHidehiro Kawai err = jbd2_journal_destroy(sbi->s_journal); 76947b4a50bSJan Kara sbi->s_journal = NULL; 770ef2cabf7SHidehiro Kawai if (err < 0) 771c67d859eSTheodore Ts'o ext4_abort(sb, "Couldn't clean up the journal"); 7720390131bSFrank Mayhar } 773d4edac31SJosef Bacik 774a1c6c569SSergey Senozhatsky del_timer(&sbi->s_err_report); 775d4edac31SJosef Bacik ext4_release_system_zone(sb); 776d4edac31SJosef Bacik ext4_mb_release(sb); 777d4edac31SJosef Bacik ext4_ext_release(sb); 778d4edac31SJosef Bacik ext4_xattr_put_super(sb); 779d4edac31SJosef Bacik 780ac27a0ecSDave Kleikamp if (!(sb->s_flags & MS_RDONLY)) { 781617ba13bSMingming Cao EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 782ac27a0ecSDave Kleikamp es->s_state = cpu_to_le16(sbi->s_mount_state); 783e2d67052STheodore Ts'o ext4_commit_super(sb, 1); 784ac27a0ecSDave Kleikamp } 785240799cdSTheodore Ts'o if (sbi->s_proc) { 7869f6200bbSTheodore Ts'o remove_proc_entry(sb->s_id, ext4_proc_root); 787240799cdSTheodore Ts'o } 7883197ebdbSTheodore Ts'o kobject_del(&sbi->s_kobj); 789ac27a0ecSDave Kleikamp 790ac27a0ecSDave Kleikamp for (i = 0; i < sbi->s_gdb_count; i++) 791ac27a0ecSDave Kleikamp brelse(sbi->s_group_desc[i]); 792ac27a0ecSDave Kleikamp kfree(sbi->s_group_desc); 793c5ca7c76STheodore Ts'o if (is_vmalloc_addr(sbi->s_flex_groups)) 794c5ca7c76STheodore Ts'o vfree(sbi->s_flex_groups); 795c5ca7c76STheodore Ts'o else 796772cb7c8SJose R. Santos kfree(sbi->s_flex_groups); 797ac27a0ecSDave Kleikamp percpu_counter_destroy(&sbi->s_freeblocks_counter); 798ac27a0ecSDave Kleikamp percpu_counter_destroy(&sbi->s_freeinodes_counter); 799ac27a0ecSDave Kleikamp percpu_counter_destroy(&sbi->s_dirs_counter); 8006bc6e63fSAneesh Kumar K.V percpu_counter_destroy(&sbi->s_dirtyblocks_counter); 801ac27a0ecSDave Kleikamp brelse(sbi->s_sbh); 802ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 803ac27a0ecSDave Kleikamp for (i = 0; i < MAXQUOTAS; i++) 804ac27a0ecSDave Kleikamp kfree(sbi->s_qf_names[i]); 805ac27a0ecSDave Kleikamp #endif 806ac27a0ecSDave Kleikamp 807ac27a0ecSDave Kleikamp /* Debugging code just in case the in-memory inode orphan list 808ac27a0ecSDave Kleikamp * isn't empty. The on-disk one can be non-empty if we've 809ac27a0ecSDave Kleikamp * detected an error and taken the fs readonly, but the 810ac27a0ecSDave Kleikamp * in-memory list had better be clean by this point. */ 811ac27a0ecSDave Kleikamp if (!list_empty(&sbi->s_orphan)) 812ac27a0ecSDave Kleikamp dump_orphan_list(sb, sbi); 813ac27a0ecSDave Kleikamp J_ASSERT(list_empty(&sbi->s_orphan)); 814ac27a0ecSDave Kleikamp 815f98393a6SPeter Zijlstra invalidate_bdev(sb->s_bdev); 816ac27a0ecSDave Kleikamp if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) { 817ac27a0ecSDave Kleikamp /* 818ac27a0ecSDave Kleikamp * Invalidate the journal device's buffers. We don't want them 819ac27a0ecSDave Kleikamp * floating about in memory - the physical journal device may 820ac27a0ecSDave Kleikamp * hotswapped, and it breaks the `ro-after' testing code. 821ac27a0ecSDave Kleikamp */ 822ac27a0ecSDave Kleikamp sync_blockdev(sbi->journal_bdev); 823f98393a6SPeter Zijlstra invalidate_bdev(sbi->journal_bdev); 824617ba13bSMingming Cao ext4_blkdev_remove(sbi); 825ac27a0ecSDave Kleikamp } 826c5e06d10SJohann Lombardi if (sbi->s_mmp_tsk) 827c5e06d10SJohann Lombardi kthread_stop(sbi->s_mmp_tsk); 828ac27a0ecSDave Kleikamp sb->s_fs_info = NULL; 8293197ebdbSTheodore Ts'o /* 8303197ebdbSTheodore Ts'o * Now that we are completely done shutting down the 8313197ebdbSTheodore Ts'o * superblock, we need to actually destroy the kobject. 8323197ebdbSTheodore Ts'o */ 8333197ebdbSTheodore Ts'o unlock_super(sb); 8343197ebdbSTheodore Ts'o kobject_put(&sbi->s_kobj); 8353197ebdbSTheodore Ts'o wait_for_completion(&sbi->s_kobj_unregister); 836705895b6SPekka Enberg kfree(sbi->s_blockgroup_lock); 837ac27a0ecSDave Kleikamp kfree(sbi); 838ac27a0ecSDave Kleikamp } 839ac27a0ecSDave Kleikamp 840e18b890bSChristoph Lameter static struct kmem_cache *ext4_inode_cachep; 841ac27a0ecSDave Kleikamp 842ac27a0ecSDave Kleikamp /* 843ac27a0ecSDave Kleikamp * Called inside transaction, so use GFP_NOFS 844ac27a0ecSDave Kleikamp */ 845617ba13bSMingming Cao static struct inode *ext4_alloc_inode(struct super_block *sb) 846ac27a0ecSDave Kleikamp { 847617ba13bSMingming Cao struct ext4_inode_info *ei; 848ac27a0ecSDave Kleikamp 849e6b4f8daSChristoph Lameter ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS); 850ac27a0ecSDave Kleikamp if (!ei) 851ac27a0ecSDave Kleikamp return NULL; 8520b8e58a1SAndreas Dilger 853ac27a0ecSDave Kleikamp ei->vfs_inode.i_version = 1; 85491246c00SAneesh Kumar K.V ei->vfs_inode.i_data.writeback_index = 0; 855a86c6181SAlex Tomas memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); 856c9de560dSAlex Tomas INIT_LIST_HEAD(&ei->i_prealloc_list); 857c9de560dSAlex Tomas spin_lock_init(&ei->i_prealloc_lock); 858d2a17637SMingming Cao ei->i_reserved_data_blocks = 0; 859d2a17637SMingming Cao ei->i_reserved_meta_blocks = 0; 860d2a17637SMingming Cao ei->i_allocated_meta_blocks = 0; 8619d0be502STheodore Ts'o ei->i_da_metadata_calc_len = 0; 862d2a17637SMingming Cao spin_lock_init(&(ei->i_block_reservation_lock)); 863a9e7f447SDmitry Monakhov #ifdef CONFIG_QUOTA 864a9e7f447SDmitry Monakhov ei->i_reserved_quota = 0; 865a9e7f447SDmitry Monakhov #endif 8668aefcd55STheodore Ts'o ei->jinode = NULL; 867c7064ef1SJiaying Zhang INIT_LIST_HEAD(&ei->i_completed_io_list); 868744692dcSJiaying Zhang spin_lock_init(&ei->i_completed_io_lock); 8698d5d02e6SMingming Cao ei->cur_aio_dio = NULL; 870b436b9beSJan Kara ei->i_sync_tid = 0; 871b436b9beSJan Kara ei->i_datasync_tid = 0; 872f7ad6d2eSTheodore Ts'o atomic_set(&ei->i_ioend_count, 0); 873e9e3bcecSEric Sandeen atomic_set(&ei->i_aiodio_unwritten, 0); 8740b8e58a1SAndreas Dilger 875ac27a0ecSDave Kleikamp return &ei->vfs_inode; 876ac27a0ecSDave Kleikamp } 877ac27a0ecSDave Kleikamp 8787ff9c073STheodore Ts'o static int ext4_drop_inode(struct inode *inode) 8797ff9c073STheodore Ts'o { 8807ff9c073STheodore Ts'o int drop = generic_drop_inode(inode); 8817ff9c073STheodore Ts'o 8827ff9c073STheodore Ts'o trace_ext4_drop_inode(inode, drop); 8837ff9c073STheodore Ts'o return drop; 8847ff9c073STheodore Ts'o } 8857ff9c073STheodore Ts'o 886fa0d7e3dSNick Piggin static void ext4_i_callback(struct rcu_head *head) 887fa0d7e3dSNick Piggin { 888fa0d7e3dSNick Piggin struct inode *inode = container_of(head, struct inode, i_rcu); 889fa0d7e3dSNick Piggin INIT_LIST_HEAD(&inode->i_dentry); 890fa0d7e3dSNick Piggin kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); 891fa0d7e3dSNick Piggin } 892fa0d7e3dSNick Piggin 893617ba13bSMingming Cao static void ext4_destroy_inode(struct inode *inode) 894ac27a0ecSDave Kleikamp { 895f7ad6d2eSTheodore Ts'o ext4_ioend_wait(inode); 8969f7dd93dSVasily Averin if (!list_empty(&(EXT4_I(inode)->i_orphan))) { 897b31e1552SEric Sandeen ext4_msg(inode->i_sb, KERN_ERR, 898b31e1552SEric Sandeen "Inode %lu (%p): orphan list check failed!", 899b31e1552SEric Sandeen inode->i_ino, EXT4_I(inode)); 9009f7dd93dSVasily Averin print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4, 9019f7dd93dSVasily Averin EXT4_I(inode), sizeof(struct ext4_inode_info), 9029f7dd93dSVasily Averin true); 9039f7dd93dSVasily Averin dump_stack(); 9049f7dd93dSVasily Averin } 905fa0d7e3dSNick Piggin call_rcu(&inode->i_rcu, ext4_i_callback); 906ac27a0ecSDave Kleikamp } 907ac27a0ecSDave Kleikamp 90851cc5068SAlexey Dobriyan static void init_once(void *foo) 909ac27a0ecSDave Kleikamp { 910617ba13bSMingming Cao struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; 911ac27a0ecSDave Kleikamp 912ac27a0ecSDave Kleikamp INIT_LIST_HEAD(&ei->i_orphan); 91303010a33STheodore Ts'o #ifdef CONFIG_EXT4_FS_XATTR 914ac27a0ecSDave Kleikamp init_rwsem(&ei->xattr_sem); 915ac27a0ecSDave Kleikamp #endif 9160e855ac8SAneesh Kumar K.V init_rwsem(&ei->i_data_sem); 917ac27a0ecSDave Kleikamp inode_init_once(&ei->vfs_inode); 918ac27a0ecSDave Kleikamp } 919ac27a0ecSDave Kleikamp 920ac27a0ecSDave Kleikamp static int init_inodecache(void) 921ac27a0ecSDave Kleikamp { 922617ba13bSMingming Cao ext4_inode_cachep = kmem_cache_create("ext4_inode_cache", 923617ba13bSMingming Cao sizeof(struct ext4_inode_info), 924ac27a0ecSDave Kleikamp 0, (SLAB_RECLAIM_ACCOUNT| 925ac27a0ecSDave Kleikamp SLAB_MEM_SPREAD), 92620c2df83SPaul Mundt init_once); 927617ba13bSMingming Cao if (ext4_inode_cachep == NULL) 928ac27a0ecSDave Kleikamp return -ENOMEM; 929ac27a0ecSDave Kleikamp return 0; 930ac27a0ecSDave Kleikamp } 931ac27a0ecSDave Kleikamp 932ac27a0ecSDave Kleikamp static void destroy_inodecache(void) 933ac27a0ecSDave Kleikamp { 934617ba13bSMingming Cao kmem_cache_destroy(ext4_inode_cachep); 935ac27a0ecSDave Kleikamp } 936ac27a0ecSDave Kleikamp 9370930fcc1SAl Viro void ext4_clear_inode(struct inode *inode) 938ac27a0ecSDave Kleikamp { 9390930fcc1SAl Viro invalidate_inode_buffers(inode); 9400930fcc1SAl Viro end_writeback(inode); 9419f754758SChristoph Hellwig dquot_drop(inode); 942c2ea3fdeSTheodore Ts'o ext4_discard_preallocations(inode); 9438aefcd55STheodore Ts'o if (EXT4_I(inode)->jinode) { 9448aefcd55STheodore Ts'o jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode), 9458aefcd55STheodore Ts'o EXT4_I(inode)->jinode); 9468aefcd55STheodore Ts'o jbd2_free_inode(EXT4_I(inode)->jinode); 9478aefcd55STheodore Ts'o EXT4_I(inode)->jinode = NULL; 9488aefcd55STheodore Ts'o } 949ac27a0ecSDave Kleikamp } 950ac27a0ecSDave Kleikamp 9512b2d6d01STheodore Ts'o static inline void ext4_show_quota_options(struct seq_file *seq, 9522b2d6d01STheodore Ts'o struct super_block *sb) 953ac27a0ecSDave Kleikamp { 954ac27a0ecSDave Kleikamp #if defined(CONFIG_QUOTA) 955617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 956ac27a0ecSDave Kleikamp 9575a20bdfcSJan Kara if (sbi->s_jquota_fmt) { 9585a20bdfcSJan Kara char *fmtname = ""; 9595a20bdfcSJan Kara 9605a20bdfcSJan Kara switch (sbi->s_jquota_fmt) { 9615a20bdfcSJan Kara case QFMT_VFS_OLD: 9625a20bdfcSJan Kara fmtname = "vfsold"; 9635a20bdfcSJan Kara break; 9645a20bdfcSJan Kara case QFMT_VFS_V0: 9655a20bdfcSJan Kara fmtname = "vfsv0"; 9665a20bdfcSJan Kara break; 9675a20bdfcSJan Kara case QFMT_VFS_V1: 9685a20bdfcSJan Kara fmtname = "vfsv1"; 9695a20bdfcSJan Kara break; 9705a20bdfcSJan Kara } 9715a20bdfcSJan Kara seq_printf(seq, ",jqfmt=%s", fmtname); 9725a20bdfcSJan Kara } 973ac27a0ecSDave Kleikamp 974ac27a0ecSDave Kleikamp if (sbi->s_qf_names[USRQUOTA]) 975ac27a0ecSDave Kleikamp seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); 976ac27a0ecSDave Kleikamp 977ac27a0ecSDave Kleikamp if (sbi->s_qf_names[GRPQUOTA]) 978ac27a0ecSDave Kleikamp seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]); 979ac27a0ecSDave Kleikamp 980482a7425SDmitry Monakhov if (test_opt(sb, USRQUOTA)) 981ac27a0ecSDave Kleikamp seq_puts(seq, ",usrquota"); 982ac27a0ecSDave Kleikamp 983482a7425SDmitry Monakhov if (test_opt(sb, GRPQUOTA)) 984ac27a0ecSDave Kleikamp seq_puts(seq, ",grpquota"); 985ac27a0ecSDave Kleikamp #endif 986ac27a0ecSDave Kleikamp } 987ac27a0ecSDave Kleikamp 988d9c9bef1SMiklos Szeredi /* 989d9c9bef1SMiklos Szeredi * Show an option if 990d9c9bef1SMiklos Szeredi * - it's set to a non-default value OR 991d9c9bef1SMiklos Szeredi * - if the per-sb default is different from the global default 992d9c9bef1SMiklos Szeredi */ 993617ba13bSMingming Cao static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) 994ac27a0ecSDave Kleikamp { 995aa22df2cSAneesh Kumar K.V int def_errors; 996aa22df2cSAneesh Kumar K.V unsigned long def_mount_opts; 997ac27a0ecSDave Kleikamp struct super_block *sb = vfs->mnt_sb; 998d9c9bef1SMiklos Szeredi struct ext4_sb_info *sbi = EXT4_SB(sb); 999d9c9bef1SMiklos Szeredi struct ext4_super_block *es = sbi->s_es; 1000d9c9bef1SMiklos Szeredi 1001d9c9bef1SMiklos Szeredi def_mount_opts = le32_to_cpu(es->s_default_mount_opts); 1002aa22df2cSAneesh Kumar K.V def_errors = le16_to_cpu(es->s_errors); 1003d9c9bef1SMiklos Szeredi 1004d9c9bef1SMiklos Szeredi if (sbi->s_sb_block != 1) 1005d9c9bef1SMiklos Szeredi seq_printf(seq, ",sb=%llu", sbi->s_sb_block); 1006d9c9bef1SMiklos Szeredi if (test_opt(sb, MINIX_DF)) 1007d9c9bef1SMiklos Szeredi seq_puts(seq, ",minixdf"); 1008aa22df2cSAneesh Kumar K.V if (test_opt(sb, GRPID) && !(def_mount_opts & EXT4_DEFM_BSDGROUPS)) 1009d9c9bef1SMiklos Szeredi seq_puts(seq, ",grpid"); 1010d9c9bef1SMiklos Szeredi if (!test_opt(sb, GRPID) && (def_mount_opts & EXT4_DEFM_BSDGROUPS)) 1011d9c9bef1SMiklos Szeredi seq_puts(seq, ",nogrpid"); 1012d9c9bef1SMiklos Szeredi if (sbi->s_resuid != EXT4_DEF_RESUID || 1013d9c9bef1SMiklos Szeredi le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID) { 1014d9c9bef1SMiklos Szeredi seq_printf(seq, ",resuid=%u", sbi->s_resuid); 1015d9c9bef1SMiklos Szeredi } 1016d9c9bef1SMiklos Szeredi if (sbi->s_resgid != EXT4_DEF_RESGID || 1017d9c9bef1SMiklos Szeredi le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) { 1018d9c9bef1SMiklos Szeredi seq_printf(seq, ",resgid=%u", sbi->s_resgid); 1019d9c9bef1SMiklos Szeredi } 1020bb4f397aSAneesh Kumar K.V if (test_opt(sb, ERRORS_RO)) { 1021d9c9bef1SMiklos Szeredi if (def_errors == EXT4_ERRORS_PANIC || 1022bb4f397aSAneesh Kumar K.V def_errors == EXT4_ERRORS_CONTINUE) { 1023d9c9bef1SMiklos Szeredi seq_puts(seq, ",errors=remount-ro"); 1024bb4f397aSAneesh Kumar K.V } 1025bb4f397aSAneesh Kumar K.V } 1026aa22df2cSAneesh Kumar K.V if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE) 1027bb4f397aSAneesh Kumar K.V seq_puts(seq, ",errors=continue"); 1028aa22df2cSAneesh Kumar K.V if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC) 1029d9c9bef1SMiklos Szeredi seq_puts(seq, ",errors=panic"); 1030aa22df2cSAneesh Kumar K.V if (test_opt(sb, NO_UID32) && !(def_mount_opts & EXT4_DEFM_UID16)) 1031d9c9bef1SMiklos Szeredi seq_puts(seq, ",nouid32"); 1032aa22df2cSAneesh Kumar K.V if (test_opt(sb, DEBUG) && !(def_mount_opts & EXT4_DEFM_DEBUG)) 1033d9c9bef1SMiklos Szeredi seq_puts(seq, ",debug"); 1034d9c9bef1SMiklos Szeredi if (test_opt(sb, OLDALLOC)) 1035d9c9bef1SMiklos Szeredi seq_puts(seq, ",oldalloc"); 103603010a33STheodore Ts'o #ifdef CONFIG_EXT4_FS_XATTR 1037ea663336SEric Sandeen if (test_opt(sb, XATTR_USER)) 1038d9c9bef1SMiklos Szeredi seq_puts(seq, ",user_xattr"); 1039ea663336SEric Sandeen if (!test_opt(sb, XATTR_USER)) 1040d9c9bef1SMiklos Szeredi seq_puts(seq, ",nouser_xattr"); 1041d9c9bef1SMiklos Szeredi #endif 104203010a33STheodore Ts'o #ifdef CONFIG_EXT4_FS_POSIX_ACL 1043aa22df2cSAneesh Kumar K.V if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) 1044d9c9bef1SMiklos Szeredi seq_puts(seq, ",acl"); 1045d9c9bef1SMiklos Szeredi if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) 1046d9c9bef1SMiklos Szeredi seq_puts(seq, ",noacl"); 1047d9c9bef1SMiklos Szeredi #endif 104830773840STheodore Ts'o if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) { 1049d9c9bef1SMiklos Szeredi seq_printf(seq, ",commit=%u", 1050d9c9bef1SMiklos Szeredi (unsigned) (sbi->s_commit_interval / HZ)); 1051d9c9bef1SMiklos Szeredi } 105230773840STheodore Ts'o if (sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME) { 105330773840STheodore Ts'o seq_printf(seq, ",min_batch_time=%u", 105430773840STheodore Ts'o (unsigned) sbi->s_min_batch_time); 105530773840STheodore Ts'o } 105630773840STheodore Ts'o if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) { 105730773840STheodore Ts'o seq_printf(seq, ",max_batch_time=%u", 105830773840STheodore Ts'o (unsigned) sbi->s_min_batch_time); 105930773840STheodore Ts'o } 106030773840STheodore Ts'o 1061571640caSEric Sandeen /* 1062571640caSEric Sandeen * We're changing the default of barrier mount option, so 1063571640caSEric Sandeen * let's always display its mount state so it's clear what its 1064571640caSEric Sandeen * status is. 1065571640caSEric Sandeen */ 1066571640caSEric Sandeen seq_puts(seq, ",barrier="); 1067571640caSEric Sandeen seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0"); 1068cd0b6a39STheodore Ts'o if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) 1069cd0b6a39STheodore Ts'o seq_puts(seq, ",journal_async_commit"); 107039a4badeSJan Kara else if (test_opt(sb, JOURNAL_CHECKSUM)) 107139a4badeSJan Kara seq_puts(seq, ",journal_checksum"); 107225ec56b5SJean Noel Cordenner if (test_opt(sb, I_VERSION)) 107325ec56b5SJean Noel Cordenner seq_puts(seq, ",i_version"); 10748b67f04aSTheodore Ts'o if (!test_opt(sb, DELALLOC) && 10758b67f04aSTheodore Ts'o !(def_mount_opts & EXT4_DEFM_NODELALLOC)) 1076dd919b98SAneesh Kumar K.V seq_puts(seq, ",nodelalloc"); 1077dd919b98SAneesh Kumar K.V 10786fd7a467STheodore Ts'o if (!test_opt(sb, MBLK_IO_SUBMIT)) 10796fd7a467STheodore Ts'o seq_puts(seq, ",nomblk_io_submit"); 1080cb45bbe4SMiklos Szeredi if (sbi->s_stripe) 1081cb45bbe4SMiklos Szeredi seq_printf(seq, ",stripe=%lu", sbi->s_stripe); 1082aa22df2cSAneesh Kumar K.V /* 1083aa22df2cSAneesh Kumar K.V * journal mode get enabled in different ways 1084aa22df2cSAneesh Kumar K.V * So just print the value even if we didn't specify it 1085aa22df2cSAneesh Kumar K.V */ 1086617ba13bSMingming Cao if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) 1087ac27a0ecSDave Kleikamp seq_puts(seq, ",data=journal"); 1088617ba13bSMingming Cao else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) 1089ac27a0ecSDave Kleikamp seq_puts(seq, ",data=ordered"); 1090617ba13bSMingming Cao else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) 1091ac27a0ecSDave Kleikamp seq_puts(seq, ",data=writeback"); 1092ac27a0ecSDave Kleikamp 1093240799cdSTheodore Ts'o if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS) 1094240799cdSTheodore Ts'o seq_printf(seq, ",inode_readahead_blks=%u", 1095240799cdSTheodore Ts'o sbi->s_inode_readahead_blks); 1096240799cdSTheodore Ts'o 10975bf5683aSHidehiro Kawai if (test_opt(sb, DATA_ERR_ABORT)) 10985bf5683aSHidehiro Kawai seq_puts(seq, ",data_err=abort"); 10995bf5683aSHidehiro Kawai 1100afd4672dSTheodore Ts'o if (test_opt(sb, NO_AUTO_DA_ALLOC)) 110106705bffSTheodore Ts'o seq_puts(seq, ",noauto_da_alloc"); 1102afd4672dSTheodore Ts'o 11038b67f04aSTheodore Ts'o if (test_opt(sb, DISCARD) && !(def_mount_opts & EXT4_DEFM_DISCARD)) 11045328e635SEric Sandeen seq_puts(seq, ",discard"); 11055328e635SEric Sandeen 1106e3bb52aeSEric Sandeen if (test_opt(sb, NOLOAD)) 1107e3bb52aeSEric Sandeen seq_puts(seq, ",norecovery"); 1108e3bb52aeSEric Sandeen 1109744692dcSJiaying Zhang if (test_opt(sb, DIOREAD_NOLOCK)) 1110744692dcSJiaying Zhang seq_puts(seq, ",dioread_nolock"); 1111744692dcSJiaying Zhang 11128b67f04aSTheodore Ts'o if (test_opt(sb, BLOCK_VALIDITY) && 11138b67f04aSTheodore Ts'o !(def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY)) 11148b67f04aSTheodore Ts'o seq_puts(seq, ",block_validity"); 11158b67f04aSTheodore Ts'o 1116bfff6873SLukas Czerner if (!test_opt(sb, INIT_INODE_TABLE)) 1117bfff6873SLukas Czerner seq_puts(seq, ",noinit_inode_table"); 111851ce6511SLukas Czerner else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT) 1119bfff6873SLukas Czerner seq_printf(seq, ",init_inode_table=%u", 1120bfff6873SLukas Czerner (unsigned) sbi->s_li_wait_mult); 1121bfff6873SLukas Czerner 1122617ba13bSMingming Cao ext4_show_quota_options(seq, sb); 11230b8e58a1SAndreas Dilger 1124ac27a0ecSDave Kleikamp return 0; 1125ac27a0ecSDave Kleikamp } 1126ac27a0ecSDave Kleikamp 11271b961ac0SChristoph Hellwig static struct inode *ext4_nfs_get_inode(struct super_block *sb, 11281b961ac0SChristoph Hellwig u64 ino, u32 generation) 1129ac27a0ecSDave Kleikamp { 1130ac27a0ecSDave Kleikamp struct inode *inode; 1131ac27a0ecSDave Kleikamp 1132617ba13bSMingming Cao if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) 1133ac27a0ecSDave Kleikamp return ERR_PTR(-ESTALE); 1134617ba13bSMingming Cao if (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)) 1135ac27a0ecSDave Kleikamp return ERR_PTR(-ESTALE); 1136ac27a0ecSDave Kleikamp 1137ac27a0ecSDave Kleikamp /* iget isn't really right if the inode is currently unallocated!! 1138ac27a0ecSDave Kleikamp * 1139617ba13bSMingming Cao * ext4_read_inode will return a bad_inode if the inode had been 1140ac27a0ecSDave Kleikamp * deleted, so we should be safe. 1141ac27a0ecSDave Kleikamp * 1142ac27a0ecSDave Kleikamp * Currently we don't know the generation for parent directory, so 1143ac27a0ecSDave Kleikamp * a generation of 0 means "accept any" 1144ac27a0ecSDave Kleikamp */ 11451d1fe1eeSDavid Howells inode = ext4_iget(sb, ino); 11461d1fe1eeSDavid Howells if (IS_ERR(inode)) 11471d1fe1eeSDavid Howells return ERR_CAST(inode); 11481d1fe1eeSDavid Howells if (generation && inode->i_generation != generation) { 1149ac27a0ecSDave Kleikamp iput(inode); 1150ac27a0ecSDave Kleikamp return ERR_PTR(-ESTALE); 1151ac27a0ecSDave Kleikamp } 11521b961ac0SChristoph Hellwig 11531b961ac0SChristoph Hellwig return inode; 1154ac27a0ecSDave Kleikamp } 11551b961ac0SChristoph Hellwig 11561b961ac0SChristoph Hellwig static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid, 11571b961ac0SChristoph Hellwig int fh_len, int fh_type) 11581b961ac0SChristoph Hellwig { 11591b961ac0SChristoph Hellwig return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 11601b961ac0SChristoph Hellwig ext4_nfs_get_inode); 11611b961ac0SChristoph Hellwig } 11621b961ac0SChristoph Hellwig 11631b961ac0SChristoph Hellwig static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid, 11641b961ac0SChristoph Hellwig int fh_len, int fh_type) 11651b961ac0SChristoph Hellwig { 11661b961ac0SChristoph Hellwig return generic_fh_to_parent(sb, fid, fh_len, fh_type, 11671b961ac0SChristoph Hellwig ext4_nfs_get_inode); 1168ac27a0ecSDave Kleikamp } 1169ac27a0ecSDave Kleikamp 1170c39a7f84SToshiyuki Okajima /* 1171c39a7f84SToshiyuki Okajima * Try to release metadata pages (indirect blocks, directories) which are 1172c39a7f84SToshiyuki Okajima * mapped via the block device. Since these pages could have journal heads 1173c39a7f84SToshiyuki Okajima * which would prevent try_to_free_buffers() from freeing them, we must use 1174c39a7f84SToshiyuki Okajima * jbd2 layer's try_to_free_buffers() function to release them. 1175c39a7f84SToshiyuki Okajima */ 11760b8e58a1SAndreas Dilger static int bdev_try_to_free_page(struct super_block *sb, struct page *page, 11770b8e58a1SAndreas Dilger gfp_t wait) 1178c39a7f84SToshiyuki Okajima { 1179c39a7f84SToshiyuki Okajima journal_t *journal = EXT4_SB(sb)->s_journal; 1180c39a7f84SToshiyuki Okajima 1181c39a7f84SToshiyuki Okajima WARN_ON(PageChecked(page)); 1182c39a7f84SToshiyuki Okajima if (!page_has_buffers(page)) 1183c39a7f84SToshiyuki Okajima return 0; 1184c39a7f84SToshiyuki Okajima if (journal) 1185c39a7f84SToshiyuki Okajima return jbd2_journal_try_to_free_buffers(journal, page, 1186c39a7f84SToshiyuki Okajima wait & ~__GFP_WAIT); 1187c39a7f84SToshiyuki Okajima return try_to_free_buffers(page); 1188c39a7f84SToshiyuki Okajima } 1189c39a7f84SToshiyuki Okajima 1190ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 1191ac27a0ecSDave Kleikamp #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group") 1192ac27a0ecSDave Kleikamp #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) 1193ac27a0ecSDave Kleikamp 1194617ba13bSMingming Cao static int ext4_write_dquot(struct dquot *dquot); 1195617ba13bSMingming Cao static int ext4_acquire_dquot(struct dquot *dquot); 1196617ba13bSMingming Cao static int ext4_release_dquot(struct dquot *dquot); 1197617ba13bSMingming Cao static int ext4_mark_dquot_dirty(struct dquot *dquot); 1198617ba13bSMingming Cao static int ext4_write_info(struct super_block *sb, int type); 11996f28e087SJan Kara static int ext4_quota_on(struct super_block *sb, int type, int format_id, 1200f00c9e44SJan Kara struct path *path); 1201ca0e05e4SDmitry Monakhov static int ext4_quota_off(struct super_block *sb, int type); 1202617ba13bSMingming Cao static int ext4_quota_on_mount(struct super_block *sb, int type); 1203617ba13bSMingming Cao static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, 1204ac27a0ecSDave Kleikamp size_t len, loff_t off); 1205617ba13bSMingming Cao static ssize_t ext4_quota_write(struct super_block *sb, int type, 1206ac27a0ecSDave Kleikamp const char *data, size_t len, loff_t off); 1207ac27a0ecSDave Kleikamp 120861e225dcSAlexey Dobriyan static const struct dquot_operations ext4_quota_operations = { 120960e58e0fSMingming Cao .get_reserved_space = ext4_get_reserved_space, 1210617ba13bSMingming Cao .write_dquot = ext4_write_dquot, 1211617ba13bSMingming Cao .acquire_dquot = ext4_acquire_dquot, 1212617ba13bSMingming Cao .release_dquot = ext4_release_dquot, 1213617ba13bSMingming Cao .mark_dirty = ext4_mark_dquot_dirty, 1214a5b5ee32SJan Kara .write_info = ext4_write_info, 1215a5b5ee32SJan Kara .alloc_dquot = dquot_alloc, 1216a5b5ee32SJan Kara .destroy_dquot = dquot_destroy, 1217ac27a0ecSDave Kleikamp }; 1218ac27a0ecSDave Kleikamp 12190d54b217SAlexey Dobriyan static const struct quotactl_ops ext4_qctl_operations = { 1220617ba13bSMingming Cao .quota_on = ext4_quota_on, 1221ca0e05e4SDmitry Monakhov .quota_off = ext4_quota_off, 1222287a8095SChristoph Hellwig .quota_sync = dquot_quota_sync, 1223287a8095SChristoph Hellwig .get_info = dquot_get_dqinfo, 1224287a8095SChristoph Hellwig .set_info = dquot_set_dqinfo, 1225287a8095SChristoph Hellwig .get_dqblk = dquot_get_dqblk, 1226287a8095SChristoph Hellwig .set_dqblk = dquot_set_dqblk 1227ac27a0ecSDave Kleikamp }; 1228ac27a0ecSDave Kleikamp #endif 1229ac27a0ecSDave Kleikamp 1230ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations ext4_sops = { 1231617ba13bSMingming Cao .alloc_inode = ext4_alloc_inode, 1232617ba13bSMingming Cao .destroy_inode = ext4_destroy_inode, 1233617ba13bSMingming Cao .write_inode = ext4_write_inode, 1234617ba13bSMingming Cao .dirty_inode = ext4_dirty_inode, 12357ff9c073STheodore Ts'o .drop_inode = ext4_drop_inode, 12360930fcc1SAl Viro .evict_inode = ext4_evict_inode, 1237617ba13bSMingming Cao .put_super = ext4_put_super, 1238617ba13bSMingming Cao .sync_fs = ext4_sync_fs, 1239c4be0c1dSTakashi Sato .freeze_fs = ext4_freeze, 1240c4be0c1dSTakashi Sato .unfreeze_fs = ext4_unfreeze, 1241617ba13bSMingming Cao .statfs = ext4_statfs, 1242617ba13bSMingming Cao .remount_fs = ext4_remount, 1243617ba13bSMingming Cao .show_options = ext4_show_options, 1244ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 1245617ba13bSMingming Cao .quota_read = ext4_quota_read, 1246617ba13bSMingming Cao .quota_write = ext4_quota_write, 1247ac27a0ecSDave Kleikamp #endif 1248c39a7f84SToshiyuki Okajima .bdev_try_to_free_page = bdev_try_to_free_page, 1249ac27a0ecSDave Kleikamp }; 1250ac27a0ecSDave Kleikamp 12519ca92389STheodore Ts'o static const struct super_operations ext4_nojournal_sops = { 12529ca92389STheodore Ts'o .alloc_inode = ext4_alloc_inode, 12539ca92389STheodore Ts'o .destroy_inode = ext4_destroy_inode, 12549ca92389STheodore Ts'o .write_inode = ext4_write_inode, 12559ca92389STheodore Ts'o .dirty_inode = ext4_dirty_inode, 12567ff9c073STheodore Ts'o .drop_inode = ext4_drop_inode, 12570930fcc1SAl Viro .evict_inode = ext4_evict_inode, 12589ca92389STheodore Ts'o .write_super = ext4_write_super, 12599ca92389STheodore Ts'o .put_super = ext4_put_super, 12609ca92389STheodore Ts'o .statfs = ext4_statfs, 12619ca92389STheodore Ts'o .remount_fs = ext4_remount, 12629ca92389STheodore Ts'o .show_options = ext4_show_options, 12639ca92389STheodore Ts'o #ifdef CONFIG_QUOTA 12649ca92389STheodore Ts'o .quota_read = ext4_quota_read, 12659ca92389STheodore Ts'o .quota_write = ext4_quota_write, 12669ca92389STheodore Ts'o #endif 12679ca92389STheodore Ts'o .bdev_try_to_free_page = bdev_try_to_free_page, 12689ca92389STheodore Ts'o }; 12699ca92389STheodore Ts'o 127039655164SChristoph Hellwig static const struct export_operations ext4_export_ops = { 12711b961ac0SChristoph Hellwig .fh_to_dentry = ext4_fh_to_dentry, 12721b961ac0SChristoph Hellwig .fh_to_parent = ext4_fh_to_parent, 1273617ba13bSMingming Cao .get_parent = ext4_get_parent, 1274ac27a0ecSDave Kleikamp }; 1275ac27a0ecSDave Kleikamp 1276ac27a0ecSDave Kleikamp enum { 1277ac27a0ecSDave Kleikamp Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, 1278ac27a0ecSDave Kleikamp Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, 127901436ef2STheodore Ts'o Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov, 1280ac27a0ecSDave Kleikamp Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, 128106705bffSTheodore Ts'o Opt_auto_da_alloc, Opt_noauto_da_alloc, Opt_noload, Opt_nobh, Opt_bh, 128230773840STheodore Ts'o Opt_commit, Opt_min_batch_time, Opt_max_batch_time, 1283c3191067STheodore Ts'o Opt_journal_update, Opt_journal_dev, 1284818d276cSGirish Shilamkar Opt_journal_checksum, Opt_journal_async_commit, 1285ac27a0ecSDave Kleikamp Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, 1286296c355cSTheodore Ts'o Opt_data_err_abort, Opt_data_err_ignore, 1287ac27a0ecSDave Kleikamp Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, 12885a20bdfcSJan Kara Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, 12895a20bdfcSJan Kara Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, 12905a20bdfcSJan Kara Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version, 12911449032bSTheodore Ts'o Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, 12921449032bSTheodore Ts'o Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, 12935328e635SEric Sandeen Opt_inode_readahead_blks, Opt_journal_ioprio, 1294744692dcSJiaying Zhang Opt_dioread_nolock, Opt_dioread_lock, 12955328e635SEric Sandeen Opt_discard, Opt_nodiscard, 1296bfff6873SLukas Czerner Opt_init_inode_table, Opt_noinit_inode_table, 1297ac27a0ecSDave Kleikamp }; 1298ac27a0ecSDave Kleikamp 1299a447c093SSteven Whitehouse static const match_table_t tokens = { 1300ac27a0ecSDave Kleikamp {Opt_bsd_df, "bsddf"}, 1301ac27a0ecSDave Kleikamp {Opt_minix_df, "minixdf"}, 1302ac27a0ecSDave Kleikamp {Opt_grpid, "grpid"}, 1303ac27a0ecSDave Kleikamp {Opt_grpid, "bsdgroups"}, 1304ac27a0ecSDave Kleikamp {Opt_nogrpid, "nogrpid"}, 1305ac27a0ecSDave Kleikamp {Opt_nogrpid, "sysvgroups"}, 1306ac27a0ecSDave Kleikamp {Opt_resgid, "resgid=%u"}, 1307ac27a0ecSDave Kleikamp {Opt_resuid, "resuid=%u"}, 1308ac27a0ecSDave Kleikamp {Opt_sb, "sb=%u"}, 1309ac27a0ecSDave Kleikamp {Opt_err_cont, "errors=continue"}, 1310ac27a0ecSDave Kleikamp {Opt_err_panic, "errors=panic"}, 1311ac27a0ecSDave Kleikamp {Opt_err_ro, "errors=remount-ro"}, 1312ac27a0ecSDave Kleikamp {Opt_nouid32, "nouid32"}, 1313ac27a0ecSDave Kleikamp {Opt_debug, "debug"}, 1314ac27a0ecSDave Kleikamp {Opt_oldalloc, "oldalloc"}, 1315ac27a0ecSDave Kleikamp {Opt_orlov, "orlov"}, 1316ac27a0ecSDave Kleikamp {Opt_user_xattr, "user_xattr"}, 1317ac27a0ecSDave Kleikamp {Opt_nouser_xattr, "nouser_xattr"}, 1318ac27a0ecSDave Kleikamp {Opt_acl, "acl"}, 1319ac27a0ecSDave Kleikamp {Opt_noacl, "noacl"}, 1320ac27a0ecSDave Kleikamp {Opt_noload, "noload"}, 1321e3bb52aeSEric Sandeen {Opt_noload, "norecovery"}, 1322ac27a0ecSDave Kleikamp {Opt_nobh, "nobh"}, 1323ac27a0ecSDave Kleikamp {Opt_bh, "bh"}, 1324ac27a0ecSDave Kleikamp {Opt_commit, "commit=%u"}, 132530773840STheodore Ts'o {Opt_min_batch_time, "min_batch_time=%u"}, 132630773840STheodore Ts'o {Opt_max_batch_time, "max_batch_time=%u"}, 1327ac27a0ecSDave Kleikamp {Opt_journal_update, "journal=update"}, 1328ac27a0ecSDave Kleikamp {Opt_journal_dev, "journal_dev=%u"}, 1329818d276cSGirish Shilamkar {Opt_journal_checksum, "journal_checksum"}, 1330818d276cSGirish Shilamkar {Opt_journal_async_commit, "journal_async_commit"}, 1331ac27a0ecSDave Kleikamp {Opt_abort, "abort"}, 1332ac27a0ecSDave Kleikamp {Opt_data_journal, "data=journal"}, 1333ac27a0ecSDave Kleikamp {Opt_data_ordered, "data=ordered"}, 1334ac27a0ecSDave Kleikamp {Opt_data_writeback, "data=writeback"}, 13355bf5683aSHidehiro Kawai {Opt_data_err_abort, "data_err=abort"}, 13365bf5683aSHidehiro Kawai {Opt_data_err_ignore, "data_err=ignore"}, 1337ac27a0ecSDave Kleikamp {Opt_offusrjquota, "usrjquota="}, 1338ac27a0ecSDave Kleikamp {Opt_usrjquota, "usrjquota=%s"}, 1339ac27a0ecSDave Kleikamp {Opt_offgrpjquota, "grpjquota="}, 1340ac27a0ecSDave Kleikamp {Opt_grpjquota, "grpjquota=%s"}, 1341ac27a0ecSDave Kleikamp {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, 1342ac27a0ecSDave Kleikamp {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, 13435a20bdfcSJan Kara {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"}, 1344ac27a0ecSDave Kleikamp {Opt_grpquota, "grpquota"}, 1345ac27a0ecSDave Kleikamp {Opt_noquota, "noquota"}, 1346ac27a0ecSDave Kleikamp {Opt_quota, "quota"}, 1347ac27a0ecSDave Kleikamp {Opt_usrquota, "usrquota"}, 1348ac27a0ecSDave Kleikamp {Opt_barrier, "barrier=%u"}, 134906705bffSTheodore Ts'o {Opt_barrier, "barrier"}, 135006705bffSTheodore Ts'o {Opt_nobarrier, "nobarrier"}, 135125ec56b5SJean Noel Cordenner {Opt_i_version, "i_version"}, 1352c9de560dSAlex Tomas {Opt_stripe, "stripe=%u"}, 1353ac27a0ecSDave Kleikamp {Opt_resize, "resize"}, 135464769240SAlex Tomas {Opt_delalloc, "delalloc"}, 1355dd919b98SAneesh Kumar K.V {Opt_nodelalloc, "nodelalloc"}, 13561449032bSTheodore Ts'o {Opt_mblk_io_submit, "mblk_io_submit"}, 13571449032bSTheodore Ts'o {Opt_nomblk_io_submit, "nomblk_io_submit"}, 13586fd058f7STheodore Ts'o {Opt_block_validity, "block_validity"}, 13596fd058f7STheodore Ts'o {Opt_noblock_validity, "noblock_validity"}, 1360240799cdSTheodore Ts'o {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, 1361b3881f74STheodore Ts'o {Opt_journal_ioprio, "journal_ioprio=%u"}, 1362afd4672dSTheodore Ts'o {Opt_auto_da_alloc, "auto_da_alloc=%u"}, 136306705bffSTheodore Ts'o {Opt_auto_da_alloc, "auto_da_alloc"}, 136406705bffSTheodore Ts'o {Opt_noauto_da_alloc, "noauto_da_alloc"}, 1365744692dcSJiaying Zhang {Opt_dioread_nolock, "dioread_nolock"}, 1366744692dcSJiaying Zhang {Opt_dioread_lock, "dioread_lock"}, 13675328e635SEric Sandeen {Opt_discard, "discard"}, 13685328e635SEric Sandeen {Opt_nodiscard, "nodiscard"}, 1369bfff6873SLukas Czerner {Opt_init_inode_table, "init_itable=%u"}, 1370bfff6873SLukas Czerner {Opt_init_inode_table, "init_itable"}, 1371bfff6873SLukas Czerner {Opt_noinit_inode_table, "noinit_itable"}, 1372f3f12faaSJosef Bacik {Opt_err, NULL}, 1373ac27a0ecSDave Kleikamp }; 1374ac27a0ecSDave Kleikamp 1375617ba13bSMingming Cao static ext4_fsblk_t get_sb_block(void **data) 1376ac27a0ecSDave Kleikamp { 1377617ba13bSMingming Cao ext4_fsblk_t sb_block; 1378ac27a0ecSDave Kleikamp char *options = (char *) *data; 1379ac27a0ecSDave Kleikamp 1380ac27a0ecSDave Kleikamp if (!options || strncmp(options, "sb=", 3) != 0) 1381ac27a0ecSDave Kleikamp return 1; /* Default location */ 13820b8e58a1SAndreas Dilger 1383ac27a0ecSDave Kleikamp options += 3; 13840b8e58a1SAndreas Dilger /* TODO: use simple_strtoll with >32bit ext4 */ 1385ac27a0ecSDave Kleikamp sb_block = simple_strtoul(options, &options, 0); 1386ac27a0ecSDave Kleikamp if (*options && *options != ',') { 13874776004fSTheodore Ts'o printk(KERN_ERR "EXT4-fs: Invalid sb specification: %s\n", 1388ac27a0ecSDave Kleikamp (char *) *data); 1389ac27a0ecSDave Kleikamp return 1; 1390ac27a0ecSDave Kleikamp } 1391ac27a0ecSDave Kleikamp if (*options == ',') 1392ac27a0ecSDave Kleikamp options++; 1393ac27a0ecSDave Kleikamp *data = (void *) options; 13940b8e58a1SAndreas Dilger 1395ac27a0ecSDave Kleikamp return sb_block; 1396ac27a0ecSDave Kleikamp } 1397ac27a0ecSDave Kleikamp 1398b3881f74STheodore Ts'o #define DEFAULT_JOURNAL_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3)) 1399437ca0fdSDmitry Monakhov static char deprecated_msg[] = "Mount option \"%s\" will be removed by %s\n" 1400437ca0fdSDmitry Monakhov "Contact linux-ext4@vger.kernel.org if you think we should keep it.\n"; 1401b3881f74STheodore Ts'o 140256c50f11SDmitry Monakhov #ifdef CONFIG_QUOTA 140356c50f11SDmitry Monakhov static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) 140456c50f11SDmitry Monakhov { 140556c50f11SDmitry Monakhov struct ext4_sb_info *sbi = EXT4_SB(sb); 140656c50f11SDmitry Monakhov char *qname; 140756c50f11SDmitry Monakhov 140856c50f11SDmitry Monakhov if (sb_any_quota_loaded(sb) && 140956c50f11SDmitry Monakhov !sbi->s_qf_names[qtype]) { 141056c50f11SDmitry Monakhov ext4_msg(sb, KERN_ERR, 141156c50f11SDmitry Monakhov "Cannot change journaled " 141256c50f11SDmitry Monakhov "quota options when quota turned on"); 141356c50f11SDmitry Monakhov return 0; 141456c50f11SDmitry Monakhov } 141556c50f11SDmitry Monakhov qname = match_strdup(args); 141656c50f11SDmitry Monakhov if (!qname) { 141756c50f11SDmitry Monakhov ext4_msg(sb, KERN_ERR, 141856c50f11SDmitry Monakhov "Not enough memory for storing quotafile name"); 141956c50f11SDmitry Monakhov return 0; 142056c50f11SDmitry Monakhov } 142156c50f11SDmitry Monakhov if (sbi->s_qf_names[qtype] && 142256c50f11SDmitry Monakhov strcmp(sbi->s_qf_names[qtype], qname)) { 142356c50f11SDmitry Monakhov ext4_msg(sb, KERN_ERR, 142456c50f11SDmitry Monakhov "%s quota file already specified", QTYPE2NAME(qtype)); 142556c50f11SDmitry Monakhov kfree(qname); 142656c50f11SDmitry Monakhov return 0; 142756c50f11SDmitry Monakhov } 142856c50f11SDmitry Monakhov sbi->s_qf_names[qtype] = qname; 142956c50f11SDmitry Monakhov if (strchr(sbi->s_qf_names[qtype], '/')) { 143056c50f11SDmitry Monakhov ext4_msg(sb, KERN_ERR, 143156c50f11SDmitry Monakhov "quotafile must be on filesystem root"); 143256c50f11SDmitry Monakhov kfree(sbi->s_qf_names[qtype]); 143356c50f11SDmitry Monakhov sbi->s_qf_names[qtype] = NULL; 143456c50f11SDmitry Monakhov return 0; 143556c50f11SDmitry Monakhov } 1436fd8c37ecSTheodore Ts'o set_opt(sb, QUOTA); 143756c50f11SDmitry Monakhov return 1; 143856c50f11SDmitry Monakhov } 143956c50f11SDmitry Monakhov 144056c50f11SDmitry Monakhov static int clear_qf_name(struct super_block *sb, int qtype) 144156c50f11SDmitry Monakhov { 144256c50f11SDmitry Monakhov 144356c50f11SDmitry Monakhov struct ext4_sb_info *sbi = EXT4_SB(sb); 144456c50f11SDmitry Monakhov 144556c50f11SDmitry Monakhov if (sb_any_quota_loaded(sb) && 144656c50f11SDmitry Monakhov sbi->s_qf_names[qtype]) { 144756c50f11SDmitry Monakhov ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options" 144856c50f11SDmitry Monakhov " when quota turned on"); 144956c50f11SDmitry Monakhov return 0; 145056c50f11SDmitry Monakhov } 145156c50f11SDmitry Monakhov /* 145256c50f11SDmitry Monakhov * The space will be released later when all options are confirmed 145356c50f11SDmitry Monakhov * to be correct 145456c50f11SDmitry Monakhov */ 145556c50f11SDmitry Monakhov sbi->s_qf_names[qtype] = NULL; 145656c50f11SDmitry Monakhov return 1; 145756c50f11SDmitry Monakhov } 145856c50f11SDmitry Monakhov #endif 145956c50f11SDmitry Monakhov 1460ac27a0ecSDave Kleikamp static int parse_options(char *options, struct super_block *sb, 1461c3191067STheodore Ts'o unsigned long *journal_devnum, 1462b3881f74STheodore Ts'o unsigned int *journal_ioprio, 1463617ba13bSMingming Cao ext4_fsblk_t *n_blocks_count, int is_remount) 1464ac27a0ecSDave Kleikamp { 1465617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 1466ac27a0ecSDave Kleikamp char *p; 1467ac27a0ecSDave Kleikamp substring_t args[MAX_OPT_ARGS]; 1468ac27a0ecSDave Kleikamp int data_opt = 0; 1469ac27a0ecSDave Kleikamp int option; 1470ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 147156c50f11SDmitry Monakhov int qfmt; 1472ac27a0ecSDave Kleikamp #endif 1473ac27a0ecSDave Kleikamp 1474ac27a0ecSDave Kleikamp if (!options) 1475ac27a0ecSDave Kleikamp return 1; 1476ac27a0ecSDave Kleikamp 1477ac27a0ecSDave Kleikamp while ((p = strsep(&options, ",")) != NULL) { 1478ac27a0ecSDave Kleikamp int token; 1479ac27a0ecSDave Kleikamp if (!*p) 1480ac27a0ecSDave Kleikamp continue; 1481ac27a0ecSDave Kleikamp 148215121c18SEric Sandeen /* 148315121c18SEric Sandeen * Initialize args struct so we know whether arg was 148415121c18SEric Sandeen * found; some options take optional arguments. 148515121c18SEric Sandeen */ 14867dc57615SPeter Huewe args[0].to = args[0].from = NULL; 1487ac27a0ecSDave Kleikamp token = match_token(p, tokens, args); 1488ac27a0ecSDave Kleikamp switch (token) { 1489ac27a0ecSDave Kleikamp case Opt_bsd_df: 1490437ca0fdSDmitry Monakhov ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38"); 1491fd8c37ecSTheodore Ts'o clear_opt(sb, MINIX_DF); 1492ac27a0ecSDave Kleikamp break; 1493ac27a0ecSDave Kleikamp case Opt_minix_df: 1494437ca0fdSDmitry Monakhov ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38"); 1495fd8c37ecSTheodore Ts'o set_opt(sb, MINIX_DF); 1496437ca0fdSDmitry Monakhov 1497ac27a0ecSDave Kleikamp break; 1498ac27a0ecSDave Kleikamp case Opt_grpid: 1499437ca0fdSDmitry Monakhov ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38"); 1500fd8c37ecSTheodore Ts'o set_opt(sb, GRPID); 1501437ca0fdSDmitry Monakhov 1502ac27a0ecSDave Kleikamp break; 1503ac27a0ecSDave Kleikamp case Opt_nogrpid: 1504437ca0fdSDmitry Monakhov ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38"); 1505fd8c37ecSTheodore Ts'o clear_opt(sb, GRPID); 1506437ca0fdSDmitry Monakhov 1507ac27a0ecSDave Kleikamp break; 1508ac27a0ecSDave Kleikamp case Opt_resuid: 1509ac27a0ecSDave Kleikamp if (match_int(&args[0], &option)) 1510ac27a0ecSDave Kleikamp return 0; 1511ac27a0ecSDave Kleikamp sbi->s_resuid = option; 1512ac27a0ecSDave Kleikamp break; 1513ac27a0ecSDave Kleikamp case Opt_resgid: 1514ac27a0ecSDave Kleikamp if (match_int(&args[0], &option)) 1515ac27a0ecSDave Kleikamp return 0; 1516ac27a0ecSDave Kleikamp sbi->s_resgid = option; 1517ac27a0ecSDave Kleikamp break; 1518ac27a0ecSDave Kleikamp case Opt_sb: 1519ac27a0ecSDave Kleikamp /* handled by get_sb_block() instead of here */ 1520ac27a0ecSDave Kleikamp /* *sb_block = match_int(&args[0]); */ 1521ac27a0ecSDave Kleikamp break; 1522ac27a0ecSDave Kleikamp case Opt_err_panic: 1523fd8c37ecSTheodore Ts'o clear_opt(sb, ERRORS_CONT); 1524fd8c37ecSTheodore Ts'o clear_opt(sb, ERRORS_RO); 1525fd8c37ecSTheodore Ts'o set_opt(sb, ERRORS_PANIC); 1526ac27a0ecSDave Kleikamp break; 1527ac27a0ecSDave Kleikamp case Opt_err_ro: 1528fd8c37ecSTheodore Ts'o clear_opt(sb, ERRORS_CONT); 1529fd8c37ecSTheodore Ts'o clear_opt(sb, ERRORS_PANIC); 1530fd8c37ecSTheodore Ts'o set_opt(sb, ERRORS_RO); 1531ac27a0ecSDave Kleikamp break; 1532ac27a0ecSDave Kleikamp case Opt_err_cont: 1533fd8c37ecSTheodore Ts'o clear_opt(sb, ERRORS_RO); 1534fd8c37ecSTheodore Ts'o clear_opt(sb, ERRORS_PANIC); 1535fd8c37ecSTheodore Ts'o set_opt(sb, ERRORS_CONT); 1536ac27a0ecSDave Kleikamp break; 1537ac27a0ecSDave Kleikamp case Opt_nouid32: 1538fd8c37ecSTheodore Ts'o set_opt(sb, NO_UID32); 1539ac27a0ecSDave Kleikamp break; 1540ac27a0ecSDave Kleikamp case Opt_debug: 1541fd8c37ecSTheodore Ts'o set_opt(sb, DEBUG); 1542ac27a0ecSDave Kleikamp break; 1543ac27a0ecSDave Kleikamp case Opt_oldalloc: 1544fd8c37ecSTheodore Ts'o set_opt(sb, OLDALLOC); 1545ac27a0ecSDave Kleikamp break; 1546ac27a0ecSDave Kleikamp case Opt_orlov: 1547fd8c37ecSTheodore Ts'o clear_opt(sb, OLDALLOC); 1548ac27a0ecSDave Kleikamp break; 154903010a33STheodore Ts'o #ifdef CONFIG_EXT4_FS_XATTR 1550ac27a0ecSDave Kleikamp case Opt_user_xattr: 1551fd8c37ecSTheodore Ts'o set_opt(sb, XATTR_USER); 1552ac27a0ecSDave Kleikamp break; 1553ac27a0ecSDave Kleikamp case Opt_nouser_xattr: 1554fd8c37ecSTheodore Ts'o clear_opt(sb, XATTR_USER); 1555ac27a0ecSDave Kleikamp break; 1556ac27a0ecSDave Kleikamp #else 1557ac27a0ecSDave Kleikamp case Opt_user_xattr: 1558ac27a0ecSDave Kleikamp case Opt_nouser_xattr: 1559b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "(no)user_xattr options not supported"); 1560ac27a0ecSDave Kleikamp break; 1561ac27a0ecSDave Kleikamp #endif 156203010a33STheodore Ts'o #ifdef CONFIG_EXT4_FS_POSIX_ACL 1563ac27a0ecSDave Kleikamp case Opt_acl: 1564fd8c37ecSTheodore Ts'o set_opt(sb, POSIX_ACL); 1565ac27a0ecSDave Kleikamp break; 1566ac27a0ecSDave Kleikamp case Opt_noacl: 1567fd8c37ecSTheodore Ts'o clear_opt(sb, POSIX_ACL); 1568ac27a0ecSDave Kleikamp break; 1569ac27a0ecSDave Kleikamp #else 1570ac27a0ecSDave Kleikamp case Opt_acl: 1571ac27a0ecSDave Kleikamp case Opt_noacl: 1572b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "(no)acl options not supported"); 1573ac27a0ecSDave Kleikamp break; 1574ac27a0ecSDave Kleikamp #endif 1575ac27a0ecSDave Kleikamp case Opt_journal_update: 1576ac27a0ecSDave Kleikamp /* @@@ FIXME */ 1577ac27a0ecSDave Kleikamp /* Eventually we will want to be able to create 1578ac27a0ecSDave Kleikamp a journal file here. For now, only allow the 1579ac27a0ecSDave Kleikamp user to specify an existing inode to be the 1580ac27a0ecSDave Kleikamp journal file. */ 1581ac27a0ecSDave Kleikamp if (is_remount) { 1582b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 1583b31e1552SEric Sandeen "Cannot specify journal on remount"); 1584ac27a0ecSDave Kleikamp return 0; 1585ac27a0ecSDave Kleikamp } 1586fd8c37ecSTheodore Ts'o set_opt(sb, UPDATE_JOURNAL); 1587ac27a0ecSDave Kleikamp break; 1588ac27a0ecSDave Kleikamp case Opt_journal_dev: 1589ac27a0ecSDave Kleikamp if (is_remount) { 1590b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 1591b31e1552SEric Sandeen "Cannot specify journal on remount"); 1592ac27a0ecSDave Kleikamp return 0; 1593ac27a0ecSDave Kleikamp } 1594ac27a0ecSDave Kleikamp if (match_int(&args[0], &option)) 1595ac27a0ecSDave Kleikamp return 0; 1596ac27a0ecSDave Kleikamp *journal_devnum = option; 1597ac27a0ecSDave Kleikamp break; 1598818d276cSGirish Shilamkar case Opt_journal_checksum: 1599fd8c37ecSTheodore Ts'o set_opt(sb, JOURNAL_CHECKSUM); 1600d4da6c9cSLinus Torvalds break; 1601818d276cSGirish Shilamkar case Opt_journal_async_commit: 1602fd8c37ecSTheodore Ts'o set_opt(sb, JOURNAL_ASYNC_COMMIT); 1603fd8c37ecSTheodore Ts'o set_opt(sb, JOURNAL_CHECKSUM); 1604818d276cSGirish Shilamkar break; 1605ac27a0ecSDave Kleikamp case Opt_noload: 1606fd8c37ecSTheodore Ts'o set_opt(sb, NOLOAD); 1607ac27a0ecSDave Kleikamp break; 1608ac27a0ecSDave Kleikamp case Opt_commit: 1609ac27a0ecSDave Kleikamp if (match_int(&args[0], &option)) 1610ac27a0ecSDave Kleikamp return 0; 1611ac27a0ecSDave Kleikamp if (option < 0) 1612ac27a0ecSDave Kleikamp return 0; 1613ac27a0ecSDave Kleikamp if (option == 0) 1614cd02ff0bSMingming Cao option = JBD2_DEFAULT_MAX_COMMIT_AGE; 1615ac27a0ecSDave Kleikamp sbi->s_commit_interval = HZ * option; 1616ac27a0ecSDave Kleikamp break; 161730773840STheodore Ts'o case Opt_max_batch_time: 161830773840STheodore Ts'o if (match_int(&args[0], &option)) 161930773840STheodore Ts'o return 0; 162030773840STheodore Ts'o if (option < 0) 162130773840STheodore Ts'o return 0; 162230773840STheodore Ts'o if (option == 0) 162330773840STheodore Ts'o option = EXT4_DEF_MAX_BATCH_TIME; 162430773840STheodore Ts'o sbi->s_max_batch_time = option; 162530773840STheodore Ts'o break; 162630773840STheodore Ts'o case Opt_min_batch_time: 162730773840STheodore Ts'o if (match_int(&args[0], &option)) 162830773840STheodore Ts'o return 0; 162930773840STheodore Ts'o if (option < 0) 163030773840STheodore Ts'o return 0; 163130773840STheodore Ts'o sbi->s_min_batch_time = option; 163230773840STheodore Ts'o break; 1633ac27a0ecSDave Kleikamp case Opt_data_journal: 1634617ba13bSMingming Cao data_opt = EXT4_MOUNT_JOURNAL_DATA; 1635ac27a0ecSDave Kleikamp goto datacheck; 1636ac27a0ecSDave Kleikamp case Opt_data_ordered: 1637617ba13bSMingming Cao data_opt = EXT4_MOUNT_ORDERED_DATA; 1638ac27a0ecSDave Kleikamp goto datacheck; 1639ac27a0ecSDave Kleikamp case Opt_data_writeback: 1640617ba13bSMingming Cao data_opt = EXT4_MOUNT_WRITEBACK_DATA; 1641ac27a0ecSDave Kleikamp datacheck: 1642ac27a0ecSDave Kleikamp if (is_remount) { 1643482a7425SDmitry Monakhov if (test_opt(sb, DATA_FLAGS) != data_opt) { 1644b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 1645b31e1552SEric Sandeen "Cannot change data mode on remount"); 1646ac27a0ecSDave Kleikamp return 0; 1647ac27a0ecSDave Kleikamp } 1648ac27a0ecSDave Kleikamp } else { 1649fd8c37ecSTheodore Ts'o clear_opt(sb, DATA_FLAGS); 1650ac27a0ecSDave Kleikamp sbi->s_mount_opt |= data_opt; 1651ac27a0ecSDave Kleikamp } 1652ac27a0ecSDave Kleikamp break; 16535bf5683aSHidehiro Kawai case Opt_data_err_abort: 1654fd8c37ecSTheodore Ts'o set_opt(sb, DATA_ERR_ABORT); 16555bf5683aSHidehiro Kawai break; 16565bf5683aSHidehiro Kawai case Opt_data_err_ignore: 1657fd8c37ecSTheodore Ts'o clear_opt(sb, DATA_ERR_ABORT); 16585bf5683aSHidehiro Kawai break; 1659ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 1660ac27a0ecSDave Kleikamp case Opt_usrjquota: 166156c50f11SDmitry Monakhov if (!set_qf_name(sb, USRQUOTA, &args[0])) 166256c50f11SDmitry Monakhov return 0; 166356c50f11SDmitry Monakhov break; 1664ac27a0ecSDave Kleikamp case Opt_grpjquota: 166556c50f11SDmitry Monakhov if (!set_qf_name(sb, GRPQUOTA, &args[0])) 1666ac27a0ecSDave Kleikamp return 0; 1667ac27a0ecSDave Kleikamp break; 1668ac27a0ecSDave Kleikamp case Opt_offusrjquota: 166956c50f11SDmitry Monakhov if (!clear_qf_name(sb, USRQUOTA)) 1670ac27a0ecSDave Kleikamp return 0; 1671ac27a0ecSDave Kleikamp break; 167256c50f11SDmitry Monakhov case Opt_offgrpjquota: 167356c50f11SDmitry Monakhov if (!clear_qf_name(sb, GRPQUOTA)) 167456c50f11SDmitry Monakhov return 0; 167556c50f11SDmitry Monakhov break; 167656c50f11SDmitry Monakhov 1677ac27a0ecSDave Kleikamp case Opt_jqfmt_vfsold: 1678dfc5d03fSJan Kara qfmt = QFMT_VFS_OLD; 1679dfc5d03fSJan Kara goto set_qf_format; 1680ac27a0ecSDave Kleikamp case Opt_jqfmt_vfsv0: 1681dfc5d03fSJan Kara qfmt = QFMT_VFS_V0; 16825a20bdfcSJan Kara goto set_qf_format; 16835a20bdfcSJan Kara case Opt_jqfmt_vfsv1: 16845a20bdfcSJan Kara qfmt = QFMT_VFS_V1; 1685dfc5d03fSJan Kara set_qf_format: 168617bd13b3SJan Kara if (sb_any_quota_loaded(sb) && 1687dfc5d03fSJan Kara sbi->s_jquota_fmt != qfmt) { 1688b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "Cannot change " 1689dfc5d03fSJan Kara "journaled quota options when " 1690b31e1552SEric Sandeen "quota turned on"); 1691dfc5d03fSJan Kara return 0; 1692dfc5d03fSJan Kara } 1693dfc5d03fSJan Kara sbi->s_jquota_fmt = qfmt; 1694ac27a0ecSDave Kleikamp break; 1695ac27a0ecSDave Kleikamp case Opt_quota: 1696ac27a0ecSDave Kleikamp case Opt_usrquota: 1697fd8c37ecSTheodore Ts'o set_opt(sb, QUOTA); 1698fd8c37ecSTheodore Ts'o set_opt(sb, USRQUOTA); 1699ac27a0ecSDave Kleikamp break; 1700ac27a0ecSDave Kleikamp case Opt_grpquota: 1701fd8c37ecSTheodore Ts'o set_opt(sb, QUOTA); 1702fd8c37ecSTheodore Ts'o set_opt(sb, GRPQUOTA); 1703ac27a0ecSDave Kleikamp break; 1704ac27a0ecSDave Kleikamp case Opt_noquota: 170517bd13b3SJan Kara if (sb_any_quota_loaded(sb)) { 1706b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "Cannot change quota " 1707b31e1552SEric Sandeen "options when quota turned on"); 1708ac27a0ecSDave Kleikamp return 0; 1709ac27a0ecSDave Kleikamp } 1710fd8c37ecSTheodore Ts'o clear_opt(sb, QUOTA); 1711fd8c37ecSTheodore Ts'o clear_opt(sb, USRQUOTA); 1712fd8c37ecSTheodore Ts'o clear_opt(sb, GRPQUOTA); 1713ac27a0ecSDave Kleikamp break; 1714ac27a0ecSDave Kleikamp #else 1715ac27a0ecSDave Kleikamp case Opt_quota: 1716ac27a0ecSDave Kleikamp case Opt_usrquota: 1717ac27a0ecSDave Kleikamp case Opt_grpquota: 1718b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 1719b31e1552SEric Sandeen "quota options not supported"); 1720cd59e7b9SJan Kara break; 1721ac27a0ecSDave Kleikamp case Opt_usrjquota: 1722ac27a0ecSDave Kleikamp case Opt_grpjquota: 1723ac27a0ecSDave Kleikamp case Opt_offusrjquota: 1724ac27a0ecSDave Kleikamp case Opt_offgrpjquota: 1725ac27a0ecSDave Kleikamp case Opt_jqfmt_vfsold: 1726ac27a0ecSDave Kleikamp case Opt_jqfmt_vfsv0: 17275a20bdfcSJan Kara case Opt_jqfmt_vfsv1: 1728b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 1729b31e1552SEric Sandeen "journaled quota options not supported"); 1730ac27a0ecSDave Kleikamp break; 1731ac27a0ecSDave Kleikamp case Opt_noquota: 1732ac27a0ecSDave Kleikamp break; 1733ac27a0ecSDave Kleikamp #endif 1734ac27a0ecSDave Kleikamp case Opt_abort: 17354ab2f15bSTheodore Ts'o sbi->s_mount_flags |= EXT4_MF_FS_ABORTED; 1736ac27a0ecSDave Kleikamp break; 173706705bffSTheodore Ts'o case Opt_nobarrier: 1738fd8c37ecSTheodore Ts'o clear_opt(sb, BARRIER); 173906705bffSTheodore Ts'o break; 1740ac27a0ecSDave Kleikamp case Opt_barrier: 174115121c18SEric Sandeen if (args[0].from) { 174215121c18SEric Sandeen if (match_int(&args[0], &option)) 174315121c18SEric Sandeen return 0; 174415121c18SEric Sandeen } else 174515121c18SEric Sandeen option = 1; /* No argument, default to 1 */ 1746ac27a0ecSDave Kleikamp if (option) 1747fd8c37ecSTheodore Ts'o set_opt(sb, BARRIER); 1748ac27a0ecSDave Kleikamp else 1749fd8c37ecSTheodore Ts'o clear_opt(sb, BARRIER); 1750ac27a0ecSDave Kleikamp break; 1751ac27a0ecSDave Kleikamp case Opt_ignore: 1752ac27a0ecSDave Kleikamp break; 1753ac27a0ecSDave Kleikamp case Opt_resize: 1754ac27a0ecSDave Kleikamp if (!is_remount) { 1755b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 1756b31e1552SEric Sandeen "resize option only available " 1757b31e1552SEric Sandeen "for remount"); 1758ac27a0ecSDave Kleikamp return 0; 1759ac27a0ecSDave Kleikamp } 1760ac27a0ecSDave Kleikamp if (match_int(&args[0], &option) != 0) 1761ac27a0ecSDave Kleikamp return 0; 1762ac27a0ecSDave Kleikamp *n_blocks_count = option; 1763ac27a0ecSDave Kleikamp break; 1764ac27a0ecSDave Kleikamp case Opt_nobh: 1765206f7ab4SChristoph Hellwig ext4_msg(sb, KERN_WARNING, 1766206f7ab4SChristoph Hellwig "Ignoring deprecated nobh option"); 1767ac27a0ecSDave Kleikamp break; 1768ac27a0ecSDave Kleikamp case Opt_bh: 1769206f7ab4SChristoph Hellwig ext4_msg(sb, KERN_WARNING, 1770206f7ab4SChristoph Hellwig "Ignoring deprecated bh option"); 1771ac27a0ecSDave Kleikamp break; 177225ec56b5SJean Noel Cordenner case Opt_i_version: 1773fd8c37ecSTheodore Ts'o set_opt(sb, I_VERSION); 177425ec56b5SJean Noel Cordenner sb->s_flags |= MS_I_VERSION; 177525ec56b5SJean Noel Cordenner break; 1776dd919b98SAneesh Kumar K.V case Opt_nodelalloc: 1777fd8c37ecSTheodore Ts'o clear_opt(sb, DELALLOC); 1778dd919b98SAneesh Kumar K.V break; 17791449032bSTheodore Ts'o case Opt_mblk_io_submit: 1780fd8c37ecSTheodore Ts'o set_opt(sb, MBLK_IO_SUBMIT); 17811449032bSTheodore Ts'o break; 17821449032bSTheodore Ts'o case Opt_nomblk_io_submit: 1783fd8c37ecSTheodore Ts'o clear_opt(sb, MBLK_IO_SUBMIT); 17841449032bSTheodore Ts'o break; 1785c9de560dSAlex Tomas case Opt_stripe: 1786c9de560dSAlex Tomas if (match_int(&args[0], &option)) 1787c9de560dSAlex Tomas return 0; 1788c9de560dSAlex Tomas if (option < 0) 1789c9de560dSAlex Tomas return 0; 1790c9de560dSAlex Tomas sbi->s_stripe = option; 1791c9de560dSAlex Tomas break; 179264769240SAlex Tomas case Opt_delalloc: 1793fd8c37ecSTheodore Ts'o set_opt(sb, DELALLOC); 179464769240SAlex Tomas break; 17956fd058f7STheodore Ts'o case Opt_block_validity: 1796fd8c37ecSTheodore Ts'o set_opt(sb, BLOCK_VALIDITY); 17976fd058f7STheodore Ts'o break; 17986fd058f7STheodore Ts'o case Opt_noblock_validity: 1799fd8c37ecSTheodore Ts'o clear_opt(sb, BLOCK_VALIDITY); 18006fd058f7STheodore Ts'o break; 1801240799cdSTheodore Ts'o case Opt_inode_readahead_blks: 1802240799cdSTheodore Ts'o if (match_int(&args[0], &option)) 1803240799cdSTheodore Ts'o return 0; 1804240799cdSTheodore Ts'o if (option < 0 || option > (1 << 30)) 1805240799cdSTheodore Ts'o return 0; 18065dbd571dSAlexander V. Lukyanov if (option && !is_power_of_2(option)) { 1807b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 1808b31e1552SEric Sandeen "EXT4-fs: inode_readahead_blks" 1809b31e1552SEric Sandeen " must be a power of 2"); 18103197ebdbSTheodore Ts'o return 0; 18113197ebdbSTheodore Ts'o } 1812240799cdSTheodore Ts'o sbi->s_inode_readahead_blks = option; 1813240799cdSTheodore Ts'o break; 1814b3881f74STheodore Ts'o case Opt_journal_ioprio: 1815b3881f74STheodore Ts'o if (match_int(&args[0], &option)) 1816b3881f74STheodore Ts'o return 0; 1817b3881f74STheodore Ts'o if (option < 0 || option > 7) 1818b3881f74STheodore Ts'o break; 1819b3881f74STheodore Ts'o *journal_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 1820b3881f74STheodore Ts'o option); 1821b3881f74STheodore Ts'o break; 182206705bffSTheodore Ts'o case Opt_noauto_da_alloc: 1823fd8c37ecSTheodore Ts'o set_opt(sb, NO_AUTO_DA_ALLOC); 182406705bffSTheodore Ts'o break; 1825afd4672dSTheodore Ts'o case Opt_auto_da_alloc: 182615121c18SEric Sandeen if (args[0].from) { 182715121c18SEric Sandeen if (match_int(&args[0], &option)) 182815121c18SEric Sandeen return 0; 182915121c18SEric Sandeen } else 183015121c18SEric Sandeen option = 1; /* No argument, default to 1 */ 1831afd4672dSTheodore Ts'o if (option) 1832fd8c37ecSTheodore Ts'o clear_opt(sb, NO_AUTO_DA_ALLOC); 1833afd4672dSTheodore Ts'o else 1834fd8c37ecSTheodore Ts'o set_opt(sb,NO_AUTO_DA_ALLOC); 1835afd4672dSTheodore Ts'o break; 18365328e635SEric Sandeen case Opt_discard: 1837fd8c37ecSTheodore Ts'o set_opt(sb, DISCARD); 18385328e635SEric Sandeen break; 18395328e635SEric Sandeen case Opt_nodiscard: 1840fd8c37ecSTheodore Ts'o clear_opt(sb, DISCARD); 18415328e635SEric Sandeen break; 1842744692dcSJiaying Zhang case Opt_dioread_nolock: 1843fd8c37ecSTheodore Ts'o set_opt(sb, DIOREAD_NOLOCK); 1844744692dcSJiaying Zhang break; 1845744692dcSJiaying Zhang case Opt_dioread_lock: 1846fd8c37ecSTheodore Ts'o clear_opt(sb, DIOREAD_NOLOCK); 1847744692dcSJiaying Zhang break; 1848bfff6873SLukas Czerner case Opt_init_inode_table: 1849fd8c37ecSTheodore Ts'o set_opt(sb, INIT_INODE_TABLE); 1850bfff6873SLukas Czerner if (args[0].from) { 1851bfff6873SLukas Czerner if (match_int(&args[0], &option)) 1852bfff6873SLukas Czerner return 0; 1853bfff6873SLukas Czerner } else 1854bfff6873SLukas Czerner option = EXT4_DEF_LI_WAIT_MULT; 1855bfff6873SLukas Czerner if (option < 0) 1856bfff6873SLukas Czerner return 0; 1857bfff6873SLukas Czerner sbi->s_li_wait_mult = option; 1858bfff6873SLukas Czerner break; 1859bfff6873SLukas Czerner case Opt_noinit_inode_table: 1860fd8c37ecSTheodore Ts'o clear_opt(sb, INIT_INODE_TABLE); 1861bfff6873SLukas Czerner break; 1862ac27a0ecSDave Kleikamp default: 1863b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 1864b31e1552SEric Sandeen "Unrecognized mount option \"%s\" " 1865b31e1552SEric Sandeen "or missing value", p); 1866ac27a0ecSDave Kleikamp return 0; 1867ac27a0ecSDave Kleikamp } 1868ac27a0ecSDave Kleikamp } 1869ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 1870ac27a0ecSDave Kleikamp if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { 1871482a7425SDmitry Monakhov if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA]) 1872fd8c37ecSTheodore Ts'o clear_opt(sb, USRQUOTA); 1873ac27a0ecSDave Kleikamp 1874482a7425SDmitry Monakhov if (test_opt(sb, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA]) 1875fd8c37ecSTheodore Ts'o clear_opt(sb, GRPQUOTA); 1876ac27a0ecSDave Kleikamp 187756c50f11SDmitry Monakhov if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) { 1878b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "old and new quota " 1879b31e1552SEric Sandeen "format mixing"); 1880ac27a0ecSDave Kleikamp return 0; 1881ac27a0ecSDave Kleikamp } 1882ac27a0ecSDave Kleikamp 1883ac27a0ecSDave Kleikamp if (!sbi->s_jquota_fmt) { 1884b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "journaled quota format " 1885b31e1552SEric Sandeen "not specified"); 1886ac27a0ecSDave Kleikamp return 0; 1887ac27a0ecSDave Kleikamp } 1888ac27a0ecSDave Kleikamp } else { 1889ac27a0ecSDave Kleikamp if (sbi->s_jquota_fmt) { 1890b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "journaled quota format " 18912c8be6b2SJan Kara "specified with no journaling " 1892b31e1552SEric Sandeen "enabled"); 1893ac27a0ecSDave Kleikamp return 0; 1894ac27a0ecSDave Kleikamp } 1895ac27a0ecSDave Kleikamp } 1896ac27a0ecSDave Kleikamp #endif 1897ac27a0ecSDave Kleikamp return 1; 1898ac27a0ecSDave Kleikamp } 1899ac27a0ecSDave Kleikamp 1900617ba13bSMingming Cao static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, 1901ac27a0ecSDave Kleikamp int read_only) 1902ac27a0ecSDave Kleikamp { 1903617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 1904ac27a0ecSDave Kleikamp int res = 0; 1905ac27a0ecSDave Kleikamp 1906617ba13bSMingming Cao if (le32_to_cpu(es->s_rev_level) > EXT4_MAX_SUPP_REV) { 1907b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "revision level too high, " 1908b31e1552SEric Sandeen "forcing read-only mode"); 1909ac27a0ecSDave Kleikamp res = MS_RDONLY; 1910ac27a0ecSDave Kleikamp } 1911ac27a0ecSDave Kleikamp if (read_only) 1912ac27a0ecSDave Kleikamp return res; 1913617ba13bSMingming Cao if (!(sbi->s_mount_state & EXT4_VALID_FS)) 1914b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, " 1915b31e1552SEric Sandeen "running e2fsck is recommended"); 1916617ba13bSMingming Cao else if ((sbi->s_mount_state & EXT4_ERROR_FS)) 1917b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, 1918b31e1552SEric Sandeen "warning: mounting fs with errors, " 1919b31e1552SEric Sandeen "running e2fsck is recommended"); 1920ed3ce80aSTao Ma else if ((__s16) le16_to_cpu(es->s_max_mnt_count) > 0 && 1921ac27a0ecSDave Kleikamp le16_to_cpu(es->s_mnt_count) >= 1922ac27a0ecSDave Kleikamp (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) 1923b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, 1924b31e1552SEric Sandeen "warning: maximal mount count reached, " 1925b31e1552SEric Sandeen "running e2fsck is recommended"); 1926ac27a0ecSDave Kleikamp else if (le32_to_cpu(es->s_checkinterval) && 1927ac27a0ecSDave Kleikamp (le32_to_cpu(es->s_lastcheck) + 1928ac27a0ecSDave Kleikamp le32_to_cpu(es->s_checkinterval) <= get_seconds())) 1929b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, 1930b31e1552SEric Sandeen "warning: checktime reached, " 1931b31e1552SEric Sandeen "running e2fsck is recommended"); 19320390131bSFrank Mayhar if (!sbi->s_journal) 1933216c34b2SMarcin Slusarz es->s_state &= cpu_to_le16(~EXT4_VALID_FS); 1934ac27a0ecSDave Kleikamp if (!(__s16) le16_to_cpu(es->s_max_mnt_count)) 1935617ba13bSMingming Cao es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT); 1936e8546d06SMarcin Slusarz le16_add_cpu(&es->s_mnt_count, 1); 1937ac27a0ecSDave Kleikamp es->s_mtime = cpu_to_le32(get_seconds()); 1938617ba13bSMingming Cao ext4_update_dynamic_rev(sb); 19390390131bSFrank Mayhar if (sbi->s_journal) 1940617ba13bSMingming Cao EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 1941ac27a0ecSDave Kleikamp 1942e2d67052STheodore Ts'o ext4_commit_super(sb, 1); 1943ac27a0ecSDave Kleikamp if (test_opt(sb, DEBUG)) 1944a9df9a49STheodore Ts'o printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, " 1945a2595b8aSTheodore Ts'o "bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n", 1946ac27a0ecSDave Kleikamp sb->s_blocksize, 1947ac27a0ecSDave Kleikamp sbi->s_groups_count, 1948617ba13bSMingming Cao EXT4_BLOCKS_PER_GROUP(sb), 1949617ba13bSMingming Cao EXT4_INODES_PER_GROUP(sb), 1950a2595b8aSTheodore Ts'o sbi->s_mount_opt, sbi->s_mount_opt2); 1951ac27a0ecSDave Kleikamp 19527abc52c2SDan Magenheimer cleancache_init_fs(sb); 1953ac27a0ecSDave Kleikamp return res; 1954ac27a0ecSDave Kleikamp } 1955ac27a0ecSDave Kleikamp 1956772cb7c8SJose R. Santos static int ext4_fill_flex_info(struct super_block *sb) 1957772cb7c8SJose R. Santos { 1958772cb7c8SJose R. Santos struct ext4_sb_info *sbi = EXT4_SB(sb); 1959772cb7c8SJose R. Santos struct ext4_group_desc *gdp = NULL; 1960772cb7c8SJose R. Santos ext4_group_t flex_group_count; 1961772cb7c8SJose R. Santos ext4_group_t flex_group; 1962772cb7c8SJose R. Santos int groups_per_flex = 0; 1963c5ca7c76STheodore Ts'o size_t size; 1964772cb7c8SJose R. Santos int i; 1965772cb7c8SJose R. Santos 1966503358aeSTheodore Ts'o sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; 1967503358aeSTheodore Ts'o groups_per_flex = 1 << sbi->s_log_groups_per_flex; 1968503358aeSTheodore Ts'o 1969503358aeSTheodore Ts'o if (groups_per_flex < 2) { 1970772cb7c8SJose R. Santos sbi->s_log_groups_per_flex = 0; 1971772cb7c8SJose R. Santos return 1; 1972772cb7c8SJose R. Santos } 1973772cb7c8SJose R. Santos 1974c62a11fdSFrederic Bohe /* We allocate both existing and potentially added groups */ 1975c62a11fdSFrederic Bohe flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + 1976d94e99a6SAneesh Kumar K.V ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << 1977d94e99a6SAneesh Kumar K.V EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex; 1978c5ca7c76STheodore Ts'o size = flex_group_count * sizeof(struct flex_groups); 1979c5ca7c76STheodore Ts'o sbi->s_flex_groups = kzalloc(size, GFP_KERNEL); 1980c5ca7c76STheodore Ts'o if (sbi->s_flex_groups == NULL) { 198194de56abSJoe Perches sbi->s_flex_groups = vzalloc(size); 1982772cb7c8SJose R. Santos if (sbi->s_flex_groups == NULL) { 198394de56abSJoe Perches ext4_msg(sb, KERN_ERR, 198494de56abSJoe Perches "not enough memory for %u flex groups", 198594de56abSJoe Perches flex_group_count); 1986772cb7c8SJose R. Santos goto failed; 1987772cb7c8SJose R. Santos } 198894de56abSJoe Perches } 1989772cb7c8SJose R. Santos 1990772cb7c8SJose R. Santos for (i = 0; i < sbi->s_groups_count; i++) { 199188b6edd1STheodore Ts'o gdp = ext4_get_group_desc(sb, i, NULL); 1992772cb7c8SJose R. Santos 1993772cb7c8SJose R. Santos flex_group = ext4_flex_group(sbi, i); 19947ad9bb65STheodore Ts'o atomic_add(ext4_free_inodes_count(sb, gdp), 19957ad9bb65STheodore Ts'o &sbi->s_flex_groups[flex_group].free_inodes); 19967ad9bb65STheodore Ts'o atomic_add(ext4_free_blks_count(sb, gdp), 19977ad9bb65STheodore Ts'o &sbi->s_flex_groups[flex_group].free_blocks); 19987ad9bb65STheodore Ts'o atomic_add(ext4_used_dirs_count(sb, gdp), 19997ad9bb65STheodore Ts'o &sbi->s_flex_groups[flex_group].used_dirs); 2000772cb7c8SJose R. Santos } 2001772cb7c8SJose R. Santos 2002772cb7c8SJose R. Santos return 1; 2003772cb7c8SJose R. Santos failed: 2004772cb7c8SJose R. Santos return 0; 2005772cb7c8SJose R. Santos } 2006772cb7c8SJose R. Santos 2007717d50e4SAndreas Dilger __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, 2008717d50e4SAndreas Dilger struct ext4_group_desc *gdp) 2009717d50e4SAndreas Dilger { 2010717d50e4SAndreas Dilger __u16 crc = 0; 2011717d50e4SAndreas Dilger 2012717d50e4SAndreas Dilger if (sbi->s_es->s_feature_ro_compat & 2013717d50e4SAndreas Dilger cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 2014717d50e4SAndreas Dilger int offset = offsetof(struct ext4_group_desc, bg_checksum); 2015717d50e4SAndreas Dilger __le32 le_group = cpu_to_le32(block_group); 2016717d50e4SAndreas Dilger 2017717d50e4SAndreas Dilger crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid)); 2018717d50e4SAndreas Dilger crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group)); 2019717d50e4SAndreas Dilger crc = crc16(crc, (__u8 *)gdp, offset); 2020717d50e4SAndreas Dilger offset += sizeof(gdp->bg_checksum); /* skip checksum */ 2021717d50e4SAndreas Dilger /* for checksum of struct ext4_group_desc do the rest...*/ 2022717d50e4SAndreas Dilger if ((sbi->s_es->s_feature_incompat & 2023717d50e4SAndreas Dilger cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) && 2024717d50e4SAndreas Dilger offset < le16_to_cpu(sbi->s_es->s_desc_size)) 2025717d50e4SAndreas Dilger crc = crc16(crc, (__u8 *)gdp + offset, 2026717d50e4SAndreas Dilger le16_to_cpu(sbi->s_es->s_desc_size) - 2027717d50e4SAndreas Dilger offset); 2028717d50e4SAndreas Dilger } 2029717d50e4SAndreas Dilger 2030717d50e4SAndreas Dilger return cpu_to_le16(crc); 2031717d50e4SAndreas Dilger } 2032717d50e4SAndreas Dilger 2033717d50e4SAndreas Dilger int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 block_group, 2034717d50e4SAndreas Dilger struct ext4_group_desc *gdp) 2035717d50e4SAndreas Dilger { 2036717d50e4SAndreas Dilger if ((sbi->s_es->s_feature_ro_compat & 2037717d50e4SAndreas Dilger cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) && 2038717d50e4SAndreas Dilger (gdp->bg_checksum != ext4_group_desc_csum(sbi, block_group, gdp))) 2039717d50e4SAndreas Dilger return 0; 2040717d50e4SAndreas Dilger 2041717d50e4SAndreas Dilger return 1; 2042717d50e4SAndreas Dilger } 2043717d50e4SAndreas Dilger 2044ac27a0ecSDave Kleikamp /* Called at mount-time, super-block is locked */ 2045bfff6873SLukas Czerner static int ext4_check_descriptors(struct super_block *sb, 2046bfff6873SLukas Czerner ext4_group_t *first_not_zeroed) 2047ac27a0ecSDave Kleikamp { 2048617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 2049617ba13bSMingming Cao ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); 2050617ba13bSMingming Cao ext4_fsblk_t last_block; 2051bd81d8eeSLaurent Vivier ext4_fsblk_t block_bitmap; 2052bd81d8eeSLaurent Vivier ext4_fsblk_t inode_bitmap; 2053bd81d8eeSLaurent Vivier ext4_fsblk_t inode_table; 2054ce421581SJose R. Santos int flexbg_flag = 0; 2055bfff6873SLukas Czerner ext4_group_t i, grp = sbi->s_groups_count; 2056ac27a0ecSDave Kleikamp 2057ce421581SJose R. Santos if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) 2058ce421581SJose R. Santos flexbg_flag = 1; 2059ce421581SJose R. Santos 2060617ba13bSMingming Cao ext4_debug("Checking group descriptors"); 2061ac27a0ecSDave Kleikamp 2062197cd65aSAkinobu Mita for (i = 0; i < sbi->s_groups_count; i++) { 2063197cd65aSAkinobu Mita struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL); 2064197cd65aSAkinobu Mita 2065ce421581SJose R. Santos if (i == sbi->s_groups_count - 1 || flexbg_flag) 2066bd81d8eeSLaurent Vivier last_block = ext4_blocks_count(sbi->s_es) - 1; 2067ac27a0ecSDave Kleikamp else 2068ac27a0ecSDave Kleikamp last_block = first_block + 2069617ba13bSMingming Cao (EXT4_BLOCKS_PER_GROUP(sb) - 1); 2070ac27a0ecSDave Kleikamp 2071bfff6873SLukas Czerner if ((grp == sbi->s_groups_count) && 2072bfff6873SLukas Czerner !(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) 2073bfff6873SLukas Czerner grp = i; 2074bfff6873SLukas Czerner 20758fadc143SAlexandre Ratchov block_bitmap = ext4_block_bitmap(sb, gdp); 20762b2d6d01STheodore Ts'o if (block_bitmap < first_block || block_bitmap > last_block) { 2077b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " 2078a9df9a49STheodore Ts'o "Block bitmap for group %u not in group " 2079b31e1552SEric Sandeen "(block %llu)!", i, block_bitmap); 2080ac27a0ecSDave Kleikamp return 0; 2081ac27a0ecSDave Kleikamp } 20828fadc143SAlexandre Ratchov inode_bitmap = ext4_inode_bitmap(sb, gdp); 20832b2d6d01STheodore Ts'o if (inode_bitmap < first_block || inode_bitmap > last_block) { 2084b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " 2085a9df9a49STheodore Ts'o "Inode bitmap for group %u not in group " 2086b31e1552SEric Sandeen "(block %llu)!", i, inode_bitmap); 2087ac27a0ecSDave Kleikamp return 0; 2088ac27a0ecSDave Kleikamp } 20898fadc143SAlexandre Ratchov inode_table = ext4_inode_table(sb, gdp); 2090bd81d8eeSLaurent Vivier if (inode_table < first_block || 20912b2d6d01STheodore Ts'o inode_table + sbi->s_itb_per_group - 1 > last_block) { 2092b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " 2093a9df9a49STheodore Ts'o "Inode table for group %u not in group " 2094b31e1552SEric Sandeen "(block %llu)!", i, inode_table); 2095ac27a0ecSDave Kleikamp return 0; 2096ac27a0ecSDave Kleikamp } 2097955ce5f5SAneesh Kumar K.V ext4_lock_group(sb, i); 2098717d50e4SAndreas Dilger if (!ext4_group_desc_csum_verify(sbi, i, gdp)) { 2099b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " 2100b31e1552SEric Sandeen "Checksum for group %u failed (%u!=%u)", 2101fd2d4291SAvantika Mathur i, le16_to_cpu(ext4_group_desc_csum(sbi, i, 2102fd2d4291SAvantika Mathur gdp)), le16_to_cpu(gdp->bg_checksum)); 21037ee1ec4cSLi Zefan if (!(sb->s_flags & MS_RDONLY)) { 2104955ce5f5SAneesh Kumar K.V ext4_unlock_group(sb, i); 2105717d50e4SAndreas Dilger return 0; 2106717d50e4SAndreas Dilger } 21077ee1ec4cSLi Zefan } 2108955ce5f5SAneesh Kumar K.V ext4_unlock_group(sb, i); 2109ce421581SJose R. Santos if (!flexbg_flag) 2110617ba13bSMingming Cao first_block += EXT4_BLOCKS_PER_GROUP(sb); 2111ac27a0ecSDave Kleikamp } 2112bfff6873SLukas Czerner if (NULL != first_not_zeroed) 2113bfff6873SLukas Czerner *first_not_zeroed = grp; 2114ac27a0ecSDave Kleikamp 2115bd81d8eeSLaurent Vivier ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb)); 2116617ba13bSMingming Cao sbi->s_es->s_free_inodes_count =cpu_to_le32(ext4_count_free_inodes(sb)); 2117ac27a0ecSDave Kleikamp return 1; 2118ac27a0ecSDave Kleikamp } 2119ac27a0ecSDave Kleikamp 2120617ba13bSMingming Cao /* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at 2121ac27a0ecSDave Kleikamp * the superblock) which were deleted from all directories, but held open by 2122ac27a0ecSDave Kleikamp * a process at the time of a crash. We walk the list and try to delete these 2123ac27a0ecSDave Kleikamp * inodes at recovery time (only with a read-write filesystem). 2124ac27a0ecSDave Kleikamp * 2125ac27a0ecSDave Kleikamp * In order to keep the orphan inode chain consistent during traversal (in 2126ac27a0ecSDave Kleikamp * case of crash during recovery), we link each inode into the superblock 2127ac27a0ecSDave Kleikamp * orphan list_head and handle it the same way as an inode deletion during 2128ac27a0ecSDave Kleikamp * normal operation (which journals the operations for us). 2129ac27a0ecSDave Kleikamp * 2130ac27a0ecSDave Kleikamp * We only do an iget() and an iput() on each inode, which is very safe if we 2131ac27a0ecSDave Kleikamp * accidentally point at an in-use or already deleted inode. The worst that 2132ac27a0ecSDave Kleikamp * can happen in this case is that we get a "bit already cleared" message from 2133617ba13bSMingming Cao * ext4_free_inode(). The only reason we would point at a wrong inode is if 2134ac27a0ecSDave Kleikamp * e2fsck was run on this filesystem, and it must have already done the orphan 2135ac27a0ecSDave Kleikamp * inode cleanup for us, so we can safely abort without any further action. 2136ac27a0ecSDave Kleikamp */ 2137617ba13bSMingming Cao static void ext4_orphan_cleanup(struct super_block *sb, 2138617ba13bSMingming Cao struct ext4_super_block *es) 2139ac27a0ecSDave Kleikamp { 2140ac27a0ecSDave Kleikamp unsigned int s_flags = sb->s_flags; 2141ac27a0ecSDave Kleikamp int nr_orphans = 0, nr_truncates = 0; 2142ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 2143ac27a0ecSDave Kleikamp int i; 2144ac27a0ecSDave Kleikamp #endif 2145ac27a0ecSDave Kleikamp if (!es->s_last_orphan) { 2146ac27a0ecSDave Kleikamp jbd_debug(4, "no orphan inodes to clean up\n"); 2147ac27a0ecSDave Kleikamp return; 2148ac27a0ecSDave Kleikamp } 2149ac27a0ecSDave Kleikamp 2150a8f48a95SEric Sandeen if (bdev_read_only(sb->s_bdev)) { 2151b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "write access " 2152b31e1552SEric Sandeen "unavailable, skipping orphan cleanup"); 2153a8f48a95SEric Sandeen return; 2154a8f48a95SEric Sandeen } 2155a8f48a95SEric Sandeen 2156d39195c3SAmir Goldstein /* Check if feature set would not allow a r/w mount */ 2157d39195c3SAmir Goldstein if (!ext4_feature_set_ok(sb, 0)) { 2158d39195c3SAmir Goldstein ext4_msg(sb, KERN_INFO, "Skipping orphan cleanup due to " 2159d39195c3SAmir Goldstein "unknown ROCOMPAT features"); 2160d39195c3SAmir Goldstein return; 2161d39195c3SAmir Goldstein } 2162d39195c3SAmir Goldstein 2163617ba13bSMingming Cao if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) { 2164ac27a0ecSDave Kleikamp if (es->s_last_orphan) 2165ac27a0ecSDave Kleikamp jbd_debug(1, "Errors on filesystem, " 2166ac27a0ecSDave Kleikamp "clearing orphan list.\n"); 2167ac27a0ecSDave Kleikamp es->s_last_orphan = 0; 2168ac27a0ecSDave Kleikamp jbd_debug(1, "Skipping orphan recovery on fs with errors.\n"); 2169ac27a0ecSDave Kleikamp return; 2170ac27a0ecSDave Kleikamp } 2171ac27a0ecSDave Kleikamp 2172ac27a0ecSDave Kleikamp if (s_flags & MS_RDONLY) { 2173b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "orphan cleanup on readonly fs"); 2174ac27a0ecSDave Kleikamp sb->s_flags &= ~MS_RDONLY; 2175ac27a0ecSDave Kleikamp } 2176ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 2177ac27a0ecSDave Kleikamp /* Needed for iput() to work correctly and not trash data */ 2178ac27a0ecSDave Kleikamp sb->s_flags |= MS_ACTIVE; 2179ac27a0ecSDave Kleikamp /* Turn on quotas so that they are updated correctly */ 2180ac27a0ecSDave Kleikamp for (i = 0; i < MAXQUOTAS; i++) { 2181617ba13bSMingming Cao if (EXT4_SB(sb)->s_qf_names[i]) { 2182617ba13bSMingming Cao int ret = ext4_quota_on_mount(sb, i); 2183ac27a0ecSDave Kleikamp if (ret < 0) 2184b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 2185b31e1552SEric Sandeen "Cannot turn on journaled " 2186b31e1552SEric Sandeen "quota: error %d", ret); 2187ac27a0ecSDave Kleikamp } 2188ac27a0ecSDave Kleikamp } 2189ac27a0ecSDave Kleikamp #endif 2190ac27a0ecSDave Kleikamp 2191ac27a0ecSDave Kleikamp while (es->s_last_orphan) { 2192ac27a0ecSDave Kleikamp struct inode *inode; 2193ac27a0ecSDave Kleikamp 219497bd42b9SJosef Bacik inode = ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan)); 219597bd42b9SJosef Bacik if (IS_ERR(inode)) { 2196ac27a0ecSDave Kleikamp es->s_last_orphan = 0; 2197ac27a0ecSDave Kleikamp break; 2198ac27a0ecSDave Kleikamp } 2199ac27a0ecSDave Kleikamp 2200617ba13bSMingming Cao list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan); 2201871a2931SChristoph Hellwig dquot_initialize(inode); 2202ac27a0ecSDave Kleikamp if (inode->i_nlink) { 2203b31e1552SEric Sandeen ext4_msg(sb, KERN_DEBUG, 2204b31e1552SEric Sandeen "%s: truncating inode %lu to %lld bytes", 220546e665e9SHarvey Harrison __func__, inode->i_ino, inode->i_size); 2206e5f8eab8STheodore Ts'o jbd_debug(2, "truncating inode %lu to %lld bytes\n", 2207ac27a0ecSDave Kleikamp inode->i_ino, inode->i_size); 2208617ba13bSMingming Cao ext4_truncate(inode); 2209ac27a0ecSDave Kleikamp nr_truncates++; 2210ac27a0ecSDave Kleikamp } else { 2211b31e1552SEric Sandeen ext4_msg(sb, KERN_DEBUG, 2212b31e1552SEric Sandeen "%s: deleting unreferenced inode %lu", 221346e665e9SHarvey Harrison __func__, inode->i_ino); 2214ac27a0ecSDave Kleikamp jbd_debug(2, "deleting unreferenced inode %lu\n", 2215ac27a0ecSDave Kleikamp inode->i_ino); 2216ac27a0ecSDave Kleikamp nr_orphans++; 2217ac27a0ecSDave Kleikamp } 2218ac27a0ecSDave Kleikamp iput(inode); /* The delete magic happens here! */ 2219ac27a0ecSDave Kleikamp } 2220ac27a0ecSDave Kleikamp 2221ac27a0ecSDave Kleikamp #define PLURAL(x) (x), ((x) == 1) ? "" : "s" 2222ac27a0ecSDave Kleikamp 2223ac27a0ecSDave Kleikamp if (nr_orphans) 2224b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "%d orphan inode%s deleted", 2225b31e1552SEric Sandeen PLURAL(nr_orphans)); 2226ac27a0ecSDave Kleikamp if (nr_truncates) 2227b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up", 2228b31e1552SEric Sandeen PLURAL(nr_truncates)); 2229ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 2230ac27a0ecSDave Kleikamp /* Turn quotas off */ 2231ac27a0ecSDave Kleikamp for (i = 0; i < MAXQUOTAS; i++) { 2232ac27a0ecSDave Kleikamp if (sb_dqopt(sb)->files[i]) 2233287a8095SChristoph Hellwig dquot_quota_off(sb, i); 2234ac27a0ecSDave Kleikamp } 2235ac27a0ecSDave Kleikamp #endif 2236ac27a0ecSDave Kleikamp sb->s_flags = s_flags; /* Restore MS_RDONLY status */ 2237ac27a0ecSDave Kleikamp } 22380b8e58a1SAndreas Dilger 2239cd2291a4SEric Sandeen /* 2240cd2291a4SEric Sandeen * Maximal extent format file size. 2241cd2291a4SEric Sandeen * Resulting logical blkno at s_maxbytes must fit in our on-disk 2242cd2291a4SEric Sandeen * extent format containers, within a sector_t, and within i_blocks 2243cd2291a4SEric Sandeen * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, 2244cd2291a4SEric Sandeen * so that won't be a limiting factor. 2245cd2291a4SEric Sandeen * 2246*f17722f9SLukas Czerner * However there is other limiting factor. We do store extents in the form 2247*f17722f9SLukas Czerner * of starting block and length, hence the resulting length of the extent 2248*f17722f9SLukas Czerner * covering maximum file size must fit into on-disk format containers as 2249*f17722f9SLukas Czerner * well. Given that length is always by 1 unit bigger than max unit (because 2250*f17722f9SLukas Czerner * we count 0 as well) we have to lower the s_maxbytes by one fs block. 2251*f17722f9SLukas Czerner * 2252cd2291a4SEric Sandeen * Note, this does *not* consider any metadata overhead for vfs i_blocks. 2253cd2291a4SEric Sandeen */ 2254f287a1a5STheodore Ts'o static loff_t ext4_max_size(int blkbits, int has_huge_files) 2255cd2291a4SEric Sandeen { 2256cd2291a4SEric Sandeen loff_t res; 2257cd2291a4SEric Sandeen loff_t upper_limit = MAX_LFS_FILESIZE; 2258cd2291a4SEric Sandeen 2259cd2291a4SEric Sandeen /* small i_blocks in vfs inode? */ 2260f287a1a5STheodore Ts'o if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) { 2261cd2291a4SEric Sandeen /* 226290c699a9SBartlomiej Zolnierkiewicz * CONFIG_LBDAF is not enabled implies the inode 2263cd2291a4SEric Sandeen * i_block represent total blocks in 512 bytes 2264cd2291a4SEric Sandeen * 32 == size of vfs inode i_blocks * 8 2265cd2291a4SEric Sandeen */ 2266cd2291a4SEric Sandeen upper_limit = (1LL << 32) - 1; 2267cd2291a4SEric Sandeen 2268cd2291a4SEric Sandeen /* total blocks in file system block size */ 2269cd2291a4SEric Sandeen upper_limit >>= (blkbits - 9); 2270cd2291a4SEric Sandeen upper_limit <<= blkbits; 2271cd2291a4SEric Sandeen } 2272cd2291a4SEric Sandeen 2273*f17722f9SLukas Czerner /* 2274*f17722f9SLukas Czerner * 32-bit extent-start container, ee_block. We lower the maxbytes 2275*f17722f9SLukas Czerner * by one fs block, so ee_len can cover the extent of maximum file 2276*f17722f9SLukas Czerner * size 2277*f17722f9SLukas Czerner */ 2278*f17722f9SLukas Czerner res = (1LL << 32) - 1; 2279cd2291a4SEric Sandeen res <<= blkbits; 2280cd2291a4SEric Sandeen 2281cd2291a4SEric Sandeen /* Sanity check against vm- & vfs- imposed limits */ 2282cd2291a4SEric Sandeen if (res > upper_limit) 2283cd2291a4SEric Sandeen res = upper_limit; 2284cd2291a4SEric Sandeen 2285cd2291a4SEric Sandeen return res; 2286cd2291a4SEric Sandeen } 2287ac27a0ecSDave Kleikamp 2288ac27a0ecSDave Kleikamp /* 2289cd2291a4SEric Sandeen * Maximal bitmap file size. There is a direct, and {,double-,triple-}indirect 22900fc1b451SAneesh Kumar K.V * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks. 22910fc1b451SAneesh Kumar K.V * We need to be 1 filesystem block less than the 2^48 sector limit. 2292ac27a0ecSDave Kleikamp */ 2293f287a1a5STheodore Ts'o static loff_t ext4_max_bitmap_size(int bits, int has_huge_files) 2294ac27a0ecSDave Kleikamp { 2295617ba13bSMingming Cao loff_t res = EXT4_NDIR_BLOCKS; 22960fc1b451SAneesh Kumar K.V int meta_blocks; 22970fc1b451SAneesh Kumar K.V loff_t upper_limit; 22980b8e58a1SAndreas Dilger /* This is calculated to be the largest file size for a dense, block 22990b8e58a1SAndreas Dilger * mapped file such that the file's total number of 512-byte sectors, 23000b8e58a1SAndreas Dilger * including data and all indirect blocks, does not exceed (2^48 - 1). 23010b8e58a1SAndreas Dilger * 23020b8e58a1SAndreas Dilger * __u32 i_blocks_lo and _u16 i_blocks_high represent the total 23030b8e58a1SAndreas Dilger * number of 512-byte sectors of the file. 23040fc1b451SAneesh Kumar K.V */ 23050fc1b451SAneesh Kumar K.V 2306f287a1a5STheodore Ts'o if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) { 23070fc1b451SAneesh Kumar K.V /* 230890c699a9SBartlomiej Zolnierkiewicz * !has_huge_files or CONFIG_LBDAF not enabled implies that 23090b8e58a1SAndreas Dilger * the inode i_block field represents total file blocks in 23100b8e58a1SAndreas Dilger * 2^32 512-byte sectors == size of vfs inode i_blocks * 8 23110fc1b451SAneesh Kumar K.V */ 23120fc1b451SAneesh Kumar K.V upper_limit = (1LL << 32) - 1; 23130fc1b451SAneesh Kumar K.V 23140fc1b451SAneesh Kumar K.V /* total blocks in file system block size */ 23150fc1b451SAneesh Kumar K.V upper_limit >>= (bits - 9); 23160fc1b451SAneesh Kumar K.V 23170fc1b451SAneesh Kumar K.V } else { 23188180a562SAneesh Kumar K.V /* 23198180a562SAneesh Kumar K.V * We use 48 bit ext4_inode i_blocks 23208180a562SAneesh Kumar K.V * With EXT4_HUGE_FILE_FL set the i_blocks 23218180a562SAneesh Kumar K.V * represent total number of blocks in 23228180a562SAneesh Kumar K.V * file system block size 23238180a562SAneesh Kumar K.V */ 23240fc1b451SAneesh Kumar K.V upper_limit = (1LL << 48) - 1; 23250fc1b451SAneesh Kumar K.V 23260fc1b451SAneesh Kumar K.V } 23270fc1b451SAneesh Kumar K.V 23280fc1b451SAneesh Kumar K.V /* indirect blocks */ 23290fc1b451SAneesh Kumar K.V meta_blocks = 1; 23300fc1b451SAneesh Kumar K.V /* double indirect blocks */ 23310fc1b451SAneesh Kumar K.V meta_blocks += 1 + (1LL << (bits-2)); 23320fc1b451SAneesh Kumar K.V /* tripple indirect blocks */ 23330fc1b451SAneesh Kumar K.V meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2))); 23340fc1b451SAneesh Kumar K.V 23350fc1b451SAneesh Kumar K.V upper_limit -= meta_blocks; 23360fc1b451SAneesh Kumar K.V upper_limit <<= bits; 2337ac27a0ecSDave Kleikamp 2338ac27a0ecSDave Kleikamp res += 1LL << (bits-2); 2339ac27a0ecSDave Kleikamp res += 1LL << (2*(bits-2)); 2340ac27a0ecSDave Kleikamp res += 1LL << (3*(bits-2)); 2341ac27a0ecSDave Kleikamp res <<= bits; 2342ac27a0ecSDave Kleikamp if (res > upper_limit) 2343ac27a0ecSDave Kleikamp res = upper_limit; 23440fc1b451SAneesh Kumar K.V 23450fc1b451SAneesh Kumar K.V if (res > MAX_LFS_FILESIZE) 23460fc1b451SAneesh Kumar K.V res = MAX_LFS_FILESIZE; 23470fc1b451SAneesh Kumar K.V 2348ac27a0ecSDave Kleikamp return res; 2349ac27a0ecSDave Kleikamp } 2350ac27a0ecSDave Kleikamp 2351617ba13bSMingming Cao static ext4_fsblk_t descriptor_loc(struct super_block *sb, 235270bbb3e0SAndrew Morton ext4_fsblk_t logical_sb_block, int nr) 2353ac27a0ecSDave Kleikamp { 2354617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 2355fd2d4291SAvantika Mathur ext4_group_t bg, first_meta_bg; 2356ac27a0ecSDave Kleikamp int has_super = 0; 2357ac27a0ecSDave Kleikamp 2358ac27a0ecSDave Kleikamp first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); 2359ac27a0ecSDave Kleikamp 2360617ba13bSMingming Cao if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) || 2361ac27a0ecSDave Kleikamp nr < first_meta_bg) 236270bbb3e0SAndrew Morton return logical_sb_block + nr + 1; 2363ac27a0ecSDave Kleikamp bg = sbi->s_desc_per_block * nr; 2364617ba13bSMingming Cao if (ext4_bg_has_super(sb, bg)) 2365ac27a0ecSDave Kleikamp has_super = 1; 23660b8e58a1SAndreas Dilger 2367617ba13bSMingming Cao return (has_super + ext4_group_first_block_no(sb, bg)); 2368ac27a0ecSDave Kleikamp } 2369ac27a0ecSDave Kleikamp 2370c9de560dSAlex Tomas /** 2371c9de560dSAlex Tomas * ext4_get_stripe_size: Get the stripe size. 2372c9de560dSAlex Tomas * @sbi: In memory super block info 2373c9de560dSAlex Tomas * 2374c9de560dSAlex Tomas * If we have specified it via mount option, then 2375c9de560dSAlex Tomas * use the mount option value. If the value specified at mount time is 2376c9de560dSAlex Tomas * greater than the blocks per group use the super block value. 2377c9de560dSAlex Tomas * If the super block value is greater than blocks per group return 0. 2378c9de560dSAlex Tomas * Allocator needs it be less than blocks per group. 2379c9de560dSAlex Tomas * 2380c9de560dSAlex Tomas */ 2381c9de560dSAlex Tomas static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi) 2382c9de560dSAlex Tomas { 2383c9de560dSAlex Tomas unsigned long stride = le16_to_cpu(sbi->s_es->s_raid_stride); 2384c9de560dSAlex Tomas unsigned long stripe_width = 2385c9de560dSAlex Tomas le32_to_cpu(sbi->s_es->s_raid_stripe_width); 2386c9de560dSAlex Tomas 2387c9de560dSAlex Tomas if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group) 2388c9de560dSAlex Tomas return sbi->s_stripe; 2389c9de560dSAlex Tomas 2390c9de560dSAlex Tomas if (stripe_width <= sbi->s_blocks_per_group) 2391c9de560dSAlex Tomas return stripe_width; 2392c9de560dSAlex Tomas 2393c9de560dSAlex Tomas if (stride <= sbi->s_blocks_per_group) 2394c9de560dSAlex Tomas return stride; 2395c9de560dSAlex Tomas 2396c9de560dSAlex Tomas return 0; 2397c9de560dSAlex Tomas } 2398ac27a0ecSDave Kleikamp 23993197ebdbSTheodore Ts'o /* sysfs supprt */ 24003197ebdbSTheodore Ts'o 24013197ebdbSTheodore Ts'o struct ext4_attr { 24023197ebdbSTheodore Ts'o struct attribute attr; 24033197ebdbSTheodore Ts'o ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *); 24043197ebdbSTheodore Ts'o ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *, 24053197ebdbSTheodore Ts'o const char *, size_t); 24063197ebdbSTheodore Ts'o int offset; 24073197ebdbSTheodore Ts'o }; 24083197ebdbSTheodore Ts'o 24093197ebdbSTheodore Ts'o static int parse_strtoul(const char *buf, 24103197ebdbSTheodore Ts'o unsigned long max, unsigned long *value) 24113197ebdbSTheodore Ts'o { 24123197ebdbSTheodore Ts'o char *endp; 24133197ebdbSTheodore Ts'o 2414e7d2860bSAndré Goddard Rosa *value = simple_strtoul(skip_spaces(buf), &endp, 0); 2415e7d2860bSAndré Goddard Rosa endp = skip_spaces(endp); 24163197ebdbSTheodore Ts'o if (*endp || *value > max) 24173197ebdbSTheodore Ts'o return -EINVAL; 24183197ebdbSTheodore Ts'o 24193197ebdbSTheodore Ts'o return 0; 24203197ebdbSTheodore Ts'o } 24213197ebdbSTheodore Ts'o 24223197ebdbSTheodore Ts'o static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a, 24233197ebdbSTheodore Ts'o struct ext4_sb_info *sbi, 24243197ebdbSTheodore Ts'o char *buf) 24253197ebdbSTheodore Ts'o { 24263197ebdbSTheodore Ts'o return snprintf(buf, PAGE_SIZE, "%llu\n", 24273197ebdbSTheodore Ts'o (s64) percpu_counter_sum(&sbi->s_dirtyblocks_counter)); 24283197ebdbSTheodore Ts'o } 24293197ebdbSTheodore Ts'o 24303197ebdbSTheodore Ts'o static ssize_t session_write_kbytes_show(struct ext4_attr *a, 24313197ebdbSTheodore Ts'o struct ext4_sb_info *sbi, char *buf) 24323197ebdbSTheodore Ts'o { 24333197ebdbSTheodore Ts'o struct super_block *sb = sbi->s_buddy_cache->i_sb; 24343197ebdbSTheodore Ts'o 2435f613dfcbSTheodore Ts'o if (!sb->s_bdev->bd_part) 2436f613dfcbSTheodore Ts'o return snprintf(buf, PAGE_SIZE, "0\n"); 24373197ebdbSTheodore Ts'o return snprintf(buf, PAGE_SIZE, "%lu\n", 24383197ebdbSTheodore Ts'o (part_stat_read(sb->s_bdev->bd_part, sectors[1]) - 24393197ebdbSTheodore Ts'o sbi->s_sectors_written_start) >> 1); 24403197ebdbSTheodore Ts'o } 24413197ebdbSTheodore Ts'o 24423197ebdbSTheodore Ts'o static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, 24433197ebdbSTheodore Ts'o struct ext4_sb_info *sbi, char *buf) 24443197ebdbSTheodore Ts'o { 24453197ebdbSTheodore Ts'o struct super_block *sb = sbi->s_buddy_cache->i_sb; 24463197ebdbSTheodore Ts'o 2447f613dfcbSTheodore Ts'o if (!sb->s_bdev->bd_part) 2448f613dfcbSTheodore Ts'o return snprintf(buf, PAGE_SIZE, "0\n"); 24493197ebdbSTheodore Ts'o return snprintf(buf, PAGE_SIZE, "%llu\n", 2450a6b43e38SAndrew Morton (unsigned long long)(sbi->s_kbytes_written + 24513197ebdbSTheodore Ts'o ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - 2452a6b43e38SAndrew Morton EXT4_SB(sb)->s_sectors_written_start) >> 1))); 24533197ebdbSTheodore Ts'o } 24543197ebdbSTheodore Ts'o 245577f4135fSVivek Haldar static ssize_t extent_cache_hits_show(struct ext4_attr *a, 245677f4135fSVivek Haldar struct ext4_sb_info *sbi, char *buf) 245777f4135fSVivek Haldar { 245877f4135fSVivek Haldar return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits); 245977f4135fSVivek Haldar } 246077f4135fSVivek Haldar 246177f4135fSVivek Haldar static ssize_t extent_cache_misses_show(struct ext4_attr *a, 246277f4135fSVivek Haldar struct ext4_sb_info *sbi, char *buf) 246377f4135fSVivek Haldar { 246477f4135fSVivek Haldar return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses); 246577f4135fSVivek Haldar } 246677f4135fSVivek Haldar 24673197ebdbSTheodore Ts'o static ssize_t inode_readahead_blks_store(struct ext4_attr *a, 24683197ebdbSTheodore Ts'o struct ext4_sb_info *sbi, 24693197ebdbSTheodore Ts'o const char *buf, size_t count) 24703197ebdbSTheodore Ts'o { 24713197ebdbSTheodore Ts'o unsigned long t; 24723197ebdbSTheodore Ts'o 24733197ebdbSTheodore Ts'o if (parse_strtoul(buf, 0x40000000, &t)) 24743197ebdbSTheodore Ts'o return -EINVAL; 24753197ebdbSTheodore Ts'o 24765dbd571dSAlexander V. Lukyanov if (t && !is_power_of_2(t)) 24773197ebdbSTheodore Ts'o return -EINVAL; 24783197ebdbSTheodore Ts'o 24793197ebdbSTheodore Ts'o sbi->s_inode_readahead_blks = t; 24803197ebdbSTheodore Ts'o return count; 24813197ebdbSTheodore Ts'o } 24823197ebdbSTheodore Ts'o 24833197ebdbSTheodore Ts'o static ssize_t sbi_ui_show(struct ext4_attr *a, 24843197ebdbSTheodore Ts'o struct ext4_sb_info *sbi, char *buf) 24853197ebdbSTheodore Ts'o { 24863197ebdbSTheodore Ts'o unsigned int *ui = (unsigned int *) (((char *) sbi) + a->offset); 24873197ebdbSTheodore Ts'o 24883197ebdbSTheodore Ts'o return snprintf(buf, PAGE_SIZE, "%u\n", *ui); 24893197ebdbSTheodore Ts'o } 24903197ebdbSTheodore Ts'o 24913197ebdbSTheodore Ts'o static ssize_t sbi_ui_store(struct ext4_attr *a, 24923197ebdbSTheodore Ts'o struct ext4_sb_info *sbi, 24933197ebdbSTheodore Ts'o const char *buf, size_t count) 24943197ebdbSTheodore Ts'o { 24953197ebdbSTheodore Ts'o unsigned int *ui = (unsigned int *) (((char *) sbi) + a->offset); 24963197ebdbSTheodore Ts'o unsigned long t; 24973197ebdbSTheodore Ts'o 24983197ebdbSTheodore Ts'o if (parse_strtoul(buf, 0xffffffff, &t)) 24993197ebdbSTheodore Ts'o return -EINVAL; 25003197ebdbSTheodore Ts'o *ui = t; 25013197ebdbSTheodore Ts'o return count; 25023197ebdbSTheodore Ts'o } 25033197ebdbSTheodore Ts'o 25043197ebdbSTheodore Ts'o #define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \ 25053197ebdbSTheodore Ts'o static struct ext4_attr ext4_attr_##_name = { \ 25063197ebdbSTheodore Ts'o .attr = {.name = __stringify(_name), .mode = _mode }, \ 25073197ebdbSTheodore Ts'o .show = _show, \ 25083197ebdbSTheodore Ts'o .store = _store, \ 25093197ebdbSTheodore Ts'o .offset = offsetof(struct ext4_sb_info, _elname), \ 25103197ebdbSTheodore Ts'o } 25113197ebdbSTheodore Ts'o #define EXT4_ATTR(name, mode, show, store) \ 25123197ebdbSTheodore Ts'o static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) 25133197ebdbSTheodore Ts'o 2514857ac889SLukas Czerner #define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL) 25153197ebdbSTheodore Ts'o #define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL) 25163197ebdbSTheodore Ts'o #define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store) 25173197ebdbSTheodore Ts'o #define EXT4_RW_ATTR_SBI_UI(name, elname) \ 25183197ebdbSTheodore Ts'o EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname) 25193197ebdbSTheodore Ts'o #define ATTR_LIST(name) &ext4_attr_##name.attr 25203197ebdbSTheodore Ts'o 25213197ebdbSTheodore Ts'o EXT4_RO_ATTR(delayed_allocation_blocks); 25223197ebdbSTheodore Ts'o EXT4_RO_ATTR(session_write_kbytes); 25233197ebdbSTheodore Ts'o EXT4_RO_ATTR(lifetime_write_kbytes); 252477f4135fSVivek Haldar EXT4_RO_ATTR(extent_cache_hits); 252577f4135fSVivek Haldar EXT4_RO_ATTR(extent_cache_misses); 25263197ebdbSTheodore Ts'o EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, 25273197ebdbSTheodore Ts'o inode_readahead_blks_store, s_inode_readahead_blks); 252811013911SAndreas Dilger EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); 25293197ebdbSTheodore Ts'o EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); 25303197ebdbSTheodore Ts'o EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); 25313197ebdbSTheodore Ts'o EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan); 25323197ebdbSTheodore Ts'o EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs); 25333197ebdbSTheodore Ts'o EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request); 25343197ebdbSTheodore Ts'o EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc); 253555138e0bSTheodore Ts'o EXT4_RW_ATTR_SBI_UI(max_writeback_mb_bump, s_max_writeback_mb_bump); 25363197ebdbSTheodore Ts'o 25373197ebdbSTheodore Ts'o static struct attribute *ext4_attrs[] = { 25383197ebdbSTheodore Ts'o ATTR_LIST(delayed_allocation_blocks), 25393197ebdbSTheodore Ts'o ATTR_LIST(session_write_kbytes), 25403197ebdbSTheodore Ts'o ATTR_LIST(lifetime_write_kbytes), 254177f4135fSVivek Haldar ATTR_LIST(extent_cache_hits), 254277f4135fSVivek Haldar ATTR_LIST(extent_cache_misses), 25433197ebdbSTheodore Ts'o ATTR_LIST(inode_readahead_blks), 254411013911SAndreas Dilger ATTR_LIST(inode_goal), 25453197ebdbSTheodore Ts'o ATTR_LIST(mb_stats), 25463197ebdbSTheodore Ts'o ATTR_LIST(mb_max_to_scan), 25473197ebdbSTheodore Ts'o ATTR_LIST(mb_min_to_scan), 25483197ebdbSTheodore Ts'o ATTR_LIST(mb_order2_req), 25493197ebdbSTheodore Ts'o ATTR_LIST(mb_stream_req), 25503197ebdbSTheodore Ts'o ATTR_LIST(mb_group_prealloc), 255155138e0bSTheodore Ts'o ATTR_LIST(max_writeback_mb_bump), 25523197ebdbSTheodore Ts'o NULL, 25533197ebdbSTheodore Ts'o }; 25543197ebdbSTheodore Ts'o 2555857ac889SLukas Czerner /* Features this copy of ext4 supports */ 2556857ac889SLukas Czerner EXT4_INFO_ATTR(lazy_itable_init); 255727ee40dfSLukas Czerner EXT4_INFO_ATTR(batched_discard); 2558857ac889SLukas Czerner 2559857ac889SLukas Czerner static struct attribute *ext4_feat_attrs[] = { 2560857ac889SLukas Czerner ATTR_LIST(lazy_itable_init), 256127ee40dfSLukas Czerner ATTR_LIST(batched_discard), 2562857ac889SLukas Czerner NULL, 2563857ac889SLukas Czerner }; 2564857ac889SLukas Czerner 25653197ebdbSTheodore Ts'o static ssize_t ext4_attr_show(struct kobject *kobj, 25663197ebdbSTheodore Ts'o struct attribute *attr, char *buf) 25673197ebdbSTheodore Ts'o { 25683197ebdbSTheodore Ts'o struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 25693197ebdbSTheodore Ts'o s_kobj); 25703197ebdbSTheodore Ts'o struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); 25713197ebdbSTheodore Ts'o 25723197ebdbSTheodore Ts'o return a->show ? a->show(a, sbi, buf) : 0; 25733197ebdbSTheodore Ts'o } 25743197ebdbSTheodore Ts'o 25753197ebdbSTheodore Ts'o static ssize_t ext4_attr_store(struct kobject *kobj, 25763197ebdbSTheodore Ts'o struct attribute *attr, 25773197ebdbSTheodore Ts'o const char *buf, size_t len) 25783197ebdbSTheodore Ts'o { 25793197ebdbSTheodore Ts'o struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 25803197ebdbSTheodore Ts'o s_kobj); 25813197ebdbSTheodore Ts'o struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); 25823197ebdbSTheodore Ts'o 25833197ebdbSTheodore Ts'o return a->store ? a->store(a, sbi, buf, len) : 0; 25843197ebdbSTheodore Ts'o } 25853197ebdbSTheodore Ts'o 25863197ebdbSTheodore Ts'o static void ext4_sb_release(struct kobject *kobj) 25873197ebdbSTheodore Ts'o { 25883197ebdbSTheodore Ts'o struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, 25893197ebdbSTheodore Ts'o s_kobj); 25903197ebdbSTheodore Ts'o complete(&sbi->s_kobj_unregister); 25913197ebdbSTheodore Ts'o } 25923197ebdbSTheodore Ts'o 259352cf25d0SEmese Revfy static const struct sysfs_ops ext4_attr_ops = { 25943197ebdbSTheodore Ts'o .show = ext4_attr_show, 25953197ebdbSTheodore Ts'o .store = ext4_attr_store, 25963197ebdbSTheodore Ts'o }; 25973197ebdbSTheodore Ts'o 25983197ebdbSTheodore Ts'o static struct kobj_type ext4_ktype = { 25993197ebdbSTheodore Ts'o .default_attrs = ext4_attrs, 26003197ebdbSTheodore Ts'o .sysfs_ops = &ext4_attr_ops, 26013197ebdbSTheodore Ts'o .release = ext4_sb_release, 26023197ebdbSTheodore Ts'o }; 26033197ebdbSTheodore Ts'o 2604857ac889SLukas Czerner static void ext4_feat_release(struct kobject *kobj) 2605857ac889SLukas Czerner { 2606857ac889SLukas Czerner complete(&ext4_feat->f_kobj_unregister); 2607857ac889SLukas Czerner } 2608857ac889SLukas Czerner 2609857ac889SLukas Czerner static struct kobj_type ext4_feat_ktype = { 2610857ac889SLukas Czerner .default_attrs = ext4_feat_attrs, 2611857ac889SLukas Czerner .sysfs_ops = &ext4_attr_ops, 2612857ac889SLukas Czerner .release = ext4_feat_release, 2613857ac889SLukas Czerner }; 2614857ac889SLukas Czerner 2615a13fb1a4SEric Sandeen /* 2616a13fb1a4SEric Sandeen * Check whether this filesystem can be mounted based on 2617a13fb1a4SEric Sandeen * the features present and the RDONLY/RDWR mount requested. 2618a13fb1a4SEric Sandeen * Returns 1 if this filesystem can be mounted as requested, 2619a13fb1a4SEric Sandeen * 0 if it cannot be. 2620a13fb1a4SEric Sandeen */ 2621a13fb1a4SEric Sandeen static int ext4_feature_set_ok(struct super_block *sb, int readonly) 2622a13fb1a4SEric Sandeen { 2623a13fb1a4SEric Sandeen if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT4_FEATURE_INCOMPAT_SUPP)) { 2624a13fb1a4SEric Sandeen ext4_msg(sb, KERN_ERR, 2625a13fb1a4SEric Sandeen "Couldn't mount because of " 2626a13fb1a4SEric Sandeen "unsupported optional features (%x)", 2627a13fb1a4SEric Sandeen (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_incompat) & 2628a13fb1a4SEric Sandeen ~EXT4_FEATURE_INCOMPAT_SUPP)); 2629a13fb1a4SEric Sandeen return 0; 2630a13fb1a4SEric Sandeen } 2631a13fb1a4SEric Sandeen 2632a13fb1a4SEric Sandeen if (readonly) 2633a13fb1a4SEric Sandeen return 1; 2634a13fb1a4SEric Sandeen 2635a13fb1a4SEric Sandeen /* Check that feature set is OK for a read-write mount */ 2636a13fb1a4SEric Sandeen if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP)) { 2637a13fb1a4SEric Sandeen ext4_msg(sb, KERN_ERR, "couldn't mount RDWR because of " 2638a13fb1a4SEric Sandeen "unsupported optional features (%x)", 2639a13fb1a4SEric Sandeen (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_ro_compat) & 2640a13fb1a4SEric Sandeen ~EXT4_FEATURE_RO_COMPAT_SUPP)); 2641a13fb1a4SEric Sandeen return 0; 2642a13fb1a4SEric Sandeen } 2643a13fb1a4SEric Sandeen /* 2644a13fb1a4SEric Sandeen * Large file size enabled file system can only be mounted 2645a13fb1a4SEric Sandeen * read-write on 32-bit systems if kernel is built with CONFIG_LBDAF 2646a13fb1a4SEric Sandeen */ 2647a13fb1a4SEric Sandeen if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { 2648a13fb1a4SEric Sandeen if (sizeof(blkcnt_t) < sizeof(u64)) { 2649a13fb1a4SEric Sandeen ext4_msg(sb, KERN_ERR, "Filesystem with huge files " 2650a13fb1a4SEric Sandeen "cannot be mounted RDWR without " 2651a13fb1a4SEric Sandeen "CONFIG_LBDAF"); 2652a13fb1a4SEric Sandeen return 0; 2653a13fb1a4SEric Sandeen } 2654a13fb1a4SEric Sandeen } 2655a13fb1a4SEric Sandeen return 1; 2656a13fb1a4SEric Sandeen } 2657a13fb1a4SEric Sandeen 265866e61a9eSTheodore Ts'o /* 265966e61a9eSTheodore Ts'o * This function is called once a day if we have errors logged 266066e61a9eSTheodore Ts'o * on the file system 266166e61a9eSTheodore Ts'o */ 266266e61a9eSTheodore Ts'o static void print_daily_error_info(unsigned long arg) 266366e61a9eSTheodore Ts'o { 266466e61a9eSTheodore Ts'o struct super_block *sb = (struct super_block *) arg; 266566e61a9eSTheodore Ts'o struct ext4_sb_info *sbi; 266666e61a9eSTheodore Ts'o struct ext4_super_block *es; 266766e61a9eSTheodore Ts'o 266866e61a9eSTheodore Ts'o sbi = EXT4_SB(sb); 266966e61a9eSTheodore Ts'o es = sbi->s_es; 267066e61a9eSTheodore Ts'o 267166e61a9eSTheodore Ts'o if (es->s_error_count) 267266e61a9eSTheodore Ts'o ext4_msg(sb, KERN_NOTICE, "error count: %u", 267366e61a9eSTheodore Ts'o le32_to_cpu(es->s_error_count)); 267466e61a9eSTheodore Ts'o if (es->s_first_error_time) { 267566e61a9eSTheodore Ts'o printk(KERN_NOTICE "EXT4-fs (%s): initial error at %u: %.*s:%d", 267666e61a9eSTheodore Ts'o sb->s_id, le32_to_cpu(es->s_first_error_time), 267766e61a9eSTheodore Ts'o (int) sizeof(es->s_first_error_func), 267866e61a9eSTheodore Ts'o es->s_first_error_func, 267966e61a9eSTheodore Ts'o le32_to_cpu(es->s_first_error_line)); 268066e61a9eSTheodore Ts'o if (es->s_first_error_ino) 268166e61a9eSTheodore Ts'o printk(": inode %u", 268266e61a9eSTheodore Ts'o le32_to_cpu(es->s_first_error_ino)); 268366e61a9eSTheodore Ts'o if (es->s_first_error_block) 268466e61a9eSTheodore Ts'o printk(": block %llu", (unsigned long long) 268566e61a9eSTheodore Ts'o le64_to_cpu(es->s_first_error_block)); 268666e61a9eSTheodore Ts'o printk("\n"); 268766e61a9eSTheodore Ts'o } 268866e61a9eSTheodore Ts'o if (es->s_last_error_time) { 268966e61a9eSTheodore Ts'o printk(KERN_NOTICE "EXT4-fs (%s): last error at %u: %.*s:%d", 269066e61a9eSTheodore Ts'o sb->s_id, le32_to_cpu(es->s_last_error_time), 269166e61a9eSTheodore Ts'o (int) sizeof(es->s_last_error_func), 269266e61a9eSTheodore Ts'o es->s_last_error_func, 269366e61a9eSTheodore Ts'o le32_to_cpu(es->s_last_error_line)); 269466e61a9eSTheodore Ts'o if (es->s_last_error_ino) 269566e61a9eSTheodore Ts'o printk(": inode %u", 269666e61a9eSTheodore Ts'o le32_to_cpu(es->s_last_error_ino)); 269766e61a9eSTheodore Ts'o if (es->s_last_error_block) 269866e61a9eSTheodore Ts'o printk(": block %llu", (unsigned long long) 269966e61a9eSTheodore Ts'o le64_to_cpu(es->s_last_error_block)); 270066e61a9eSTheodore Ts'o printk("\n"); 270166e61a9eSTheodore Ts'o } 270266e61a9eSTheodore Ts'o mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ 270366e61a9eSTheodore Ts'o } 270466e61a9eSTheodore Ts'o 2705bfff6873SLukas Czerner /* Find next suitable group and run ext4_init_inode_table */ 2706bfff6873SLukas Czerner static int ext4_run_li_request(struct ext4_li_request *elr) 2707bfff6873SLukas Czerner { 2708bfff6873SLukas Czerner struct ext4_group_desc *gdp = NULL; 2709bfff6873SLukas Czerner ext4_group_t group, ngroups; 2710bfff6873SLukas Czerner struct super_block *sb; 2711bfff6873SLukas Czerner unsigned long timeout = 0; 2712bfff6873SLukas Czerner int ret = 0; 2713bfff6873SLukas Czerner 2714bfff6873SLukas Czerner sb = elr->lr_super; 2715bfff6873SLukas Czerner ngroups = EXT4_SB(sb)->s_groups_count; 2716bfff6873SLukas Czerner 2717bfff6873SLukas Czerner for (group = elr->lr_next_group; group < ngroups; group++) { 2718bfff6873SLukas Czerner gdp = ext4_get_group_desc(sb, group, NULL); 2719bfff6873SLukas Czerner if (!gdp) { 2720bfff6873SLukas Czerner ret = 1; 2721bfff6873SLukas Czerner break; 2722bfff6873SLukas Czerner } 2723bfff6873SLukas Czerner 2724bfff6873SLukas Czerner if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) 2725bfff6873SLukas Czerner break; 2726bfff6873SLukas Czerner } 2727bfff6873SLukas Czerner 2728bfff6873SLukas Czerner if (group == ngroups) 2729bfff6873SLukas Czerner ret = 1; 2730bfff6873SLukas Czerner 2731bfff6873SLukas Czerner if (!ret) { 2732bfff6873SLukas Czerner timeout = jiffies; 2733bfff6873SLukas Czerner ret = ext4_init_inode_table(sb, group, 2734bfff6873SLukas Czerner elr->lr_timeout ? 0 : 1); 2735bfff6873SLukas Czerner if (elr->lr_timeout == 0) { 273651ce6511SLukas Czerner timeout = (jiffies - timeout) * 273751ce6511SLukas Czerner elr->lr_sbi->s_li_wait_mult; 2738bfff6873SLukas Czerner elr->lr_timeout = timeout; 2739bfff6873SLukas Czerner } 2740bfff6873SLukas Czerner elr->lr_next_sched = jiffies + elr->lr_timeout; 2741bfff6873SLukas Czerner elr->lr_next_group = group + 1; 2742bfff6873SLukas Czerner } 2743bfff6873SLukas Czerner 2744bfff6873SLukas Czerner return ret; 2745bfff6873SLukas Czerner } 2746bfff6873SLukas Czerner 2747bfff6873SLukas Czerner /* 2748bfff6873SLukas Czerner * Remove lr_request from the list_request and free the 27494ed5c033SLukas Czerner * request structure. Should be called with li_list_mtx held 2750bfff6873SLukas Czerner */ 2751bfff6873SLukas Czerner static void ext4_remove_li_request(struct ext4_li_request *elr) 2752bfff6873SLukas Czerner { 2753bfff6873SLukas Czerner struct ext4_sb_info *sbi; 2754bfff6873SLukas Czerner 2755bfff6873SLukas Czerner if (!elr) 2756bfff6873SLukas Czerner return; 2757bfff6873SLukas Czerner 2758bfff6873SLukas Czerner sbi = elr->lr_sbi; 2759bfff6873SLukas Czerner 2760bfff6873SLukas Czerner list_del(&elr->lr_request); 2761bfff6873SLukas Czerner sbi->s_li_request = NULL; 2762bfff6873SLukas Czerner kfree(elr); 2763bfff6873SLukas Czerner } 2764bfff6873SLukas Czerner 2765bfff6873SLukas Czerner static void ext4_unregister_li_request(struct super_block *sb) 2766bfff6873SLukas Czerner { 27671bb933fbSLukas Czerner mutex_lock(&ext4_li_mtx); 27681bb933fbSLukas Czerner if (!ext4_li_info) { 27691bb933fbSLukas Czerner mutex_unlock(&ext4_li_mtx); 2770bfff6873SLukas Czerner return; 27711bb933fbSLukas Czerner } 2772bfff6873SLukas Czerner 2773bfff6873SLukas Czerner mutex_lock(&ext4_li_info->li_list_mtx); 27741bb933fbSLukas Czerner ext4_remove_li_request(EXT4_SB(sb)->s_li_request); 2775bfff6873SLukas Czerner mutex_unlock(&ext4_li_info->li_list_mtx); 27761bb933fbSLukas Czerner mutex_unlock(&ext4_li_mtx); 2777bfff6873SLukas Czerner } 2778bfff6873SLukas Czerner 27798f1f7453SEric Sandeen static struct task_struct *ext4_lazyinit_task; 27808f1f7453SEric Sandeen 2781bfff6873SLukas Czerner /* 2782bfff6873SLukas Czerner * This is the function where ext4lazyinit thread lives. It walks 2783bfff6873SLukas Czerner * through the request list searching for next scheduled filesystem. 2784bfff6873SLukas Czerner * When such a fs is found, run the lazy initialization request 2785bfff6873SLukas Czerner * (ext4_rn_li_request) and keep track of the time spend in this 2786bfff6873SLukas Czerner * function. Based on that time we compute next schedule time of 2787bfff6873SLukas Czerner * the request. When walking through the list is complete, compute 2788bfff6873SLukas Czerner * next waking time and put itself into sleep. 2789bfff6873SLukas Czerner */ 2790bfff6873SLukas Czerner static int ext4_lazyinit_thread(void *arg) 2791bfff6873SLukas Czerner { 2792bfff6873SLukas Czerner struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg; 2793bfff6873SLukas Czerner struct list_head *pos, *n; 2794bfff6873SLukas Czerner struct ext4_li_request *elr; 27954ed5c033SLukas Czerner unsigned long next_wakeup, cur; 2796bfff6873SLukas Czerner 2797bfff6873SLukas Czerner BUG_ON(NULL == eli); 2798bfff6873SLukas Czerner 2799bfff6873SLukas Czerner cont_thread: 2800bfff6873SLukas Czerner while (true) { 2801bfff6873SLukas Czerner next_wakeup = MAX_JIFFY_OFFSET; 2802bfff6873SLukas Czerner 2803bfff6873SLukas Czerner mutex_lock(&eli->li_list_mtx); 2804bfff6873SLukas Czerner if (list_empty(&eli->li_request_list)) { 2805bfff6873SLukas Czerner mutex_unlock(&eli->li_list_mtx); 2806bfff6873SLukas Czerner goto exit_thread; 2807bfff6873SLukas Czerner } 2808bfff6873SLukas Czerner 2809bfff6873SLukas Czerner list_for_each_safe(pos, n, &eli->li_request_list) { 2810bfff6873SLukas Czerner elr = list_entry(pos, struct ext4_li_request, 2811bfff6873SLukas Czerner lr_request); 2812bfff6873SLukas Czerner 2813b2c78cd0STheodore Ts'o if (time_after_eq(jiffies, elr->lr_next_sched)) { 2814b2c78cd0STheodore Ts'o if (ext4_run_li_request(elr) != 0) { 2815b2c78cd0STheodore Ts'o /* error, remove the lazy_init job */ 2816bfff6873SLukas Czerner ext4_remove_li_request(elr); 2817bfff6873SLukas Czerner continue; 2818bfff6873SLukas Czerner } 2819b2c78cd0STheodore Ts'o } 2820bfff6873SLukas Czerner 2821bfff6873SLukas Czerner if (time_before(elr->lr_next_sched, next_wakeup)) 2822bfff6873SLukas Czerner next_wakeup = elr->lr_next_sched; 2823bfff6873SLukas Czerner } 2824bfff6873SLukas Czerner mutex_unlock(&eli->li_list_mtx); 2825bfff6873SLukas Czerner 2826bfff6873SLukas Czerner if (freezing(current)) 2827bfff6873SLukas Czerner refrigerator(); 2828bfff6873SLukas Czerner 28294ed5c033SLukas Czerner cur = jiffies; 28304ed5c033SLukas Czerner if ((time_after_eq(cur, next_wakeup)) || 2831f4245bd4SLukas Czerner (MAX_JIFFY_OFFSET == next_wakeup)) { 2832bfff6873SLukas Czerner cond_resched(); 2833bfff6873SLukas Czerner continue; 2834bfff6873SLukas Czerner } 2835bfff6873SLukas Czerner 28364ed5c033SLukas Czerner schedule_timeout_interruptible(next_wakeup - cur); 28374ed5c033SLukas Czerner 28388f1f7453SEric Sandeen if (kthread_should_stop()) { 28398f1f7453SEric Sandeen ext4_clear_request_list(); 28408f1f7453SEric Sandeen goto exit_thread; 28418f1f7453SEric Sandeen } 2842bfff6873SLukas Czerner } 2843bfff6873SLukas Czerner 2844bfff6873SLukas Czerner exit_thread: 2845bfff6873SLukas Czerner /* 2846bfff6873SLukas Czerner * It looks like the request list is empty, but we need 2847bfff6873SLukas Czerner * to check it under the li_list_mtx lock, to prevent any 2848bfff6873SLukas Czerner * additions into it, and of course we should lock ext4_li_mtx 2849bfff6873SLukas Czerner * to atomically free the list and ext4_li_info, because at 2850bfff6873SLukas Czerner * this point another ext4 filesystem could be registering 2851bfff6873SLukas Czerner * new one. 2852bfff6873SLukas Czerner */ 2853bfff6873SLukas Czerner mutex_lock(&ext4_li_mtx); 2854bfff6873SLukas Czerner mutex_lock(&eli->li_list_mtx); 2855bfff6873SLukas Czerner if (!list_empty(&eli->li_request_list)) { 2856bfff6873SLukas Czerner mutex_unlock(&eli->li_list_mtx); 2857bfff6873SLukas Czerner mutex_unlock(&ext4_li_mtx); 2858bfff6873SLukas Czerner goto cont_thread; 2859bfff6873SLukas Czerner } 2860bfff6873SLukas Czerner mutex_unlock(&eli->li_list_mtx); 2861bfff6873SLukas Czerner kfree(ext4_li_info); 2862bfff6873SLukas Czerner ext4_li_info = NULL; 2863bfff6873SLukas Czerner mutex_unlock(&ext4_li_mtx); 2864bfff6873SLukas Czerner 2865bfff6873SLukas Czerner return 0; 2866bfff6873SLukas Czerner } 2867bfff6873SLukas Czerner 2868bfff6873SLukas Czerner static void ext4_clear_request_list(void) 2869bfff6873SLukas Czerner { 2870bfff6873SLukas Czerner struct list_head *pos, *n; 2871bfff6873SLukas Czerner struct ext4_li_request *elr; 2872bfff6873SLukas Czerner 2873bfff6873SLukas Czerner mutex_lock(&ext4_li_info->li_list_mtx); 2874bfff6873SLukas Czerner list_for_each_safe(pos, n, &ext4_li_info->li_request_list) { 2875bfff6873SLukas Czerner elr = list_entry(pos, struct ext4_li_request, 2876bfff6873SLukas Czerner lr_request); 2877bfff6873SLukas Czerner ext4_remove_li_request(elr); 2878bfff6873SLukas Czerner } 2879bfff6873SLukas Czerner mutex_unlock(&ext4_li_info->li_list_mtx); 2880bfff6873SLukas Czerner } 2881bfff6873SLukas Czerner 2882bfff6873SLukas Czerner static int ext4_run_lazyinit_thread(void) 2883bfff6873SLukas Czerner { 28848f1f7453SEric Sandeen ext4_lazyinit_task = kthread_run(ext4_lazyinit_thread, 28858f1f7453SEric Sandeen ext4_li_info, "ext4lazyinit"); 28868f1f7453SEric Sandeen if (IS_ERR(ext4_lazyinit_task)) { 28878f1f7453SEric Sandeen int err = PTR_ERR(ext4_lazyinit_task); 2888bfff6873SLukas Czerner ext4_clear_request_list(); 2889bfff6873SLukas Czerner kfree(ext4_li_info); 2890bfff6873SLukas Czerner ext4_li_info = NULL; 2891bfff6873SLukas Czerner printk(KERN_CRIT "EXT4: error %d creating inode table " 2892bfff6873SLukas Czerner "initialization thread\n", 2893bfff6873SLukas Czerner err); 2894bfff6873SLukas Czerner return err; 2895bfff6873SLukas Czerner } 2896bfff6873SLukas Czerner ext4_li_info->li_state |= EXT4_LAZYINIT_RUNNING; 2897bfff6873SLukas Czerner return 0; 2898bfff6873SLukas Czerner } 2899bfff6873SLukas Czerner 2900bfff6873SLukas Czerner /* 2901bfff6873SLukas Czerner * Check whether it make sense to run itable init. thread or not. 2902bfff6873SLukas Czerner * If there is at least one uninitialized inode table, return 2903bfff6873SLukas Czerner * corresponding group number, else the loop goes through all 2904bfff6873SLukas Czerner * groups and return total number of groups. 2905bfff6873SLukas Czerner */ 2906bfff6873SLukas Czerner static ext4_group_t ext4_has_uninit_itable(struct super_block *sb) 2907bfff6873SLukas Czerner { 2908bfff6873SLukas Czerner ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; 2909bfff6873SLukas Czerner struct ext4_group_desc *gdp = NULL; 2910bfff6873SLukas Czerner 2911bfff6873SLukas Czerner for (group = 0; group < ngroups; group++) { 2912bfff6873SLukas Czerner gdp = ext4_get_group_desc(sb, group, NULL); 2913bfff6873SLukas Czerner if (!gdp) 2914bfff6873SLukas Czerner continue; 2915bfff6873SLukas Czerner 2916bfff6873SLukas Czerner if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) 2917bfff6873SLukas Czerner break; 2918bfff6873SLukas Czerner } 2919bfff6873SLukas Czerner 2920bfff6873SLukas Czerner return group; 2921bfff6873SLukas Czerner } 2922bfff6873SLukas Czerner 2923bfff6873SLukas Czerner static int ext4_li_info_new(void) 2924bfff6873SLukas Czerner { 2925bfff6873SLukas Czerner struct ext4_lazy_init *eli = NULL; 2926bfff6873SLukas Czerner 2927bfff6873SLukas Czerner eli = kzalloc(sizeof(*eli), GFP_KERNEL); 2928bfff6873SLukas Czerner if (!eli) 2929bfff6873SLukas Czerner return -ENOMEM; 2930bfff6873SLukas Czerner 2931bfff6873SLukas Czerner INIT_LIST_HEAD(&eli->li_request_list); 2932bfff6873SLukas Czerner mutex_init(&eli->li_list_mtx); 2933bfff6873SLukas Czerner 2934bfff6873SLukas Czerner eli->li_state |= EXT4_LAZYINIT_QUIT; 2935bfff6873SLukas Czerner 2936bfff6873SLukas Czerner ext4_li_info = eli; 2937bfff6873SLukas Czerner 2938bfff6873SLukas Czerner return 0; 2939bfff6873SLukas Czerner } 2940bfff6873SLukas Czerner 2941bfff6873SLukas Czerner static struct ext4_li_request *ext4_li_request_new(struct super_block *sb, 2942bfff6873SLukas Czerner ext4_group_t start) 2943bfff6873SLukas Czerner { 2944bfff6873SLukas Czerner struct ext4_sb_info *sbi = EXT4_SB(sb); 2945bfff6873SLukas Czerner struct ext4_li_request *elr; 2946bfff6873SLukas Czerner unsigned long rnd; 2947bfff6873SLukas Czerner 2948bfff6873SLukas Czerner elr = kzalloc(sizeof(*elr), GFP_KERNEL); 2949bfff6873SLukas Czerner if (!elr) 2950bfff6873SLukas Czerner return NULL; 2951bfff6873SLukas Czerner 2952bfff6873SLukas Czerner elr->lr_super = sb; 2953bfff6873SLukas Czerner elr->lr_sbi = sbi; 2954bfff6873SLukas Czerner elr->lr_next_group = start; 2955bfff6873SLukas Czerner 2956bfff6873SLukas Czerner /* 2957bfff6873SLukas Czerner * Randomize first schedule time of the request to 2958bfff6873SLukas Czerner * spread the inode table initialization requests 2959bfff6873SLukas Czerner * better. 2960bfff6873SLukas Czerner */ 2961bfff6873SLukas Czerner get_random_bytes(&rnd, sizeof(rnd)); 2962bfff6873SLukas Czerner elr->lr_next_sched = jiffies + (unsigned long)rnd % 2963bfff6873SLukas Czerner (EXT4_DEF_LI_MAX_START_DELAY * HZ); 2964bfff6873SLukas Czerner 2965bfff6873SLukas Czerner return elr; 2966bfff6873SLukas Czerner } 2967bfff6873SLukas Czerner 2968bfff6873SLukas Czerner static int ext4_register_li_request(struct super_block *sb, 2969bfff6873SLukas Czerner ext4_group_t first_not_zeroed) 2970bfff6873SLukas Czerner { 2971bfff6873SLukas Czerner struct ext4_sb_info *sbi = EXT4_SB(sb); 2972bfff6873SLukas Czerner struct ext4_li_request *elr; 2973bfff6873SLukas Czerner ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; 29746c5a6cb9SAndrew Morton int ret = 0; 2975bfff6873SLukas Czerner 297651ce6511SLukas Czerner if (sbi->s_li_request != NULL) { 297751ce6511SLukas Czerner /* 297851ce6511SLukas Czerner * Reset timeout so it can be computed again, because 297951ce6511SLukas Czerner * s_li_wait_mult might have changed. 298051ce6511SLukas Czerner */ 298151ce6511SLukas Czerner sbi->s_li_request->lr_timeout = 0; 2982beed5ecbSNicolas Kaiser return 0; 298351ce6511SLukas Czerner } 2984bfff6873SLukas Czerner 2985bfff6873SLukas Czerner if (first_not_zeroed == ngroups || 2986bfff6873SLukas Czerner (sb->s_flags & MS_RDONLY) || 298755ff3840STao Ma !test_opt(sb, INIT_INODE_TABLE)) 2988beed5ecbSNicolas Kaiser return 0; 2989bfff6873SLukas Czerner 2990bfff6873SLukas Czerner elr = ext4_li_request_new(sb, first_not_zeroed); 2991beed5ecbSNicolas Kaiser if (!elr) 2992beed5ecbSNicolas Kaiser return -ENOMEM; 2993bfff6873SLukas Czerner 2994bfff6873SLukas Czerner mutex_lock(&ext4_li_mtx); 2995bfff6873SLukas Czerner 2996bfff6873SLukas Czerner if (NULL == ext4_li_info) { 2997bfff6873SLukas Czerner ret = ext4_li_info_new(); 2998bfff6873SLukas Czerner if (ret) 2999bfff6873SLukas Czerner goto out; 3000bfff6873SLukas Czerner } 3001bfff6873SLukas Czerner 3002bfff6873SLukas Czerner mutex_lock(&ext4_li_info->li_list_mtx); 3003bfff6873SLukas Czerner list_add(&elr->lr_request, &ext4_li_info->li_request_list); 3004bfff6873SLukas Czerner mutex_unlock(&ext4_li_info->li_list_mtx); 3005bfff6873SLukas Czerner 3006bfff6873SLukas Czerner sbi->s_li_request = elr; 300746e4690bSTao Ma /* 300846e4690bSTao Ma * set elr to NULL here since it has been inserted to 300946e4690bSTao Ma * the request_list and the removal and free of it is 301046e4690bSTao Ma * handled by ext4_clear_request_list from now on. 301146e4690bSTao Ma */ 301246e4690bSTao Ma elr = NULL; 3013bfff6873SLukas Czerner 3014bfff6873SLukas Czerner if (!(ext4_li_info->li_state & EXT4_LAZYINIT_RUNNING)) { 3015bfff6873SLukas Czerner ret = ext4_run_lazyinit_thread(); 3016bfff6873SLukas Czerner if (ret) 3017bfff6873SLukas Czerner goto out; 3018bfff6873SLukas Czerner } 3019bfff6873SLukas Czerner out: 3020bfff6873SLukas Czerner mutex_unlock(&ext4_li_mtx); 3021beed5ecbSNicolas Kaiser if (ret) 3022bfff6873SLukas Czerner kfree(elr); 3023bfff6873SLukas Czerner return ret; 3024bfff6873SLukas Czerner } 3025bfff6873SLukas Czerner 3026bfff6873SLukas Czerner /* 3027bfff6873SLukas Czerner * We do not need to lock anything since this is called on 3028bfff6873SLukas Czerner * module unload. 3029bfff6873SLukas Czerner */ 3030bfff6873SLukas Czerner static void ext4_destroy_lazyinit_thread(void) 3031bfff6873SLukas Czerner { 3032bfff6873SLukas Czerner /* 3033bfff6873SLukas Czerner * If thread exited earlier 3034bfff6873SLukas Czerner * there's nothing to be done. 3035bfff6873SLukas Czerner */ 30368f1f7453SEric Sandeen if (!ext4_li_info || !ext4_lazyinit_task) 3037bfff6873SLukas Czerner return; 3038bfff6873SLukas Czerner 30398f1f7453SEric Sandeen kthread_stop(ext4_lazyinit_task); 3040bfff6873SLukas Czerner } 3041bfff6873SLukas Czerner 3042617ba13bSMingming Cao static int ext4_fill_super(struct super_block *sb, void *data, int silent) 30437477827fSAneesh Kumar K.V __releases(kernel_lock) 30447477827fSAneesh Kumar K.V __acquires(kernel_lock) 3045ac27a0ecSDave Kleikamp { 3046d4c402d9SCurt Wohlgemuth char *orig_data = kstrdup(data, GFP_KERNEL); 3047ac27a0ecSDave Kleikamp struct buffer_head *bh; 3048617ba13bSMingming Cao struct ext4_super_block *es = NULL; 3049617ba13bSMingming Cao struct ext4_sb_info *sbi; 3050617ba13bSMingming Cao ext4_fsblk_t block; 3051617ba13bSMingming Cao ext4_fsblk_t sb_block = get_sb_block(&data); 305270bbb3e0SAndrew Morton ext4_fsblk_t logical_sb_block; 3053ac27a0ecSDave Kleikamp unsigned long offset = 0; 3054ac27a0ecSDave Kleikamp unsigned long journal_devnum = 0; 3055ac27a0ecSDave Kleikamp unsigned long def_mount_opts; 3056ac27a0ecSDave Kleikamp struct inode *root; 30579f6200bbSTheodore Ts'o char *cp; 30580390131bSFrank Mayhar const char *descr; 3059dcc7dae3SCyrill Gorcunov int ret = -ENOMEM; 3060ac27a0ecSDave Kleikamp int blocksize; 30614ec11028STheodore Ts'o unsigned int db_count; 30624ec11028STheodore Ts'o unsigned int i; 3063f287a1a5STheodore Ts'o int needs_recovery, has_huge_files; 3064bd81d8eeSLaurent Vivier __u64 blocks_count; 3065833f4077SPeter Zijlstra int err; 3066b3881f74STheodore Ts'o unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; 3067bfff6873SLukas Czerner ext4_group_t first_not_zeroed; 3068ac27a0ecSDave Kleikamp 3069ac27a0ecSDave Kleikamp sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); 3070ac27a0ecSDave Kleikamp if (!sbi) 3071dcc7dae3SCyrill Gorcunov goto out_free_orig; 3072705895b6SPekka Enberg 3073705895b6SPekka Enberg sbi->s_blockgroup_lock = 3074705895b6SPekka Enberg kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); 3075705895b6SPekka Enberg if (!sbi->s_blockgroup_lock) { 3076705895b6SPekka Enberg kfree(sbi); 3077dcc7dae3SCyrill Gorcunov goto out_free_orig; 3078705895b6SPekka Enberg } 3079ac27a0ecSDave Kleikamp sb->s_fs_info = sbi; 3080ac27a0ecSDave Kleikamp sbi->s_mount_opt = 0; 3081617ba13bSMingming Cao sbi->s_resuid = EXT4_DEF_RESUID; 3082617ba13bSMingming Cao sbi->s_resgid = EXT4_DEF_RESGID; 3083240799cdSTheodore Ts'o sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS; 3084d9c9bef1SMiklos Szeredi sbi->s_sb_block = sb_block; 3085f613dfcbSTheodore Ts'o if (sb->s_bdev->bd_part) 3086f613dfcbSTheodore Ts'o sbi->s_sectors_written_start = 3087f613dfcbSTheodore Ts'o part_stat_read(sb->s_bdev->bd_part, sectors[1]); 3088ac27a0ecSDave Kleikamp 30899f6200bbSTheodore Ts'o /* Cleanup superblock name */ 30909f6200bbSTheodore Ts'o for (cp = sb->s_id; (cp = strchr(cp, '/'));) 30919f6200bbSTheodore Ts'o *cp = '!'; 30929f6200bbSTheodore Ts'o 3093dcc7dae3SCyrill Gorcunov ret = -EINVAL; 3094617ba13bSMingming Cao blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); 3095ac27a0ecSDave Kleikamp if (!blocksize) { 3096b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "unable to set blocksize"); 3097ac27a0ecSDave Kleikamp goto out_fail; 3098ac27a0ecSDave Kleikamp } 3099ac27a0ecSDave Kleikamp 3100ac27a0ecSDave Kleikamp /* 3101617ba13bSMingming Cao * The ext4 superblock will not be buffer aligned for other than 1kB 3102ac27a0ecSDave Kleikamp * block sizes. We need to calculate the offset from buffer start. 3103ac27a0ecSDave Kleikamp */ 3104617ba13bSMingming Cao if (blocksize != EXT4_MIN_BLOCK_SIZE) { 310570bbb3e0SAndrew Morton logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE; 310670bbb3e0SAndrew Morton offset = do_div(logical_sb_block, blocksize); 3107ac27a0ecSDave Kleikamp } else { 310870bbb3e0SAndrew Morton logical_sb_block = sb_block; 3109ac27a0ecSDave Kleikamp } 3110ac27a0ecSDave Kleikamp 311170bbb3e0SAndrew Morton if (!(bh = sb_bread(sb, logical_sb_block))) { 3112b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "unable to read superblock"); 3113ac27a0ecSDave Kleikamp goto out_fail; 3114ac27a0ecSDave Kleikamp } 3115ac27a0ecSDave Kleikamp /* 3116ac27a0ecSDave Kleikamp * Note: s_es must be initialized as soon as possible because 3117617ba13bSMingming Cao * some ext4 macro-instructions depend on its value 3118ac27a0ecSDave Kleikamp */ 3119617ba13bSMingming Cao es = (struct ext4_super_block *) (((char *)bh->b_data) + offset); 3120ac27a0ecSDave Kleikamp sbi->s_es = es; 3121ac27a0ecSDave Kleikamp sb->s_magic = le16_to_cpu(es->s_magic); 3122617ba13bSMingming Cao if (sb->s_magic != EXT4_SUPER_MAGIC) 3123617ba13bSMingming Cao goto cantfind_ext4; 3124afc32f7eSTheodore Ts'o sbi->s_kbytes_written = le64_to_cpu(es->s_kbytes_written); 3125ac27a0ecSDave Kleikamp 3126ac27a0ecSDave Kleikamp /* Set defaults before we parse the mount options */ 3127ac27a0ecSDave Kleikamp def_mount_opts = le32_to_cpu(es->s_default_mount_opts); 3128fd8c37ecSTheodore Ts'o set_opt(sb, INIT_INODE_TABLE); 3129617ba13bSMingming Cao if (def_mount_opts & EXT4_DEFM_DEBUG) 3130fd8c37ecSTheodore Ts'o set_opt(sb, DEBUG); 3131437ca0fdSDmitry Monakhov if (def_mount_opts & EXT4_DEFM_BSDGROUPS) { 3132437ca0fdSDmitry Monakhov ext4_msg(sb, KERN_WARNING, deprecated_msg, "bsdgroups", 3133437ca0fdSDmitry Monakhov "2.6.38"); 3134fd8c37ecSTheodore Ts'o set_opt(sb, GRPID); 3135437ca0fdSDmitry Monakhov } 3136617ba13bSMingming Cao if (def_mount_opts & EXT4_DEFM_UID16) 3137fd8c37ecSTheodore Ts'o set_opt(sb, NO_UID32); 3138ea663336SEric Sandeen /* xattr user namespace & acls are now defaulted on */ 313903010a33STheodore Ts'o #ifdef CONFIG_EXT4_FS_XATTR 3140fd8c37ecSTheodore Ts'o set_opt(sb, XATTR_USER); 31412e7842b8SHugh Dickins #endif 314203010a33STheodore Ts'o #ifdef CONFIG_EXT4_FS_POSIX_ACL 3143fd8c37ecSTheodore Ts'o set_opt(sb, POSIX_ACL); 31442e7842b8SHugh Dickins #endif 31456fd7a467STheodore Ts'o set_opt(sb, MBLK_IO_SUBMIT); 3146617ba13bSMingming Cao if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) 3147fd8c37ecSTheodore Ts'o set_opt(sb, JOURNAL_DATA); 3148617ba13bSMingming Cao else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED) 3149fd8c37ecSTheodore Ts'o set_opt(sb, ORDERED_DATA); 3150617ba13bSMingming Cao else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_WBACK) 3151fd8c37ecSTheodore Ts'o set_opt(sb, WRITEBACK_DATA); 3152ac27a0ecSDave Kleikamp 3153617ba13bSMingming Cao if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC) 3154fd8c37ecSTheodore Ts'o set_opt(sb, ERRORS_PANIC); 3155bb4f397aSAneesh Kumar K.V else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_CONTINUE) 3156fd8c37ecSTheodore Ts'o set_opt(sb, ERRORS_CONT); 3157bb4f397aSAneesh Kumar K.V else 3158fd8c37ecSTheodore Ts'o set_opt(sb, ERRORS_RO); 31598b67f04aSTheodore Ts'o if (def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY) 3160fd8c37ecSTheodore Ts'o set_opt(sb, BLOCK_VALIDITY); 31618b67f04aSTheodore Ts'o if (def_mount_opts & EXT4_DEFM_DISCARD) 3162fd8c37ecSTheodore Ts'o set_opt(sb, DISCARD); 3163ac27a0ecSDave Kleikamp 3164ac27a0ecSDave Kleikamp sbi->s_resuid = le16_to_cpu(es->s_def_resuid); 3165ac27a0ecSDave Kleikamp sbi->s_resgid = le16_to_cpu(es->s_def_resgid); 316630773840STheodore Ts'o sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ; 316730773840STheodore Ts'o sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME; 316830773840STheodore Ts'o sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME; 3169ac27a0ecSDave Kleikamp 31708b67f04aSTheodore Ts'o if ((def_mount_opts & EXT4_DEFM_NOBARRIER) == 0) 3171fd8c37ecSTheodore Ts'o set_opt(sb, BARRIER); 3172ac27a0ecSDave Kleikamp 31731e2462f9SMingming Cao /* 3174dd919b98SAneesh Kumar K.V * enable delayed allocation by default 3175dd919b98SAneesh Kumar K.V * Use -o nodelalloc to turn it off 3176dd919b98SAneesh Kumar K.V */ 31778b67f04aSTheodore Ts'o if (!IS_EXT3_SB(sb) && 31788b67f04aSTheodore Ts'o ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0)) 3179fd8c37ecSTheodore Ts'o set_opt(sb, DELALLOC); 3180dd919b98SAneesh Kumar K.V 318151ce6511SLukas Czerner /* 318251ce6511SLukas Czerner * set default s_li_wait_mult for lazyinit, for the case there is 318351ce6511SLukas Czerner * no mount option specified. 318451ce6511SLukas Czerner */ 318551ce6511SLukas Czerner sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT; 318651ce6511SLukas Czerner 31878b67f04aSTheodore Ts'o if (!parse_options((char *) sbi->s_es->s_mount_opts, sb, 31888b67f04aSTheodore Ts'o &journal_devnum, &journal_ioprio, NULL, 0)) { 31898b67f04aSTheodore Ts'o ext4_msg(sb, KERN_WARNING, 31908b67f04aSTheodore Ts'o "failed to parse options in superblock: %s", 31918b67f04aSTheodore Ts'o sbi->s_es->s_mount_opts); 31928b67f04aSTheodore Ts'o } 3193b3881f74STheodore Ts'o if (!parse_options((char *) data, sb, &journal_devnum, 3194b3881f74STheodore Ts'o &journal_ioprio, NULL, 0)) 3195ac27a0ecSDave Kleikamp goto failed_mount; 3196ac27a0ecSDave Kleikamp 3197ac27a0ecSDave Kleikamp sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | 3198482a7425SDmitry Monakhov (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); 3199ac27a0ecSDave Kleikamp 3200617ba13bSMingming Cao if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV && 3201617ba13bSMingming Cao (EXT4_HAS_COMPAT_FEATURE(sb, ~0U) || 3202617ba13bSMingming Cao EXT4_HAS_RO_COMPAT_FEATURE(sb, ~0U) || 3203617ba13bSMingming Cao EXT4_HAS_INCOMPAT_FEATURE(sb, ~0U))) 3204b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, 3205b31e1552SEric Sandeen "feature flags set on rev 0 fs, " 3206b31e1552SEric Sandeen "running e2fsck is recommended"); 3207469108ffSTheodore Tso 32082035e776STheodore Ts'o if (IS_EXT2_SB(sb)) { 32092035e776STheodore Ts'o if (ext2_feature_set_ok(sb)) 32102035e776STheodore Ts'o ext4_msg(sb, KERN_INFO, "mounting ext2 file system " 32112035e776STheodore Ts'o "using the ext4 subsystem"); 32122035e776STheodore Ts'o else { 32132035e776STheodore Ts'o ext4_msg(sb, KERN_ERR, "couldn't mount as ext2 due " 32142035e776STheodore Ts'o "to feature incompatibilities"); 32152035e776STheodore Ts'o goto failed_mount; 32162035e776STheodore Ts'o } 32172035e776STheodore Ts'o } 32182035e776STheodore Ts'o 32192035e776STheodore Ts'o if (IS_EXT3_SB(sb)) { 32202035e776STheodore Ts'o if (ext3_feature_set_ok(sb)) 32212035e776STheodore Ts'o ext4_msg(sb, KERN_INFO, "mounting ext3 file system " 32222035e776STheodore Ts'o "using the ext4 subsystem"); 32232035e776STheodore Ts'o else { 32242035e776STheodore Ts'o ext4_msg(sb, KERN_ERR, "couldn't mount as ext3 due " 32252035e776STheodore Ts'o "to feature incompatibilities"); 32262035e776STheodore Ts'o goto failed_mount; 32272035e776STheodore Ts'o } 32282035e776STheodore Ts'o } 32292035e776STheodore Ts'o 3230469108ffSTheodore Tso /* 3231ac27a0ecSDave Kleikamp * Check feature flags regardless of the revision level, since we 3232ac27a0ecSDave Kleikamp * previously didn't change the revision level when setting the flags, 3233ac27a0ecSDave Kleikamp * so there is a chance incompat flags are set on a rev 0 filesystem. 3234ac27a0ecSDave Kleikamp */ 3235a13fb1a4SEric Sandeen if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY))) 3236ac27a0ecSDave Kleikamp goto failed_mount; 3237a13fb1a4SEric Sandeen 3238ac27a0ecSDave Kleikamp blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); 3239ac27a0ecSDave Kleikamp 3240617ba13bSMingming Cao if (blocksize < EXT4_MIN_BLOCK_SIZE || 3241617ba13bSMingming Cao blocksize > EXT4_MAX_BLOCK_SIZE) { 3242b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3243b31e1552SEric Sandeen "Unsupported filesystem blocksize %d", blocksize); 3244ac27a0ecSDave Kleikamp goto failed_mount; 3245ac27a0ecSDave Kleikamp } 3246ac27a0ecSDave Kleikamp 3247ac27a0ecSDave Kleikamp if (sb->s_blocksize != blocksize) { 3248ce40733cSAneesh Kumar K.V /* Validate the filesystem blocksize */ 3249ce40733cSAneesh Kumar K.V if (!sb_set_blocksize(sb, blocksize)) { 3250b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "bad block size %d", 3251ce40733cSAneesh Kumar K.V blocksize); 3252ac27a0ecSDave Kleikamp goto failed_mount; 3253ac27a0ecSDave Kleikamp } 3254ac27a0ecSDave Kleikamp 3255ac27a0ecSDave Kleikamp brelse(bh); 325670bbb3e0SAndrew Morton logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE; 325770bbb3e0SAndrew Morton offset = do_div(logical_sb_block, blocksize); 325870bbb3e0SAndrew Morton bh = sb_bread(sb, logical_sb_block); 3259ac27a0ecSDave Kleikamp if (!bh) { 3260b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3261b31e1552SEric Sandeen "Can't read superblock on 2nd try"); 3262ac27a0ecSDave Kleikamp goto failed_mount; 3263ac27a0ecSDave Kleikamp } 3264617ba13bSMingming Cao es = (struct ext4_super_block *)(((char *)bh->b_data) + offset); 3265ac27a0ecSDave Kleikamp sbi->s_es = es; 3266617ba13bSMingming Cao if (es->s_magic != cpu_to_le16(EXT4_SUPER_MAGIC)) { 3267b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3268b31e1552SEric Sandeen "Magic mismatch, very weird!"); 3269ac27a0ecSDave Kleikamp goto failed_mount; 3270ac27a0ecSDave Kleikamp } 3271ac27a0ecSDave Kleikamp } 3272ac27a0ecSDave Kleikamp 3273a13fb1a4SEric Sandeen has_huge_files = EXT4_HAS_RO_COMPAT_FEATURE(sb, 3274a13fb1a4SEric Sandeen EXT4_FEATURE_RO_COMPAT_HUGE_FILE); 3275f287a1a5STheodore Ts'o sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits, 3276f287a1a5STheodore Ts'o has_huge_files); 3277f287a1a5STheodore Ts'o sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files); 3278ac27a0ecSDave Kleikamp 3279617ba13bSMingming Cao if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) { 3280617ba13bSMingming Cao sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE; 3281617ba13bSMingming Cao sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO; 3282ac27a0ecSDave Kleikamp } else { 3283ac27a0ecSDave Kleikamp sbi->s_inode_size = le16_to_cpu(es->s_inode_size); 3284ac27a0ecSDave Kleikamp sbi->s_first_ino = le32_to_cpu(es->s_first_ino); 3285617ba13bSMingming Cao if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || 32861330593eSVignesh Babu (!is_power_of_2(sbi->s_inode_size)) || 3287ac27a0ecSDave Kleikamp (sbi->s_inode_size > blocksize)) { 3288b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3289b31e1552SEric Sandeen "unsupported inode size: %d", 3290ac27a0ecSDave Kleikamp sbi->s_inode_size); 3291ac27a0ecSDave Kleikamp goto failed_mount; 3292ac27a0ecSDave Kleikamp } 3293ef7f3835SKalpak Shah if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) 3294ef7f3835SKalpak Shah sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2); 3295ac27a0ecSDave Kleikamp } 32960b8e58a1SAndreas Dilger 32970d1ee42fSAlexandre Ratchov sbi->s_desc_size = le16_to_cpu(es->s_desc_size); 32980d1ee42fSAlexandre Ratchov if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) { 32998fadc143SAlexandre Ratchov if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT || 33000d1ee42fSAlexandre Ratchov sbi->s_desc_size > EXT4_MAX_DESC_SIZE || 3301d8ea6cf8Svignesh babu !is_power_of_2(sbi->s_desc_size)) { 3302b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3303b31e1552SEric Sandeen "unsupported descriptor size %lu", 33040d1ee42fSAlexandre Ratchov sbi->s_desc_size); 33050d1ee42fSAlexandre Ratchov goto failed_mount; 33060d1ee42fSAlexandre Ratchov } 33070d1ee42fSAlexandre Ratchov } else 33080d1ee42fSAlexandre Ratchov sbi->s_desc_size = EXT4_MIN_DESC_SIZE; 33090b8e58a1SAndreas Dilger 3310ac27a0ecSDave Kleikamp sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group); 3311ac27a0ecSDave Kleikamp sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group); 3312b47b6f38SAndries E. Brouwer if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0) 3313617ba13bSMingming Cao goto cantfind_ext4; 33140b8e58a1SAndreas Dilger 3315617ba13bSMingming Cao sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb); 3316ac27a0ecSDave Kleikamp if (sbi->s_inodes_per_block == 0) 3317617ba13bSMingming Cao goto cantfind_ext4; 3318ac27a0ecSDave Kleikamp sbi->s_itb_per_group = sbi->s_inodes_per_group / 3319ac27a0ecSDave Kleikamp sbi->s_inodes_per_block; 33200d1ee42fSAlexandre Ratchov sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb); 3321ac27a0ecSDave Kleikamp sbi->s_sbh = bh; 3322ac27a0ecSDave Kleikamp sbi->s_mount_state = le16_to_cpu(es->s_state); 3323e57aa839SFengguang Wu sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb)); 3324e57aa839SFengguang Wu sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb)); 33250b8e58a1SAndreas Dilger 3326ac27a0ecSDave Kleikamp for (i = 0; i < 4; i++) 3327ac27a0ecSDave Kleikamp sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); 3328ac27a0ecSDave Kleikamp sbi->s_def_hash_version = es->s_def_hash_version; 3329f99b2589STheodore Ts'o i = le32_to_cpu(es->s_flags); 3330f99b2589STheodore Ts'o if (i & EXT2_FLAGS_UNSIGNED_HASH) 3331f99b2589STheodore Ts'o sbi->s_hash_unsigned = 3; 3332f99b2589STheodore Ts'o else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { 3333f99b2589STheodore Ts'o #ifdef __CHAR_UNSIGNED__ 3334f99b2589STheodore Ts'o es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); 3335f99b2589STheodore Ts'o sbi->s_hash_unsigned = 3; 3336f99b2589STheodore Ts'o #else 3337f99b2589STheodore Ts'o es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); 3338f99b2589STheodore Ts'o #endif 3339f99b2589STheodore Ts'o sb->s_dirt = 1; 3340f99b2589STheodore Ts'o } 3341ac27a0ecSDave Kleikamp 3342ac27a0ecSDave Kleikamp if (sbi->s_blocks_per_group > blocksize * 8) { 3343b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3344b31e1552SEric Sandeen "#blocks per group too big: %lu", 3345ac27a0ecSDave Kleikamp sbi->s_blocks_per_group); 3346ac27a0ecSDave Kleikamp goto failed_mount; 3347ac27a0ecSDave Kleikamp } 3348ac27a0ecSDave Kleikamp if (sbi->s_inodes_per_group > blocksize * 8) { 3349b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3350b31e1552SEric Sandeen "#inodes per group too big: %lu", 3351ac27a0ecSDave Kleikamp sbi->s_inodes_per_group); 3352ac27a0ecSDave Kleikamp goto failed_mount; 3353ac27a0ecSDave Kleikamp } 3354ac27a0ecSDave Kleikamp 3355bf43d84bSEric Sandeen /* 3356bf43d84bSEric Sandeen * Test whether we have more sectors than will fit in sector_t, 3357bf43d84bSEric Sandeen * and whether the max offset is addressable by the page cache. 3358bf43d84bSEric Sandeen */ 33595a9ae68aSDarrick J. Wong err = generic_check_addressable(sb->s_blocksize_bits, 336030ca22c7SPatrick J. LoPresti ext4_blocks_count(es)); 33615a9ae68aSDarrick J. Wong if (err) { 3362b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "filesystem" 3363bf43d84bSEric Sandeen " too large to mount safely on this system"); 3364ac27a0ecSDave Kleikamp if (sizeof(sector_t) < 8) 336590c699a9SBartlomiej Zolnierkiewicz ext4_msg(sb, KERN_WARNING, "CONFIG_LBDAF not enabled"); 33665a9ae68aSDarrick J. Wong ret = err; 3367ac27a0ecSDave Kleikamp goto failed_mount; 3368ac27a0ecSDave Kleikamp } 3369ac27a0ecSDave Kleikamp 3370617ba13bSMingming Cao if (EXT4_BLOCKS_PER_GROUP(sb) == 0) 3371617ba13bSMingming Cao goto cantfind_ext4; 3372e7c95593SEric Sandeen 33730f2ddca6SFrom: Thiemo Nagel /* check blocks count against device size */ 33740f2ddca6SFrom: Thiemo Nagel blocks_count = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; 33750f2ddca6SFrom: Thiemo Nagel if (blocks_count && ext4_blocks_count(es) > blocks_count) { 3376b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, "bad geometry: block count %llu " 3377b31e1552SEric Sandeen "exceeds size of device (%llu blocks)", 33780f2ddca6SFrom: Thiemo Nagel ext4_blocks_count(es), blocks_count); 33790f2ddca6SFrom: Thiemo Nagel goto failed_mount; 33800f2ddca6SFrom: Thiemo Nagel } 33810f2ddca6SFrom: Thiemo Nagel 33824ec11028STheodore Ts'o /* 33834ec11028STheodore Ts'o * It makes no sense for the first data block to be beyond the end 33844ec11028STheodore Ts'o * of the filesystem. 33854ec11028STheodore Ts'o */ 33864ec11028STheodore Ts'o if (le32_to_cpu(es->s_first_data_block) >= ext4_blocks_count(es)) { 3387b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, "bad geometry: first data" 3388b31e1552SEric Sandeen "block %u is beyond end of filesystem (%llu)", 3389e7c95593SEric Sandeen le32_to_cpu(es->s_first_data_block), 33904ec11028STheodore Ts'o ext4_blocks_count(es)); 3391e7c95593SEric Sandeen goto failed_mount; 3392e7c95593SEric Sandeen } 3393bd81d8eeSLaurent Vivier blocks_count = (ext4_blocks_count(es) - 3394bd81d8eeSLaurent Vivier le32_to_cpu(es->s_first_data_block) + 3395bd81d8eeSLaurent Vivier EXT4_BLOCKS_PER_GROUP(sb) - 1); 3396bd81d8eeSLaurent Vivier do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb)); 33974ec11028STheodore Ts'o if (blocks_count > ((uint64_t)1<<32) - EXT4_DESC_PER_BLOCK(sb)) { 3398b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, "groups count too large: %u " 33994ec11028STheodore Ts'o "(block count %llu, first data block %u, " 3400b31e1552SEric Sandeen "blocks per group %lu)", sbi->s_groups_count, 34014ec11028STheodore Ts'o ext4_blocks_count(es), 34024ec11028STheodore Ts'o le32_to_cpu(es->s_first_data_block), 34034ec11028STheodore Ts'o EXT4_BLOCKS_PER_GROUP(sb)); 34044ec11028STheodore Ts'o goto failed_mount; 34054ec11028STheodore Ts'o } 3406bd81d8eeSLaurent Vivier sbi->s_groups_count = blocks_count; 3407fb0a387dSEric Sandeen sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count, 3408fb0a387dSEric Sandeen (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb))); 3409617ba13bSMingming Cao db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / 3410617ba13bSMingming Cao EXT4_DESC_PER_BLOCK(sb); 3411ac27a0ecSDave Kleikamp sbi->s_group_desc = kmalloc(db_count * sizeof(struct buffer_head *), 3412ac27a0ecSDave Kleikamp GFP_KERNEL); 3413ac27a0ecSDave Kleikamp if (sbi->s_group_desc == NULL) { 3414b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "not enough memory"); 3415ac27a0ecSDave Kleikamp goto failed_mount; 3416ac27a0ecSDave Kleikamp } 3417ac27a0ecSDave Kleikamp 34183244fcb1SAlexander Beregalov #ifdef CONFIG_PROC_FS 34199f6200bbSTheodore Ts'o if (ext4_proc_root) 34209f6200bbSTheodore Ts'o sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); 34213244fcb1SAlexander Beregalov #endif 3422240799cdSTheodore Ts'o 3423705895b6SPekka Enberg bgl_lock_init(sbi->s_blockgroup_lock); 3424ac27a0ecSDave Kleikamp 3425ac27a0ecSDave Kleikamp for (i = 0; i < db_count; i++) { 342670bbb3e0SAndrew Morton block = descriptor_loc(sb, logical_sb_block, i); 3427ac27a0ecSDave Kleikamp sbi->s_group_desc[i] = sb_bread(sb, block); 3428ac27a0ecSDave Kleikamp if (!sbi->s_group_desc[i]) { 3429b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3430b31e1552SEric Sandeen "can't read group descriptor %d", i); 3431ac27a0ecSDave Kleikamp db_count = i; 3432ac27a0ecSDave Kleikamp goto failed_mount2; 3433ac27a0ecSDave Kleikamp } 3434ac27a0ecSDave Kleikamp } 3435bfff6873SLukas Czerner if (!ext4_check_descriptors(sb, &first_not_zeroed)) { 3436b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); 3437ac27a0ecSDave Kleikamp goto failed_mount2; 3438ac27a0ecSDave Kleikamp } 3439772cb7c8SJose R. Santos if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) 3440772cb7c8SJose R. Santos if (!ext4_fill_flex_info(sb)) { 3441b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3442b31e1552SEric Sandeen "unable to initialize " 3443b31e1552SEric Sandeen "flex_bg meta info!"); 3444772cb7c8SJose R. Santos goto failed_mount2; 3445772cb7c8SJose R. Santos } 3446772cb7c8SJose R. Santos 3447ac27a0ecSDave Kleikamp sbi->s_gdb_count = db_count; 3448ac27a0ecSDave Kleikamp get_random_bytes(&sbi->s_next_generation, sizeof(u32)); 3449ac27a0ecSDave Kleikamp spin_lock_init(&sbi->s_next_gen_lock); 3450ac27a0ecSDave Kleikamp 345104496411STao Ma init_timer(&sbi->s_err_report); 345204496411STao Ma sbi->s_err_report.function = print_daily_error_info; 345304496411STao Ma sbi->s_err_report.data = (unsigned long) sb; 345404496411STao Ma 3455ce7e010aSTheodore Ts'o err = percpu_counter_init(&sbi->s_freeblocks_counter, 3456ce7e010aSTheodore Ts'o ext4_count_free_blocks(sb)); 3457ce7e010aSTheodore Ts'o if (!err) { 3458ce7e010aSTheodore Ts'o err = percpu_counter_init(&sbi->s_freeinodes_counter, 3459ce7e010aSTheodore Ts'o ext4_count_free_inodes(sb)); 3460ce7e010aSTheodore Ts'o } 3461ce7e010aSTheodore Ts'o if (!err) { 3462ce7e010aSTheodore Ts'o err = percpu_counter_init(&sbi->s_dirs_counter, 3463ce7e010aSTheodore Ts'o ext4_count_dirs(sb)); 3464ce7e010aSTheodore Ts'o } 3465ce7e010aSTheodore Ts'o if (!err) { 3466ce7e010aSTheodore Ts'o err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0); 3467ce7e010aSTheodore Ts'o } 3468ce7e010aSTheodore Ts'o if (err) { 3469ce7e010aSTheodore Ts'o ext4_msg(sb, KERN_ERR, "insufficient memory"); 3470ce7e010aSTheodore Ts'o goto failed_mount3; 3471ce7e010aSTheodore Ts'o } 3472ce7e010aSTheodore Ts'o 3473c9de560dSAlex Tomas sbi->s_stripe = ext4_get_stripe_size(sbi); 347455138e0bSTheodore Ts'o sbi->s_max_writeback_mb_bump = 128; 3475c9de560dSAlex Tomas 3476ac27a0ecSDave Kleikamp /* 3477ac27a0ecSDave Kleikamp * set up enough so that it can read an inode 3478ac27a0ecSDave Kleikamp */ 34799ca92389STheodore Ts'o if (!test_opt(sb, NOLOAD) && 34809ca92389STheodore Ts'o EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) 3481617ba13bSMingming Cao sb->s_op = &ext4_sops; 34829ca92389STheodore Ts'o else 34839ca92389STheodore Ts'o sb->s_op = &ext4_nojournal_sops; 3484617ba13bSMingming Cao sb->s_export_op = &ext4_export_ops; 3485617ba13bSMingming Cao sb->s_xattr = ext4_xattr_handlers; 3486ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 3487617ba13bSMingming Cao sb->s_qcop = &ext4_qctl_operations; 3488617ba13bSMingming Cao sb->dq_op = &ext4_quota_operations; 3489ac27a0ecSDave Kleikamp #endif 3490f2fa2ffcSAneesh Kumar K.V memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); 3491f2fa2ffcSAneesh Kumar K.V 3492ac27a0ecSDave Kleikamp INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ 34933b9d4ed2STheodore Ts'o mutex_init(&sbi->s_orphan_lock); 349432ed5058STheodore Ts'o mutex_init(&sbi->s_resize_lock); 3495ac27a0ecSDave Kleikamp 3496ac27a0ecSDave Kleikamp sb->s_root = NULL; 3497ac27a0ecSDave Kleikamp 3498ac27a0ecSDave Kleikamp needs_recovery = (es->s_last_orphan != 0 || 3499617ba13bSMingming Cao EXT4_HAS_INCOMPAT_FEATURE(sb, 3500617ba13bSMingming Cao EXT4_FEATURE_INCOMPAT_RECOVER)); 3501ac27a0ecSDave Kleikamp 3502c5e06d10SJohann Lombardi if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_MMP) && 3503c5e06d10SJohann Lombardi !(sb->s_flags & MS_RDONLY)) 3504c5e06d10SJohann Lombardi if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block))) 3505c5e06d10SJohann Lombardi goto failed_mount3; 3506c5e06d10SJohann Lombardi 3507ac27a0ecSDave Kleikamp /* 3508ac27a0ecSDave Kleikamp * The first inode we look at is the journal inode. Don't try 3509ac27a0ecSDave Kleikamp * root first: it may be modified in the journal! 3510ac27a0ecSDave Kleikamp */ 3511ac27a0ecSDave Kleikamp if (!test_opt(sb, NOLOAD) && 3512617ba13bSMingming Cao EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { 3513617ba13bSMingming Cao if (ext4_load_journal(sb, es, journal_devnum)) 3514ac27a0ecSDave Kleikamp goto failed_mount3; 35150390131bSFrank Mayhar } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && 35160390131bSFrank Mayhar EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { 3517b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "required journal recovery " 3518b31e1552SEric Sandeen "suppressed and not mounted read-only"); 3519744692dcSJiaying Zhang goto failed_mount_wq; 3520ac27a0ecSDave Kleikamp } else { 3521fd8c37ecSTheodore Ts'o clear_opt(sb, DATA_FLAGS); 35220390131bSFrank Mayhar sbi->s_journal = NULL; 35230390131bSFrank Mayhar needs_recovery = 0; 35240390131bSFrank Mayhar goto no_journal; 3525ac27a0ecSDave Kleikamp } 3526ac27a0ecSDave Kleikamp 3527eb40a09cSJose R. Santos if (ext4_blocks_count(es) > 0xffffffffULL && 3528eb40a09cSJose R. Santos !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0, 3529eb40a09cSJose R. Santos JBD2_FEATURE_INCOMPAT_64BIT)) { 3530b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature"); 3531744692dcSJiaying Zhang goto failed_mount_wq; 3532eb40a09cSJose R. Santos } 3533eb40a09cSJose R. Santos 3534d4da6c9cSLinus Torvalds if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) { 3535d4da6c9cSLinus Torvalds jbd2_journal_set_features(sbi->s_journal, 3536d4da6c9cSLinus Torvalds JBD2_FEATURE_COMPAT_CHECKSUM, 0, 3537d4da6c9cSLinus Torvalds JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); 3538d4da6c9cSLinus Torvalds } else if (test_opt(sb, JOURNAL_CHECKSUM)) { 3539818d276cSGirish Shilamkar jbd2_journal_set_features(sbi->s_journal, 3540818d276cSGirish Shilamkar JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0); 3541818d276cSGirish Shilamkar jbd2_journal_clear_features(sbi->s_journal, 0, 0, 3542818d276cSGirish Shilamkar JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); 3543d4da6c9cSLinus Torvalds } else { 3544d4da6c9cSLinus Torvalds jbd2_journal_clear_features(sbi->s_journal, 3545d4da6c9cSLinus Torvalds JBD2_FEATURE_COMPAT_CHECKSUM, 0, 3546d4da6c9cSLinus Torvalds JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); 3547d4da6c9cSLinus Torvalds } 3548818d276cSGirish Shilamkar 3549ac27a0ecSDave Kleikamp /* We have now updated the journal if required, so we can 3550ac27a0ecSDave Kleikamp * validate the data journaling mode. */ 3551ac27a0ecSDave Kleikamp switch (test_opt(sb, DATA_FLAGS)) { 3552ac27a0ecSDave Kleikamp case 0: 3553ac27a0ecSDave Kleikamp /* No mode set, assume a default based on the journal 355463f57933SAndrew Morton * capabilities: ORDERED_DATA if the journal can 355563f57933SAndrew Morton * cope, else JOURNAL_DATA 355663f57933SAndrew Morton */ 3557dab291afSMingming Cao if (jbd2_journal_check_available_features 3558dab291afSMingming Cao (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) 3559fd8c37ecSTheodore Ts'o set_opt(sb, ORDERED_DATA); 3560ac27a0ecSDave Kleikamp else 3561fd8c37ecSTheodore Ts'o set_opt(sb, JOURNAL_DATA); 3562ac27a0ecSDave Kleikamp break; 3563ac27a0ecSDave Kleikamp 3564617ba13bSMingming Cao case EXT4_MOUNT_ORDERED_DATA: 3565617ba13bSMingming Cao case EXT4_MOUNT_WRITEBACK_DATA: 3566dab291afSMingming Cao if (!jbd2_journal_check_available_features 3567dab291afSMingming Cao (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) { 3568b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "Journal does not support " 3569b31e1552SEric Sandeen "requested data journaling mode"); 3570744692dcSJiaying Zhang goto failed_mount_wq; 3571ac27a0ecSDave Kleikamp } 3572ac27a0ecSDave Kleikamp default: 3573ac27a0ecSDave Kleikamp break; 3574ac27a0ecSDave Kleikamp } 3575b3881f74STheodore Ts'o set_task_ioprio(sbi->s_journal->j_task, journal_ioprio); 3576ac27a0ecSDave Kleikamp 3577ce7e010aSTheodore Ts'o /* 3578ce7e010aSTheodore Ts'o * The journal may have updated the bg summary counts, so we 3579ce7e010aSTheodore Ts'o * need to update the global counters. 3580ce7e010aSTheodore Ts'o */ 3581ce7e010aSTheodore Ts'o percpu_counter_set(&sbi->s_freeblocks_counter, 358284061e07SDmitry Monakhov ext4_count_free_blocks(sb)); 3583ce7e010aSTheodore Ts'o percpu_counter_set(&sbi->s_freeinodes_counter, 358484061e07SDmitry Monakhov ext4_count_free_inodes(sb)); 3585ce7e010aSTheodore Ts'o percpu_counter_set(&sbi->s_dirs_counter, 358684061e07SDmitry Monakhov ext4_count_dirs(sb)); 3587ce7e010aSTheodore Ts'o percpu_counter_set(&sbi->s_dirtyblocks_counter, 0); 3588206f7ab4SChristoph Hellwig 3589ce7e010aSTheodore Ts'o no_journal: 3590fd89d5f2STejun Heo /* 3591fd89d5f2STejun Heo * The maximum number of concurrent works can be high and 3592fd89d5f2STejun Heo * concurrency isn't really necessary. Limit it to 1. 3593fd89d5f2STejun Heo */ 3594fd89d5f2STejun Heo EXT4_SB(sb)->dio_unwritten_wq = 3595ae005cbeSLinus Torvalds alloc_workqueue("ext4-dio-unwritten", WQ_MEM_RECLAIM | WQ_UNBOUND, 1); 35964c0425ffSMingming Cao if (!EXT4_SB(sb)->dio_unwritten_wq) { 35974c0425ffSMingming Cao printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); 35984c0425ffSMingming Cao goto failed_mount_wq; 35994c0425ffSMingming Cao } 36004c0425ffSMingming Cao 3601ac27a0ecSDave Kleikamp /* 3602dab291afSMingming Cao * The jbd2_journal_load will have done any necessary log recovery, 3603ac27a0ecSDave Kleikamp * so we can safely mount the rest of the filesystem now. 3604ac27a0ecSDave Kleikamp */ 3605ac27a0ecSDave Kleikamp 36061d1fe1eeSDavid Howells root = ext4_iget(sb, EXT4_ROOT_INO); 36071d1fe1eeSDavid Howells if (IS_ERR(root)) { 3608b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "get root inode failed"); 36091d1fe1eeSDavid Howells ret = PTR_ERR(root); 361032a9bb57SManish Katiyar root = NULL; 3611ac27a0ecSDave Kleikamp goto failed_mount4; 3612ac27a0ecSDave Kleikamp } 3613ac27a0ecSDave Kleikamp if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { 3614b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck"); 3615ac27a0ecSDave Kleikamp goto failed_mount4; 3616ac27a0ecSDave Kleikamp } 36171d1fe1eeSDavid Howells sb->s_root = d_alloc_root(root); 36181d1fe1eeSDavid Howells if (!sb->s_root) { 3619b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "get root dentry failed"); 36201d1fe1eeSDavid Howells ret = -ENOMEM; 36211d1fe1eeSDavid Howells goto failed_mount4; 36221d1fe1eeSDavid Howells } 3623ac27a0ecSDave Kleikamp 3624617ba13bSMingming Cao ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY); 3625ef7f3835SKalpak Shah 3626ef7f3835SKalpak Shah /* determine the minimum size of new large inodes, if present */ 3627ef7f3835SKalpak Shah if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) { 3628ef7f3835SKalpak Shah sbi->s_want_extra_isize = sizeof(struct ext4_inode) - 3629ef7f3835SKalpak Shah EXT4_GOOD_OLD_INODE_SIZE; 3630ef7f3835SKalpak Shah if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 3631ef7f3835SKalpak Shah EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)) { 3632ef7f3835SKalpak Shah if (sbi->s_want_extra_isize < 3633ef7f3835SKalpak Shah le16_to_cpu(es->s_want_extra_isize)) 3634ef7f3835SKalpak Shah sbi->s_want_extra_isize = 3635ef7f3835SKalpak Shah le16_to_cpu(es->s_want_extra_isize); 3636ef7f3835SKalpak Shah if (sbi->s_want_extra_isize < 3637ef7f3835SKalpak Shah le16_to_cpu(es->s_min_extra_isize)) 3638ef7f3835SKalpak Shah sbi->s_want_extra_isize = 3639ef7f3835SKalpak Shah le16_to_cpu(es->s_min_extra_isize); 3640ef7f3835SKalpak Shah } 3641ef7f3835SKalpak Shah } 3642ef7f3835SKalpak Shah /* Check if enough inode space is available */ 3643ef7f3835SKalpak Shah if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize > 3644ef7f3835SKalpak Shah sbi->s_inode_size) { 3645ef7f3835SKalpak Shah sbi->s_want_extra_isize = sizeof(struct ext4_inode) - 3646ef7f3835SKalpak Shah EXT4_GOOD_OLD_INODE_SIZE; 3647b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "required extra inode space not" 3648b31e1552SEric Sandeen "available"); 3649ef7f3835SKalpak Shah } 3650ef7f3835SKalpak Shah 365190576c0bSTheodore Ts'o if (test_opt(sb, DELALLOC) && 365290576c0bSTheodore Ts'o (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) { 3653b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - " 3654b31e1552SEric Sandeen "requested data journaling mode"); 3655fd8c37ecSTheodore Ts'o clear_opt(sb, DELALLOC); 365690576c0bSTheodore Ts'o } 3657744692dcSJiaying Zhang if (test_opt(sb, DIOREAD_NOLOCK)) { 3658744692dcSJiaying Zhang if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) { 3659744692dcSJiaying Zhang ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock " 3660744692dcSJiaying Zhang "option - requested data journaling mode"); 3661fd8c37ecSTheodore Ts'o clear_opt(sb, DIOREAD_NOLOCK); 3662744692dcSJiaying Zhang } 3663744692dcSJiaying Zhang if (sb->s_blocksize < PAGE_SIZE) { 3664744692dcSJiaying Zhang ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock " 3665744692dcSJiaying Zhang "option - block size is too small"); 3666fd8c37ecSTheodore Ts'o clear_opt(sb, DIOREAD_NOLOCK); 3667744692dcSJiaying Zhang } 3668744692dcSJiaying Zhang } 3669c2774d84SAneesh Kumar K.V 36706fd058f7STheodore Ts'o err = ext4_setup_system_zone(sb); 36716fd058f7STheodore Ts'o if (err) { 3672b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "failed to initialize system " 3673fbe845ddSCurt Wohlgemuth "zone (%d)", err); 36746fd058f7STheodore Ts'o goto failed_mount4; 36756fd058f7STheodore Ts'o } 36766fd058f7STheodore Ts'o 3677c2774d84SAneesh Kumar K.V ext4_ext_init(sb); 3678c2774d84SAneesh Kumar K.V err = ext4_mb_init(sb, needs_recovery); 3679c2774d84SAneesh Kumar K.V if (err) { 3680421f91d2SUwe Kleine-König ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)", 3681c2774d84SAneesh Kumar K.V err); 3682c2774d84SAneesh Kumar K.V goto failed_mount4; 3683c2774d84SAneesh Kumar K.V } 3684c2774d84SAneesh Kumar K.V 3685bfff6873SLukas Czerner err = ext4_register_li_request(sb, first_not_zeroed); 3686bfff6873SLukas Czerner if (err) 3687bfff6873SLukas Czerner goto failed_mount4; 3688bfff6873SLukas Czerner 36893197ebdbSTheodore Ts'o sbi->s_kobj.kset = ext4_kset; 36903197ebdbSTheodore Ts'o init_completion(&sbi->s_kobj_unregister); 36913197ebdbSTheodore Ts'o err = kobject_init_and_add(&sbi->s_kobj, &ext4_ktype, NULL, 36923197ebdbSTheodore Ts'o "%s", sb->s_id); 36933197ebdbSTheodore Ts'o if (err) { 36943197ebdbSTheodore Ts'o ext4_mb_release(sb); 36953197ebdbSTheodore Ts'o ext4_ext_release(sb); 36963197ebdbSTheodore Ts'o goto failed_mount4; 36973197ebdbSTheodore Ts'o }; 36983197ebdbSTheodore Ts'o 3699617ba13bSMingming Cao EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS; 3700617ba13bSMingming Cao ext4_orphan_cleanup(sb, es); 3701617ba13bSMingming Cao EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS; 37020390131bSFrank Mayhar if (needs_recovery) { 3703b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "recovery complete"); 3704617ba13bSMingming Cao ext4_mark_recovery_complete(sb, es); 37050390131bSFrank Mayhar } 37060390131bSFrank Mayhar if (EXT4_SB(sb)->s_journal) { 37070390131bSFrank Mayhar if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) 37080390131bSFrank Mayhar descr = " journalled data mode"; 37090390131bSFrank Mayhar else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) 37100390131bSFrank Mayhar descr = " ordered data mode"; 37110390131bSFrank Mayhar else 37120390131bSFrank Mayhar descr = " writeback data mode"; 37130390131bSFrank Mayhar } else 37140390131bSFrank Mayhar descr = "out journal"; 37150390131bSFrank Mayhar 3716d4c402d9SCurt Wohlgemuth ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " 37178b67f04aSTheodore Ts'o "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts, 37188b67f04aSTheodore Ts'o *sbi->s_es->s_mount_opts ? "; " : "", orig_data); 3719ac27a0ecSDave Kleikamp 372066e61a9eSTheodore Ts'o if (es->s_error_count) 372166e61a9eSTheodore Ts'o mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ 3722ac27a0ecSDave Kleikamp 3723d4c402d9SCurt Wohlgemuth kfree(orig_data); 3724ac27a0ecSDave Kleikamp return 0; 3725ac27a0ecSDave Kleikamp 3726617ba13bSMingming Cao cantfind_ext4: 3727ac27a0ecSDave Kleikamp if (!silent) 3728b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem"); 3729ac27a0ecSDave Kleikamp goto failed_mount; 3730ac27a0ecSDave Kleikamp 3731ac27a0ecSDave Kleikamp failed_mount4: 373232a9bb57SManish Katiyar iput(root); 373332a9bb57SManish Katiyar sb->s_root = NULL; 3734b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "mount failed"); 37354c0425ffSMingming Cao destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq); 37364c0425ffSMingming Cao failed_mount_wq: 37376fd058f7STheodore Ts'o ext4_release_system_zone(sb); 37380390131bSFrank Mayhar if (sbi->s_journal) { 3739dab291afSMingming Cao jbd2_journal_destroy(sbi->s_journal); 374047b4a50bSJan Kara sbi->s_journal = NULL; 37410390131bSFrank Mayhar } 3742ac27a0ecSDave Kleikamp failed_mount3: 374304496411STao Ma del_timer(&sbi->s_err_report); 3744c5ca7c76STheodore Ts'o if (sbi->s_flex_groups) { 3745c5ca7c76STheodore Ts'o if (is_vmalloc_addr(sbi->s_flex_groups)) 3746c5ca7c76STheodore Ts'o vfree(sbi->s_flex_groups); 3747c5ca7c76STheodore Ts'o else 3748c5ca7c76STheodore Ts'o kfree(sbi->s_flex_groups); 3749c5ca7c76STheodore Ts'o } 3750ce7e010aSTheodore Ts'o percpu_counter_destroy(&sbi->s_freeblocks_counter); 3751ce7e010aSTheodore Ts'o percpu_counter_destroy(&sbi->s_freeinodes_counter); 3752ce7e010aSTheodore Ts'o percpu_counter_destroy(&sbi->s_dirs_counter); 3753ce7e010aSTheodore Ts'o percpu_counter_destroy(&sbi->s_dirtyblocks_counter); 3754c5e06d10SJohann Lombardi if (sbi->s_mmp_tsk) 3755c5e06d10SJohann Lombardi kthread_stop(sbi->s_mmp_tsk); 3756ac27a0ecSDave Kleikamp failed_mount2: 3757ac27a0ecSDave Kleikamp for (i = 0; i < db_count; i++) 3758ac27a0ecSDave Kleikamp brelse(sbi->s_group_desc[i]); 3759ac27a0ecSDave Kleikamp kfree(sbi->s_group_desc); 3760ac27a0ecSDave Kleikamp failed_mount: 3761240799cdSTheodore Ts'o if (sbi->s_proc) { 37629f6200bbSTheodore Ts'o remove_proc_entry(sb->s_id, ext4_proc_root); 3763240799cdSTheodore Ts'o } 3764ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 3765ac27a0ecSDave Kleikamp for (i = 0; i < MAXQUOTAS; i++) 3766ac27a0ecSDave Kleikamp kfree(sbi->s_qf_names[i]); 3767ac27a0ecSDave Kleikamp #endif 3768617ba13bSMingming Cao ext4_blkdev_remove(sbi); 3769ac27a0ecSDave Kleikamp brelse(bh); 3770ac27a0ecSDave Kleikamp out_fail: 3771ac27a0ecSDave Kleikamp sb->s_fs_info = NULL; 3772f6830165SManish Katiyar kfree(sbi->s_blockgroup_lock); 3773ac27a0ecSDave Kleikamp kfree(sbi); 3774dcc7dae3SCyrill Gorcunov out_free_orig: 3775d4c402d9SCurt Wohlgemuth kfree(orig_data); 37761d1fe1eeSDavid Howells return ret; 3777ac27a0ecSDave Kleikamp } 3778ac27a0ecSDave Kleikamp 3779ac27a0ecSDave Kleikamp /* 3780ac27a0ecSDave Kleikamp * Setup any per-fs journal parameters now. We'll do this both on 3781ac27a0ecSDave Kleikamp * initial mount, once the journal has been initialised but before we've 3782ac27a0ecSDave Kleikamp * done any recovery; and again on any subsequent remount. 3783ac27a0ecSDave Kleikamp */ 3784617ba13bSMingming Cao static void ext4_init_journal_params(struct super_block *sb, journal_t *journal) 3785ac27a0ecSDave Kleikamp { 3786617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 3787ac27a0ecSDave Kleikamp 3788ac27a0ecSDave Kleikamp journal->j_commit_interval = sbi->s_commit_interval; 378930773840STheodore Ts'o journal->j_min_batch_time = sbi->s_min_batch_time; 379030773840STheodore Ts'o journal->j_max_batch_time = sbi->s_max_batch_time; 3791ac27a0ecSDave Kleikamp 3792a931da6aSTheodore Ts'o write_lock(&journal->j_state_lock); 3793ac27a0ecSDave Kleikamp if (test_opt(sb, BARRIER)) 3794dab291afSMingming Cao journal->j_flags |= JBD2_BARRIER; 3795ac27a0ecSDave Kleikamp else 3796dab291afSMingming Cao journal->j_flags &= ~JBD2_BARRIER; 37975bf5683aSHidehiro Kawai if (test_opt(sb, DATA_ERR_ABORT)) 37985bf5683aSHidehiro Kawai journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR; 37995bf5683aSHidehiro Kawai else 38005bf5683aSHidehiro Kawai journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR; 3801a931da6aSTheodore Ts'o write_unlock(&journal->j_state_lock); 3802ac27a0ecSDave Kleikamp } 3803ac27a0ecSDave Kleikamp 3804617ba13bSMingming Cao static journal_t *ext4_get_journal(struct super_block *sb, 3805ac27a0ecSDave Kleikamp unsigned int journal_inum) 3806ac27a0ecSDave Kleikamp { 3807ac27a0ecSDave Kleikamp struct inode *journal_inode; 3808ac27a0ecSDave Kleikamp journal_t *journal; 3809ac27a0ecSDave Kleikamp 38100390131bSFrank Mayhar BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)); 38110390131bSFrank Mayhar 3812ac27a0ecSDave Kleikamp /* First, test for the existence of a valid inode on disk. Bad 3813ac27a0ecSDave Kleikamp * things happen if we iget() an unused inode, as the subsequent 3814ac27a0ecSDave Kleikamp * iput() will try to delete it. */ 3815ac27a0ecSDave Kleikamp 38161d1fe1eeSDavid Howells journal_inode = ext4_iget(sb, journal_inum); 38171d1fe1eeSDavid Howells if (IS_ERR(journal_inode)) { 3818b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "no journal found"); 3819ac27a0ecSDave Kleikamp return NULL; 3820ac27a0ecSDave Kleikamp } 3821ac27a0ecSDave Kleikamp if (!journal_inode->i_nlink) { 3822ac27a0ecSDave Kleikamp make_bad_inode(journal_inode); 3823ac27a0ecSDave Kleikamp iput(journal_inode); 3824b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "journal inode is deleted"); 3825ac27a0ecSDave Kleikamp return NULL; 3826ac27a0ecSDave Kleikamp } 3827ac27a0ecSDave Kleikamp 3828e5f8eab8STheodore Ts'o jbd_debug(2, "Journal inode found at %p: %lld bytes\n", 3829ac27a0ecSDave Kleikamp journal_inode, journal_inode->i_size); 38301d1fe1eeSDavid Howells if (!S_ISREG(journal_inode->i_mode)) { 3831b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "invalid journal inode"); 3832ac27a0ecSDave Kleikamp iput(journal_inode); 3833ac27a0ecSDave Kleikamp return NULL; 3834ac27a0ecSDave Kleikamp } 3835ac27a0ecSDave Kleikamp 3836dab291afSMingming Cao journal = jbd2_journal_init_inode(journal_inode); 3837ac27a0ecSDave Kleikamp if (!journal) { 3838b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "Could not load journal inode"); 3839ac27a0ecSDave Kleikamp iput(journal_inode); 3840ac27a0ecSDave Kleikamp return NULL; 3841ac27a0ecSDave Kleikamp } 3842ac27a0ecSDave Kleikamp journal->j_private = sb; 3843617ba13bSMingming Cao ext4_init_journal_params(sb, journal); 3844ac27a0ecSDave Kleikamp return journal; 3845ac27a0ecSDave Kleikamp } 3846ac27a0ecSDave Kleikamp 3847617ba13bSMingming Cao static journal_t *ext4_get_dev_journal(struct super_block *sb, 3848ac27a0ecSDave Kleikamp dev_t j_dev) 3849ac27a0ecSDave Kleikamp { 3850ac27a0ecSDave Kleikamp struct buffer_head *bh; 3851ac27a0ecSDave Kleikamp journal_t *journal; 3852617ba13bSMingming Cao ext4_fsblk_t start; 3853617ba13bSMingming Cao ext4_fsblk_t len; 3854ac27a0ecSDave Kleikamp int hblock, blocksize; 3855617ba13bSMingming Cao ext4_fsblk_t sb_block; 3856ac27a0ecSDave Kleikamp unsigned long offset; 3857617ba13bSMingming Cao struct ext4_super_block *es; 3858ac27a0ecSDave Kleikamp struct block_device *bdev; 3859ac27a0ecSDave Kleikamp 38600390131bSFrank Mayhar BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)); 38610390131bSFrank Mayhar 3862b31e1552SEric Sandeen bdev = ext4_blkdev_get(j_dev, sb); 3863ac27a0ecSDave Kleikamp if (bdev == NULL) 3864ac27a0ecSDave Kleikamp return NULL; 3865ac27a0ecSDave Kleikamp 3866ac27a0ecSDave Kleikamp blocksize = sb->s_blocksize; 3867e1defc4fSMartin K. Petersen hblock = bdev_logical_block_size(bdev); 3868ac27a0ecSDave Kleikamp if (blocksize < hblock) { 3869b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 3870b31e1552SEric Sandeen "blocksize too small for journal device"); 3871ac27a0ecSDave Kleikamp goto out_bdev; 3872ac27a0ecSDave Kleikamp } 3873ac27a0ecSDave Kleikamp 3874617ba13bSMingming Cao sb_block = EXT4_MIN_BLOCK_SIZE / blocksize; 3875617ba13bSMingming Cao offset = EXT4_MIN_BLOCK_SIZE % blocksize; 3876ac27a0ecSDave Kleikamp set_blocksize(bdev, blocksize); 3877ac27a0ecSDave Kleikamp if (!(bh = __bread(bdev, sb_block, blocksize))) { 3878b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "couldn't read superblock of " 3879b31e1552SEric Sandeen "external journal"); 3880ac27a0ecSDave Kleikamp goto out_bdev; 3881ac27a0ecSDave Kleikamp } 3882ac27a0ecSDave Kleikamp 3883617ba13bSMingming Cao es = (struct ext4_super_block *) (((char *)bh->b_data) + offset); 3884617ba13bSMingming Cao if ((le16_to_cpu(es->s_magic) != EXT4_SUPER_MAGIC) || 3885ac27a0ecSDave Kleikamp !(le32_to_cpu(es->s_feature_incompat) & 3886617ba13bSMingming Cao EXT4_FEATURE_INCOMPAT_JOURNAL_DEV)) { 3887b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "external journal has " 3888b31e1552SEric Sandeen "bad superblock"); 3889ac27a0ecSDave Kleikamp brelse(bh); 3890ac27a0ecSDave Kleikamp goto out_bdev; 3891ac27a0ecSDave Kleikamp } 3892ac27a0ecSDave Kleikamp 3893617ba13bSMingming Cao if (memcmp(EXT4_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) { 3894b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "journal UUID does not match"); 3895ac27a0ecSDave Kleikamp brelse(bh); 3896ac27a0ecSDave Kleikamp goto out_bdev; 3897ac27a0ecSDave Kleikamp } 3898ac27a0ecSDave Kleikamp 3899bd81d8eeSLaurent Vivier len = ext4_blocks_count(es); 3900ac27a0ecSDave Kleikamp start = sb_block + 1; 3901ac27a0ecSDave Kleikamp brelse(bh); /* we're done with the superblock */ 3902ac27a0ecSDave Kleikamp 3903dab291afSMingming Cao journal = jbd2_journal_init_dev(bdev, sb->s_bdev, 3904ac27a0ecSDave Kleikamp start, len, blocksize); 3905ac27a0ecSDave Kleikamp if (!journal) { 3906b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "failed to create device journal"); 3907ac27a0ecSDave Kleikamp goto out_bdev; 3908ac27a0ecSDave Kleikamp } 3909ac27a0ecSDave Kleikamp journal->j_private = sb; 3910ac27a0ecSDave Kleikamp ll_rw_block(READ, 1, &journal->j_sb_buffer); 3911ac27a0ecSDave Kleikamp wait_on_buffer(journal->j_sb_buffer); 3912ac27a0ecSDave Kleikamp if (!buffer_uptodate(journal->j_sb_buffer)) { 3913b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "I/O error on journal device"); 3914ac27a0ecSDave Kleikamp goto out_journal; 3915ac27a0ecSDave Kleikamp } 3916ac27a0ecSDave Kleikamp if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) { 3917b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "External journal has more than one " 3918b31e1552SEric Sandeen "user (unsupported) - %d", 3919ac27a0ecSDave Kleikamp be32_to_cpu(journal->j_superblock->s_nr_users)); 3920ac27a0ecSDave Kleikamp goto out_journal; 3921ac27a0ecSDave Kleikamp } 3922617ba13bSMingming Cao EXT4_SB(sb)->journal_bdev = bdev; 3923617ba13bSMingming Cao ext4_init_journal_params(sb, journal); 3924ac27a0ecSDave Kleikamp return journal; 39250b8e58a1SAndreas Dilger 3926ac27a0ecSDave Kleikamp out_journal: 3927dab291afSMingming Cao jbd2_journal_destroy(journal); 3928ac27a0ecSDave Kleikamp out_bdev: 3929617ba13bSMingming Cao ext4_blkdev_put(bdev); 3930ac27a0ecSDave Kleikamp return NULL; 3931ac27a0ecSDave Kleikamp } 3932ac27a0ecSDave Kleikamp 3933617ba13bSMingming Cao static int ext4_load_journal(struct super_block *sb, 3934617ba13bSMingming Cao struct ext4_super_block *es, 3935ac27a0ecSDave Kleikamp unsigned long journal_devnum) 3936ac27a0ecSDave Kleikamp { 3937ac27a0ecSDave Kleikamp journal_t *journal; 3938ac27a0ecSDave Kleikamp unsigned int journal_inum = le32_to_cpu(es->s_journal_inum); 3939ac27a0ecSDave Kleikamp dev_t journal_dev; 3940ac27a0ecSDave Kleikamp int err = 0; 3941ac27a0ecSDave Kleikamp int really_read_only; 3942ac27a0ecSDave Kleikamp 39430390131bSFrank Mayhar BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)); 39440390131bSFrank Mayhar 3945ac27a0ecSDave Kleikamp if (journal_devnum && 3946ac27a0ecSDave Kleikamp journal_devnum != le32_to_cpu(es->s_journal_dev)) { 3947b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "external journal device major/minor " 3948b31e1552SEric Sandeen "numbers have changed"); 3949ac27a0ecSDave Kleikamp journal_dev = new_decode_dev(journal_devnum); 3950ac27a0ecSDave Kleikamp } else 3951ac27a0ecSDave Kleikamp journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev)); 3952ac27a0ecSDave Kleikamp 3953ac27a0ecSDave Kleikamp really_read_only = bdev_read_only(sb->s_bdev); 3954ac27a0ecSDave Kleikamp 3955ac27a0ecSDave Kleikamp /* 3956ac27a0ecSDave Kleikamp * Are we loading a blank journal or performing recovery after a 3957ac27a0ecSDave Kleikamp * crash? For recovery, we need to check in advance whether we 3958ac27a0ecSDave Kleikamp * can get read-write access to the device. 3959ac27a0ecSDave Kleikamp */ 3960617ba13bSMingming Cao if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { 3961ac27a0ecSDave Kleikamp if (sb->s_flags & MS_RDONLY) { 3962b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "INFO: recovery " 3963b31e1552SEric Sandeen "required on readonly filesystem"); 3964ac27a0ecSDave Kleikamp if (really_read_only) { 3965b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "write access " 3966b31e1552SEric Sandeen "unavailable, cannot proceed"); 3967ac27a0ecSDave Kleikamp return -EROFS; 3968ac27a0ecSDave Kleikamp } 3969b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "write access will " 3970b31e1552SEric Sandeen "be enabled during recovery"); 3971ac27a0ecSDave Kleikamp } 3972ac27a0ecSDave Kleikamp } 3973ac27a0ecSDave Kleikamp 3974ac27a0ecSDave Kleikamp if (journal_inum && journal_dev) { 3975b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "filesystem has both journal " 3976b31e1552SEric Sandeen "and inode journals!"); 3977ac27a0ecSDave Kleikamp return -EINVAL; 3978ac27a0ecSDave Kleikamp } 3979ac27a0ecSDave Kleikamp 3980ac27a0ecSDave Kleikamp if (journal_inum) { 3981617ba13bSMingming Cao if (!(journal = ext4_get_journal(sb, journal_inum))) 3982ac27a0ecSDave Kleikamp return -EINVAL; 3983ac27a0ecSDave Kleikamp } else { 3984617ba13bSMingming Cao if (!(journal = ext4_get_dev_journal(sb, journal_dev))) 3985ac27a0ecSDave Kleikamp return -EINVAL; 3986ac27a0ecSDave Kleikamp } 3987ac27a0ecSDave Kleikamp 398890576c0bSTheodore Ts'o if (!(journal->j_flags & JBD2_BARRIER)) 3989b31e1552SEric Sandeen ext4_msg(sb, KERN_INFO, "barriers disabled"); 39904776004fSTheodore Ts'o 3991ac27a0ecSDave Kleikamp if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { 3992dab291afSMingming Cao err = jbd2_journal_update_format(journal); 3993ac27a0ecSDave Kleikamp if (err) { 3994b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "error updating journal"); 3995dab291afSMingming Cao jbd2_journal_destroy(journal); 3996ac27a0ecSDave Kleikamp return err; 3997ac27a0ecSDave Kleikamp } 3998ac27a0ecSDave Kleikamp } 3999ac27a0ecSDave Kleikamp 4000617ba13bSMingming Cao if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) 4001dab291afSMingming Cao err = jbd2_journal_wipe(journal, !really_read_only); 40021c13d5c0STheodore Ts'o if (!err) { 40031c13d5c0STheodore Ts'o char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL); 40041c13d5c0STheodore Ts'o if (save) 40051c13d5c0STheodore Ts'o memcpy(save, ((char *) es) + 40061c13d5c0STheodore Ts'o EXT4_S_ERR_START, EXT4_S_ERR_LEN); 4007dab291afSMingming Cao err = jbd2_journal_load(journal); 40081c13d5c0STheodore Ts'o if (save) 40091c13d5c0STheodore Ts'o memcpy(((char *) es) + EXT4_S_ERR_START, 40101c13d5c0STheodore Ts'o save, EXT4_S_ERR_LEN); 40111c13d5c0STheodore Ts'o kfree(save); 40121c13d5c0STheodore Ts'o } 4013ac27a0ecSDave Kleikamp 4014ac27a0ecSDave Kleikamp if (err) { 4015b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "error loading journal"); 4016dab291afSMingming Cao jbd2_journal_destroy(journal); 4017ac27a0ecSDave Kleikamp return err; 4018ac27a0ecSDave Kleikamp } 4019ac27a0ecSDave Kleikamp 4020617ba13bSMingming Cao EXT4_SB(sb)->s_journal = journal; 4021617ba13bSMingming Cao ext4_clear_journal_err(sb, es); 4022ac27a0ecSDave Kleikamp 4023c41303ceSMaciej Żenczykowski if (!really_read_only && journal_devnum && 4024ac27a0ecSDave Kleikamp journal_devnum != le32_to_cpu(es->s_journal_dev)) { 4025ac27a0ecSDave Kleikamp es->s_journal_dev = cpu_to_le32(journal_devnum); 4026ac27a0ecSDave Kleikamp 4027ac27a0ecSDave Kleikamp /* Make sure we flush the recovery flag to disk. */ 4028e2d67052STheodore Ts'o ext4_commit_super(sb, 1); 4029ac27a0ecSDave Kleikamp } 4030ac27a0ecSDave Kleikamp 4031ac27a0ecSDave Kleikamp return 0; 4032ac27a0ecSDave Kleikamp } 4033ac27a0ecSDave Kleikamp 4034e2d67052STheodore Ts'o static int ext4_commit_super(struct super_block *sb, int sync) 4035ac27a0ecSDave Kleikamp { 4036e2d67052STheodore Ts'o struct ext4_super_block *es = EXT4_SB(sb)->s_es; 4037617ba13bSMingming Cao struct buffer_head *sbh = EXT4_SB(sb)->s_sbh; 4038c4be0c1dSTakashi Sato int error = 0; 4039ac27a0ecSDave Kleikamp 4040ac27a0ecSDave Kleikamp if (!sbh) 4041c4be0c1dSTakashi Sato return error; 4042914258bfSTheodore Ts'o if (buffer_write_io_error(sbh)) { 4043914258bfSTheodore Ts'o /* 4044914258bfSTheodore Ts'o * Oh, dear. A previous attempt to write the 4045914258bfSTheodore Ts'o * superblock failed. This could happen because the 4046914258bfSTheodore Ts'o * USB device was yanked out. Or it could happen to 4047914258bfSTheodore Ts'o * be a transient write error and maybe the block will 4048914258bfSTheodore Ts'o * be remapped. Nothing we can do but to retry the 4049914258bfSTheodore Ts'o * write and hope for the best. 4050914258bfSTheodore Ts'o */ 4051b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "previous I/O error to " 4052b31e1552SEric Sandeen "superblock detected"); 4053914258bfSTheodore Ts'o clear_buffer_write_io_error(sbh); 4054914258bfSTheodore Ts'o set_buffer_uptodate(sbh); 4055914258bfSTheodore Ts'o } 405671290b36STheodore Ts'o /* 405771290b36STheodore Ts'o * If the file system is mounted read-only, don't update the 405871290b36STheodore Ts'o * superblock write time. This avoids updating the superblock 405971290b36STheodore Ts'o * write time when we are mounting the root file system 406071290b36STheodore Ts'o * read/only but we need to replay the journal; at that point, 406171290b36STheodore Ts'o * for people who are east of GMT and who make their clock 406271290b36STheodore Ts'o * tick in localtime for Windows bug-for-bug compatibility, 406371290b36STheodore Ts'o * the clock is set in the future, and this will cause e2fsck 406471290b36STheodore Ts'o * to complain and force a full file system check. 406571290b36STheodore Ts'o */ 406671290b36STheodore Ts'o if (!(sb->s_flags & MS_RDONLY)) 4067ac27a0ecSDave Kleikamp es->s_wtime = cpu_to_le32(get_seconds()); 4068f613dfcbSTheodore Ts'o if (sb->s_bdev->bd_part) 4069afc32f7eSTheodore Ts'o es->s_kbytes_written = 4070afc32f7eSTheodore Ts'o cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + 4071afc32f7eSTheodore Ts'o ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - 4072afc32f7eSTheodore Ts'o EXT4_SB(sb)->s_sectors_written_start) >> 1)); 4073f613dfcbSTheodore Ts'o else 4074f613dfcbSTheodore Ts'o es->s_kbytes_written = 4075f613dfcbSTheodore Ts'o cpu_to_le64(EXT4_SB(sb)->s_kbytes_written); 40765d1b1b3fSAneesh Kumar K.V ext4_free_blocks_count_set(es, percpu_counter_sum_positive( 40775d1b1b3fSAneesh Kumar K.V &EXT4_SB(sb)->s_freeblocks_counter)); 40787f93cff9STheodore Ts'o es->s_free_inodes_count = 40797f93cff9STheodore Ts'o cpu_to_le32(percpu_counter_sum_positive( 40805d1b1b3fSAneesh Kumar K.V &EXT4_SB(sb)->s_freeinodes_counter)); 40817234ab2aSTheodore Ts'o sb->s_dirt = 0; 4082ac27a0ecSDave Kleikamp BUFFER_TRACE(sbh, "marking dirty"); 4083ac27a0ecSDave Kleikamp mark_buffer_dirty(sbh); 4084914258bfSTheodore Ts'o if (sync) { 4085c4be0c1dSTakashi Sato error = sync_dirty_buffer(sbh); 4086c4be0c1dSTakashi Sato if (error) 4087c4be0c1dSTakashi Sato return error; 4088c4be0c1dSTakashi Sato 4089c4be0c1dSTakashi Sato error = buffer_write_io_error(sbh); 4090c4be0c1dSTakashi Sato if (error) { 4091b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, "I/O error while writing " 4092b31e1552SEric Sandeen "superblock"); 4093914258bfSTheodore Ts'o clear_buffer_write_io_error(sbh); 4094914258bfSTheodore Ts'o set_buffer_uptodate(sbh); 4095914258bfSTheodore Ts'o } 4096914258bfSTheodore Ts'o } 4097c4be0c1dSTakashi Sato return error; 4098ac27a0ecSDave Kleikamp } 4099ac27a0ecSDave Kleikamp 4100ac27a0ecSDave Kleikamp /* 4101ac27a0ecSDave Kleikamp * Have we just finished recovery? If so, and if we are mounting (or 4102ac27a0ecSDave Kleikamp * remounting) the filesystem readonly, then we will end up with a 4103ac27a0ecSDave Kleikamp * consistent fs on disk. Record that fact. 4104ac27a0ecSDave Kleikamp */ 4105617ba13bSMingming Cao static void ext4_mark_recovery_complete(struct super_block *sb, 4106617ba13bSMingming Cao struct ext4_super_block *es) 4107ac27a0ecSDave Kleikamp { 4108617ba13bSMingming Cao journal_t *journal = EXT4_SB(sb)->s_journal; 4109ac27a0ecSDave Kleikamp 41100390131bSFrank Mayhar if (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { 41110390131bSFrank Mayhar BUG_ON(journal != NULL); 41120390131bSFrank Mayhar return; 41130390131bSFrank Mayhar } 4114dab291afSMingming Cao jbd2_journal_lock_updates(journal); 41157ffe1ea8SHidehiro Kawai if (jbd2_journal_flush(journal) < 0) 41167ffe1ea8SHidehiro Kawai goto out; 41177ffe1ea8SHidehiro Kawai 4118617ba13bSMingming Cao if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && 4119ac27a0ecSDave Kleikamp sb->s_flags & MS_RDONLY) { 4120617ba13bSMingming Cao EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 4121e2d67052STheodore Ts'o ext4_commit_super(sb, 1); 4122ac27a0ecSDave Kleikamp } 41237ffe1ea8SHidehiro Kawai 41247ffe1ea8SHidehiro Kawai out: 4125dab291afSMingming Cao jbd2_journal_unlock_updates(journal); 4126ac27a0ecSDave Kleikamp } 4127ac27a0ecSDave Kleikamp 4128ac27a0ecSDave Kleikamp /* 4129ac27a0ecSDave Kleikamp * If we are mounting (or read-write remounting) a filesystem whose journal 4130ac27a0ecSDave Kleikamp * has recorded an error from a previous lifetime, move that error to the 4131ac27a0ecSDave Kleikamp * main filesystem now. 4132ac27a0ecSDave Kleikamp */ 4133617ba13bSMingming Cao static void ext4_clear_journal_err(struct super_block *sb, 4134617ba13bSMingming Cao struct ext4_super_block *es) 4135ac27a0ecSDave Kleikamp { 4136ac27a0ecSDave Kleikamp journal_t *journal; 4137ac27a0ecSDave Kleikamp int j_errno; 4138ac27a0ecSDave Kleikamp const char *errstr; 4139ac27a0ecSDave Kleikamp 41400390131bSFrank Mayhar BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)); 41410390131bSFrank Mayhar 4142617ba13bSMingming Cao journal = EXT4_SB(sb)->s_journal; 4143ac27a0ecSDave Kleikamp 4144ac27a0ecSDave Kleikamp /* 4145ac27a0ecSDave Kleikamp * Now check for any error status which may have been recorded in the 4146617ba13bSMingming Cao * journal by a prior ext4_error() or ext4_abort() 4147ac27a0ecSDave Kleikamp */ 4148ac27a0ecSDave Kleikamp 4149dab291afSMingming Cao j_errno = jbd2_journal_errno(journal); 4150ac27a0ecSDave Kleikamp if (j_errno) { 4151ac27a0ecSDave Kleikamp char nbuf[16]; 4152ac27a0ecSDave Kleikamp 4153617ba13bSMingming Cao errstr = ext4_decode_error(sb, j_errno, nbuf); 415412062dddSEric Sandeen ext4_warning(sb, "Filesystem error recorded " 4155ac27a0ecSDave Kleikamp "from previous mount: %s", errstr); 415612062dddSEric Sandeen ext4_warning(sb, "Marking fs in need of filesystem check."); 4157ac27a0ecSDave Kleikamp 4158617ba13bSMingming Cao EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; 4159617ba13bSMingming Cao es->s_state |= cpu_to_le16(EXT4_ERROR_FS); 4160e2d67052STheodore Ts'o ext4_commit_super(sb, 1); 4161ac27a0ecSDave Kleikamp 4162dab291afSMingming Cao jbd2_journal_clear_err(journal); 4163ac27a0ecSDave Kleikamp } 4164ac27a0ecSDave Kleikamp } 4165ac27a0ecSDave Kleikamp 4166ac27a0ecSDave Kleikamp /* 4167ac27a0ecSDave Kleikamp * Force the running and committing transactions to commit, 4168ac27a0ecSDave Kleikamp * and wait on the commit. 4169ac27a0ecSDave Kleikamp */ 4170617ba13bSMingming Cao int ext4_force_commit(struct super_block *sb) 4171ac27a0ecSDave Kleikamp { 4172ac27a0ecSDave Kleikamp journal_t *journal; 41730390131bSFrank Mayhar int ret = 0; 4174ac27a0ecSDave Kleikamp 4175ac27a0ecSDave Kleikamp if (sb->s_flags & MS_RDONLY) 4176ac27a0ecSDave Kleikamp return 0; 4177ac27a0ecSDave Kleikamp 4178617ba13bSMingming Cao journal = EXT4_SB(sb)->s_journal; 41796b0310fbSEric Sandeen if (journal) { 4180437f88ccSEric Sandeen vfs_check_frozen(sb, SB_FREEZE_TRANS); 4181617ba13bSMingming Cao ret = ext4_journal_force_commit(journal); 41826b0310fbSEric Sandeen } 41830390131bSFrank Mayhar 4184ac27a0ecSDave Kleikamp return ret; 4185ac27a0ecSDave Kleikamp } 4186ac27a0ecSDave Kleikamp 4187617ba13bSMingming Cao static void ext4_write_super(struct super_block *sb) 4188ac27a0ecSDave Kleikamp { 4189ebc1ac16SChristoph Hellwig lock_super(sb); 4190e2d67052STheodore Ts'o ext4_commit_super(sb, 1); 4191ebc1ac16SChristoph Hellwig unlock_super(sb); 41920390131bSFrank Mayhar } 4193ac27a0ecSDave Kleikamp 4194617ba13bSMingming Cao static int ext4_sync_fs(struct super_block *sb, int wait) 4195ac27a0ecSDave Kleikamp { 419614ce0cb4STheodore Ts'o int ret = 0; 41979eddacf9SJan Kara tid_t target; 41988d5d02e6SMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 4199ac27a0ecSDave Kleikamp 42009bffad1eSTheodore Ts'o trace_ext4_sync_fs(sb, wait); 42018d5d02e6SMingming Cao flush_workqueue(sbi->dio_unwritten_wq); 42028d5d02e6SMingming Cao if (jbd2_journal_start_commit(sbi->s_journal, &target)) { 4203ac27a0ecSDave Kleikamp if (wait) 42048d5d02e6SMingming Cao jbd2_log_wait_commit(sbi->s_journal, target); 42050390131bSFrank Mayhar } 420614ce0cb4STheodore Ts'o return ret; 4207ac27a0ecSDave Kleikamp } 4208ac27a0ecSDave Kleikamp 4209ac27a0ecSDave Kleikamp /* 4210ac27a0ecSDave Kleikamp * LVM calls this function before a (read-only) snapshot is created. This 4211ac27a0ecSDave Kleikamp * gives us a chance to flush the journal completely and mark the fs clean. 4212be4f27d3SYongqiang Yang * 4213be4f27d3SYongqiang Yang * Note that only this function cannot bring a filesystem to be in a clean 4214be4f27d3SYongqiang Yang * state independently, because ext4 prevents a new handle from being started 4215be4f27d3SYongqiang Yang * by @sb->s_frozen, which stays in an upper layer. It thus needs help from 4216be4f27d3SYongqiang Yang * the upper layer. 4217ac27a0ecSDave Kleikamp */ 4218c4be0c1dSTakashi Sato static int ext4_freeze(struct super_block *sb) 4219ac27a0ecSDave Kleikamp { 4220c4be0c1dSTakashi Sato int error = 0; 4221c4be0c1dSTakashi Sato journal_t *journal; 4222ac27a0ecSDave Kleikamp 42239ca92389STheodore Ts'o if (sb->s_flags & MS_RDONLY) 42249ca92389STheodore Ts'o return 0; 42259ca92389STheodore Ts'o 4226c4be0c1dSTakashi Sato journal = EXT4_SB(sb)->s_journal; 4227ac27a0ecSDave Kleikamp 4228ac27a0ecSDave Kleikamp /* Now we set up the journal barrier. */ 4229dab291afSMingming Cao jbd2_journal_lock_updates(journal); 42307ffe1ea8SHidehiro Kawai 42317ffe1ea8SHidehiro Kawai /* 42329ca92389STheodore Ts'o * Don't clear the needs_recovery flag if we failed to flush 42339ca92389STheodore Ts'o * the journal. 42347ffe1ea8SHidehiro Kawai */ 4235c4be0c1dSTakashi Sato error = jbd2_journal_flush(journal); 42366b0310fbSEric Sandeen if (error < 0) 42376b0310fbSEric Sandeen goto out; 4238ac27a0ecSDave Kleikamp 4239ac27a0ecSDave Kleikamp /* Journal blocked and flushed, clear needs_recovery flag. */ 4240617ba13bSMingming Cao EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 4241e2d67052STheodore Ts'o error = ext4_commit_super(sb, 1); 42426b0310fbSEric Sandeen out: 42436b0310fbSEric Sandeen /* we rely on s_frozen to stop further updates */ 42446b0310fbSEric Sandeen jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 42456b0310fbSEric Sandeen return error; 4246ac27a0ecSDave Kleikamp } 4247ac27a0ecSDave Kleikamp 4248ac27a0ecSDave Kleikamp /* 4249ac27a0ecSDave Kleikamp * Called by LVM after the snapshot is done. We need to reset the RECOVER 4250ac27a0ecSDave Kleikamp * flag here, even though the filesystem is not technically dirty yet. 4251ac27a0ecSDave Kleikamp */ 4252c4be0c1dSTakashi Sato static int ext4_unfreeze(struct super_block *sb) 4253ac27a0ecSDave Kleikamp { 42549ca92389STheodore Ts'o if (sb->s_flags & MS_RDONLY) 42559ca92389STheodore Ts'o return 0; 42569ca92389STheodore Ts'o 4257ac27a0ecSDave Kleikamp lock_super(sb); 42589ca92389STheodore Ts'o /* Reset the needs_recovery flag before the fs is unlocked. */ 4259617ba13bSMingming Cao EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 4260e2d67052STheodore Ts'o ext4_commit_super(sb, 1); 4261ac27a0ecSDave Kleikamp unlock_super(sb); 4262c4be0c1dSTakashi Sato return 0; 4263ac27a0ecSDave Kleikamp } 4264ac27a0ecSDave Kleikamp 4265673c6100STheodore Ts'o /* 4266673c6100STheodore Ts'o * Structure to save mount options for ext4_remount's benefit 4267673c6100STheodore Ts'o */ 4268673c6100STheodore Ts'o struct ext4_mount_options { 4269673c6100STheodore Ts'o unsigned long s_mount_opt; 4270a2595b8aSTheodore Ts'o unsigned long s_mount_opt2; 4271673c6100STheodore Ts'o uid_t s_resuid; 4272673c6100STheodore Ts'o gid_t s_resgid; 4273673c6100STheodore Ts'o unsigned long s_commit_interval; 4274673c6100STheodore Ts'o u32 s_min_batch_time, s_max_batch_time; 4275673c6100STheodore Ts'o #ifdef CONFIG_QUOTA 4276673c6100STheodore Ts'o int s_jquota_fmt; 4277673c6100STheodore Ts'o char *s_qf_names[MAXQUOTAS]; 4278673c6100STheodore Ts'o #endif 4279673c6100STheodore Ts'o }; 4280673c6100STheodore Ts'o 4281617ba13bSMingming Cao static int ext4_remount(struct super_block *sb, int *flags, char *data) 4282ac27a0ecSDave Kleikamp { 4283617ba13bSMingming Cao struct ext4_super_block *es; 4284617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 4285617ba13bSMingming Cao ext4_fsblk_t n_blocks_count = 0; 4286ac27a0ecSDave Kleikamp unsigned long old_sb_flags; 4287617ba13bSMingming Cao struct ext4_mount_options old_opts; 4288c79d967dSChristoph Hellwig int enable_quota = 0; 42898a266467STheodore Ts'o ext4_group_t g; 4290b3881f74STheodore Ts'o unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; 4291c5e06d10SJohann Lombardi int err = 0; 4292ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 4293ac27a0ecSDave Kleikamp int i; 4294ac27a0ecSDave Kleikamp #endif 4295d4c402d9SCurt Wohlgemuth char *orig_data = kstrdup(data, GFP_KERNEL); 4296ac27a0ecSDave Kleikamp 4297ac27a0ecSDave Kleikamp /* Store the original options */ 4298bbd6851aSAl Viro lock_super(sb); 4299ac27a0ecSDave Kleikamp old_sb_flags = sb->s_flags; 4300ac27a0ecSDave Kleikamp old_opts.s_mount_opt = sbi->s_mount_opt; 4301a2595b8aSTheodore Ts'o old_opts.s_mount_opt2 = sbi->s_mount_opt2; 4302ac27a0ecSDave Kleikamp old_opts.s_resuid = sbi->s_resuid; 4303ac27a0ecSDave Kleikamp old_opts.s_resgid = sbi->s_resgid; 4304ac27a0ecSDave Kleikamp old_opts.s_commit_interval = sbi->s_commit_interval; 430530773840STheodore Ts'o old_opts.s_min_batch_time = sbi->s_min_batch_time; 430630773840STheodore Ts'o old_opts.s_max_batch_time = sbi->s_max_batch_time; 4307ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 4308ac27a0ecSDave Kleikamp old_opts.s_jquota_fmt = sbi->s_jquota_fmt; 4309ac27a0ecSDave Kleikamp for (i = 0; i < MAXQUOTAS; i++) 4310ac27a0ecSDave Kleikamp old_opts.s_qf_names[i] = sbi->s_qf_names[i]; 4311ac27a0ecSDave Kleikamp #endif 4312b3881f74STheodore Ts'o if (sbi->s_journal && sbi->s_journal->j_task->io_context) 4313b3881f74STheodore Ts'o journal_ioprio = sbi->s_journal->j_task->io_context->ioprio; 4314ac27a0ecSDave Kleikamp 4315ac27a0ecSDave Kleikamp /* 4316ac27a0ecSDave Kleikamp * Allow the "check" option to be passed as a remount option. 4317ac27a0ecSDave Kleikamp */ 4318b3881f74STheodore Ts'o if (!parse_options(data, sb, NULL, &journal_ioprio, 4319b3881f74STheodore Ts'o &n_blocks_count, 1)) { 4320ac27a0ecSDave Kleikamp err = -EINVAL; 4321ac27a0ecSDave Kleikamp goto restore_opts; 4322ac27a0ecSDave Kleikamp } 4323ac27a0ecSDave Kleikamp 43244ab2f15bSTheodore Ts'o if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) 4325c67d859eSTheodore Ts'o ext4_abort(sb, "Abort forced by user"); 4326ac27a0ecSDave Kleikamp 4327ac27a0ecSDave Kleikamp sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | 4328482a7425SDmitry Monakhov (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); 4329ac27a0ecSDave Kleikamp 4330ac27a0ecSDave Kleikamp es = sbi->s_es; 4331ac27a0ecSDave Kleikamp 4332b3881f74STheodore Ts'o if (sbi->s_journal) { 4333617ba13bSMingming Cao ext4_init_journal_params(sb, sbi->s_journal); 4334b3881f74STheodore Ts'o set_task_ioprio(sbi->s_journal->j_task, journal_ioprio); 4335b3881f74STheodore Ts'o } 4336ac27a0ecSDave Kleikamp 4337ac27a0ecSDave Kleikamp if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) || 4338bd81d8eeSLaurent Vivier n_blocks_count > ext4_blocks_count(es)) { 43394ab2f15bSTheodore Ts'o if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) { 4340ac27a0ecSDave Kleikamp err = -EROFS; 4341ac27a0ecSDave Kleikamp goto restore_opts; 4342ac27a0ecSDave Kleikamp } 4343ac27a0ecSDave Kleikamp 4344ac27a0ecSDave Kleikamp if (*flags & MS_RDONLY) { 43450f0dd62fSChristoph Hellwig err = dquot_suspend(sb, -1); 43460f0dd62fSChristoph Hellwig if (err < 0) 4347c79d967dSChristoph Hellwig goto restore_opts; 4348c79d967dSChristoph Hellwig 4349ac27a0ecSDave Kleikamp /* 4350ac27a0ecSDave Kleikamp * First of all, the unconditional stuff we have to do 4351ac27a0ecSDave Kleikamp * to disable replay of the journal when we next remount 4352ac27a0ecSDave Kleikamp */ 4353ac27a0ecSDave Kleikamp sb->s_flags |= MS_RDONLY; 4354ac27a0ecSDave Kleikamp 4355ac27a0ecSDave Kleikamp /* 4356ac27a0ecSDave Kleikamp * OK, test if we are remounting a valid rw partition 4357ac27a0ecSDave Kleikamp * readonly, and if so set the rdonly flag and then 4358ac27a0ecSDave Kleikamp * mark the partition as valid again. 4359ac27a0ecSDave Kleikamp */ 4360617ba13bSMingming Cao if (!(es->s_state & cpu_to_le16(EXT4_VALID_FS)) && 4361617ba13bSMingming Cao (sbi->s_mount_state & EXT4_VALID_FS)) 4362ac27a0ecSDave Kleikamp es->s_state = cpu_to_le16(sbi->s_mount_state); 4363ac27a0ecSDave Kleikamp 4364a63c9eb2STheodore Ts'o if (sbi->s_journal) 4365617ba13bSMingming Cao ext4_mark_recovery_complete(sb, es); 4366ac27a0ecSDave Kleikamp } else { 4367a13fb1a4SEric Sandeen /* Make sure we can mount this feature set readwrite */ 4368a13fb1a4SEric Sandeen if (!ext4_feature_set_ok(sb, 0)) { 4369ac27a0ecSDave Kleikamp err = -EROFS; 4370ac27a0ecSDave Kleikamp goto restore_opts; 4371ac27a0ecSDave Kleikamp } 4372ead6596bSEric Sandeen /* 43738a266467STheodore Ts'o * Make sure the group descriptor checksums 43740b8e58a1SAndreas Dilger * are sane. If they aren't, refuse to remount r/w. 43758a266467STheodore Ts'o */ 43768a266467STheodore Ts'o for (g = 0; g < sbi->s_groups_count; g++) { 43778a266467STheodore Ts'o struct ext4_group_desc *gdp = 43788a266467STheodore Ts'o ext4_get_group_desc(sb, g, NULL); 43798a266467STheodore Ts'o 43808a266467STheodore Ts'o if (!ext4_group_desc_csum_verify(sbi, g, gdp)) { 4381b31e1552SEric Sandeen ext4_msg(sb, KERN_ERR, 4382b31e1552SEric Sandeen "ext4_remount: Checksum for group %u failed (%u!=%u)", 43838a266467STheodore Ts'o g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)), 43848a266467STheodore Ts'o le16_to_cpu(gdp->bg_checksum)); 43858a266467STheodore Ts'o err = -EINVAL; 43868a266467STheodore Ts'o goto restore_opts; 43878a266467STheodore Ts'o } 43888a266467STheodore Ts'o } 43898a266467STheodore Ts'o 43908a266467STheodore Ts'o /* 4391ead6596bSEric Sandeen * If we have an unprocessed orphan list hanging 4392ead6596bSEric Sandeen * around from a previously readonly bdev mount, 4393ead6596bSEric Sandeen * require a full umount/remount for now. 4394ead6596bSEric Sandeen */ 4395ead6596bSEric Sandeen if (es->s_last_orphan) { 4396b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, "Couldn't " 4397ead6596bSEric Sandeen "remount RDWR because of unprocessed " 4398ead6596bSEric Sandeen "orphan inode list. Please " 4399b31e1552SEric Sandeen "umount/remount instead"); 4400ead6596bSEric Sandeen err = -EINVAL; 4401ead6596bSEric Sandeen goto restore_opts; 4402ead6596bSEric Sandeen } 4403ead6596bSEric Sandeen 4404ac27a0ecSDave Kleikamp /* 4405ac27a0ecSDave Kleikamp * Mounting a RDONLY partition read-write, so reread 4406ac27a0ecSDave Kleikamp * and store the current valid flag. (It may have 4407ac27a0ecSDave Kleikamp * been changed by e2fsck since we originally mounted 4408ac27a0ecSDave Kleikamp * the partition.) 4409ac27a0ecSDave Kleikamp */ 44100390131bSFrank Mayhar if (sbi->s_journal) 4411617ba13bSMingming Cao ext4_clear_journal_err(sb, es); 4412ac27a0ecSDave Kleikamp sbi->s_mount_state = le16_to_cpu(es->s_state); 4413617ba13bSMingming Cao if ((err = ext4_group_extend(sb, es, n_blocks_count))) 4414ac27a0ecSDave Kleikamp goto restore_opts; 4415617ba13bSMingming Cao if (!ext4_setup_super(sb, es, 0)) 4416ac27a0ecSDave Kleikamp sb->s_flags &= ~MS_RDONLY; 4417c5e06d10SJohann Lombardi if (EXT4_HAS_INCOMPAT_FEATURE(sb, 4418c5e06d10SJohann Lombardi EXT4_FEATURE_INCOMPAT_MMP)) 4419c5e06d10SJohann Lombardi if (ext4_multi_mount_protect(sb, 4420c5e06d10SJohann Lombardi le64_to_cpu(es->s_mmp_block))) { 4421c5e06d10SJohann Lombardi err = -EROFS; 4422c5e06d10SJohann Lombardi goto restore_opts; 4423c5e06d10SJohann Lombardi } 4424c79d967dSChristoph Hellwig enable_quota = 1; 4425ac27a0ecSDave Kleikamp } 4426ac27a0ecSDave Kleikamp } 4427bfff6873SLukas Czerner 4428bfff6873SLukas Czerner /* 4429bfff6873SLukas Czerner * Reinitialize lazy itable initialization thread based on 4430bfff6873SLukas Czerner * current settings 4431bfff6873SLukas Czerner */ 4432bfff6873SLukas Czerner if ((sb->s_flags & MS_RDONLY) || !test_opt(sb, INIT_INODE_TABLE)) 4433bfff6873SLukas Czerner ext4_unregister_li_request(sb); 4434bfff6873SLukas Czerner else { 4435bfff6873SLukas Czerner ext4_group_t first_not_zeroed; 4436bfff6873SLukas Czerner first_not_zeroed = ext4_has_uninit_itable(sb); 4437bfff6873SLukas Czerner ext4_register_li_request(sb, first_not_zeroed); 4438bfff6873SLukas Czerner } 4439bfff6873SLukas Czerner 44406fd058f7STheodore Ts'o ext4_setup_system_zone(sb); 44410390131bSFrank Mayhar if (sbi->s_journal == NULL) 4442e2d67052STheodore Ts'o ext4_commit_super(sb, 1); 44430390131bSFrank Mayhar 4444ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 4445ac27a0ecSDave Kleikamp /* Release old quota file names */ 4446ac27a0ecSDave Kleikamp for (i = 0; i < MAXQUOTAS; i++) 4447ac27a0ecSDave Kleikamp if (old_opts.s_qf_names[i] && 4448ac27a0ecSDave Kleikamp old_opts.s_qf_names[i] != sbi->s_qf_names[i]) 4449ac27a0ecSDave Kleikamp kfree(old_opts.s_qf_names[i]); 4450ac27a0ecSDave Kleikamp #endif 4451bbd6851aSAl Viro unlock_super(sb); 4452c79d967dSChristoph Hellwig if (enable_quota) 44530f0dd62fSChristoph Hellwig dquot_resume(sb, -1); 4454d4c402d9SCurt Wohlgemuth 4455d4c402d9SCurt Wohlgemuth ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data); 4456d4c402d9SCurt Wohlgemuth kfree(orig_data); 4457ac27a0ecSDave Kleikamp return 0; 44580b8e58a1SAndreas Dilger 4459ac27a0ecSDave Kleikamp restore_opts: 4460ac27a0ecSDave Kleikamp sb->s_flags = old_sb_flags; 4461ac27a0ecSDave Kleikamp sbi->s_mount_opt = old_opts.s_mount_opt; 4462a2595b8aSTheodore Ts'o sbi->s_mount_opt2 = old_opts.s_mount_opt2; 4463ac27a0ecSDave Kleikamp sbi->s_resuid = old_opts.s_resuid; 4464ac27a0ecSDave Kleikamp sbi->s_resgid = old_opts.s_resgid; 4465ac27a0ecSDave Kleikamp sbi->s_commit_interval = old_opts.s_commit_interval; 446630773840STheodore Ts'o sbi->s_min_batch_time = old_opts.s_min_batch_time; 446730773840STheodore Ts'o sbi->s_max_batch_time = old_opts.s_max_batch_time; 4468ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 4469ac27a0ecSDave Kleikamp sbi->s_jquota_fmt = old_opts.s_jquota_fmt; 4470ac27a0ecSDave Kleikamp for (i = 0; i < MAXQUOTAS; i++) { 4471ac27a0ecSDave Kleikamp if (sbi->s_qf_names[i] && 4472ac27a0ecSDave Kleikamp old_opts.s_qf_names[i] != sbi->s_qf_names[i]) 4473ac27a0ecSDave Kleikamp kfree(sbi->s_qf_names[i]); 4474ac27a0ecSDave Kleikamp sbi->s_qf_names[i] = old_opts.s_qf_names[i]; 4475ac27a0ecSDave Kleikamp } 4476ac27a0ecSDave Kleikamp #endif 4477bbd6851aSAl Viro unlock_super(sb); 4478d4c402d9SCurt Wohlgemuth kfree(orig_data); 4479ac27a0ecSDave Kleikamp return err; 4480ac27a0ecSDave Kleikamp } 4481ac27a0ecSDave Kleikamp 4482617ba13bSMingming Cao static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) 4483ac27a0ecSDave Kleikamp { 4484ac27a0ecSDave Kleikamp struct super_block *sb = dentry->d_sb; 4485617ba13bSMingming Cao struct ext4_sb_info *sbi = EXT4_SB(sb); 4486617ba13bSMingming Cao struct ext4_super_block *es = sbi->s_es; 4487960cc398SPekka Enberg u64 fsid; 4488d02a9391SKazuya Mio s64 bfree; 4489ac27a0ecSDave Kleikamp 44905e70030dSBadari Pulavarty if (test_opt(sb, MINIX_DF)) { 44915e70030dSBadari Pulavarty sbi->s_overhead_last = 0; 44926bc9feffSAneesh Kumar K.V } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { 44938df9675fSTheodore Ts'o ext4_group_t i, ngroups = ext4_get_groups_count(sb); 44945e70030dSBadari Pulavarty ext4_fsblk_t overhead = 0; 4495ac27a0ecSDave Kleikamp 4496ac27a0ecSDave Kleikamp /* 44975e70030dSBadari Pulavarty * Compute the overhead (FS structures). This is constant 44985e70030dSBadari Pulavarty * for a given filesystem unless the number of block groups 44995e70030dSBadari Pulavarty * changes so we cache the previous value until it does. 4500ac27a0ecSDave Kleikamp */ 4501ac27a0ecSDave Kleikamp 4502ac27a0ecSDave Kleikamp /* 4503ac27a0ecSDave Kleikamp * All of the blocks before first_data_block are 4504ac27a0ecSDave Kleikamp * overhead 4505ac27a0ecSDave Kleikamp */ 4506ac27a0ecSDave Kleikamp overhead = le32_to_cpu(es->s_first_data_block); 4507ac27a0ecSDave Kleikamp 4508ac27a0ecSDave Kleikamp /* 4509ac27a0ecSDave Kleikamp * Add the overhead attributed to the superblock and 4510ac27a0ecSDave Kleikamp * block group descriptors. If the sparse superblocks 4511ac27a0ecSDave Kleikamp * feature is turned on, then not all groups have this. 4512ac27a0ecSDave Kleikamp */ 4513ac27a0ecSDave Kleikamp for (i = 0; i < ngroups; i++) { 4514617ba13bSMingming Cao overhead += ext4_bg_has_super(sb, i) + 4515617ba13bSMingming Cao ext4_bg_num_gdb(sb, i); 4516ac27a0ecSDave Kleikamp cond_resched(); 4517ac27a0ecSDave Kleikamp } 4518ac27a0ecSDave Kleikamp 4519ac27a0ecSDave Kleikamp /* 4520ac27a0ecSDave Kleikamp * Every block group has an inode bitmap, a block 4521ac27a0ecSDave Kleikamp * bitmap, and an inode table. 4522ac27a0ecSDave Kleikamp */ 45235e70030dSBadari Pulavarty overhead += ngroups * (2 + sbi->s_itb_per_group); 45245e70030dSBadari Pulavarty sbi->s_overhead_last = overhead; 45255e70030dSBadari Pulavarty smp_wmb(); 45266bc9feffSAneesh Kumar K.V sbi->s_blocks_last = ext4_blocks_count(es); 4527ac27a0ecSDave Kleikamp } 4528ac27a0ecSDave Kleikamp 4529617ba13bSMingming Cao buf->f_type = EXT4_SUPER_MAGIC; 4530ac27a0ecSDave Kleikamp buf->f_bsize = sb->s_blocksize; 45315e70030dSBadari Pulavarty buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; 4532d02a9391SKazuya Mio bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - 45336bc6e63fSAneesh Kumar K.V percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); 4534d02a9391SKazuya Mio /* prevent underflow in case that few free space is available */ 4535d02a9391SKazuya Mio buf->f_bfree = max_t(s64, bfree, 0); 4536bd81d8eeSLaurent Vivier buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); 4537bd81d8eeSLaurent Vivier if (buf->f_bfree < ext4_r_blocks_count(es)) 4538ac27a0ecSDave Kleikamp buf->f_bavail = 0; 4539ac27a0ecSDave Kleikamp buf->f_files = le32_to_cpu(es->s_inodes_count); 454052d9f3b4SPeter Zijlstra buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter); 4541617ba13bSMingming Cao buf->f_namelen = EXT4_NAME_LEN; 4542960cc398SPekka Enberg fsid = le64_to_cpup((void *)es->s_uuid) ^ 4543960cc398SPekka Enberg le64_to_cpup((void *)es->s_uuid + sizeof(u64)); 4544960cc398SPekka Enberg buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL; 4545960cc398SPekka Enberg buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL; 45460b8e58a1SAndreas Dilger 4547ac27a0ecSDave Kleikamp return 0; 4548ac27a0ecSDave Kleikamp } 4549ac27a0ecSDave Kleikamp 45500b8e58a1SAndreas Dilger /* Helper function for writing quotas on sync - we need to start transaction 45510b8e58a1SAndreas Dilger * before quota file is locked for write. Otherwise the are possible deadlocks: 4552ac27a0ecSDave Kleikamp * Process 1 Process 2 4553617ba13bSMingming Cao * ext4_create() quota_sync() 4554dab291afSMingming Cao * jbd2_journal_start() write_dquot() 4555871a2931SChristoph Hellwig * dquot_initialize() down(dqio_mutex) 4556dab291afSMingming Cao * down(dqio_mutex) jbd2_journal_start() 4557ac27a0ecSDave Kleikamp * 4558ac27a0ecSDave Kleikamp */ 4559ac27a0ecSDave Kleikamp 4560ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA 4561ac27a0ecSDave Kleikamp 4562ac27a0ecSDave Kleikamp static inline struct inode *dquot_to_inode(struct dquot *dquot) 4563ac27a0ecSDave Kleikamp { 4564ac27a0ecSDave Kleikamp return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type]; 4565ac27a0ecSDave Kleikamp } 4566ac27a0ecSDave Kleikamp 4567617ba13bSMingming Cao static int ext4_write_dquot(struct dquot *dquot) 4568ac27a0ecSDave Kleikamp { 4569ac27a0ecSDave Kleikamp int ret, err; 4570ac27a0ecSDave Kleikamp handle_t *handle; 4571ac27a0ecSDave Kleikamp struct inode *inode; 4572ac27a0ecSDave Kleikamp 4573ac27a0ecSDave Kleikamp inode = dquot_to_inode(dquot); 4574617ba13bSMingming Cao handle = ext4_journal_start(inode, 4575617ba13bSMingming Cao EXT4_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); 4576ac27a0ecSDave Kleikamp if (IS_ERR(handle)) 4577ac27a0ecSDave Kleikamp return PTR_ERR(handle); 4578ac27a0ecSDave Kleikamp ret = dquot_commit(dquot); 4579617ba13bSMingming Cao err = ext4_journal_stop(handle); 4580ac27a0ecSDave Kleikamp if (!ret) 4581ac27a0ecSDave Kleikamp ret = err; 4582ac27a0ecSDave Kleikamp return ret; 4583ac27a0ecSDave Kleikamp } 4584ac27a0ecSDave Kleikamp 4585617ba13bSMingming Cao static int ext4_acquire_dquot(struct dquot *dquot) 4586ac27a0ecSDave Kleikamp { 4587ac27a0ecSDave Kleikamp int ret, err; 4588ac27a0ecSDave Kleikamp handle_t *handle; 4589ac27a0ecSDave Kleikamp 4590617ba13bSMingming Cao handle = ext4_journal_start(dquot_to_inode(dquot), 4591617ba13bSMingming Cao EXT4_QUOTA_INIT_BLOCKS(dquot->dq_sb)); 4592ac27a0ecSDave Kleikamp if (IS_ERR(handle)) 4593ac27a0ecSDave Kleikamp return PTR_ERR(handle); 4594ac27a0ecSDave Kleikamp ret = dquot_acquire(dquot); 4595617ba13bSMingming Cao err = ext4_journal_stop(handle); 4596ac27a0ecSDave Kleikamp if (!ret) 4597ac27a0ecSDave Kleikamp ret = err; 4598ac27a0ecSDave Kleikamp return ret; 4599ac27a0ecSDave Kleikamp } 4600ac27a0ecSDave Kleikamp 4601617ba13bSMingming Cao static int ext4_release_dquot(struct dquot *dquot) 4602ac27a0ecSDave Kleikamp { 4603ac27a0ecSDave Kleikamp int ret, err; 4604ac27a0ecSDave Kleikamp handle_t *handle; 4605ac27a0ecSDave Kleikamp 4606617ba13bSMingming Cao handle = ext4_journal_start(dquot_to_inode(dquot), 4607617ba13bSMingming Cao EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb)); 46089c3013e9SJan Kara if (IS_ERR(handle)) { 46099c3013e9SJan Kara /* Release dquot anyway to avoid endless cycle in dqput() */ 46109c3013e9SJan Kara dquot_release(dquot); 4611ac27a0ecSDave Kleikamp return PTR_ERR(handle); 46129c3013e9SJan Kara } 4613ac27a0ecSDave Kleikamp ret = dquot_release(dquot); 4614617ba13bSMingming Cao err = ext4_journal_stop(handle); 4615ac27a0ecSDave Kleikamp if (!ret) 4616ac27a0ecSDave Kleikamp ret = err; 4617ac27a0ecSDave Kleikamp return ret; 4618ac27a0ecSDave Kleikamp } 4619ac27a0ecSDave Kleikamp 4620617ba13bSMingming Cao static int ext4_mark_dquot_dirty(struct dquot *dquot) 4621ac27a0ecSDave Kleikamp { 46222c8be6b2SJan Kara /* Are we journaling quotas? */ 4623617ba13bSMingming Cao if (EXT4_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || 4624617ba13bSMingming Cao EXT4_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { 4625ac27a0ecSDave Kleikamp dquot_mark_dquot_dirty(dquot); 4626617ba13bSMingming Cao return ext4_write_dquot(dquot); 4627ac27a0ecSDave Kleikamp } else { 4628ac27a0ecSDave Kleikamp return dquot_mark_dquot_dirty(dquot); 4629ac27a0ecSDave Kleikamp } 4630ac27a0ecSDave Kleikamp } 4631ac27a0ecSDave Kleikamp 4632617ba13bSMingming Cao static int ext4_write_info(struct super_block *sb, int type) 4633ac27a0ecSDave Kleikamp { 4634ac27a0ecSDave Kleikamp int ret, err; 4635ac27a0ecSDave Kleikamp handle_t *handle; 4636ac27a0ecSDave Kleikamp 4637ac27a0ecSDave Kleikamp /* Data block + inode block */ 4638617ba13bSMingming Cao handle = ext4_journal_start(sb->s_root->d_inode, 2); 4639ac27a0ecSDave Kleikamp if (IS_ERR(handle)) 4640ac27a0ecSDave Kleikamp return PTR_ERR(handle); 4641ac27a0ecSDave Kleikamp ret = dquot_commit_info(sb, type); 4642617ba13bSMingming Cao err = ext4_journal_stop(handle); 4643ac27a0ecSDave Kleikamp if (!ret) 4644ac27a0ecSDave Kleikamp ret = err; 4645ac27a0ecSDave Kleikamp return ret; 4646ac27a0ecSDave Kleikamp } 4647ac27a0ecSDave Kleikamp 4648ac27a0ecSDave Kleikamp /* 4649ac27a0ecSDave Kleikamp * Turn on quotas during mount time - we need to find 4650ac27a0ecSDave Kleikamp * the quota file and such... 4651ac27a0ecSDave Kleikamp */ 4652617ba13bSMingming Cao static int ext4_quota_on_mount(struct super_block *sb, int type) 4653ac27a0ecSDave Kleikamp { 4654287a8095SChristoph Hellwig return dquot_quota_on_mount(sb, EXT4_SB(sb)->s_qf_names[type], 4655617ba13bSMingming Cao EXT4_SB(sb)->s_jquota_fmt, type); 4656ac27a0ecSDave Kleikamp } 4657ac27a0ecSDave Kleikamp 4658ac27a0ecSDave Kleikamp /* 4659ac27a0ecSDave Kleikamp * Standard function to be called on quota_on 4660ac27a0ecSDave Kleikamp */ 4661617ba13bSMingming Cao static int ext4_quota_on(struct super_block *sb, int type, int format_id, 4662f00c9e44SJan Kara struct path *path) 4663ac27a0ecSDave Kleikamp { 4664ac27a0ecSDave Kleikamp int err; 4665ac27a0ecSDave Kleikamp 4666ac27a0ecSDave Kleikamp if (!test_opt(sb, QUOTA)) 4667ac27a0ecSDave Kleikamp return -EINVAL; 46680623543bSJan Kara 4669ac27a0ecSDave Kleikamp /* Quotafile not on the same filesystem? */ 4670f00c9e44SJan Kara if (path->mnt->mnt_sb != sb) 4671ac27a0ecSDave Kleikamp return -EXDEV; 46720623543bSJan Kara /* Journaling quota? */ 46730623543bSJan Kara if (EXT4_SB(sb)->s_qf_names[type]) { 46742b2d6d01STheodore Ts'o /* Quotafile not in fs root? */ 4675f00c9e44SJan Kara if (path->dentry->d_parent != sb->s_root) 4676b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, 4677b31e1552SEric Sandeen "Quota file not on filesystem root. " 4678b31e1552SEric Sandeen "Journaled quota will not work"); 46790623543bSJan Kara } 46800623543bSJan Kara 46810623543bSJan Kara /* 46820623543bSJan Kara * When we journal data on quota file, we have to flush journal to see 46830623543bSJan Kara * all updates to the file when we bypass pagecache... 46840623543bSJan Kara */ 46850390131bSFrank Mayhar if (EXT4_SB(sb)->s_journal && 4686f00c9e44SJan Kara ext4_should_journal_data(path->dentry->d_inode)) { 46870623543bSJan Kara /* 46880623543bSJan Kara * We don't need to lock updates but journal_flush() could 46890623543bSJan Kara * otherwise be livelocked... 46900623543bSJan Kara */ 46910623543bSJan Kara jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 46927ffe1ea8SHidehiro Kawai err = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 46930623543bSJan Kara jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 4694f00c9e44SJan Kara if (err) 46957ffe1ea8SHidehiro Kawai return err; 46967ffe1ea8SHidehiro Kawai } 46970623543bSJan Kara 4698f00c9e44SJan Kara return dquot_quota_on(sb, type, format_id, path); 4699ac27a0ecSDave Kleikamp } 4700ac27a0ecSDave Kleikamp 4701ca0e05e4SDmitry Monakhov static int ext4_quota_off(struct super_block *sb, int type) 4702ca0e05e4SDmitry Monakhov { 470321f97697SJan Kara struct inode *inode = sb_dqopt(sb)->files[type]; 470421f97697SJan Kara handle_t *handle; 470521f97697SJan Kara 470687009d86SDmitry Monakhov /* Force all delayed allocation blocks to be allocated. 470787009d86SDmitry Monakhov * Caller already holds s_umount sem */ 470887009d86SDmitry Monakhov if (test_opt(sb, DELALLOC)) 4709ca0e05e4SDmitry Monakhov sync_filesystem(sb); 4710ca0e05e4SDmitry Monakhov 47110b268590SAmir Goldstein if (!inode) 47120b268590SAmir Goldstein goto out; 47130b268590SAmir Goldstein 471421f97697SJan Kara /* Update modification times of quota files when userspace can 471521f97697SJan Kara * start looking at them */ 471621f97697SJan Kara handle = ext4_journal_start(inode, 1); 471721f97697SJan Kara if (IS_ERR(handle)) 471821f97697SJan Kara goto out; 471921f97697SJan Kara inode->i_mtime = inode->i_ctime = CURRENT_TIME; 472021f97697SJan Kara ext4_mark_inode_dirty(handle, inode); 472121f97697SJan Kara ext4_journal_stop(handle); 472221f97697SJan Kara 472321f97697SJan Kara out: 4724ca0e05e4SDmitry Monakhov return dquot_quota_off(sb, type); 4725ca0e05e4SDmitry Monakhov } 4726ca0e05e4SDmitry Monakhov 4727ac27a0ecSDave Kleikamp /* Read data from quotafile - avoid pagecache and such because we cannot afford 4728ac27a0ecSDave Kleikamp * acquiring the locks... As quota files are never truncated and quota code 4729ac27a0ecSDave Kleikamp * itself serializes the operations (and no one else should touch the files) 4730ac27a0ecSDave Kleikamp * we don't have to be afraid of races */ 4731617ba13bSMingming Cao static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, 4732ac27a0ecSDave Kleikamp size_t len, loff_t off) 4733ac27a0ecSDave Kleikamp { 4734ac27a0ecSDave Kleikamp struct inode *inode = sb_dqopt(sb)->files[type]; 4735725d26d3SAneesh Kumar K.V ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb); 4736ac27a0ecSDave Kleikamp int err = 0; 4737ac27a0ecSDave Kleikamp int offset = off & (sb->s_blocksize - 1); 4738ac27a0ecSDave Kleikamp int tocopy; 4739ac27a0ecSDave Kleikamp size_t toread; 4740ac27a0ecSDave Kleikamp struct buffer_head *bh; 4741ac27a0ecSDave Kleikamp loff_t i_size = i_size_read(inode); 4742ac27a0ecSDave Kleikamp 4743ac27a0ecSDave Kleikamp if (off > i_size) 4744ac27a0ecSDave Kleikamp return 0; 4745ac27a0ecSDave Kleikamp if (off+len > i_size) 4746ac27a0ecSDave Kleikamp len = i_size-off; 4747ac27a0ecSDave Kleikamp toread = len; 4748ac27a0ecSDave Kleikamp while (toread > 0) { 4749ac27a0ecSDave Kleikamp tocopy = sb->s_blocksize - offset < toread ? 4750ac27a0ecSDave Kleikamp sb->s_blocksize - offset : toread; 4751617ba13bSMingming Cao bh = ext4_bread(NULL, inode, blk, 0, &err); 4752ac27a0ecSDave Kleikamp if (err) 4753ac27a0ecSDave Kleikamp return err; 4754ac27a0ecSDave Kleikamp if (!bh) /* A hole? */ 4755ac27a0ecSDave Kleikamp memset(data, 0, tocopy); 4756ac27a0ecSDave Kleikamp else 4757ac27a0ecSDave Kleikamp memcpy(data, bh->b_data+offset, tocopy); 4758ac27a0ecSDave Kleikamp brelse(bh); 4759ac27a0ecSDave Kleikamp offset = 0; 4760ac27a0ecSDave Kleikamp toread -= tocopy; 4761ac27a0ecSDave Kleikamp data += tocopy; 4762ac27a0ecSDave Kleikamp blk++; 4763ac27a0ecSDave Kleikamp } 4764ac27a0ecSDave Kleikamp return len; 4765ac27a0ecSDave Kleikamp } 4766ac27a0ecSDave Kleikamp 4767ac27a0ecSDave Kleikamp /* Write to quotafile (we know the transaction is already started and has 4768ac27a0ecSDave Kleikamp * enough credits) */ 4769617ba13bSMingming Cao static ssize_t ext4_quota_write(struct super_block *sb, int type, 4770ac27a0ecSDave Kleikamp const char *data, size_t len, loff_t off) 4771ac27a0ecSDave Kleikamp { 4772ac27a0ecSDave Kleikamp struct inode *inode = sb_dqopt(sb)->files[type]; 4773725d26d3SAneesh Kumar K.V ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb); 4774ac27a0ecSDave Kleikamp int err = 0; 4775ac27a0ecSDave Kleikamp int offset = off & (sb->s_blocksize - 1); 4776ac27a0ecSDave Kleikamp struct buffer_head *bh; 4777ac27a0ecSDave Kleikamp handle_t *handle = journal_current_handle(); 4778ac27a0ecSDave Kleikamp 47790390131bSFrank Mayhar if (EXT4_SB(sb)->s_journal && !handle) { 4780b31e1552SEric Sandeen ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)" 4781b31e1552SEric Sandeen " cancelled because transaction is not started", 47829c3013e9SJan Kara (unsigned long long)off, (unsigned long long)len); 47839c3013e9SJan Kara return -EIO; 47849c3013e9SJan Kara } 478567eeb568SDmitry Monakhov /* 478667eeb568SDmitry Monakhov * Since we account only one data block in transaction credits, 478767eeb568SDmitry Monakhov * then it is impossible to cross a block boundary. 478867eeb568SDmitry Monakhov */ 478967eeb568SDmitry Monakhov if (sb->s_blocksize - offset < len) { 479067eeb568SDmitry Monakhov ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)" 479167eeb568SDmitry Monakhov " cancelled because not block aligned", 479267eeb568SDmitry Monakhov (unsigned long long)off, (unsigned long long)len); 479367eeb568SDmitry Monakhov return -EIO; 479467eeb568SDmitry Monakhov } 479567eeb568SDmitry Monakhov 4796ac27a0ecSDave Kleikamp mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); 4797617ba13bSMingming Cao bh = ext4_bread(handle, inode, blk, 1, &err); 4798ac27a0ecSDave Kleikamp if (!bh) 4799ac27a0ecSDave Kleikamp goto out; 4800617ba13bSMingming Cao err = ext4_journal_get_write_access(handle, bh); 4801ac27a0ecSDave Kleikamp if (err) { 4802ac27a0ecSDave Kleikamp brelse(bh); 4803ac27a0ecSDave Kleikamp goto out; 4804ac27a0ecSDave Kleikamp } 4805ac27a0ecSDave Kleikamp lock_buffer(bh); 480667eeb568SDmitry Monakhov memcpy(bh->b_data+offset, data, len); 4807ac27a0ecSDave Kleikamp flush_dcache_page(bh->b_page); 4808ac27a0ecSDave Kleikamp unlock_buffer(bh); 48090390131bSFrank Mayhar err = ext4_handle_dirty_metadata(handle, NULL, bh); 4810ac27a0ecSDave Kleikamp brelse(bh); 4811ac27a0ecSDave Kleikamp out: 481267eeb568SDmitry Monakhov if (err) { 48134d04e4fbSJan Kara mutex_unlock(&inode->i_mutex); 4814ac27a0ecSDave Kleikamp return err; 48154d04e4fbSJan Kara } 481667eeb568SDmitry Monakhov if (inode->i_size < off + len) { 481767eeb568SDmitry Monakhov i_size_write(inode, off + len); 4818617ba13bSMingming Cao EXT4_I(inode)->i_disksize = inode->i_size; 4819617ba13bSMingming Cao ext4_mark_inode_dirty(handle, inode); 482021f97697SJan Kara } 4821ac27a0ecSDave Kleikamp mutex_unlock(&inode->i_mutex); 482267eeb568SDmitry Monakhov return len; 4823ac27a0ecSDave Kleikamp } 4824ac27a0ecSDave Kleikamp 4825ac27a0ecSDave Kleikamp #endif 4826ac27a0ecSDave Kleikamp 4827152a0836SAl Viro static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, 4828152a0836SAl Viro const char *dev_name, void *data) 4829ac27a0ecSDave Kleikamp { 4830152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super); 4831ac27a0ecSDave Kleikamp } 4832ac27a0ecSDave Kleikamp 483337f328ebSTheodore Ts'o #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) 483424b58424STheodore Ts'o static inline void register_as_ext2(void) 483524b58424STheodore Ts'o { 483624b58424STheodore Ts'o int err = register_filesystem(&ext2_fs_type); 483724b58424STheodore Ts'o if (err) 483824b58424STheodore Ts'o printk(KERN_WARNING 483924b58424STheodore Ts'o "EXT4-fs: Unable to register as ext2 (%d)\n", err); 484024b58424STheodore Ts'o } 484124b58424STheodore Ts'o 484224b58424STheodore Ts'o static inline void unregister_as_ext2(void) 484324b58424STheodore Ts'o { 484424b58424STheodore Ts'o unregister_filesystem(&ext2_fs_type); 484524b58424STheodore Ts'o } 48462035e776STheodore Ts'o 48472035e776STheodore Ts'o static inline int ext2_feature_set_ok(struct super_block *sb) 48482035e776STheodore Ts'o { 48492035e776STheodore Ts'o if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP)) 48502035e776STheodore Ts'o return 0; 48512035e776STheodore Ts'o if (sb->s_flags & MS_RDONLY) 48522035e776STheodore Ts'o return 1; 48532035e776STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP)) 48542035e776STheodore Ts'o return 0; 48552035e776STheodore Ts'o return 1; 48562035e776STheodore Ts'o } 485751b7e3c9STheodore Ts'o MODULE_ALIAS("ext2"); 485824b58424STheodore Ts'o #else 485924b58424STheodore Ts'o static inline void register_as_ext2(void) { } 486024b58424STheodore Ts'o static inline void unregister_as_ext2(void) { } 48612035e776STheodore Ts'o static inline int ext2_feature_set_ok(struct super_block *sb) { return 0; } 486224b58424STheodore Ts'o #endif 486324b58424STheodore Ts'o 486437f328ebSTheodore Ts'o #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) 486524b58424STheodore Ts'o static inline void register_as_ext3(void) 486624b58424STheodore Ts'o { 486724b58424STheodore Ts'o int err = register_filesystem(&ext3_fs_type); 486824b58424STheodore Ts'o if (err) 486924b58424STheodore Ts'o printk(KERN_WARNING 487024b58424STheodore Ts'o "EXT4-fs: Unable to register as ext3 (%d)\n", err); 487124b58424STheodore Ts'o } 487224b58424STheodore Ts'o 487324b58424STheodore Ts'o static inline void unregister_as_ext3(void) 487424b58424STheodore Ts'o { 487524b58424STheodore Ts'o unregister_filesystem(&ext3_fs_type); 487624b58424STheodore Ts'o } 48772035e776STheodore Ts'o 48782035e776STheodore Ts'o static inline int ext3_feature_set_ok(struct super_block *sb) 48792035e776STheodore Ts'o { 48802035e776STheodore Ts'o if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP)) 48812035e776STheodore Ts'o return 0; 48822035e776STheodore Ts'o if (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) 48832035e776STheodore Ts'o return 0; 48842035e776STheodore Ts'o if (sb->s_flags & MS_RDONLY) 48852035e776STheodore Ts'o return 1; 48862035e776STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) 48872035e776STheodore Ts'o return 0; 48882035e776STheodore Ts'o return 1; 48892035e776STheodore Ts'o } 489051b7e3c9STheodore Ts'o MODULE_ALIAS("ext3"); 489124b58424STheodore Ts'o #else 489224b58424STheodore Ts'o static inline void register_as_ext3(void) { } 489324b58424STheodore Ts'o static inline void unregister_as_ext3(void) { } 48942035e776STheodore Ts'o static inline int ext3_feature_set_ok(struct super_block *sb) { return 0; } 489524b58424STheodore Ts'o #endif 489624b58424STheodore Ts'o 489703010a33STheodore Ts'o static struct file_system_type ext4_fs_type = { 4898ac27a0ecSDave Kleikamp .owner = THIS_MODULE, 489903010a33STheodore Ts'o .name = "ext4", 4900152a0836SAl Viro .mount = ext4_mount, 4901ac27a0ecSDave Kleikamp .kill_sb = kill_block_super, 4902ac27a0ecSDave Kleikamp .fs_flags = FS_REQUIRES_DEV, 4903ac27a0ecSDave Kleikamp }; 4904ac27a0ecSDave Kleikamp 49058f021222SLukas Czerner static int __init ext4_init_feat_adverts(void) 4906857ac889SLukas Czerner { 4907857ac889SLukas Czerner struct ext4_features *ef; 4908857ac889SLukas Czerner int ret = -ENOMEM; 4909857ac889SLukas Czerner 4910857ac889SLukas Czerner ef = kzalloc(sizeof(struct ext4_features), GFP_KERNEL); 4911857ac889SLukas Czerner if (!ef) 4912857ac889SLukas Czerner goto out; 4913857ac889SLukas Czerner 4914857ac889SLukas Czerner ef->f_kobj.kset = ext4_kset; 4915857ac889SLukas Czerner init_completion(&ef->f_kobj_unregister); 4916857ac889SLukas Czerner ret = kobject_init_and_add(&ef->f_kobj, &ext4_feat_ktype, NULL, 4917857ac889SLukas Czerner "features"); 4918857ac889SLukas Czerner if (ret) { 4919857ac889SLukas Czerner kfree(ef); 4920857ac889SLukas Czerner goto out; 4921857ac889SLukas Czerner } 4922857ac889SLukas Czerner 4923857ac889SLukas Czerner ext4_feat = ef; 4924857ac889SLukas Czerner ret = 0; 4925857ac889SLukas Czerner out: 4926857ac889SLukas Czerner return ret; 4927857ac889SLukas Czerner } 4928857ac889SLukas Czerner 49298f021222SLukas Czerner static void ext4_exit_feat_adverts(void) 49308f021222SLukas Czerner { 49318f021222SLukas Czerner kobject_put(&ext4_feat->f_kobj); 49328f021222SLukas Czerner wait_for_completion(&ext4_feat->f_kobj_unregister); 49338f021222SLukas Czerner kfree(ext4_feat); 49348f021222SLukas Czerner } 49358f021222SLukas Czerner 4936e9e3bcecSEric Sandeen /* Shared across all ext4 file systems */ 4937e9e3bcecSEric Sandeen wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; 4938e9e3bcecSEric Sandeen struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ]; 4939e9e3bcecSEric Sandeen 49405dabfc78STheodore Ts'o static int __init ext4_init_fs(void) 4941ac27a0ecSDave Kleikamp { 4942e9e3bcecSEric Sandeen int i, err; 4943c9de560dSAlex Tomas 494412e9b892SDmitry Monakhov ext4_check_flag_values(); 4945e9e3bcecSEric Sandeen 4946e9e3bcecSEric Sandeen for (i = 0; i < EXT4_WQ_HASH_SZ; i++) { 4947e9e3bcecSEric Sandeen mutex_init(&ext4__aio_mutex[i]); 4948e9e3bcecSEric Sandeen init_waitqueue_head(&ext4__ioend_wq[i]); 4949e9e3bcecSEric Sandeen } 4950e9e3bcecSEric Sandeen 49515dabfc78STheodore Ts'o err = ext4_init_pageio(); 49526fd058f7STheodore Ts'o if (err) 49536fd058f7STheodore Ts'o return err; 49545dabfc78STheodore Ts'o err = ext4_init_system_zone(); 4955bd2d0210STheodore Ts'o if (err) 4956dd68314cSTheodore Ts'o goto out7; 49573197ebdbSTheodore Ts'o ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj); 49583197ebdbSTheodore Ts'o if (!ext4_kset) 4959dd68314cSTheodore Ts'o goto out6; 49609f6200bbSTheodore Ts'o ext4_proc_root = proc_mkdir("fs/ext4", NULL); 4961dd68314cSTheodore Ts'o if (!ext4_proc_root) 4962dd68314cSTheodore Ts'o goto out5; 4963857ac889SLukas Czerner 4964857ac889SLukas Czerner err = ext4_init_feat_adverts(); 4965dd68314cSTheodore Ts'o if (err) 4966dd68314cSTheodore Ts'o goto out4; 4967857ac889SLukas Czerner 49685dabfc78STheodore Ts'o err = ext4_init_mballoc(); 4969ac27a0ecSDave Kleikamp if (err) 49706fd058f7STheodore Ts'o goto out3; 4971c9de560dSAlex Tomas 49725dabfc78STheodore Ts'o err = ext4_init_xattr(); 4973c9de560dSAlex Tomas if (err) 4974c9de560dSAlex Tomas goto out2; 4975ac27a0ecSDave Kleikamp err = init_inodecache(); 4976ac27a0ecSDave Kleikamp if (err) 4977ac27a0ecSDave Kleikamp goto out1; 497824b58424STheodore Ts'o register_as_ext3(); 49792035e776STheodore Ts'o register_as_ext2(); 498003010a33STheodore Ts'o err = register_filesystem(&ext4_fs_type); 4981ac27a0ecSDave Kleikamp if (err) 4982ac27a0ecSDave Kleikamp goto out; 4983bfff6873SLukas Czerner 4984bfff6873SLukas Czerner ext4_li_info = NULL; 4985bfff6873SLukas Czerner mutex_init(&ext4_li_mtx); 4986ac27a0ecSDave Kleikamp return 0; 4987ac27a0ecSDave Kleikamp out: 498824b58424STheodore Ts'o unregister_as_ext2(); 498924b58424STheodore Ts'o unregister_as_ext3(); 4990ac27a0ecSDave Kleikamp destroy_inodecache(); 4991ac27a0ecSDave Kleikamp out1: 49925dabfc78STheodore Ts'o ext4_exit_xattr(); 4993c9de560dSAlex Tomas out2: 49945dabfc78STheodore Ts'o ext4_exit_mballoc(); 49956fd058f7STheodore Ts'o out3: 49968f021222SLukas Czerner ext4_exit_feat_adverts(); 49976fd058f7STheodore Ts'o out4: 4998dd68314cSTheodore Ts'o remove_proc_entry("fs/ext4", NULL); 4999bd2d0210STheodore Ts'o out5: 5000dd68314cSTheodore Ts'o kset_unregister(ext4_kset); 5001dd68314cSTheodore Ts'o out6: 5002dd68314cSTheodore Ts'o ext4_exit_system_zone(); 5003dd68314cSTheodore Ts'o out7: 50045dabfc78STheodore Ts'o ext4_exit_pageio(); 5005ac27a0ecSDave Kleikamp return err; 5006ac27a0ecSDave Kleikamp } 5007ac27a0ecSDave Kleikamp 50085dabfc78STheodore Ts'o static void __exit ext4_exit_fs(void) 5009ac27a0ecSDave Kleikamp { 5010bfff6873SLukas Czerner ext4_destroy_lazyinit_thread(); 501124b58424STheodore Ts'o unregister_as_ext2(); 501224b58424STheodore Ts'o unregister_as_ext3(); 501303010a33STheodore Ts'o unregister_filesystem(&ext4_fs_type); 5014ac27a0ecSDave Kleikamp destroy_inodecache(); 50155dabfc78STheodore Ts'o ext4_exit_xattr(); 50165dabfc78STheodore Ts'o ext4_exit_mballoc(); 50178f021222SLukas Czerner ext4_exit_feat_adverts(); 50189f6200bbSTheodore Ts'o remove_proc_entry("fs/ext4", NULL); 50193197ebdbSTheodore Ts'o kset_unregister(ext4_kset); 50205dabfc78STheodore Ts'o ext4_exit_system_zone(); 50215dabfc78STheodore Ts'o ext4_exit_pageio(); 5022ac27a0ecSDave Kleikamp } 5023ac27a0ecSDave Kleikamp 5024ac27a0ecSDave Kleikamp MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); 502583982b6fSTheodore Ts'o MODULE_DESCRIPTION("Fourth Extended Filesystem"); 5026ac27a0ecSDave Kleikamp MODULE_LICENSE("GPL"); 50275dabfc78STheodore Ts'o module_init(ext4_init_fs) 50285dabfc78STheodore Ts'o module_exit(ext4_exit_fs) 5029