162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * super.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * load/unload driver, mount/dismount volumes 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle. All rights reserved. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/fs.h> 1262306a36Sopenharmony_ci#include <linux/types.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/highmem.h> 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/random.h> 1762306a36Sopenharmony_ci#include <linux/statfs.h> 1862306a36Sopenharmony_ci#include <linux/moduleparam.h> 1962306a36Sopenharmony_ci#include <linux/blkdev.h> 2062306a36Sopenharmony_ci#include <linux/socket.h> 2162306a36Sopenharmony_ci#include <linux/inet.h> 2262306a36Sopenharmony_ci#include <linux/parser.h> 2362306a36Sopenharmony_ci#include <linux/crc32.h> 2462306a36Sopenharmony_ci#include <linux/debugfs.h> 2562306a36Sopenharmony_ci#include <linux/mount.h> 2662306a36Sopenharmony_ci#include <linux/seq_file.h> 2762306a36Sopenharmony_ci#include <linux/quotaops.h> 2862306a36Sopenharmony_ci#include <linux/signal.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define CREATE_TRACE_POINTS 3162306a36Sopenharmony_ci#include "ocfs2_trace.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <cluster/masklog.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include "ocfs2.h" 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* this should be the only file to include a version 1 header */ 3862306a36Sopenharmony_ci#include "ocfs1_fs_compat.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include "alloc.h" 4162306a36Sopenharmony_ci#include "aops.h" 4262306a36Sopenharmony_ci#include "blockcheck.h" 4362306a36Sopenharmony_ci#include "dlmglue.h" 4462306a36Sopenharmony_ci#include "export.h" 4562306a36Sopenharmony_ci#include "extent_map.h" 4662306a36Sopenharmony_ci#include "heartbeat.h" 4762306a36Sopenharmony_ci#include "inode.h" 4862306a36Sopenharmony_ci#include "journal.h" 4962306a36Sopenharmony_ci#include "localalloc.h" 5062306a36Sopenharmony_ci#include "namei.h" 5162306a36Sopenharmony_ci#include "slot_map.h" 5262306a36Sopenharmony_ci#include "super.h" 5362306a36Sopenharmony_ci#include "sysfile.h" 5462306a36Sopenharmony_ci#include "uptodate.h" 5562306a36Sopenharmony_ci#include "xattr.h" 5662306a36Sopenharmony_ci#include "quota.h" 5762306a36Sopenharmony_ci#include "refcounttree.h" 5862306a36Sopenharmony_ci#include "suballoc.h" 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#include "buffer_head_io.h" 6162306a36Sopenharmony_ci#include "filecheck.h" 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic struct kmem_cache *ocfs2_inode_cachep; 6462306a36Sopenharmony_cistruct kmem_cache *ocfs2_dquot_cachep; 6562306a36Sopenharmony_cistruct kmem_cache *ocfs2_qf_chunk_cachep; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic struct dentry *ocfs2_debugfs_root; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciMODULE_AUTHOR("Oracle"); 7062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 7162306a36Sopenharmony_ciMODULE_DESCRIPTION("OCFS2 cluster file system"); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistruct mount_options 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci unsigned long commit_interval; 7662306a36Sopenharmony_ci unsigned long mount_opt; 7762306a36Sopenharmony_ci unsigned int atime_quantum; 7862306a36Sopenharmony_ci unsigned short slot; 7962306a36Sopenharmony_ci int localalloc_opt; 8062306a36Sopenharmony_ci unsigned int resv_level; 8162306a36Sopenharmony_ci int dir_resv_level; 8262306a36Sopenharmony_ci char cluster_stack[OCFS2_STACK_LABEL_LEN + 1]; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int ocfs2_parse_options(struct super_block *sb, char *options, 8662306a36Sopenharmony_ci struct mount_options *mopt, 8762306a36Sopenharmony_ci int is_remount); 8862306a36Sopenharmony_cistatic int ocfs2_check_set_options(struct super_block *sb, 8962306a36Sopenharmony_ci struct mount_options *options); 9062306a36Sopenharmony_cistatic int ocfs2_show_options(struct seq_file *s, struct dentry *root); 9162306a36Sopenharmony_cistatic void ocfs2_put_super(struct super_block *sb); 9262306a36Sopenharmony_cistatic int ocfs2_mount_volume(struct super_block *sb); 9362306a36Sopenharmony_cistatic int ocfs2_remount(struct super_block *sb, int *flags, char *data); 9462306a36Sopenharmony_cistatic void ocfs2_dismount_volume(struct super_block *sb, int mnt_err); 9562306a36Sopenharmony_cistatic int ocfs2_initialize_mem_caches(void); 9662306a36Sopenharmony_cistatic void ocfs2_free_mem_caches(void); 9762306a36Sopenharmony_cistatic void ocfs2_delete_osb(struct ocfs2_super *osb); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic int ocfs2_sync_fs(struct super_block *sb, int wait); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic int ocfs2_init_global_system_inodes(struct ocfs2_super *osb); 10462306a36Sopenharmony_cistatic int ocfs2_init_local_system_inodes(struct ocfs2_super *osb); 10562306a36Sopenharmony_cistatic void ocfs2_release_system_inodes(struct ocfs2_super *osb); 10662306a36Sopenharmony_cistatic int ocfs2_check_volume(struct ocfs2_super *osb); 10762306a36Sopenharmony_cistatic int ocfs2_verify_volume(struct ocfs2_dinode *di, 10862306a36Sopenharmony_ci struct buffer_head *bh, 10962306a36Sopenharmony_ci u32 sectsize, 11062306a36Sopenharmony_ci struct ocfs2_blockcheck_stats *stats); 11162306a36Sopenharmony_cistatic int ocfs2_initialize_super(struct super_block *sb, 11262306a36Sopenharmony_ci struct buffer_head *bh, 11362306a36Sopenharmony_ci int sector_size, 11462306a36Sopenharmony_ci struct ocfs2_blockcheck_stats *stats); 11562306a36Sopenharmony_cistatic int ocfs2_get_sector(struct super_block *sb, 11662306a36Sopenharmony_ci struct buffer_head **bh, 11762306a36Sopenharmony_ci int block, 11862306a36Sopenharmony_ci int sect_size); 11962306a36Sopenharmony_cistatic struct inode *ocfs2_alloc_inode(struct super_block *sb); 12062306a36Sopenharmony_cistatic void ocfs2_free_inode(struct inode *inode); 12162306a36Sopenharmony_cistatic int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend); 12262306a36Sopenharmony_cistatic int ocfs2_enable_quotas(struct ocfs2_super *osb); 12362306a36Sopenharmony_cistatic void ocfs2_disable_quotas(struct ocfs2_super *osb); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic struct dquot __rcu **ocfs2_get_dquots(struct inode *inode) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci return OCFS2_I(inode)->i_dquot; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic const struct super_operations ocfs2_sops = { 13162306a36Sopenharmony_ci .statfs = ocfs2_statfs, 13262306a36Sopenharmony_ci .alloc_inode = ocfs2_alloc_inode, 13362306a36Sopenharmony_ci .free_inode = ocfs2_free_inode, 13462306a36Sopenharmony_ci .drop_inode = ocfs2_drop_inode, 13562306a36Sopenharmony_ci .evict_inode = ocfs2_evict_inode, 13662306a36Sopenharmony_ci .sync_fs = ocfs2_sync_fs, 13762306a36Sopenharmony_ci .put_super = ocfs2_put_super, 13862306a36Sopenharmony_ci .remount_fs = ocfs2_remount, 13962306a36Sopenharmony_ci .show_options = ocfs2_show_options, 14062306a36Sopenharmony_ci .quota_read = ocfs2_quota_read, 14162306a36Sopenharmony_ci .quota_write = ocfs2_quota_write, 14262306a36Sopenharmony_ci .get_dquots = ocfs2_get_dquots, 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cienum { 14662306a36Sopenharmony_ci Opt_barrier, 14762306a36Sopenharmony_ci Opt_err_panic, 14862306a36Sopenharmony_ci Opt_err_ro, 14962306a36Sopenharmony_ci Opt_intr, 15062306a36Sopenharmony_ci Opt_nointr, 15162306a36Sopenharmony_ci Opt_hb_none, 15262306a36Sopenharmony_ci Opt_hb_local, 15362306a36Sopenharmony_ci Opt_hb_global, 15462306a36Sopenharmony_ci Opt_data_ordered, 15562306a36Sopenharmony_ci Opt_data_writeback, 15662306a36Sopenharmony_ci Opt_atime_quantum, 15762306a36Sopenharmony_ci Opt_slot, 15862306a36Sopenharmony_ci Opt_commit, 15962306a36Sopenharmony_ci Opt_localalloc, 16062306a36Sopenharmony_ci Opt_localflocks, 16162306a36Sopenharmony_ci Opt_stack, 16262306a36Sopenharmony_ci Opt_user_xattr, 16362306a36Sopenharmony_ci Opt_nouser_xattr, 16462306a36Sopenharmony_ci Opt_inode64, 16562306a36Sopenharmony_ci Opt_acl, 16662306a36Sopenharmony_ci Opt_noacl, 16762306a36Sopenharmony_ci Opt_usrquota, 16862306a36Sopenharmony_ci Opt_grpquota, 16962306a36Sopenharmony_ci Opt_coherency_buffered, 17062306a36Sopenharmony_ci Opt_coherency_full, 17162306a36Sopenharmony_ci Opt_resv_level, 17262306a36Sopenharmony_ci Opt_dir_resv_level, 17362306a36Sopenharmony_ci Opt_journal_async_commit, 17462306a36Sopenharmony_ci Opt_err_cont, 17562306a36Sopenharmony_ci Opt_err, 17662306a36Sopenharmony_ci}; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic const match_table_t tokens = { 17962306a36Sopenharmony_ci {Opt_barrier, "barrier=%u"}, 18062306a36Sopenharmony_ci {Opt_err_panic, "errors=panic"}, 18162306a36Sopenharmony_ci {Opt_err_ro, "errors=remount-ro"}, 18262306a36Sopenharmony_ci {Opt_intr, "intr"}, 18362306a36Sopenharmony_ci {Opt_nointr, "nointr"}, 18462306a36Sopenharmony_ci {Opt_hb_none, OCFS2_HB_NONE}, 18562306a36Sopenharmony_ci {Opt_hb_local, OCFS2_HB_LOCAL}, 18662306a36Sopenharmony_ci {Opt_hb_global, OCFS2_HB_GLOBAL}, 18762306a36Sopenharmony_ci {Opt_data_ordered, "data=ordered"}, 18862306a36Sopenharmony_ci {Opt_data_writeback, "data=writeback"}, 18962306a36Sopenharmony_ci {Opt_atime_quantum, "atime_quantum=%u"}, 19062306a36Sopenharmony_ci {Opt_slot, "preferred_slot=%u"}, 19162306a36Sopenharmony_ci {Opt_commit, "commit=%u"}, 19262306a36Sopenharmony_ci {Opt_localalloc, "localalloc=%d"}, 19362306a36Sopenharmony_ci {Opt_localflocks, "localflocks"}, 19462306a36Sopenharmony_ci {Opt_stack, "cluster_stack=%s"}, 19562306a36Sopenharmony_ci {Opt_user_xattr, "user_xattr"}, 19662306a36Sopenharmony_ci {Opt_nouser_xattr, "nouser_xattr"}, 19762306a36Sopenharmony_ci {Opt_inode64, "inode64"}, 19862306a36Sopenharmony_ci {Opt_acl, "acl"}, 19962306a36Sopenharmony_ci {Opt_noacl, "noacl"}, 20062306a36Sopenharmony_ci {Opt_usrquota, "usrquota"}, 20162306a36Sopenharmony_ci {Opt_grpquota, "grpquota"}, 20262306a36Sopenharmony_ci {Opt_coherency_buffered, "coherency=buffered"}, 20362306a36Sopenharmony_ci {Opt_coherency_full, "coherency=full"}, 20462306a36Sopenharmony_ci {Opt_resv_level, "resv_level=%u"}, 20562306a36Sopenharmony_ci {Opt_dir_resv_level, "dir_resv_level=%u"}, 20662306a36Sopenharmony_ci {Opt_journal_async_commit, "journal_async_commit"}, 20762306a36Sopenharmony_ci {Opt_err_cont, "errors=continue"}, 20862306a36Sopenharmony_ci {Opt_err, NULL} 20962306a36Sopenharmony_ci}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 21262306a36Sopenharmony_cistatic int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct ocfs2_cluster_connection *cconn = osb->cconn; 21562306a36Sopenharmony_ci struct ocfs2_recovery_map *rm = osb->recovery_map; 21662306a36Sopenharmony_ci struct ocfs2_orphan_scan *os = &osb->osb_orphan_scan; 21762306a36Sopenharmony_ci int i, out = 0; 21862306a36Sopenharmony_ci unsigned long flags; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 22162306a36Sopenharmony_ci "%10s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n", 22262306a36Sopenharmony_ci "Device", osb->dev_str, osb->uuid_str, 22362306a36Sopenharmony_ci osb->fs_generation, osb->vol_label); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 22662306a36Sopenharmony_ci "%10s => State: %d Flags: 0x%lX\n", "Volume", 22762306a36Sopenharmony_ci atomic_read(&osb->vol_state), osb->osb_flags); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 23062306a36Sopenharmony_ci "%10s => Block: %lu Cluster: %d\n", "Sizes", 23162306a36Sopenharmony_ci osb->sb->s_blocksize, osb->s_clustersize); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 23462306a36Sopenharmony_ci "%10s => Compat: 0x%X Incompat: 0x%X " 23562306a36Sopenharmony_ci "ROcompat: 0x%X\n", 23662306a36Sopenharmony_ci "Features", osb->s_feature_compat, 23762306a36Sopenharmony_ci osb->s_feature_incompat, osb->s_feature_ro_compat); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 24062306a36Sopenharmony_ci "%10s => Opts: 0x%lX AtimeQuanta: %u\n", "Mount", 24162306a36Sopenharmony_ci osb->s_mount_opt, osb->s_atime_quantum); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (cconn) { 24462306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 24562306a36Sopenharmony_ci "%10s => Stack: %s Name: %*s " 24662306a36Sopenharmony_ci "Version: %d.%d\n", "Cluster", 24762306a36Sopenharmony_ci (*osb->osb_cluster_stack == '\0' ? 24862306a36Sopenharmony_ci "o2cb" : osb->osb_cluster_stack), 24962306a36Sopenharmony_ci cconn->cc_namelen, cconn->cc_name, 25062306a36Sopenharmony_ci cconn->cc_version.pv_major, 25162306a36Sopenharmony_ci cconn->cc_version.pv_minor); 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci spin_lock_irqsave(&osb->dc_task_lock, flags); 25562306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 25662306a36Sopenharmony_ci "%10s => Pid: %d Count: %lu WakeSeq: %lu " 25762306a36Sopenharmony_ci "WorkSeq: %lu\n", "DownCnvt", 25862306a36Sopenharmony_ci (osb->dc_task ? task_pid_nr(osb->dc_task) : -1), 25962306a36Sopenharmony_ci osb->blocked_lock_count, osb->dc_wake_sequence, 26062306a36Sopenharmony_ci osb->dc_work_sequence); 26162306a36Sopenharmony_ci spin_unlock_irqrestore(&osb->dc_task_lock, flags); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 26462306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, "%10s => Pid: %d Nodes:", 26562306a36Sopenharmony_ci "Recovery", 26662306a36Sopenharmony_ci (osb->recovery_thread_task ? 26762306a36Sopenharmony_ci task_pid_nr(osb->recovery_thread_task) : -1)); 26862306a36Sopenharmony_ci if (rm->rm_used == 0) 26962306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, " None\n"); 27062306a36Sopenharmony_ci else { 27162306a36Sopenharmony_ci for (i = 0; i < rm->rm_used; i++) 27262306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, " %d", 27362306a36Sopenharmony_ci rm->rm_entries[i]); 27462306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, "\n"); 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 27962306a36Sopenharmony_ci "%10s => Pid: %d Interval: %lu\n", "Commit", 28062306a36Sopenharmony_ci (osb->commit_task ? task_pid_nr(osb->commit_task) : -1), 28162306a36Sopenharmony_ci osb->osb_commit_interval); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 28462306a36Sopenharmony_ci "%10s => State: %d TxnId: %lu NumTxns: %d\n", 28562306a36Sopenharmony_ci "Journal", osb->journal->j_state, 28662306a36Sopenharmony_ci osb->journal->j_trans_id, 28762306a36Sopenharmony_ci atomic_read(&osb->journal->j_num_trans)); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 29062306a36Sopenharmony_ci "%10s => GlobalAllocs: %d LocalAllocs: %d " 29162306a36Sopenharmony_ci "SubAllocs: %d LAWinMoves: %d SAExtends: %d\n", 29262306a36Sopenharmony_ci "Stats", 29362306a36Sopenharmony_ci atomic_read(&osb->alloc_stats.bitmap_data), 29462306a36Sopenharmony_ci atomic_read(&osb->alloc_stats.local_data), 29562306a36Sopenharmony_ci atomic_read(&osb->alloc_stats.bg_allocs), 29662306a36Sopenharmony_ci atomic_read(&osb->alloc_stats.moves), 29762306a36Sopenharmony_ci atomic_read(&osb->alloc_stats.bg_extends)); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 30062306a36Sopenharmony_ci "%10s => State: %u Descriptor: %llu Size: %u bits " 30162306a36Sopenharmony_ci "Default: %u bits\n", 30262306a36Sopenharmony_ci "LocalAlloc", osb->local_alloc_state, 30362306a36Sopenharmony_ci (unsigned long long)osb->la_last_gd, 30462306a36Sopenharmony_ci osb->local_alloc_bits, osb->local_alloc_default_bits); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 30762306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 30862306a36Sopenharmony_ci "%10s => InodeSlot: %d StolenInodes: %d, " 30962306a36Sopenharmony_ci "MetaSlot: %d StolenMeta: %d\n", "Steal", 31062306a36Sopenharmony_ci osb->s_inode_steal_slot, 31162306a36Sopenharmony_ci atomic_read(&osb->s_num_inodes_stolen), 31262306a36Sopenharmony_ci osb->s_meta_steal_slot, 31362306a36Sopenharmony_ci atomic_read(&osb->s_num_meta_stolen)); 31462306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, "OrphanScan => "); 31762306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, "Local: %u Global: %u ", 31862306a36Sopenharmony_ci os->os_count, os->os_seqno); 31962306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, " Last Scan: "); 32062306a36Sopenharmony_ci if (atomic_read(&os->os_state) == ORPHAN_SCAN_INACTIVE) 32162306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, "Disabled\n"); 32262306a36Sopenharmony_ci else 32362306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, "%lu seconds ago\n", 32462306a36Sopenharmony_ci (unsigned long)(ktime_get_seconds() - os->os_scantime)); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, "%10s => %3s %10s\n", 32762306a36Sopenharmony_ci "Slots", "Num", "RecoGen"); 32862306a36Sopenharmony_ci for (i = 0; i < osb->max_slots; ++i) { 32962306a36Sopenharmony_ci out += scnprintf(buf + out, len - out, 33062306a36Sopenharmony_ci "%10s %c %3d %10d\n", 33162306a36Sopenharmony_ci " ", 33262306a36Sopenharmony_ci (i == osb->slot_num ? '*' : ' '), 33362306a36Sopenharmony_ci i, osb->slot_recovery_generations[i]); 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci return out; 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic int ocfs2_osb_debug_open(struct inode *inode, struct file *file) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci struct ocfs2_super *osb = inode->i_private; 34262306a36Sopenharmony_ci char *buf = NULL; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 34562306a36Sopenharmony_ci if (!buf) 34662306a36Sopenharmony_ci goto bail; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci i_size_write(inode, ocfs2_osb_dump(osb, buf, PAGE_SIZE)); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci file->private_data = buf; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci return 0; 35362306a36Sopenharmony_cibail: 35462306a36Sopenharmony_ci return -ENOMEM; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic int ocfs2_debug_release(struct inode *inode, struct file *file) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci kfree(file->private_data); 36062306a36Sopenharmony_ci return 0; 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic ssize_t ocfs2_debug_read(struct file *file, char __user *buf, 36462306a36Sopenharmony_ci size_t nbytes, loff_t *ppos) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci return simple_read_from_buffer(buf, nbytes, ppos, file->private_data, 36762306a36Sopenharmony_ci i_size_read(file->f_mapping->host)); 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ci#else 37062306a36Sopenharmony_cistatic int ocfs2_osb_debug_open(struct inode *inode, struct file *file) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci return 0; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_cistatic int ocfs2_debug_release(struct inode *inode, struct file *file) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci return 0; 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_cistatic ssize_t ocfs2_debug_read(struct file *file, char __user *buf, 37962306a36Sopenharmony_ci size_t nbytes, loff_t *ppos) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci return 0; 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */ 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic const struct file_operations ocfs2_osb_debug_fops = { 38662306a36Sopenharmony_ci .open = ocfs2_osb_debug_open, 38762306a36Sopenharmony_ci .release = ocfs2_debug_release, 38862306a36Sopenharmony_ci .read = ocfs2_debug_read, 38962306a36Sopenharmony_ci .llseek = generic_file_llseek, 39062306a36Sopenharmony_ci}; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic int ocfs2_sync_fs(struct super_block *sb, int wait) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci int status; 39562306a36Sopenharmony_ci tid_t target; 39662306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(sb); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci if (ocfs2_is_hard_readonly(osb)) 39962306a36Sopenharmony_ci return -EROFS; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci if (wait) { 40262306a36Sopenharmony_ci status = ocfs2_flush_truncate_log(osb); 40362306a36Sopenharmony_ci if (status < 0) 40462306a36Sopenharmony_ci mlog_errno(status); 40562306a36Sopenharmony_ci } else { 40662306a36Sopenharmony_ci ocfs2_schedule_truncate_log_flush(osb, 0); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci if (jbd2_journal_start_commit(osb->journal->j_journal, 41062306a36Sopenharmony_ci &target)) { 41162306a36Sopenharmony_ci if (wait) 41262306a36Sopenharmony_ci jbd2_log_wait_commit(osb->journal->j_journal, 41362306a36Sopenharmony_ci target); 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci return 0; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic int ocfs2_need_system_inode(struct ocfs2_super *osb, int ino) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci if (!OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, OCFS2_FEATURE_RO_COMPAT_USRQUOTA) 42162306a36Sopenharmony_ci && (ino == USER_QUOTA_SYSTEM_INODE 42262306a36Sopenharmony_ci || ino == LOCAL_USER_QUOTA_SYSTEM_INODE)) 42362306a36Sopenharmony_ci return 0; 42462306a36Sopenharmony_ci if (!OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA) 42562306a36Sopenharmony_ci && (ino == GROUP_QUOTA_SYSTEM_INODE 42662306a36Sopenharmony_ci || ino == LOCAL_GROUP_QUOTA_SYSTEM_INODE)) 42762306a36Sopenharmony_ci return 0; 42862306a36Sopenharmony_ci return 1; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic int ocfs2_init_global_system_inodes(struct ocfs2_super *osb) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci struct inode *new = NULL; 43462306a36Sopenharmony_ci int status = 0; 43562306a36Sopenharmony_ci int i; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci new = ocfs2_iget(osb, osb->root_blkno, OCFS2_FI_FLAG_SYSFILE, 0); 43862306a36Sopenharmony_ci if (IS_ERR(new)) { 43962306a36Sopenharmony_ci status = PTR_ERR(new); 44062306a36Sopenharmony_ci mlog_errno(status); 44162306a36Sopenharmony_ci goto bail; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci osb->root_inode = new; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci new = ocfs2_iget(osb, osb->system_dir_blkno, OCFS2_FI_FLAG_SYSFILE, 0); 44662306a36Sopenharmony_ci if (IS_ERR(new)) { 44762306a36Sopenharmony_ci status = PTR_ERR(new); 44862306a36Sopenharmony_ci mlog_errno(status); 44962306a36Sopenharmony_ci goto bail; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci osb->sys_root_inode = new; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci for (i = OCFS2_FIRST_ONLINE_SYSTEM_INODE; 45462306a36Sopenharmony_ci i <= OCFS2_LAST_GLOBAL_SYSTEM_INODE; i++) { 45562306a36Sopenharmony_ci if (!ocfs2_need_system_inode(osb, i)) 45662306a36Sopenharmony_ci continue; 45762306a36Sopenharmony_ci new = ocfs2_get_system_file_inode(osb, i, osb->slot_num); 45862306a36Sopenharmony_ci if (!new) { 45962306a36Sopenharmony_ci ocfs2_release_system_inodes(osb); 46062306a36Sopenharmony_ci status = ocfs2_is_soft_readonly(osb) ? -EROFS : -EINVAL; 46162306a36Sopenharmony_ci mlog_errno(status); 46262306a36Sopenharmony_ci mlog(ML_ERROR, "Unable to load system inode %d, " 46362306a36Sopenharmony_ci "possibly corrupt fs?", i); 46462306a36Sopenharmony_ci goto bail; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci // the array now has one ref, so drop this one 46762306a36Sopenharmony_ci iput(new); 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cibail: 47162306a36Sopenharmony_ci if (status) 47262306a36Sopenharmony_ci mlog_errno(status); 47362306a36Sopenharmony_ci return status; 47462306a36Sopenharmony_ci} 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_cistatic int ocfs2_init_local_system_inodes(struct ocfs2_super *osb) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct inode *new = NULL; 47962306a36Sopenharmony_ci int status = 0; 48062306a36Sopenharmony_ci int i; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1; 48362306a36Sopenharmony_ci i < NUM_SYSTEM_INODES; 48462306a36Sopenharmony_ci i++) { 48562306a36Sopenharmony_ci if (!ocfs2_need_system_inode(osb, i)) 48662306a36Sopenharmony_ci continue; 48762306a36Sopenharmony_ci new = ocfs2_get_system_file_inode(osb, i, osb->slot_num); 48862306a36Sopenharmony_ci if (!new) { 48962306a36Sopenharmony_ci ocfs2_release_system_inodes(osb); 49062306a36Sopenharmony_ci status = ocfs2_is_soft_readonly(osb) ? -EROFS : -EINVAL; 49162306a36Sopenharmony_ci mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n", 49262306a36Sopenharmony_ci status, i, osb->slot_num); 49362306a36Sopenharmony_ci goto bail; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci /* the array now has one ref, so drop this one */ 49662306a36Sopenharmony_ci iput(new); 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_cibail: 50062306a36Sopenharmony_ci if (status) 50162306a36Sopenharmony_ci mlog_errno(status); 50262306a36Sopenharmony_ci return status; 50362306a36Sopenharmony_ci} 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistatic void ocfs2_release_system_inodes(struct ocfs2_super *osb) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci int i; 50862306a36Sopenharmony_ci struct inode *inode; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) { 51162306a36Sopenharmony_ci inode = osb->global_system_inodes[i]; 51262306a36Sopenharmony_ci if (inode) { 51362306a36Sopenharmony_ci iput(inode); 51462306a36Sopenharmony_ci osb->global_system_inodes[i] = NULL; 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci inode = osb->sys_root_inode; 51962306a36Sopenharmony_ci if (inode) { 52062306a36Sopenharmony_ci iput(inode); 52162306a36Sopenharmony_ci osb->sys_root_inode = NULL; 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci inode = osb->root_inode; 52562306a36Sopenharmony_ci if (inode) { 52662306a36Sopenharmony_ci iput(inode); 52762306a36Sopenharmony_ci osb->root_inode = NULL; 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci if (!osb->local_system_inodes) 53162306a36Sopenharmony_ci return; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci for (i = 0; i < NUM_LOCAL_SYSTEM_INODES * osb->max_slots; i++) { 53462306a36Sopenharmony_ci if (osb->local_system_inodes[i]) { 53562306a36Sopenharmony_ci iput(osb->local_system_inodes[i]); 53662306a36Sopenharmony_ci osb->local_system_inodes[i] = NULL; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci kfree(osb->local_system_inodes); 54162306a36Sopenharmony_ci osb->local_system_inodes = NULL; 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci/* We're allocating fs objects, use GFP_NOFS */ 54562306a36Sopenharmony_cistatic struct inode *ocfs2_alloc_inode(struct super_block *sb) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci struct ocfs2_inode_info *oi; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci oi = alloc_inode_sb(sb, ocfs2_inode_cachep, GFP_NOFS); 55062306a36Sopenharmony_ci if (!oi) 55162306a36Sopenharmony_ci return NULL; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci oi->i_sync_tid = 0; 55462306a36Sopenharmony_ci oi->i_datasync_tid = 0; 55562306a36Sopenharmony_ci memset(&oi->i_dquot, 0, sizeof(oi->i_dquot)); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci jbd2_journal_init_jbd_inode(&oi->ip_jinode, &oi->vfs_inode); 55862306a36Sopenharmony_ci return &oi->vfs_inode; 55962306a36Sopenharmony_ci} 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_cistatic void ocfs2_free_inode(struct inode *inode) 56262306a36Sopenharmony_ci{ 56362306a36Sopenharmony_ci kmem_cache_free(ocfs2_inode_cachep, OCFS2_I(inode)); 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cistatic unsigned long long ocfs2_max_file_offset(unsigned int bbits, 56762306a36Sopenharmony_ci unsigned int cbits) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci unsigned int bytes = 1 << cbits; 57062306a36Sopenharmony_ci unsigned int trim = bytes; 57162306a36Sopenharmony_ci unsigned int bitshift = 32; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci /* 57462306a36Sopenharmony_ci * i_size and all block offsets in ocfs2 are always 64 bits 57562306a36Sopenharmony_ci * wide. i_clusters is 32 bits, in cluster-sized units. So on 57662306a36Sopenharmony_ci * 64 bit platforms, cluster size will be the limiting factor. 57762306a36Sopenharmony_ci */ 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci#if BITS_PER_LONG == 32 58062306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(sector_t) != 8); 58162306a36Sopenharmony_ci /* 58262306a36Sopenharmony_ci * We might be limited by page cache size. 58362306a36Sopenharmony_ci */ 58462306a36Sopenharmony_ci if (bytes > PAGE_SIZE) { 58562306a36Sopenharmony_ci bytes = PAGE_SIZE; 58662306a36Sopenharmony_ci trim = 1; 58762306a36Sopenharmony_ci /* 58862306a36Sopenharmony_ci * Shift by 31 here so that we don't get larger than 58962306a36Sopenharmony_ci * MAX_LFS_FILESIZE 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci bitshift = 31; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci#endif 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* 59662306a36Sopenharmony_ci * Trim by a whole cluster when we can actually approach the 59762306a36Sopenharmony_ci * on-disk limits. Otherwise we can overflow i_clusters when 59862306a36Sopenharmony_ci * an extent start is at the max offset. 59962306a36Sopenharmony_ci */ 60062306a36Sopenharmony_ci return (((unsigned long long)bytes) << bitshift) - trim; 60162306a36Sopenharmony_ci} 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_cistatic int ocfs2_remount(struct super_block *sb, int *flags, char *data) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci int incompat_features; 60662306a36Sopenharmony_ci int ret = 0; 60762306a36Sopenharmony_ci struct mount_options parsed_options; 60862306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(sb); 60962306a36Sopenharmony_ci u32 tmp; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci sync_filesystem(sb); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci if (!ocfs2_parse_options(sb, data, &parsed_options, 1) || 61462306a36Sopenharmony_ci !ocfs2_check_set_options(sb, &parsed_options)) { 61562306a36Sopenharmony_ci ret = -EINVAL; 61662306a36Sopenharmony_ci goto out; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci tmp = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL | 62062306a36Sopenharmony_ci OCFS2_MOUNT_HB_NONE; 62162306a36Sopenharmony_ci if ((osb->s_mount_opt & tmp) != (parsed_options.mount_opt & tmp)) { 62262306a36Sopenharmony_ci ret = -EINVAL; 62362306a36Sopenharmony_ci mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n"); 62462306a36Sopenharmony_ci goto out; 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci if ((osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK) != 62862306a36Sopenharmony_ci (parsed_options.mount_opt & OCFS2_MOUNT_DATA_WRITEBACK)) { 62962306a36Sopenharmony_ci ret = -EINVAL; 63062306a36Sopenharmony_ci mlog(ML_ERROR, "Cannot change data mode on remount\n"); 63162306a36Sopenharmony_ci goto out; 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* Probably don't want this on remount; it might 63562306a36Sopenharmony_ci * mess with other nodes */ 63662306a36Sopenharmony_ci if (!(osb->s_mount_opt & OCFS2_MOUNT_INODE64) && 63762306a36Sopenharmony_ci (parsed_options.mount_opt & OCFS2_MOUNT_INODE64)) { 63862306a36Sopenharmony_ci ret = -EINVAL; 63962306a36Sopenharmony_ci mlog(ML_ERROR, "Cannot enable inode64 on remount\n"); 64062306a36Sopenharmony_ci goto out; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* We're going to/from readonly mode. */ 64462306a36Sopenharmony_ci if ((bool)(*flags & SB_RDONLY) != sb_rdonly(sb)) { 64562306a36Sopenharmony_ci /* Disable quota accounting before remounting RO */ 64662306a36Sopenharmony_ci if (*flags & SB_RDONLY) { 64762306a36Sopenharmony_ci ret = ocfs2_susp_quotas(osb, 0); 64862306a36Sopenharmony_ci if (ret < 0) 64962306a36Sopenharmony_ci goto out; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci /* Lock here so the check of HARD_RO and the potential 65262306a36Sopenharmony_ci * setting of SOFT_RO is atomic. */ 65362306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 65462306a36Sopenharmony_ci if (osb->osb_flags & OCFS2_OSB_HARD_RO) { 65562306a36Sopenharmony_ci mlog(ML_ERROR, "Remount on readonly device is forbidden.\n"); 65662306a36Sopenharmony_ci ret = -EROFS; 65762306a36Sopenharmony_ci goto unlock_osb; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (*flags & SB_RDONLY) { 66162306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 66262306a36Sopenharmony_ci osb->osb_flags |= OCFS2_OSB_SOFT_RO; 66362306a36Sopenharmony_ci } else { 66462306a36Sopenharmony_ci if (osb->osb_flags & OCFS2_OSB_ERROR_FS) { 66562306a36Sopenharmony_ci mlog(ML_ERROR, "Cannot remount RDWR " 66662306a36Sopenharmony_ci "filesystem due to previous errors.\n"); 66762306a36Sopenharmony_ci ret = -EROFS; 66862306a36Sopenharmony_ci goto unlock_osb; 66962306a36Sopenharmony_ci } 67062306a36Sopenharmony_ci incompat_features = OCFS2_HAS_RO_COMPAT_FEATURE(sb, ~OCFS2_FEATURE_RO_COMPAT_SUPP); 67162306a36Sopenharmony_ci if (incompat_features) { 67262306a36Sopenharmony_ci mlog(ML_ERROR, "Cannot remount RDWR because " 67362306a36Sopenharmony_ci "of unsupported optional features " 67462306a36Sopenharmony_ci "(%x).\n", incompat_features); 67562306a36Sopenharmony_ci ret = -EINVAL; 67662306a36Sopenharmony_ci goto unlock_osb; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci sb->s_flags &= ~SB_RDONLY; 67962306a36Sopenharmony_ci osb->osb_flags &= ~OCFS2_OSB_SOFT_RO; 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci trace_ocfs2_remount(sb->s_flags, osb->osb_flags, *flags); 68262306a36Sopenharmony_ciunlock_osb: 68362306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 68462306a36Sopenharmony_ci /* Enable quota accounting after remounting RW */ 68562306a36Sopenharmony_ci if (!ret && !(*flags & SB_RDONLY)) { 68662306a36Sopenharmony_ci if (sb_any_quota_suspended(sb)) 68762306a36Sopenharmony_ci ret = ocfs2_susp_quotas(osb, 1); 68862306a36Sopenharmony_ci else 68962306a36Sopenharmony_ci ret = ocfs2_enable_quotas(osb); 69062306a36Sopenharmony_ci if (ret < 0) { 69162306a36Sopenharmony_ci /* Return back changes... */ 69262306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 69362306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 69462306a36Sopenharmony_ci osb->osb_flags |= OCFS2_OSB_SOFT_RO; 69562306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 69662306a36Sopenharmony_ci goto out; 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci if (!ret) { 70262306a36Sopenharmony_ci /* Only save off the new mount options in case of a successful 70362306a36Sopenharmony_ci * remount. */ 70462306a36Sopenharmony_ci osb->s_mount_opt = parsed_options.mount_opt; 70562306a36Sopenharmony_ci osb->s_atime_quantum = parsed_options.atime_quantum; 70662306a36Sopenharmony_ci osb->preferred_slot = parsed_options.slot; 70762306a36Sopenharmony_ci if (parsed_options.commit_interval) 70862306a36Sopenharmony_ci osb->osb_commit_interval = parsed_options.commit_interval; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci if (!ocfs2_is_hard_readonly(osb)) 71162306a36Sopenharmony_ci ocfs2_set_journal_params(osb); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | 71462306a36Sopenharmony_ci ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) ? 71562306a36Sopenharmony_ci SB_POSIXACL : 0); 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ciout: 71862306a36Sopenharmony_ci return ret; 71962306a36Sopenharmony_ci} 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_cistatic int ocfs2_sb_probe(struct super_block *sb, 72262306a36Sopenharmony_ci struct buffer_head **bh, 72362306a36Sopenharmony_ci int *sector_size, 72462306a36Sopenharmony_ci struct ocfs2_blockcheck_stats *stats) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci int status, tmpstat; 72762306a36Sopenharmony_ci struct ocfs1_vol_disk_hdr *hdr; 72862306a36Sopenharmony_ci struct ocfs2_dinode *di; 72962306a36Sopenharmony_ci int blksize; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci *bh = NULL; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci /* may be > 512 */ 73462306a36Sopenharmony_ci *sector_size = bdev_logical_block_size(sb->s_bdev); 73562306a36Sopenharmony_ci if (*sector_size > OCFS2_MAX_BLOCKSIZE) { 73662306a36Sopenharmony_ci mlog(ML_ERROR, "Hardware sector size too large: %d (max=%d)\n", 73762306a36Sopenharmony_ci *sector_size, OCFS2_MAX_BLOCKSIZE); 73862306a36Sopenharmony_ci status = -EINVAL; 73962306a36Sopenharmony_ci goto bail; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci /* Can this really happen? */ 74362306a36Sopenharmony_ci if (*sector_size < OCFS2_MIN_BLOCKSIZE) 74462306a36Sopenharmony_ci *sector_size = OCFS2_MIN_BLOCKSIZE; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci /* check block zero for old format */ 74762306a36Sopenharmony_ci status = ocfs2_get_sector(sb, bh, 0, *sector_size); 74862306a36Sopenharmony_ci if (status < 0) { 74962306a36Sopenharmony_ci mlog_errno(status); 75062306a36Sopenharmony_ci goto bail; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci hdr = (struct ocfs1_vol_disk_hdr *) (*bh)->b_data; 75362306a36Sopenharmony_ci if (hdr->major_version == OCFS1_MAJOR_VERSION) { 75462306a36Sopenharmony_ci mlog(ML_ERROR, "incompatible version: %u.%u\n", 75562306a36Sopenharmony_ci hdr->major_version, hdr->minor_version); 75662306a36Sopenharmony_ci status = -EINVAL; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci if (memcmp(hdr->signature, OCFS1_VOLUME_SIGNATURE, 75962306a36Sopenharmony_ci strlen(OCFS1_VOLUME_SIGNATURE)) == 0) { 76062306a36Sopenharmony_ci mlog(ML_ERROR, "incompatible volume signature: %8s\n", 76162306a36Sopenharmony_ci hdr->signature); 76262306a36Sopenharmony_ci status = -EINVAL; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci brelse(*bh); 76562306a36Sopenharmony_ci *bh = NULL; 76662306a36Sopenharmony_ci if (status < 0) { 76762306a36Sopenharmony_ci mlog(ML_ERROR, "This is an ocfs v1 filesystem which must be " 76862306a36Sopenharmony_ci "upgraded before mounting with ocfs v2\n"); 76962306a36Sopenharmony_ci goto bail; 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci /* 77362306a36Sopenharmony_ci * Now check at magic offset for 512, 1024, 2048, 4096 77462306a36Sopenharmony_ci * blocksizes. 4096 is the maximum blocksize because it is 77562306a36Sopenharmony_ci * the minimum clustersize. 77662306a36Sopenharmony_ci */ 77762306a36Sopenharmony_ci status = -EINVAL; 77862306a36Sopenharmony_ci for (blksize = *sector_size; 77962306a36Sopenharmony_ci blksize <= OCFS2_MAX_BLOCKSIZE; 78062306a36Sopenharmony_ci blksize <<= 1) { 78162306a36Sopenharmony_ci tmpstat = ocfs2_get_sector(sb, bh, 78262306a36Sopenharmony_ci OCFS2_SUPER_BLOCK_BLKNO, 78362306a36Sopenharmony_ci blksize); 78462306a36Sopenharmony_ci if (tmpstat < 0) { 78562306a36Sopenharmony_ci status = tmpstat; 78662306a36Sopenharmony_ci mlog_errno(status); 78762306a36Sopenharmony_ci break; 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci di = (struct ocfs2_dinode *) (*bh)->b_data; 79062306a36Sopenharmony_ci memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats)); 79162306a36Sopenharmony_ci spin_lock_init(&stats->b_lock); 79262306a36Sopenharmony_ci tmpstat = ocfs2_verify_volume(di, *bh, blksize, stats); 79362306a36Sopenharmony_ci if (tmpstat < 0) { 79462306a36Sopenharmony_ci brelse(*bh); 79562306a36Sopenharmony_ci *bh = NULL; 79662306a36Sopenharmony_ci } 79762306a36Sopenharmony_ci if (tmpstat != -EAGAIN) { 79862306a36Sopenharmony_ci status = tmpstat; 79962306a36Sopenharmony_ci break; 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci } 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cibail: 80462306a36Sopenharmony_ci return status; 80562306a36Sopenharmony_ci} 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_cistatic int ocfs2_verify_heartbeat(struct ocfs2_super *osb) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci u32 hb_enabled = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci if (osb->s_mount_opt & hb_enabled) { 81262306a36Sopenharmony_ci if (ocfs2_mount_local(osb)) { 81362306a36Sopenharmony_ci mlog(ML_ERROR, "Cannot heartbeat on a locally " 81462306a36Sopenharmony_ci "mounted device.\n"); 81562306a36Sopenharmony_ci return -EINVAL; 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci if (ocfs2_userspace_stack(osb)) { 81862306a36Sopenharmony_ci mlog(ML_ERROR, "Userspace stack expected, but " 81962306a36Sopenharmony_ci "o2cb heartbeat arguments passed to mount\n"); 82062306a36Sopenharmony_ci return -EINVAL; 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci if (((osb->s_mount_opt & OCFS2_MOUNT_HB_GLOBAL) && 82362306a36Sopenharmony_ci !ocfs2_cluster_o2cb_global_heartbeat(osb)) || 82462306a36Sopenharmony_ci ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) && 82562306a36Sopenharmony_ci ocfs2_cluster_o2cb_global_heartbeat(osb))) { 82662306a36Sopenharmony_ci mlog(ML_ERROR, "Mismatching o2cb heartbeat modes\n"); 82762306a36Sopenharmony_ci return -EINVAL; 82862306a36Sopenharmony_ci } 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (!(osb->s_mount_opt & hb_enabled)) { 83262306a36Sopenharmony_ci if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) && 83362306a36Sopenharmony_ci !ocfs2_userspace_stack(osb)) { 83462306a36Sopenharmony_ci mlog(ML_ERROR, "Heartbeat has to be started to mount " 83562306a36Sopenharmony_ci "a read-write clustered device.\n"); 83662306a36Sopenharmony_ci return -EINVAL; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci } 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci return 0; 84162306a36Sopenharmony_ci} 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci/* 84462306a36Sopenharmony_ci * If we're using a userspace stack, mount should have passed 84562306a36Sopenharmony_ci * a name that matches the disk. If not, mount should not 84662306a36Sopenharmony_ci * have passed a stack. 84762306a36Sopenharmony_ci */ 84862306a36Sopenharmony_cistatic int ocfs2_verify_userspace_stack(struct ocfs2_super *osb, 84962306a36Sopenharmony_ci struct mount_options *mopt) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci if (!ocfs2_userspace_stack(osb) && mopt->cluster_stack[0]) { 85262306a36Sopenharmony_ci mlog(ML_ERROR, 85362306a36Sopenharmony_ci "cluster stack passed to mount, but this filesystem " 85462306a36Sopenharmony_ci "does not support it\n"); 85562306a36Sopenharmony_ci return -EINVAL; 85662306a36Sopenharmony_ci } 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci if (ocfs2_userspace_stack(osb) && 85962306a36Sopenharmony_ci strncmp(osb->osb_cluster_stack, mopt->cluster_stack, 86062306a36Sopenharmony_ci OCFS2_STACK_LABEL_LEN)) { 86162306a36Sopenharmony_ci mlog(ML_ERROR, 86262306a36Sopenharmony_ci "cluster stack passed to mount (\"%s\") does not " 86362306a36Sopenharmony_ci "match the filesystem (\"%s\")\n", 86462306a36Sopenharmony_ci mopt->cluster_stack, 86562306a36Sopenharmony_ci osb->osb_cluster_stack); 86662306a36Sopenharmony_ci return -EINVAL; 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci return 0; 87062306a36Sopenharmony_ci} 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_cistatic int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci int type; 87562306a36Sopenharmony_ci struct super_block *sb = osb->sb; 87662306a36Sopenharmony_ci unsigned int feature[OCFS2_MAXQUOTAS] = { 87762306a36Sopenharmony_ci OCFS2_FEATURE_RO_COMPAT_USRQUOTA, 87862306a36Sopenharmony_ci OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; 87962306a36Sopenharmony_ci int status = 0; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci for (type = 0; type < OCFS2_MAXQUOTAS; type++) { 88262306a36Sopenharmony_ci if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) 88362306a36Sopenharmony_ci continue; 88462306a36Sopenharmony_ci if (unsuspend) 88562306a36Sopenharmony_ci status = dquot_resume(sb, type); 88662306a36Sopenharmony_ci else { 88762306a36Sopenharmony_ci struct ocfs2_mem_dqinfo *oinfo; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci /* Cancel periodic syncing before suspending */ 89062306a36Sopenharmony_ci oinfo = sb_dqinfo(sb, type)->dqi_priv; 89162306a36Sopenharmony_ci cancel_delayed_work_sync(&oinfo->dqi_sync_work); 89262306a36Sopenharmony_ci status = dquot_suspend(sb, type); 89362306a36Sopenharmony_ci } 89462306a36Sopenharmony_ci if (status < 0) 89562306a36Sopenharmony_ci break; 89662306a36Sopenharmony_ci } 89762306a36Sopenharmony_ci if (status < 0) 89862306a36Sopenharmony_ci mlog(ML_ERROR, "Failed to suspend/unsuspend quotas on " 89962306a36Sopenharmony_ci "remount (error = %d).\n", status); 90062306a36Sopenharmony_ci return status; 90162306a36Sopenharmony_ci} 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_cistatic int ocfs2_enable_quotas(struct ocfs2_super *osb) 90462306a36Sopenharmony_ci{ 90562306a36Sopenharmony_ci struct inode *inode[OCFS2_MAXQUOTAS] = { NULL, NULL }; 90662306a36Sopenharmony_ci struct super_block *sb = osb->sb; 90762306a36Sopenharmony_ci unsigned int feature[OCFS2_MAXQUOTAS] = { 90862306a36Sopenharmony_ci OCFS2_FEATURE_RO_COMPAT_USRQUOTA, 90962306a36Sopenharmony_ci OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; 91062306a36Sopenharmony_ci unsigned int ino[OCFS2_MAXQUOTAS] = { 91162306a36Sopenharmony_ci LOCAL_USER_QUOTA_SYSTEM_INODE, 91262306a36Sopenharmony_ci LOCAL_GROUP_QUOTA_SYSTEM_INODE }; 91362306a36Sopenharmony_ci int status; 91462306a36Sopenharmony_ci int type; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NEGATIVE_USAGE; 91762306a36Sopenharmony_ci for (type = 0; type < OCFS2_MAXQUOTAS; type++) { 91862306a36Sopenharmony_ci if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) 91962306a36Sopenharmony_ci continue; 92062306a36Sopenharmony_ci inode[type] = ocfs2_get_system_file_inode(osb, ino[type], 92162306a36Sopenharmony_ci osb->slot_num); 92262306a36Sopenharmony_ci if (!inode[type]) { 92362306a36Sopenharmony_ci status = -ENOENT; 92462306a36Sopenharmony_ci goto out_quota_off; 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci status = dquot_load_quota_inode(inode[type], type, QFMT_OCFS2, 92762306a36Sopenharmony_ci DQUOT_USAGE_ENABLED); 92862306a36Sopenharmony_ci if (status < 0) 92962306a36Sopenharmony_ci goto out_quota_off; 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci for (type = 0; type < OCFS2_MAXQUOTAS; type++) 93362306a36Sopenharmony_ci iput(inode[type]); 93462306a36Sopenharmony_ci return 0; 93562306a36Sopenharmony_ciout_quota_off: 93662306a36Sopenharmony_ci ocfs2_disable_quotas(osb); 93762306a36Sopenharmony_ci for (type = 0; type < OCFS2_MAXQUOTAS; type++) 93862306a36Sopenharmony_ci iput(inode[type]); 93962306a36Sopenharmony_ci mlog_errno(status); 94062306a36Sopenharmony_ci return status; 94162306a36Sopenharmony_ci} 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_cistatic void ocfs2_disable_quotas(struct ocfs2_super *osb) 94462306a36Sopenharmony_ci{ 94562306a36Sopenharmony_ci int type; 94662306a36Sopenharmony_ci struct inode *inode; 94762306a36Sopenharmony_ci struct super_block *sb = osb->sb; 94862306a36Sopenharmony_ci struct ocfs2_mem_dqinfo *oinfo; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci /* We mostly ignore errors in this function because there's not much 95162306a36Sopenharmony_ci * we can do when we see them */ 95262306a36Sopenharmony_ci for (type = 0; type < OCFS2_MAXQUOTAS; type++) { 95362306a36Sopenharmony_ci if (!sb_has_quota_loaded(sb, type)) 95462306a36Sopenharmony_ci continue; 95562306a36Sopenharmony_ci if (!sb_has_quota_suspended(sb, type)) { 95662306a36Sopenharmony_ci oinfo = sb_dqinfo(sb, type)->dqi_priv; 95762306a36Sopenharmony_ci cancel_delayed_work_sync(&oinfo->dqi_sync_work); 95862306a36Sopenharmony_ci } 95962306a36Sopenharmony_ci inode = igrab(sb->s_dquot.files[type]); 96062306a36Sopenharmony_ci /* Turn off quotas. This will remove all dquot structures from 96162306a36Sopenharmony_ci * memory and so they will be automatically synced to global 96262306a36Sopenharmony_ci * quota files */ 96362306a36Sopenharmony_ci dquot_disable(sb, type, DQUOT_USAGE_ENABLED | 96462306a36Sopenharmony_ci DQUOT_LIMITS_ENABLED); 96562306a36Sopenharmony_ci iput(inode); 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci} 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_cistatic int ocfs2_fill_super(struct super_block *sb, void *data, int silent) 97062306a36Sopenharmony_ci{ 97162306a36Sopenharmony_ci struct dentry *root; 97262306a36Sopenharmony_ci int status, sector_size; 97362306a36Sopenharmony_ci struct mount_options parsed_options; 97462306a36Sopenharmony_ci struct inode *inode = NULL; 97562306a36Sopenharmony_ci struct ocfs2_super *osb = NULL; 97662306a36Sopenharmony_ci struct buffer_head *bh = NULL; 97762306a36Sopenharmony_ci char nodestr[12]; 97862306a36Sopenharmony_ci struct ocfs2_blockcheck_stats stats; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci trace_ocfs2_fill_super(sb, data, silent); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) { 98362306a36Sopenharmony_ci status = -EINVAL; 98462306a36Sopenharmony_ci goto out; 98562306a36Sopenharmony_ci } 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci /* probe for superblock */ 98862306a36Sopenharmony_ci status = ocfs2_sb_probe(sb, &bh, §or_size, &stats); 98962306a36Sopenharmony_ci if (status < 0) { 99062306a36Sopenharmony_ci mlog(ML_ERROR, "superblock probe failed!\n"); 99162306a36Sopenharmony_ci goto out; 99262306a36Sopenharmony_ci } 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci status = ocfs2_initialize_super(sb, bh, sector_size, &stats); 99562306a36Sopenharmony_ci brelse(bh); 99662306a36Sopenharmony_ci bh = NULL; 99762306a36Sopenharmony_ci if (status < 0) 99862306a36Sopenharmony_ci goto out; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci osb = OCFS2_SB(sb); 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci if (!ocfs2_check_set_options(sb, &parsed_options)) { 100362306a36Sopenharmony_ci status = -EINVAL; 100462306a36Sopenharmony_ci goto out_super; 100562306a36Sopenharmony_ci } 100662306a36Sopenharmony_ci osb->s_mount_opt = parsed_options.mount_opt; 100762306a36Sopenharmony_ci osb->s_atime_quantum = parsed_options.atime_quantum; 100862306a36Sopenharmony_ci osb->preferred_slot = parsed_options.slot; 100962306a36Sopenharmony_ci osb->osb_commit_interval = parsed_options.commit_interval; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci ocfs2_la_set_sizes(osb, parsed_options.localalloc_opt); 101262306a36Sopenharmony_ci osb->osb_resv_level = parsed_options.resv_level; 101362306a36Sopenharmony_ci osb->osb_dir_resv_level = parsed_options.resv_level; 101462306a36Sopenharmony_ci if (parsed_options.dir_resv_level == -1) 101562306a36Sopenharmony_ci osb->osb_dir_resv_level = parsed_options.resv_level; 101662306a36Sopenharmony_ci else 101762306a36Sopenharmony_ci osb->osb_dir_resv_level = parsed_options.dir_resv_level; 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci status = ocfs2_verify_userspace_stack(osb, &parsed_options); 102062306a36Sopenharmony_ci if (status) 102162306a36Sopenharmony_ci goto out_super; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci sb->s_magic = OCFS2_SUPER_MAGIC; 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci sb->s_flags = (sb->s_flags & ~(SB_POSIXACL | SB_NOSEC)) | 102662306a36Sopenharmony_ci ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) ? SB_POSIXACL : 0); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci /* Hard readonly mode only if: bdev_read_only, SB_RDONLY, 102962306a36Sopenharmony_ci * heartbeat=none */ 103062306a36Sopenharmony_ci if (bdev_read_only(sb->s_bdev)) { 103162306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 103262306a36Sopenharmony_ci status = -EACCES; 103362306a36Sopenharmony_ci mlog(ML_ERROR, "Readonly device detected but readonly " 103462306a36Sopenharmony_ci "mount was not specified.\n"); 103562306a36Sopenharmony_ci goto out_super; 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci /* You should not be able to start a local heartbeat 103962306a36Sopenharmony_ci * on a readonly device. */ 104062306a36Sopenharmony_ci if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { 104162306a36Sopenharmony_ci status = -EROFS; 104262306a36Sopenharmony_ci mlog(ML_ERROR, "Local heartbeat specified on readonly " 104362306a36Sopenharmony_ci "device.\n"); 104462306a36Sopenharmony_ci goto out_super; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci status = ocfs2_check_journals_nolocks(osb); 104862306a36Sopenharmony_ci if (status < 0) { 104962306a36Sopenharmony_ci if (status == -EROFS) 105062306a36Sopenharmony_ci mlog(ML_ERROR, "Recovery required on readonly " 105162306a36Sopenharmony_ci "file system, but write access is " 105262306a36Sopenharmony_ci "unavailable.\n"); 105362306a36Sopenharmony_ci goto out_super; 105462306a36Sopenharmony_ci } 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci ocfs2_set_ro_flag(osb, 1); 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci printk(KERN_NOTICE "ocfs2: Readonly device (%s) detected. " 105962306a36Sopenharmony_ci "Cluster services will not be used for this mount. " 106062306a36Sopenharmony_ci "Recovery will be skipped.\n", osb->dev_str); 106162306a36Sopenharmony_ci } 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci if (!ocfs2_is_hard_readonly(osb)) { 106462306a36Sopenharmony_ci if (sb_rdonly(sb)) 106562306a36Sopenharmony_ci ocfs2_set_ro_flag(osb, 0); 106662306a36Sopenharmony_ci } 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci status = ocfs2_verify_heartbeat(osb); 106962306a36Sopenharmony_ci if (status < 0) 107062306a36Sopenharmony_ci goto out_super; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci osb->osb_debug_root = debugfs_create_dir(osb->uuid_str, 107362306a36Sopenharmony_ci ocfs2_debugfs_root); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci debugfs_create_file("fs_state", S_IFREG|S_IRUSR, osb->osb_debug_root, 107662306a36Sopenharmony_ci osb, &ocfs2_osb_debug_fops); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci if (ocfs2_meta_ecc(osb)) 107962306a36Sopenharmony_ci ocfs2_blockcheck_stats_debugfs_install( &osb->osb_ecc_stats, 108062306a36Sopenharmony_ci osb->osb_debug_root); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci status = ocfs2_mount_volume(sb); 108362306a36Sopenharmony_ci if (status < 0) 108462306a36Sopenharmony_ci goto out_debugfs; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci if (osb->root_inode) 108762306a36Sopenharmony_ci inode = igrab(osb->root_inode); 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci if (!inode) { 109062306a36Sopenharmony_ci status = -EIO; 109162306a36Sopenharmony_ci goto out_dismount; 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci osb->osb_dev_kset = kset_create_and_add(sb->s_id, NULL, 109562306a36Sopenharmony_ci &ocfs2_kset->kobj); 109662306a36Sopenharmony_ci if (!osb->osb_dev_kset) { 109762306a36Sopenharmony_ci status = -ENOMEM; 109862306a36Sopenharmony_ci mlog(ML_ERROR, "Unable to create device kset %s.\n", sb->s_id); 109962306a36Sopenharmony_ci goto out_dismount; 110062306a36Sopenharmony_ci } 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci /* Create filecheck sysfs related directories/files at 110362306a36Sopenharmony_ci * /sys/fs/ocfs2/<devname>/filecheck */ 110462306a36Sopenharmony_ci if (ocfs2_filecheck_create_sysfs(osb)) { 110562306a36Sopenharmony_ci status = -ENOMEM; 110662306a36Sopenharmony_ci mlog(ML_ERROR, "Unable to create filecheck sysfs directory at " 110762306a36Sopenharmony_ci "/sys/fs/ocfs2/%s/filecheck.\n", sb->s_id); 110862306a36Sopenharmony_ci goto out_dismount; 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci root = d_make_root(inode); 111262306a36Sopenharmony_ci if (!root) { 111362306a36Sopenharmony_ci status = -ENOMEM; 111462306a36Sopenharmony_ci goto out_dismount; 111562306a36Sopenharmony_ci } 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci sb->s_root = root; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci ocfs2_complete_mount_recovery(osb); 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci if (ocfs2_mount_local(osb)) 112262306a36Sopenharmony_ci snprintf(nodestr, sizeof(nodestr), "local"); 112362306a36Sopenharmony_ci else 112462306a36Sopenharmony_ci snprintf(nodestr, sizeof(nodestr), "%u", osb->node_num); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %s, slot %d) " 112762306a36Sopenharmony_ci "with %s data mode.\n", 112862306a36Sopenharmony_ci osb->dev_str, nodestr, osb->slot_num, 112962306a36Sopenharmony_ci osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK ? "writeback" : 113062306a36Sopenharmony_ci "ordered"); 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci atomic_set(&osb->vol_state, VOLUME_MOUNTED); 113362306a36Sopenharmony_ci wake_up(&osb->osb_mount_event); 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci /* Now we can initialize quotas because we can afford to wait 113662306a36Sopenharmony_ci * for cluster locks recovery now. That also means that truncation 113762306a36Sopenharmony_ci * log recovery can happen but that waits for proper quota setup */ 113862306a36Sopenharmony_ci if (!sb_rdonly(sb)) { 113962306a36Sopenharmony_ci status = ocfs2_enable_quotas(osb); 114062306a36Sopenharmony_ci if (status < 0) { 114162306a36Sopenharmony_ci /* We have to err-out specially here because 114262306a36Sopenharmony_ci * s_root is already set */ 114362306a36Sopenharmony_ci mlog_errno(status); 114462306a36Sopenharmony_ci atomic_set(&osb->vol_state, VOLUME_DISABLED); 114562306a36Sopenharmony_ci wake_up(&osb->osb_mount_event); 114662306a36Sopenharmony_ci return status; 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci } 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci ocfs2_complete_quota_recovery(osb); 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci /* Now we wake up again for processes waiting for quotas */ 115362306a36Sopenharmony_ci atomic_set(&osb->vol_state, VOLUME_MOUNTED_QUOTAS); 115462306a36Sopenharmony_ci wake_up(&osb->osb_mount_event); 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci /* Start this when the mount is almost sure of being successful */ 115762306a36Sopenharmony_ci ocfs2_orphan_scan_start(osb); 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci return status; 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ciout_dismount: 116262306a36Sopenharmony_ci atomic_set(&osb->vol_state, VOLUME_DISABLED); 116362306a36Sopenharmony_ci wake_up(&osb->osb_mount_event); 116462306a36Sopenharmony_ci ocfs2_free_replay_slots(osb); 116562306a36Sopenharmony_ci ocfs2_dismount_volume(sb, 1); 116662306a36Sopenharmony_ci goto out; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ciout_debugfs: 116962306a36Sopenharmony_ci debugfs_remove_recursive(osb->osb_debug_root); 117062306a36Sopenharmony_ciout_super: 117162306a36Sopenharmony_ci ocfs2_release_system_inodes(osb); 117262306a36Sopenharmony_ci kfree(osb->recovery_map); 117362306a36Sopenharmony_ci ocfs2_delete_osb(osb); 117462306a36Sopenharmony_ci kfree(osb); 117562306a36Sopenharmony_ciout: 117662306a36Sopenharmony_ci mlog_errno(status); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci return status; 117962306a36Sopenharmony_ci} 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_cistatic struct dentry *ocfs2_mount(struct file_system_type *fs_type, 118262306a36Sopenharmony_ci int flags, 118362306a36Sopenharmony_ci const char *dev_name, 118462306a36Sopenharmony_ci void *data) 118562306a36Sopenharmony_ci{ 118662306a36Sopenharmony_ci return mount_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super); 118762306a36Sopenharmony_ci} 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_cistatic struct file_system_type ocfs2_fs_type = { 119062306a36Sopenharmony_ci .owner = THIS_MODULE, 119162306a36Sopenharmony_ci .name = "ocfs2", 119262306a36Sopenharmony_ci .mount = ocfs2_mount, 119362306a36Sopenharmony_ci .kill_sb = kill_block_super, 119462306a36Sopenharmony_ci .fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE, 119562306a36Sopenharmony_ci .next = NULL 119662306a36Sopenharmony_ci}; 119762306a36Sopenharmony_ciMODULE_ALIAS_FS("ocfs2"); 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_cistatic int ocfs2_check_set_options(struct super_block *sb, 120062306a36Sopenharmony_ci struct mount_options *options) 120162306a36Sopenharmony_ci{ 120262306a36Sopenharmony_ci if (options->mount_opt & OCFS2_MOUNT_USRQUOTA && 120362306a36Sopenharmony_ci !OCFS2_HAS_RO_COMPAT_FEATURE(sb, 120462306a36Sopenharmony_ci OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) { 120562306a36Sopenharmony_ci mlog(ML_ERROR, "User quotas were requested, but this " 120662306a36Sopenharmony_ci "filesystem does not have the feature enabled.\n"); 120762306a36Sopenharmony_ci return 0; 120862306a36Sopenharmony_ci } 120962306a36Sopenharmony_ci if (options->mount_opt & OCFS2_MOUNT_GRPQUOTA && 121062306a36Sopenharmony_ci !OCFS2_HAS_RO_COMPAT_FEATURE(sb, 121162306a36Sopenharmony_ci OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) { 121262306a36Sopenharmony_ci mlog(ML_ERROR, "Group quotas were requested, but this " 121362306a36Sopenharmony_ci "filesystem does not have the feature enabled.\n"); 121462306a36Sopenharmony_ci return 0; 121562306a36Sopenharmony_ci } 121662306a36Sopenharmony_ci if (options->mount_opt & OCFS2_MOUNT_POSIX_ACL && 121762306a36Sopenharmony_ci !OCFS2_HAS_INCOMPAT_FEATURE(sb, OCFS2_FEATURE_INCOMPAT_XATTR)) { 121862306a36Sopenharmony_ci mlog(ML_ERROR, "ACL support requested but extended attributes " 121962306a36Sopenharmony_ci "feature is not enabled\n"); 122062306a36Sopenharmony_ci return 0; 122162306a36Sopenharmony_ci } 122262306a36Sopenharmony_ci /* No ACL setting specified? Use XATTR feature... */ 122362306a36Sopenharmony_ci if (!(options->mount_opt & (OCFS2_MOUNT_POSIX_ACL | 122462306a36Sopenharmony_ci OCFS2_MOUNT_NO_POSIX_ACL))) { 122562306a36Sopenharmony_ci if (OCFS2_HAS_INCOMPAT_FEATURE(sb, OCFS2_FEATURE_INCOMPAT_XATTR)) 122662306a36Sopenharmony_ci options->mount_opt |= OCFS2_MOUNT_POSIX_ACL; 122762306a36Sopenharmony_ci else 122862306a36Sopenharmony_ci options->mount_opt |= OCFS2_MOUNT_NO_POSIX_ACL; 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci return 1; 123162306a36Sopenharmony_ci} 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_cistatic int ocfs2_parse_options(struct super_block *sb, 123462306a36Sopenharmony_ci char *options, 123562306a36Sopenharmony_ci struct mount_options *mopt, 123662306a36Sopenharmony_ci int is_remount) 123762306a36Sopenharmony_ci{ 123862306a36Sopenharmony_ci int status, user_stack = 0; 123962306a36Sopenharmony_ci char *p; 124062306a36Sopenharmony_ci u32 tmp; 124162306a36Sopenharmony_ci int token, option; 124262306a36Sopenharmony_ci substring_t args[MAX_OPT_ARGS]; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci trace_ocfs2_parse_options(is_remount, options ? options : "(none)"); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci mopt->commit_interval = 0; 124762306a36Sopenharmony_ci mopt->mount_opt = OCFS2_MOUNT_NOINTR; 124862306a36Sopenharmony_ci mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; 124962306a36Sopenharmony_ci mopt->slot = OCFS2_INVALID_SLOT; 125062306a36Sopenharmony_ci mopt->localalloc_opt = -1; 125162306a36Sopenharmony_ci mopt->cluster_stack[0] = '\0'; 125262306a36Sopenharmony_ci mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL; 125362306a36Sopenharmony_ci mopt->dir_resv_level = -1; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci if (!options) { 125662306a36Sopenharmony_ci status = 1; 125762306a36Sopenharmony_ci goto bail; 125862306a36Sopenharmony_ci } 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci while ((p = strsep(&options, ",")) != NULL) { 126162306a36Sopenharmony_ci if (!*p) 126262306a36Sopenharmony_ci continue; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci token = match_token(p, tokens, args); 126562306a36Sopenharmony_ci switch (token) { 126662306a36Sopenharmony_ci case Opt_hb_local: 126762306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL; 126862306a36Sopenharmony_ci break; 126962306a36Sopenharmony_ci case Opt_hb_none: 127062306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_HB_NONE; 127162306a36Sopenharmony_ci break; 127262306a36Sopenharmony_ci case Opt_hb_global: 127362306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_HB_GLOBAL; 127462306a36Sopenharmony_ci break; 127562306a36Sopenharmony_ci case Opt_barrier: 127662306a36Sopenharmony_ci if (match_int(&args[0], &option)) { 127762306a36Sopenharmony_ci status = 0; 127862306a36Sopenharmony_ci goto bail; 127962306a36Sopenharmony_ci } 128062306a36Sopenharmony_ci if (option) 128162306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_BARRIER; 128262306a36Sopenharmony_ci else 128362306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_BARRIER; 128462306a36Sopenharmony_ci break; 128562306a36Sopenharmony_ci case Opt_intr: 128662306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_NOINTR; 128762306a36Sopenharmony_ci break; 128862306a36Sopenharmony_ci case Opt_nointr: 128962306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_NOINTR; 129062306a36Sopenharmony_ci break; 129162306a36Sopenharmony_ci case Opt_err_panic: 129262306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_CONT; 129362306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_ROFS; 129462306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_ERRORS_PANIC; 129562306a36Sopenharmony_ci break; 129662306a36Sopenharmony_ci case Opt_err_ro: 129762306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_CONT; 129862306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_PANIC; 129962306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_ERRORS_ROFS; 130062306a36Sopenharmony_ci break; 130162306a36Sopenharmony_ci case Opt_err_cont: 130262306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_ROFS; 130362306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_PANIC; 130462306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_ERRORS_CONT; 130562306a36Sopenharmony_ci break; 130662306a36Sopenharmony_ci case Opt_data_ordered: 130762306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_DATA_WRITEBACK; 130862306a36Sopenharmony_ci break; 130962306a36Sopenharmony_ci case Opt_data_writeback: 131062306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_DATA_WRITEBACK; 131162306a36Sopenharmony_ci break; 131262306a36Sopenharmony_ci case Opt_user_xattr: 131362306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_NOUSERXATTR; 131462306a36Sopenharmony_ci break; 131562306a36Sopenharmony_ci case Opt_nouser_xattr: 131662306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_NOUSERXATTR; 131762306a36Sopenharmony_ci break; 131862306a36Sopenharmony_ci case Opt_atime_quantum: 131962306a36Sopenharmony_ci if (match_int(&args[0], &option)) { 132062306a36Sopenharmony_ci status = 0; 132162306a36Sopenharmony_ci goto bail; 132262306a36Sopenharmony_ci } 132362306a36Sopenharmony_ci if (option >= 0) 132462306a36Sopenharmony_ci mopt->atime_quantum = option; 132562306a36Sopenharmony_ci break; 132662306a36Sopenharmony_ci case Opt_slot: 132762306a36Sopenharmony_ci if (match_int(&args[0], &option)) { 132862306a36Sopenharmony_ci status = 0; 132962306a36Sopenharmony_ci goto bail; 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci if (option) 133262306a36Sopenharmony_ci mopt->slot = (u16)option; 133362306a36Sopenharmony_ci break; 133462306a36Sopenharmony_ci case Opt_commit: 133562306a36Sopenharmony_ci if (match_int(&args[0], &option)) { 133662306a36Sopenharmony_ci status = 0; 133762306a36Sopenharmony_ci goto bail; 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci if (option < 0) 134062306a36Sopenharmony_ci return 0; 134162306a36Sopenharmony_ci if (option == 0) 134262306a36Sopenharmony_ci option = JBD2_DEFAULT_MAX_COMMIT_AGE; 134362306a36Sopenharmony_ci mopt->commit_interval = HZ * option; 134462306a36Sopenharmony_ci break; 134562306a36Sopenharmony_ci case Opt_localalloc: 134662306a36Sopenharmony_ci if (match_int(&args[0], &option)) { 134762306a36Sopenharmony_ci status = 0; 134862306a36Sopenharmony_ci goto bail; 134962306a36Sopenharmony_ci } 135062306a36Sopenharmony_ci if (option >= 0) 135162306a36Sopenharmony_ci mopt->localalloc_opt = option; 135262306a36Sopenharmony_ci break; 135362306a36Sopenharmony_ci case Opt_localflocks: 135462306a36Sopenharmony_ci /* 135562306a36Sopenharmony_ci * Changing this during remount could race 135662306a36Sopenharmony_ci * flock() requests, or "unbalance" existing 135762306a36Sopenharmony_ci * ones (e.g., a lock is taken in one mode but 135862306a36Sopenharmony_ci * dropped in the other). If users care enough 135962306a36Sopenharmony_ci * to flip locking modes during remount, we 136062306a36Sopenharmony_ci * could add a "local" flag to individual 136162306a36Sopenharmony_ci * flock structures for proper tracking of 136262306a36Sopenharmony_ci * state. 136362306a36Sopenharmony_ci */ 136462306a36Sopenharmony_ci if (!is_remount) 136562306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_LOCALFLOCKS; 136662306a36Sopenharmony_ci break; 136762306a36Sopenharmony_ci case Opt_stack: 136862306a36Sopenharmony_ci /* Check both that the option we were passed 136962306a36Sopenharmony_ci * is of the right length and that it is a proper 137062306a36Sopenharmony_ci * string of the right length. 137162306a36Sopenharmony_ci */ 137262306a36Sopenharmony_ci if (((args[0].to - args[0].from) != 137362306a36Sopenharmony_ci OCFS2_STACK_LABEL_LEN) || 137462306a36Sopenharmony_ci (strnlen(args[0].from, 137562306a36Sopenharmony_ci OCFS2_STACK_LABEL_LEN) != 137662306a36Sopenharmony_ci OCFS2_STACK_LABEL_LEN)) { 137762306a36Sopenharmony_ci mlog(ML_ERROR, 137862306a36Sopenharmony_ci "Invalid cluster_stack option\n"); 137962306a36Sopenharmony_ci status = 0; 138062306a36Sopenharmony_ci goto bail; 138162306a36Sopenharmony_ci } 138262306a36Sopenharmony_ci memcpy(mopt->cluster_stack, args[0].from, 138362306a36Sopenharmony_ci OCFS2_STACK_LABEL_LEN); 138462306a36Sopenharmony_ci mopt->cluster_stack[OCFS2_STACK_LABEL_LEN] = '\0'; 138562306a36Sopenharmony_ci /* 138662306a36Sopenharmony_ci * Open code the memcmp here as we don't have 138762306a36Sopenharmony_ci * an osb to pass to 138862306a36Sopenharmony_ci * ocfs2_userspace_stack(). 138962306a36Sopenharmony_ci */ 139062306a36Sopenharmony_ci if (memcmp(mopt->cluster_stack, 139162306a36Sopenharmony_ci OCFS2_CLASSIC_CLUSTER_STACK, 139262306a36Sopenharmony_ci OCFS2_STACK_LABEL_LEN)) 139362306a36Sopenharmony_ci user_stack = 1; 139462306a36Sopenharmony_ci break; 139562306a36Sopenharmony_ci case Opt_inode64: 139662306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_INODE64; 139762306a36Sopenharmony_ci break; 139862306a36Sopenharmony_ci case Opt_usrquota: 139962306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_USRQUOTA; 140062306a36Sopenharmony_ci break; 140162306a36Sopenharmony_ci case Opt_grpquota: 140262306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA; 140362306a36Sopenharmony_ci break; 140462306a36Sopenharmony_ci case Opt_coherency_buffered: 140562306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_COHERENCY_BUFFERED; 140662306a36Sopenharmony_ci break; 140762306a36Sopenharmony_ci case Opt_coherency_full: 140862306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_COHERENCY_BUFFERED; 140962306a36Sopenharmony_ci break; 141062306a36Sopenharmony_ci case Opt_acl: 141162306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL; 141262306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL; 141362306a36Sopenharmony_ci break; 141462306a36Sopenharmony_ci case Opt_noacl: 141562306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_NO_POSIX_ACL; 141662306a36Sopenharmony_ci mopt->mount_opt &= ~OCFS2_MOUNT_POSIX_ACL; 141762306a36Sopenharmony_ci break; 141862306a36Sopenharmony_ci case Opt_resv_level: 141962306a36Sopenharmony_ci if (is_remount) 142062306a36Sopenharmony_ci break; 142162306a36Sopenharmony_ci if (match_int(&args[0], &option)) { 142262306a36Sopenharmony_ci status = 0; 142362306a36Sopenharmony_ci goto bail; 142462306a36Sopenharmony_ci } 142562306a36Sopenharmony_ci if (option >= OCFS2_MIN_RESV_LEVEL && 142662306a36Sopenharmony_ci option < OCFS2_MAX_RESV_LEVEL) 142762306a36Sopenharmony_ci mopt->resv_level = option; 142862306a36Sopenharmony_ci break; 142962306a36Sopenharmony_ci case Opt_dir_resv_level: 143062306a36Sopenharmony_ci if (is_remount) 143162306a36Sopenharmony_ci break; 143262306a36Sopenharmony_ci if (match_int(&args[0], &option)) { 143362306a36Sopenharmony_ci status = 0; 143462306a36Sopenharmony_ci goto bail; 143562306a36Sopenharmony_ci } 143662306a36Sopenharmony_ci if (option >= OCFS2_MIN_RESV_LEVEL && 143762306a36Sopenharmony_ci option < OCFS2_MAX_RESV_LEVEL) 143862306a36Sopenharmony_ci mopt->dir_resv_level = option; 143962306a36Sopenharmony_ci break; 144062306a36Sopenharmony_ci case Opt_journal_async_commit: 144162306a36Sopenharmony_ci mopt->mount_opt |= OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT; 144262306a36Sopenharmony_ci break; 144362306a36Sopenharmony_ci default: 144462306a36Sopenharmony_ci mlog(ML_ERROR, 144562306a36Sopenharmony_ci "Unrecognized mount option \"%s\" " 144662306a36Sopenharmony_ci "or missing value\n", p); 144762306a36Sopenharmony_ci status = 0; 144862306a36Sopenharmony_ci goto bail; 144962306a36Sopenharmony_ci } 145062306a36Sopenharmony_ci } 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci if (user_stack == 0) { 145362306a36Sopenharmony_ci /* Ensure only one heartbeat mode */ 145462306a36Sopenharmony_ci tmp = mopt->mount_opt & (OCFS2_MOUNT_HB_LOCAL | 145562306a36Sopenharmony_ci OCFS2_MOUNT_HB_GLOBAL | 145662306a36Sopenharmony_ci OCFS2_MOUNT_HB_NONE); 145762306a36Sopenharmony_ci if (hweight32(tmp) != 1) { 145862306a36Sopenharmony_ci mlog(ML_ERROR, "Invalid heartbeat mount options\n"); 145962306a36Sopenharmony_ci status = 0; 146062306a36Sopenharmony_ci goto bail; 146162306a36Sopenharmony_ci } 146262306a36Sopenharmony_ci } 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci status = 1; 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_cibail: 146762306a36Sopenharmony_ci return status; 146862306a36Sopenharmony_ci} 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_cistatic int ocfs2_show_options(struct seq_file *s, struct dentry *root) 147162306a36Sopenharmony_ci{ 147262306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(root->d_sb); 147362306a36Sopenharmony_ci unsigned long opts = osb->s_mount_opt; 147462306a36Sopenharmony_ci unsigned int local_alloc_megs; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci if (opts & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL)) { 147762306a36Sopenharmony_ci seq_printf(s, ",_netdev"); 147862306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_HB_LOCAL) 147962306a36Sopenharmony_ci seq_printf(s, ",%s", OCFS2_HB_LOCAL); 148062306a36Sopenharmony_ci else 148162306a36Sopenharmony_ci seq_printf(s, ",%s", OCFS2_HB_GLOBAL); 148262306a36Sopenharmony_ci } else 148362306a36Sopenharmony_ci seq_printf(s, ",%s", OCFS2_HB_NONE); 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_NOINTR) 148662306a36Sopenharmony_ci seq_printf(s, ",nointr"); 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_DATA_WRITEBACK) 148962306a36Sopenharmony_ci seq_printf(s, ",data=writeback"); 149062306a36Sopenharmony_ci else 149162306a36Sopenharmony_ci seq_printf(s, ",data=ordered"); 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_BARRIER) 149462306a36Sopenharmony_ci seq_printf(s, ",barrier=1"); 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_ERRORS_PANIC) 149762306a36Sopenharmony_ci seq_printf(s, ",errors=panic"); 149862306a36Sopenharmony_ci else if (opts & OCFS2_MOUNT_ERRORS_CONT) 149962306a36Sopenharmony_ci seq_printf(s, ",errors=continue"); 150062306a36Sopenharmony_ci else 150162306a36Sopenharmony_ci seq_printf(s, ",errors=remount-ro"); 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci if (osb->preferred_slot != OCFS2_INVALID_SLOT) 150462306a36Sopenharmony_ci seq_printf(s, ",preferred_slot=%d", osb->preferred_slot); 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci seq_printf(s, ",atime_quantum=%u", osb->s_atime_quantum); 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci if (osb->osb_commit_interval) 150962306a36Sopenharmony_ci seq_printf(s, ",commit=%u", 151062306a36Sopenharmony_ci (unsigned) (osb->osb_commit_interval / HZ)); 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci local_alloc_megs = osb->local_alloc_bits >> (20 - osb->s_clustersize_bits); 151362306a36Sopenharmony_ci if (local_alloc_megs != ocfs2_la_default_mb(osb)) 151462306a36Sopenharmony_ci seq_printf(s, ",localalloc=%d", local_alloc_megs); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_LOCALFLOCKS) 151762306a36Sopenharmony_ci seq_printf(s, ",localflocks,"); 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci if (osb->osb_cluster_stack[0]) 152062306a36Sopenharmony_ci seq_show_option(s, "cluster_stack", osb->osb_cluster_stack); 152162306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_USRQUOTA) 152262306a36Sopenharmony_ci seq_printf(s, ",usrquota"); 152362306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_GRPQUOTA) 152462306a36Sopenharmony_ci seq_printf(s, ",grpquota"); 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_COHERENCY_BUFFERED) 152762306a36Sopenharmony_ci seq_printf(s, ",coherency=buffered"); 152862306a36Sopenharmony_ci else 152962306a36Sopenharmony_ci seq_printf(s, ",coherency=full"); 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_NOUSERXATTR) 153262306a36Sopenharmony_ci seq_printf(s, ",nouser_xattr"); 153362306a36Sopenharmony_ci else 153462306a36Sopenharmony_ci seq_printf(s, ",user_xattr"); 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_INODE64) 153762306a36Sopenharmony_ci seq_printf(s, ",inode64"); 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_POSIX_ACL) 154062306a36Sopenharmony_ci seq_printf(s, ",acl"); 154162306a36Sopenharmony_ci else 154262306a36Sopenharmony_ci seq_printf(s, ",noacl"); 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci if (osb->osb_resv_level != OCFS2_DEFAULT_RESV_LEVEL) 154562306a36Sopenharmony_ci seq_printf(s, ",resv_level=%d", osb->osb_resv_level); 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci if (osb->osb_dir_resv_level != osb->osb_resv_level) 154862306a36Sopenharmony_ci seq_printf(s, ",dir_resv_level=%d", osb->osb_resv_level); 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci if (opts & OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT) 155162306a36Sopenharmony_ci seq_printf(s, ",journal_async_commit"); 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci return 0; 155462306a36Sopenharmony_ci} 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_cistatic int __init ocfs2_init(void) 155762306a36Sopenharmony_ci{ 155862306a36Sopenharmony_ci int status; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci status = init_ocfs2_uptodate_cache(); 156162306a36Sopenharmony_ci if (status < 0) 156262306a36Sopenharmony_ci goto out1; 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci status = ocfs2_initialize_mem_caches(); 156562306a36Sopenharmony_ci if (status < 0) 156662306a36Sopenharmony_ci goto out2; 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL); 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci ocfs2_set_locking_protocol(); 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci status = register_quota_format(&ocfs2_quota_format); 157362306a36Sopenharmony_ci if (status < 0) 157462306a36Sopenharmony_ci goto out3; 157562306a36Sopenharmony_ci status = register_filesystem(&ocfs2_fs_type); 157662306a36Sopenharmony_ci if (!status) 157762306a36Sopenharmony_ci return 0; 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci unregister_quota_format(&ocfs2_quota_format); 158062306a36Sopenharmony_ciout3: 158162306a36Sopenharmony_ci debugfs_remove(ocfs2_debugfs_root); 158262306a36Sopenharmony_ci ocfs2_free_mem_caches(); 158362306a36Sopenharmony_ciout2: 158462306a36Sopenharmony_ci exit_ocfs2_uptodate_cache(); 158562306a36Sopenharmony_ciout1: 158662306a36Sopenharmony_ci mlog_errno(status); 158762306a36Sopenharmony_ci return status; 158862306a36Sopenharmony_ci} 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_cistatic void __exit ocfs2_exit(void) 159162306a36Sopenharmony_ci{ 159262306a36Sopenharmony_ci unregister_quota_format(&ocfs2_quota_format); 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci debugfs_remove(ocfs2_debugfs_root); 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci ocfs2_free_mem_caches(); 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci unregister_filesystem(&ocfs2_fs_type); 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci exit_ocfs2_uptodate_cache(); 160162306a36Sopenharmony_ci} 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_cistatic void ocfs2_put_super(struct super_block *sb) 160462306a36Sopenharmony_ci{ 160562306a36Sopenharmony_ci trace_ocfs2_put_super(sb); 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci ocfs2_sync_blockdev(sb); 160862306a36Sopenharmony_ci ocfs2_dismount_volume(sb, 0); 160962306a36Sopenharmony_ci} 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_cistatic int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) 161262306a36Sopenharmony_ci{ 161362306a36Sopenharmony_ci struct ocfs2_super *osb; 161462306a36Sopenharmony_ci u32 numbits, freebits; 161562306a36Sopenharmony_ci int status; 161662306a36Sopenharmony_ci struct ocfs2_dinode *bm_lock; 161762306a36Sopenharmony_ci struct buffer_head *bh = NULL; 161862306a36Sopenharmony_ci struct inode *inode = NULL; 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci trace_ocfs2_statfs(dentry->d_sb, buf); 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci osb = OCFS2_SB(dentry->d_sb); 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci inode = ocfs2_get_system_file_inode(osb, 162562306a36Sopenharmony_ci GLOBAL_BITMAP_SYSTEM_INODE, 162662306a36Sopenharmony_ci OCFS2_INVALID_SLOT); 162762306a36Sopenharmony_ci if (!inode) { 162862306a36Sopenharmony_ci mlog(ML_ERROR, "failed to get bitmap inode\n"); 162962306a36Sopenharmony_ci status = -EIO; 163062306a36Sopenharmony_ci goto bail; 163162306a36Sopenharmony_ci } 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci status = ocfs2_inode_lock(inode, &bh, 0); 163462306a36Sopenharmony_ci if (status < 0) { 163562306a36Sopenharmony_ci mlog_errno(status); 163662306a36Sopenharmony_ci goto bail; 163762306a36Sopenharmony_ci } 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci bm_lock = (struct ocfs2_dinode *) bh->b_data; 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci numbits = le32_to_cpu(bm_lock->id1.bitmap1.i_total); 164262306a36Sopenharmony_ci freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used); 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci buf->f_type = OCFS2_SUPER_MAGIC; 164562306a36Sopenharmony_ci buf->f_bsize = dentry->d_sb->s_blocksize; 164662306a36Sopenharmony_ci buf->f_namelen = OCFS2_MAX_FILENAME_LEN; 164762306a36Sopenharmony_ci buf->f_blocks = ((sector_t) numbits) * 164862306a36Sopenharmony_ci (osb->s_clustersize >> osb->sb->s_blocksize_bits); 164962306a36Sopenharmony_ci buf->f_bfree = ((sector_t) freebits) * 165062306a36Sopenharmony_ci (osb->s_clustersize >> osb->sb->s_blocksize_bits); 165162306a36Sopenharmony_ci buf->f_bavail = buf->f_bfree; 165262306a36Sopenharmony_ci buf->f_files = numbits; 165362306a36Sopenharmony_ci buf->f_ffree = freebits; 165462306a36Sopenharmony_ci buf->f_fsid.val[0] = crc32_le(0, osb->uuid_str, OCFS2_VOL_UUID_LEN) 165562306a36Sopenharmony_ci & 0xFFFFFFFFUL; 165662306a36Sopenharmony_ci buf->f_fsid.val[1] = crc32_le(0, osb->uuid_str + OCFS2_VOL_UUID_LEN, 165762306a36Sopenharmony_ci OCFS2_VOL_UUID_LEN) & 0xFFFFFFFFUL; 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci brelse(bh); 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci ocfs2_inode_unlock(inode, 0); 166262306a36Sopenharmony_ci status = 0; 166362306a36Sopenharmony_cibail: 166462306a36Sopenharmony_ci iput(inode); 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci if (status) 166762306a36Sopenharmony_ci mlog_errno(status); 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci return status; 167062306a36Sopenharmony_ci} 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_cistatic void ocfs2_inode_init_once(void *data) 167362306a36Sopenharmony_ci{ 167462306a36Sopenharmony_ci struct ocfs2_inode_info *oi = data; 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci oi->ip_flags = 0; 167762306a36Sopenharmony_ci oi->ip_open_count = 0; 167862306a36Sopenharmony_ci spin_lock_init(&oi->ip_lock); 167962306a36Sopenharmony_ci ocfs2_extent_map_init(&oi->vfs_inode); 168062306a36Sopenharmony_ci INIT_LIST_HEAD(&oi->ip_io_markers); 168162306a36Sopenharmony_ci INIT_LIST_HEAD(&oi->ip_unwritten_list); 168262306a36Sopenharmony_ci oi->ip_dir_start_lookup = 0; 168362306a36Sopenharmony_ci init_rwsem(&oi->ip_alloc_sem); 168462306a36Sopenharmony_ci init_rwsem(&oi->ip_xattr_sem); 168562306a36Sopenharmony_ci mutex_init(&oi->ip_io_mutex); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci oi->ip_blkno = 0ULL; 168862306a36Sopenharmony_ci oi->ip_clusters = 0; 168962306a36Sopenharmony_ci oi->ip_next_orphan = NULL; 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci ocfs2_resv_init_once(&oi->ip_la_data_resv); 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci ocfs2_lock_res_init_once(&oi->ip_rw_lockres); 169462306a36Sopenharmony_ci ocfs2_lock_res_init_once(&oi->ip_inode_lockres); 169562306a36Sopenharmony_ci ocfs2_lock_res_init_once(&oi->ip_open_lockres); 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci ocfs2_metadata_cache_init(INODE_CACHE(&oi->vfs_inode), 169862306a36Sopenharmony_ci &ocfs2_inode_caching_ops); 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci inode_init_once(&oi->vfs_inode); 170162306a36Sopenharmony_ci} 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_cistatic int ocfs2_initialize_mem_caches(void) 170462306a36Sopenharmony_ci{ 170562306a36Sopenharmony_ci ocfs2_inode_cachep = kmem_cache_create("ocfs2_inode_cache", 170662306a36Sopenharmony_ci sizeof(struct ocfs2_inode_info), 170762306a36Sopenharmony_ci 0, 170862306a36Sopenharmony_ci (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| 170962306a36Sopenharmony_ci SLAB_MEM_SPREAD|SLAB_ACCOUNT), 171062306a36Sopenharmony_ci ocfs2_inode_init_once); 171162306a36Sopenharmony_ci ocfs2_dquot_cachep = kmem_cache_create("ocfs2_dquot_cache", 171262306a36Sopenharmony_ci sizeof(struct ocfs2_dquot), 171362306a36Sopenharmony_ci 0, 171462306a36Sopenharmony_ci (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| 171562306a36Sopenharmony_ci SLAB_MEM_SPREAD), 171662306a36Sopenharmony_ci NULL); 171762306a36Sopenharmony_ci ocfs2_qf_chunk_cachep = kmem_cache_create("ocfs2_qf_chunk_cache", 171862306a36Sopenharmony_ci sizeof(struct ocfs2_quota_chunk), 171962306a36Sopenharmony_ci 0, 172062306a36Sopenharmony_ci (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), 172162306a36Sopenharmony_ci NULL); 172262306a36Sopenharmony_ci if (!ocfs2_inode_cachep || !ocfs2_dquot_cachep || 172362306a36Sopenharmony_ci !ocfs2_qf_chunk_cachep) { 172462306a36Sopenharmony_ci kmem_cache_destroy(ocfs2_inode_cachep); 172562306a36Sopenharmony_ci kmem_cache_destroy(ocfs2_dquot_cachep); 172662306a36Sopenharmony_ci kmem_cache_destroy(ocfs2_qf_chunk_cachep); 172762306a36Sopenharmony_ci return -ENOMEM; 172862306a36Sopenharmony_ci } 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci return 0; 173162306a36Sopenharmony_ci} 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_cistatic void ocfs2_free_mem_caches(void) 173462306a36Sopenharmony_ci{ 173562306a36Sopenharmony_ci /* 173662306a36Sopenharmony_ci * Make sure all delayed rcu free inodes are flushed before we 173762306a36Sopenharmony_ci * destroy cache. 173862306a36Sopenharmony_ci */ 173962306a36Sopenharmony_ci rcu_barrier(); 174062306a36Sopenharmony_ci kmem_cache_destroy(ocfs2_inode_cachep); 174162306a36Sopenharmony_ci ocfs2_inode_cachep = NULL; 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci kmem_cache_destroy(ocfs2_dquot_cachep); 174462306a36Sopenharmony_ci ocfs2_dquot_cachep = NULL; 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci kmem_cache_destroy(ocfs2_qf_chunk_cachep); 174762306a36Sopenharmony_ci ocfs2_qf_chunk_cachep = NULL; 174862306a36Sopenharmony_ci} 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_cistatic int ocfs2_get_sector(struct super_block *sb, 175162306a36Sopenharmony_ci struct buffer_head **bh, 175262306a36Sopenharmony_ci int block, 175362306a36Sopenharmony_ci int sect_size) 175462306a36Sopenharmony_ci{ 175562306a36Sopenharmony_ci if (!sb_set_blocksize(sb, sect_size)) { 175662306a36Sopenharmony_ci mlog(ML_ERROR, "unable to set blocksize\n"); 175762306a36Sopenharmony_ci return -EIO; 175862306a36Sopenharmony_ci } 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci *bh = sb_getblk(sb, block); 176162306a36Sopenharmony_ci if (!*bh) { 176262306a36Sopenharmony_ci mlog_errno(-ENOMEM); 176362306a36Sopenharmony_ci return -ENOMEM; 176462306a36Sopenharmony_ci } 176562306a36Sopenharmony_ci lock_buffer(*bh); 176662306a36Sopenharmony_ci if (!buffer_dirty(*bh)) 176762306a36Sopenharmony_ci clear_buffer_uptodate(*bh); 176862306a36Sopenharmony_ci unlock_buffer(*bh); 176962306a36Sopenharmony_ci if (bh_read(*bh, 0) < 0) { 177062306a36Sopenharmony_ci mlog_errno(-EIO); 177162306a36Sopenharmony_ci brelse(*bh); 177262306a36Sopenharmony_ci *bh = NULL; 177362306a36Sopenharmony_ci return -EIO; 177462306a36Sopenharmony_ci } 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci return 0; 177762306a36Sopenharmony_ci} 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_cistatic int ocfs2_mount_volume(struct super_block *sb) 178062306a36Sopenharmony_ci{ 178162306a36Sopenharmony_ci int status = 0; 178262306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(sb); 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci if (ocfs2_is_hard_readonly(osb)) 178562306a36Sopenharmony_ci goto out; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci mutex_init(&osb->obs_trim_fs_mutex); 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_ci status = ocfs2_dlm_init(osb); 179062306a36Sopenharmony_ci if (status < 0) { 179162306a36Sopenharmony_ci mlog_errno(status); 179262306a36Sopenharmony_ci if (status == -EBADR && ocfs2_userspace_stack(osb)) 179362306a36Sopenharmony_ci mlog(ML_ERROR, "couldn't mount because cluster name on" 179462306a36Sopenharmony_ci " disk does not match the running cluster name.\n"); 179562306a36Sopenharmony_ci goto out; 179662306a36Sopenharmony_ci } 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci status = ocfs2_super_lock(osb, 1); 179962306a36Sopenharmony_ci if (status < 0) { 180062306a36Sopenharmony_ci mlog_errno(status); 180162306a36Sopenharmony_ci goto out_dlm; 180262306a36Sopenharmony_ci } 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci /* This will load up the node map and add ourselves to it. */ 180562306a36Sopenharmony_ci status = ocfs2_find_slot(osb); 180662306a36Sopenharmony_ci if (status < 0) { 180762306a36Sopenharmony_ci mlog_errno(status); 180862306a36Sopenharmony_ci goto out_super_lock; 180962306a36Sopenharmony_ci } 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci /* load all node-local system inodes */ 181262306a36Sopenharmony_ci status = ocfs2_init_local_system_inodes(osb); 181362306a36Sopenharmony_ci if (status < 0) { 181462306a36Sopenharmony_ci mlog_errno(status); 181562306a36Sopenharmony_ci goto out_super_lock; 181662306a36Sopenharmony_ci } 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci status = ocfs2_check_volume(osb); 181962306a36Sopenharmony_ci if (status < 0) { 182062306a36Sopenharmony_ci mlog_errno(status); 182162306a36Sopenharmony_ci goto out_system_inodes; 182262306a36Sopenharmony_ci } 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci status = ocfs2_truncate_log_init(osb); 182562306a36Sopenharmony_ci if (status < 0) { 182662306a36Sopenharmony_ci mlog_errno(status); 182762306a36Sopenharmony_ci goto out_check_volume; 182862306a36Sopenharmony_ci } 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci ocfs2_super_unlock(osb, 1); 183162306a36Sopenharmony_ci return 0; 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ciout_check_volume: 183462306a36Sopenharmony_ci ocfs2_free_replay_slots(osb); 183562306a36Sopenharmony_ciout_system_inodes: 183662306a36Sopenharmony_ci if (osb->local_alloc_state == OCFS2_LA_ENABLED) 183762306a36Sopenharmony_ci ocfs2_shutdown_local_alloc(osb); 183862306a36Sopenharmony_ci ocfs2_release_system_inodes(osb); 183962306a36Sopenharmony_ci /* before journal shutdown, we should release slot_info */ 184062306a36Sopenharmony_ci ocfs2_free_slot_info(osb); 184162306a36Sopenharmony_ci ocfs2_journal_shutdown(osb); 184262306a36Sopenharmony_ciout_super_lock: 184362306a36Sopenharmony_ci ocfs2_super_unlock(osb, 1); 184462306a36Sopenharmony_ciout_dlm: 184562306a36Sopenharmony_ci ocfs2_dlm_shutdown(osb, 0); 184662306a36Sopenharmony_ciout: 184762306a36Sopenharmony_ci return status; 184862306a36Sopenharmony_ci} 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_cistatic void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) 185162306a36Sopenharmony_ci{ 185262306a36Sopenharmony_ci int tmp, hangup_needed = 0; 185362306a36Sopenharmony_ci struct ocfs2_super *osb = NULL; 185462306a36Sopenharmony_ci char nodestr[12]; 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci trace_ocfs2_dismount_volume(sb); 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci BUG_ON(!sb); 185962306a36Sopenharmony_ci osb = OCFS2_SB(sb); 186062306a36Sopenharmony_ci BUG_ON(!osb); 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci /* Remove file check sysfs related directores/files, 186362306a36Sopenharmony_ci * and wait for the pending file check operations */ 186462306a36Sopenharmony_ci ocfs2_filecheck_remove_sysfs(osb); 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_ci kset_unregister(osb->osb_dev_kset); 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci /* Orphan scan should be stopped as early as possible */ 186962306a36Sopenharmony_ci ocfs2_orphan_scan_stop(osb); 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci ocfs2_disable_quotas(osb); 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci /* All dquots should be freed by now */ 187462306a36Sopenharmony_ci WARN_ON(!llist_empty(&osb->dquot_drop_list)); 187562306a36Sopenharmony_ci /* Wait for worker to be done with the work structure in osb */ 187662306a36Sopenharmony_ci cancel_work_sync(&osb->dquot_drop_work); 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci ocfs2_shutdown_local_alloc(osb); 187962306a36Sopenharmony_ci 188062306a36Sopenharmony_ci ocfs2_truncate_log_shutdown(osb); 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci /* This will disable recovery and flush any recovery work. */ 188362306a36Sopenharmony_ci ocfs2_recovery_exit(osb); 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci ocfs2_sync_blockdev(sb); 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci ocfs2_purge_refcount_trees(osb); 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci /* No cluster connection means we've failed during mount, so skip 189062306a36Sopenharmony_ci * all the steps which depended on that to complete. */ 189162306a36Sopenharmony_ci if (osb->cconn) { 189262306a36Sopenharmony_ci tmp = ocfs2_super_lock(osb, 1); 189362306a36Sopenharmony_ci if (tmp < 0) { 189462306a36Sopenharmony_ci mlog_errno(tmp); 189562306a36Sopenharmony_ci return; 189662306a36Sopenharmony_ci } 189762306a36Sopenharmony_ci } 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci if (osb->slot_num != OCFS2_INVALID_SLOT) 190062306a36Sopenharmony_ci ocfs2_put_slot(osb); 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci if (osb->cconn) 190362306a36Sopenharmony_ci ocfs2_super_unlock(osb, 1); 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci ocfs2_release_system_inodes(osb); 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci ocfs2_journal_shutdown(osb); 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci /* 191062306a36Sopenharmony_ci * If we're dismounting due to mount error, mount.ocfs2 will clean 191162306a36Sopenharmony_ci * up heartbeat. If we're a local mount, there is no heartbeat. 191262306a36Sopenharmony_ci * If we failed before we got a uuid_str yet, we can't stop 191362306a36Sopenharmony_ci * heartbeat. Otherwise, do it. 191462306a36Sopenharmony_ci */ 191562306a36Sopenharmony_ci if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str && 191662306a36Sopenharmony_ci !ocfs2_is_hard_readonly(osb)) 191762306a36Sopenharmony_ci hangup_needed = 1; 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci ocfs2_dlm_shutdown(osb, hangup_needed); 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci ocfs2_blockcheck_stats_debugfs_remove(&osb->osb_ecc_stats); 192262306a36Sopenharmony_ci debugfs_remove_recursive(osb->osb_debug_root); 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci if (hangup_needed) 192562306a36Sopenharmony_ci ocfs2_cluster_hangup(osb->uuid_str, strlen(osb->uuid_str)); 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci atomic_set(&osb->vol_state, VOLUME_DISMOUNTED); 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci if (ocfs2_mount_local(osb)) 193062306a36Sopenharmony_ci snprintf(nodestr, sizeof(nodestr), "local"); 193162306a36Sopenharmony_ci else 193262306a36Sopenharmony_ci snprintf(nodestr, sizeof(nodestr), "%u", osb->node_num); 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %s)\n", 193562306a36Sopenharmony_ci osb->dev_str, nodestr); 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci ocfs2_delete_osb(osb); 193862306a36Sopenharmony_ci kfree(osb); 193962306a36Sopenharmony_ci sb->s_dev = 0; 194062306a36Sopenharmony_ci sb->s_fs_info = NULL; 194162306a36Sopenharmony_ci} 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_cistatic int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uuid, 194462306a36Sopenharmony_ci unsigned uuid_bytes) 194562306a36Sopenharmony_ci{ 194662306a36Sopenharmony_ci int i, ret; 194762306a36Sopenharmony_ci char *ptr; 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_ci BUG_ON(uuid_bytes != OCFS2_VOL_UUID_LEN); 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci osb->uuid_str = kzalloc(OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL); 195262306a36Sopenharmony_ci if (osb->uuid_str == NULL) 195362306a36Sopenharmony_ci return -ENOMEM; 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci for (i = 0, ptr = osb->uuid_str; i < OCFS2_VOL_UUID_LEN; i++) { 195662306a36Sopenharmony_ci /* print with null */ 195762306a36Sopenharmony_ci ret = snprintf(ptr, 3, "%02X", uuid[i]); 195862306a36Sopenharmony_ci if (ret != 2) /* drop super cleans up */ 195962306a36Sopenharmony_ci return -EINVAL; 196062306a36Sopenharmony_ci /* then only advance past the last char */ 196162306a36Sopenharmony_ci ptr += 2; 196262306a36Sopenharmony_ci } 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci return 0; 196562306a36Sopenharmony_ci} 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci/* Make sure entire volume is addressable by our journal. Requires 196862306a36Sopenharmony_ci osb_clusters_at_boot to be valid and for the journal to have been 196962306a36Sopenharmony_ci initialized by ocfs2_journal_init(). */ 197062306a36Sopenharmony_cistatic int ocfs2_journal_addressable(struct ocfs2_super *osb) 197162306a36Sopenharmony_ci{ 197262306a36Sopenharmony_ci int status = 0; 197362306a36Sopenharmony_ci u64 max_block = 197462306a36Sopenharmony_ci ocfs2_clusters_to_blocks(osb->sb, 197562306a36Sopenharmony_ci osb->osb_clusters_at_boot) - 1; 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci /* 32-bit block number is always OK. */ 197862306a36Sopenharmony_ci if (max_block <= (u32)~0ULL) 197962306a36Sopenharmony_ci goto out; 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci /* Volume is "huge", so see if our journal is new enough to 198262306a36Sopenharmony_ci support it. */ 198362306a36Sopenharmony_ci if (!(OCFS2_HAS_COMPAT_FEATURE(osb->sb, 198462306a36Sopenharmony_ci OCFS2_FEATURE_COMPAT_JBD2_SB) && 198562306a36Sopenharmony_ci jbd2_journal_check_used_features(osb->journal->j_journal, 0, 0, 198662306a36Sopenharmony_ci JBD2_FEATURE_INCOMPAT_64BIT))) { 198762306a36Sopenharmony_ci mlog(ML_ERROR, "The journal cannot address the entire volume. " 198862306a36Sopenharmony_ci "Enable the 'block64' journal option with tunefs.ocfs2"); 198962306a36Sopenharmony_ci status = -EFBIG; 199062306a36Sopenharmony_ci goto out; 199162306a36Sopenharmony_ci } 199262306a36Sopenharmony_ci 199362306a36Sopenharmony_ci out: 199462306a36Sopenharmony_ci return status; 199562306a36Sopenharmony_ci} 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_cistatic int ocfs2_initialize_super(struct super_block *sb, 199862306a36Sopenharmony_ci struct buffer_head *bh, 199962306a36Sopenharmony_ci int sector_size, 200062306a36Sopenharmony_ci struct ocfs2_blockcheck_stats *stats) 200162306a36Sopenharmony_ci{ 200262306a36Sopenharmony_ci int status; 200362306a36Sopenharmony_ci int i, cbits, bbits; 200462306a36Sopenharmony_ci struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; 200562306a36Sopenharmony_ci struct inode *inode = NULL; 200662306a36Sopenharmony_ci struct ocfs2_super *osb; 200762306a36Sopenharmony_ci u64 total_blocks; 200862306a36Sopenharmony_ci 200962306a36Sopenharmony_ci osb = kzalloc(sizeof(struct ocfs2_super), GFP_KERNEL); 201062306a36Sopenharmony_ci if (!osb) { 201162306a36Sopenharmony_ci status = -ENOMEM; 201262306a36Sopenharmony_ci mlog_errno(status); 201362306a36Sopenharmony_ci goto out; 201462306a36Sopenharmony_ci } 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci sb->s_fs_info = osb; 201762306a36Sopenharmony_ci sb->s_op = &ocfs2_sops; 201862306a36Sopenharmony_ci sb->s_d_op = &ocfs2_dentry_ops; 201962306a36Sopenharmony_ci sb->s_export_op = &ocfs2_export_ops; 202062306a36Sopenharmony_ci sb->s_qcop = &dquot_quotactl_sysfile_ops; 202162306a36Sopenharmony_ci sb->dq_op = &ocfs2_quota_operations; 202262306a36Sopenharmony_ci sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; 202362306a36Sopenharmony_ci sb->s_xattr = ocfs2_xattr_handlers; 202462306a36Sopenharmony_ci sb->s_time_gran = 1; 202562306a36Sopenharmony_ci sb->s_flags |= SB_NOATIME; 202662306a36Sopenharmony_ci /* this is needed to support O_LARGEFILE */ 202762306a36Sopenharmony_ci cbits = le32_to_cpu(di->id2.i_super.s_clustersize_bits); 202862306a36Sopenharmony_ci bbits = le32_to_cpu(di->id2.i_super.s_blocksize_bits); 202962306a36Sopenharmony_ci sb->s_maxbytes = ocfs2_max_file_offset(bbits, cbits); 203062306a36Sopenharmony_ci memcpy(&sb->s_uuid, di->id2.i_super.s_uuid, 203162306a36Sopenharmony_ci sizeof(di->id2.i_super.s_uuid)); 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_ci osb->osb_dx_mask = (1 << (cbits - bbits)) - 1; 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci for (i = 0; i < 3; i++) 203662306a36Sopenharmony_ci osb->osb_dx_seed[i] = le32_to_cpu(di->id2.i_super.s_dx_seed[i]); 203762306a36Sopenharmony_ci osb->osb_dx_seed[3] = le32_to_cpu(di->id2.i_super.s_uuid_hash); 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_ci osb->sb = sb; 204062306a36Sopenharmony_ci osb->s_sectsize_bits = blksize_bits(sector_size); 204162306a36Sopenharmony_ci BUG_ON(!osb->s_sectsize_bits); 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci spin_lock_init(&osb->dc_task_lock); 204462306a36Sopenharmony_ci init_waitqueue_head(&osb->dc_event); 204562306a36Sopenharmony_ci osb->dc_work_sequence = 0; 204662306a36Sopenharmony_ci osb->dc_wake_sequence = 0; 204762306a36Sopenharmony_ci INIT_LIST_HEAD(&osb->blocked_lock_list); 204862306a36Sopenharmony_ci osb->blocked_lock_count = 0; 204962306a36Sopenharmony_ci spin_lock_init(&osb->osb_lock); 205062306a36Sopenharmony_ci spin_lock_init(&osb->osb_xattr_lock); 205162306a36Sopenharmony_ci ocfs2_init_steal_slots(osb); 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci mutex_init(&osb->system_file_mutex); 205462306a36Sopenharmony_ci 205562306a36Sopenharmony_ci atomic_set(&osb->alloc_stats.moves, 0); 205662306a36Sopenharmony_ci atomic_set(&osb->alloc_stats.local_data, 0); 205762306a36Sopenharmony_ci atomic_set(&osb->alloc_stats.bitmap_data, 0); 205862306a36Sopenharmony_ci atomic_set(&osb->alloc_stats.bg_allocs, 0); 205962306a36Sopenharmony_ci atomic_set(&osb->alloc_stats.bg_extends, 0); 206062306a36Sopenharmony_ci 206162306a36Sopenharmony_ci /* Copy the blockcheck stats from the superblock probe */ 206262306a36Sopenharmony_ci osb->osb_ecc_stats = *stats; 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_ci ocfs2_init_node_maps(osb); 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", 206762306a36Sopenharmony_ci MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots); 207062306a36Sopenharmony_ci if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) { 207162306a36Sopenharmony_ci mlog(ML_ERROR, "Invalid number of node slots (%u)\n", 207262306a36Sopenharmony_ci osb->max_slots); 207362306a36Sopenharmony_ci status = -EINVAL; 207462306a36Sopenharmony_ci goto out; 207562306a36Sopenharmony_ci } 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci ocfs2_orphan_scan_init(osb); 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci status = ocfs2_recovery_init(osb); 208062306a36Sopenharmony_ci if (status) { 208162306a36Sopenharmony_ci mlog(ML_ERROR, "Unable to initialize recovery state\n"); 208262306a36Sopenharmony_ci mlog_errno(status); 208362306a36Sopenharmony_ci goto out; 208462306a36Sopenharmony_ci } 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_ci init_waitqueue_head(&osb->checkpoint_event); 208762306a36Sopenharmony_ci 208862306a36Sopenharmony_ci osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci osb->slot_num = OCFS2_INVALID_SLOT; 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci osb->s_xattr_inline_size = le16_to_cpu( 209362306a36Sopenharmony_ci di->id2.i_super.s_xattr_inline_size); 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci osb->local_alloc_state = OCFS2_LA_UNUSED; 209662306a36Sopenharmony_ci osb->local_alloc_bh = NULL; 209762306a36Sopenharmony_ci INIT_DELAYED_WORK(&osb->la_enable_wq, ocfs2_la_enable_worker); 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci init_waitqueue_head(&osb->osb_mount_event); 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci ocfs2_resmap_init(osb, &osb->osb_la_resmap); 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL); 210462306a36Sopenharmony_ci if (!osb->vol_label) { 210562306a36Sopenharmony_ci mlog(ML_ERROR, "unable to alloc vol label\n"); 210662306a36Sopenharmony_ci status = -ENOMEM; 210762306a36Sopenharmony_ci goto out_recovery_map; 210862306a36Sopenharmony_ci } 210962306a36Sopenharmony_ci 211062306a36Sopenharmony_ci osb->slot_recovery_generations = 211162306a36Sopenharmony_ci kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations), 211262306a36Sopenharmony_ci GFP_KERNEL); 211362306a36Sopenharmony_ci if (!osb->slot_recovery_generations) { 211462306a36Sopenharmony_ci status = -ENOMEM; 211562306a36Sopenharmony_ci mlog_errno(status); 211662306a36Sopenharmony_ci goto out_vol_label; 211762306a36Sopenharmony_ci } 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci init_waitqueue_head(&osb->osb_wipe_event); 212062306a36Sopenharmony_ci osb->osb_orphan_wipes = kcalloc(osb->max_slots, 212162306a36Sopenharmony_ci sizeof(*osb->osb_orphan_wipes), 212262306a36Sopenharmony_ci GFP_KERNEL); 212362306a36Sopenharmony_ci if (!osb->osb_orphan_wipes) { 212462306a36Sopenharmony_ci status = -ENOMEM; 212562306a36Sopenharmony_ci mlog_errno(status); 212662306a36Sopenharmony_ci goto out_slot_recovery_gen; 212762306a36Sopenharmony_ci } 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci osb->osb_rf_lock_tree = RB_ROOT; 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_ci osb->s_feature_compat = 213262306a36Sopenharmony_ci le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_compat); 213362306a36Sopenharmony_ci osb->s_feature_ro_compat = 213462306a36Sopenharmony_ci le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_ro_compat); 213562306a36Sopenharmony_ci osb->s_feature_incompat = 213662306a36Sopenharmony_ci le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_incompat); 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci if ((i = OCFS2_HAS_INCOMPAT_FEATURE(osb->sb, ~OCFS2_FEATURE_INCOMPAT_SUPP))) { 213962306a36Sopenharmony_ci mlog(ML_ERROR, "couldn't mount because of unsupported " 214062306a36Sopenharmony_ci "optional features (%x).\n", i); 214162306a36Sopenharmony_ci status = -EINVAL; 214262306a36Sopenharmony_ci goto out_orphan_wipes; 214362306a36Sopenharmony_ci } 214462306a36Sopenharmony_ci if (!sb_rdonly(osb->sb) && (i = OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, ~OCFS2_FEATURE_RO_COMPAT_SUPP))) { 214562306a36Sopenharmony_ci mlog(ML_ERROR, "couldn't mount RDWR because of " 214662306a36Sopenharmony_ci "unsupported optional features (%x).\n", i); 214762306a36Sopenharmony_ci status = -EINVAL; 214862306a36Sopenharmony_ci goto out_orphan_wipes; 214962306a36Sopenharmony_ci } 215062306a36Sopenharmony_ci 215162306a36Sopenharmony_ci if (ocfs2_clusterinfo_valid(osb)) { 215262306a36Sopenharmony_ci /* 215362306a36Sopenharmony_ci * ci_stack and ci_cluster in ocfs2_cluster_info may not be null 215462306a36Sopenharmony_ci * terminated, so make sure no overflow happens here by using 215562306a36Sopenharmony_ci * memcpy. Destination strings will always be null terminated 215662306a36Sopenharmony_ci * because osb is allocated using kzalloc. 215762306a36Sopenharmony_ci */ 215862306a36Sopenharmony_ci osb->osb_stackflags = 215962306a36Sopenharmony_ci OCFS2_RAW_SB(di)->s_cluster_info.ci_stackflags; 216062306a36Sopenharmony_ci memcpy(osb->osb_cluster_stack, 216162306a36Sopenharmony_ci OCFS2_RAW_SB(di)->s_cluster_info.ci_stack, 216262306a36Sopenharmony_ci OCFS2_STACK_LABEL_LEN); 216362306a36Sopenharmony_ci if (strlen(osb->osb_cluster_stack) != OCFS2_STACK_LABEL_LEN) { 216462306a36Sopenharmony_ci mlog(ML_ERROR, 216562306a36Sopenharmony_ci "couldn't mount because of an invalid " 216662306a36Sopenharmony_ci "cluster stack label (%s) \n", 216762306a36Sopenharmony_ci osb->osb_cluster_stack); 216862306a36Sopenharmony_ci status = -EINVAL; 216962306a36Sopenharmony_ci goto out_orphan_wipes; 217062306a36Sopenharmony_ci } 217162306a36Sopenharmony_ci memcpy(osb->osb_cluster_name, 217262306a36Sopenharmony_ci OCFS2_RAW_SB(di)->s_cluster_info.ci_cluster, 217362306a36Sopenharmony_ci OCFS2_CLUSTER_NAME_LEN); 217462306a36Sopenharmony_ci } else { 217562306a36Sopenharmony_ci /* The empty string is identical with classic tools that 217662306a36Sopenharmony_ci * don't know about s_cluster_info. */ 217762306a36Sopenharmony_ci osb->osb_cluster_stack[0] = '\0'; 217862306a36Sopenharmony_ci } 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_ci get_random_bytes(&osb->s_next_generation, sizeof(u32)); 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ci /* 218362306a36Sopenharmony_ci * FIXME 218462306a36Sopenharmony_ci * This should be done in ocfs2_journal_init(), but any inode 218562306a36Sopenharmony_ci * writes back operation will cause the filesystem to crash. 218662306a36Sopenharmony_ci */ 218762306a36Sopenharmony_ci status = ocfs2_journal_alloc(osb); 218862306a36Sopenharmony_ci if (status < 0) 218962306a36Sopenharmony_ci goto out_orphan_wipes; 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci INIT_WORK(&osb->dquot_drop_work, ocfs2_drop_dquot_refs); 219262306a36Sopenharmony_ci init_llist_head(&osb->dquot_drop_list); 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_ci /* get some pseudo constants for clustersize bits */ 219562306a36Sopenharmony_ci osb->s_clustersize_bits = 219662306a36Sopenharmony_ci le32_to_cpu(di->id2.i_super.s_clustersize_bits); 219762306a36Sopenharmony_ci osb->s_clustersize = 1 << osb->s_clustersize_bits; 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci if (osb->s_clustersize < OCFS2_MIN_CLUSTERSIZE || 220062306a36Sopenharmony_ci osb->s_clustersize > OCFS2_MAX_CLUSTERSIZE) { 220162306a36Sopenharmony_ci mlog(ML_ERROR, "Volume has invalid cluster size (%d)\n", 220262306a36Sopenharmony_ci osb->s_clustersize); 220362306a36Sopenharmony_ci status = -EINVAL; 220462306a36Sopenharmony_ci goto out_journal; 220562306a36Sopenharmony_ci } 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci total_blocks = ocfs2_clusters_to_blocks(osb->sb, 220862306a36Sopenharmony_ci le32_to_cpu(di->i_clusters)); 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci status = generic_check_addressable(osb->sb->s_blocksize_bits, 221162306a36Sopenharmony_ci total_blocks); 221262306a36Sopenharmony_ci if (status) { 221362306a36Sopenharmony_ci mlog(ML_ERROR, "Volume too large " 221462306a36Sopenharmony_ci "to mount safely on this system"); 221562306a36Sopenharmony_ci status = -EFBIG; 221662306a36Sopenharmony_ci goto out_journal; 221762306a36Sopenharmony_ci } 221862306a36Sopenharmony_ci 221962306a36Sopenharmony_ci if (ocfs2_setup_osb_uuid(osb, di->id2.i_super.s_uuid, 222062306a36Sopenharmony_ci sizeof(di->id2.i_super.s_uuid))) { 222162306a36Sopenharmony_ci mlog(ML_ERROR, "Out of memory trying to setup our uuid.\n"); 222262306a36Sopenharmony_ci status = -ENOMEM; 222362306a36Sopenharmony_ci goto out_journal; 222462306a36Sopenharmony_ci } 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci strscpy(osb->vol_label, di->id2.i_super.s_label, 222762306a36Sopenharmony_ci OCFS2_MAX_VOL_LABEL_LEN); 222862306a36Sopenharmony_ci osb->root_blkno = le64_to_cpu(di->id2.i_super.s_root_blkno); 222962306a36Sopenharmony_ci osb->system_dir_blkno = le64_to_cpu(di->id2.i_super.s_system_dir_blkno); 223062306a36Sopenharmony_ci osb->first_cluster_group_blkno = 223162306a36Sopenharmony_ci le64_to_cpu(di->id2.i_super.s_first_cluster_group); 223262306a36Sopenharmony_ci osb->fs_generation = le32_to_cpu(di->i_fs_generation); 223362306a36Sopenharmony_ci osb->uuid_hash = le32_to_cpu(di->id2.i_super.s_uuid_hash); 223462306a36Sopenharmony_ci trace_ocfs2_initialize_super(osb->vol_label, osb->uuid_str, 223562306a36Sopenharmony_ci (unsigned long long)osb->root_blkno, 223662306a36Sopenharmony_ci (unsigned long long)osb->system_dir_blkno, 223762306a36Sopenharmony_ci osb->s_clustersize_bits); 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci osb->osb_dlm_debug = ocfs2_new_dlm_debug(); 224062306a36Sopenharmony_ci if (!osb->osb_dlm_debug) { 224162306a36Sopenharmony_ci status = -ENOMEM; 224262306a36Sopenharmony_ci mlog_errno(status); 224362306a36Sopenharmony_ci goto out_uuid_str; 224462306a36Sopenharmony_ci } 224562306a36Sopenharmony_ci 224662306a36Sopenharmony_ci atomic_set(&osb->vol_state, VOLUME_INIT); 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci /* load root, system_dir, and all global system inodes */ 224962306a36Sopenharmony_ci status = ocfs2_init_global_system_inodes(osb); 225062306a36Sopenharmony_ci if (status < 0) { 225162306a36Sopenharmony_ci mlog_errno(status); 225262306a36Sopenharmony_ci goto out_dlm_out; 225362306a36Sopenharmony_ci } 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci /* 225662306a36Sopenharmony_ci * global bitmap 225762306a36Sopenharmony_ci */ 225862306a36Sopenharmony_ci inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, 225962306a36Sopenharmony_ci OCFS2_INVALID_SLOT); 226062306a36Sopenharmony_ci if (!inode) { 226162306a36Sopenharmony_ci status = -EINVAL; 226262306a36Sopenharmony_ci mlog_errno(status); 226362306a36Sopenharmony_ci goto out_system_inodes; 226462306a36Sopenharmony_ci } 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno; 226762306a36Sopenharmony_ci osb->osb_clusters_at_boot = OCFS2_I(inode)->ip_clusters; 226862306a36Sopenharmony_ci iput(inode); 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci osb->bitmap_cpg = ocfs2_group_bitmap_size(sb, 0, 227162306a36Sopenharmony_ci osb->s_feature_incompat) * 8; 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ci status = ocfs2_init_slot_info(osb); 227462306a36Sopenharmony_ci if (status < 0) { 227562306a36Sopenharmony_ci mlog_errno(status); 227662306a36Sopenharmony_ci goto out_system_inodes; 227762306a36Sopenharmony_ci } 227862306a36Sopenharmony_ci 227962306a36Sopenharmony_ci osb->ocfs2_wq = alloc_ordered_workqueue("ocfs2_wq", WQ_MEM_RECLAIM); 228062306a36Sopenharmony_ci if (!osb->ocfs2_wq) { 228162306a36Sopenharmony_ci status = -ENOMEM; 228262306a36Sopenharmony_ci mlog_errno(status); 228362306a36Sopenharmony_ci goto out_slot_info; 228462306a36Sopenharmony_ci } 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci return status; 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ciout_slot_info: 228962306a36Sopenharmony_ci ocfs2_free_slot_info(osb); 229062306a36Sopenharmony_ciout_system_inodes: 229162306a36Sopenharmony_ci ocfs2_release_system_inodes(osb); 229262306a36Sopenharmony_ciout_dlm_out: 229362306a36Sopenharmony_ci ocfs2_put_dlm_debug(osb->osb_dlm_debug); 229462306a36Sopenharmony_ciout_uuid_str: 229562306a36Sopenharmony_ci kfree(osb->uuid_str); 229662306a36Sopenharmony_ciout_journal: 229762306a36Sopenharmony_ci kfree(osb->journal); 229862306a36Sopenharmony_ciout_orphan_wipes: 229962306a36Sopenharmony_ci kfree(osb->osb_orphan_wipes); 230062306a36Sopenharmony_ciout_slot_recovery_gen: 230162306a36Sopenharmony_ci kfree(osb->slot_recovery_generations); 230262306a36Sopenharmony_ciout_vol_label: 230362306a36Sopenharmony_ci kfree(osb->vol_label); 230462306a36Sopenharmony_ciout_recovery_map: 230562306a36Sopenharmony_ci kfree(osb->recovery_map); 230662306a36Sopenharmony_ciout: 230762306a36Sopenharmony_ci kfree(osb); 230862306a36Sopenharmony_ci sb->s_fs_info = NULL; 230962306a36Sopenharmony_ci return status; 231062306a36Sopenharmony_ci} 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci/* 231362306a36Sopenharmony_ci * will return: -EAGAIN if it is ok to keep searching for superblocks 231462306a36Sopenharmony_ci * -EINVAL if there is a bad superblock 231562306a36Sopenharmony_ci * 0 on success 231662306a36Sopenharmony_ci */ 231762306a36Sopenharmony_cistatic int ocfs2_verify_volume(struct ocfs2_dinode *di, 231862306a36Sopenharmony_ci struct buffer_head *bh, 231962306a36Sopenharmony_ci u32 blksz, 232062306a36Sopenharmony_ci struct ocfs2_blockcheck_stats *stats) 232162306a36Sopenharmony_ci{ 232262306a36Sopenharmony_ci int status = -EAGAIN; 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE, 232562306a36Sopenharmony_ci strlen(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0) { 232662306a36Sopenharmony_ci /* We have to do a raw check of the feature here */ 232762306a36Sopenharmony_ci if (le32_to_cpu(di->id2.i_super.s_feature_incompat) & 232862306a36Sopenharmony_ci OCFS2_FEATURE_INCOMPAT_META_ECC) { 232962306a36Sopenharmony_ci status = ocfs2_block_check_validate(bh->b_data, 233062306a36Sopenharmony_ci bh->b_size, 233162306a36Sopenharmony_ci &di->i_check, 233262306a36Sopenharmony_ci stats); 233362306a36Sopenharmony_ci if (status) 233462306a36Sopenharmony_ci goto out; 233562306a36Sopenharmony_ci } 233662306a36Sopenharmony_ci status = -EINVAL; 233762306a36Sopenharmony_ci if ((1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits)) != blksz) { 233862306a36Sopenharmony_ci mlog(ML_ERROR, "found superblock with incorrect block " 233962306a36Sopenharmony_ci "size: found %u, should be %u\n", 234062306a36Sopenharmony_ci 1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits), 234162306a36Sopenharmony_ci blksz); 234262306a36Sopenharmony_ci } else if (le16_to_cpu(di->id2.i_super.s_major_rev_level) != 234362306a36Sopenharmony_ci OCFS2_MAJOR_REV_LEVEL || 234462306a36Sopenharmony_ci le16_to_cpu(di->id2.i_super.s_minor_rev_level) != 234562306a36Sopenharmony_ci OCFS2_MINOR_REV_LEVEL) { 234662306a36Sopenharmony_ci mlog(ML_ERROR, "found superblock with bad version: " 234762306a36Sopenharmony_ci "found %u.%u, should be %u.%u\n", 234862306a36Sopenharmony_ci le16_to_cpu(di->id2.i_super.s_major_rev_level), 234962306a36Sopenharmony_ci le16_to_cpu(di->id2.i_super.s_minor_rev_level), 235062306a36Sopenharmony_ci OCFS2_MAJOR_REV_LEVEL, 235162306a36Sopenharmony_ci OCFS2_MINOR_REV_LEVEL); 235262306a36Sopenharmony_ci } else if (bh->b_blocknr != le64_to_cpu(di->i_blkno)) { 235362306a36Sopenharmony_ci mlog(ML_ERROR, "bad block number on superblock: " 235462306a36Sopenharmony_ci "found %llu, should be %llu\n", 235562306a36Sopenharmony_ci (unsigned long long)le64_to_cpu(di->i_blkno), 235662306a36Sopenharmony_ci (unsigned long long)bh->b_blocknr); 235762306a36Sopenharmony_ci } else if (le32_to_cpu(di->id2.i_super.s_clustersize_bits) < 12 || 235862306a36Sopenharmony_ci le32_to_cpu(di->id2.i_super.s_clustersize_bits) > 20) { 235962306a36Sopenharmony_ci mlog(ML_ERROR, "bad cluster size found: %u\n", 236062306a36Sopenharmony_ci 1 << le32_to_cpu(di->id2.i_super.s_clustersize_bits)); 236162306a36Sopenharmony_ci } else if (!le64_to_cpu(di->id2.i_super.s_root_blkno)) { 236262306a36Sopenharmony_ci mlog(ML_ERROR, "bad root_blkno: 0\n"); 236362306a36Sopenharmony_ci } else if (!le64_to_cpu(di->id2.i_super.s_system_dir_blkno)) { 236462306a36Sopenharmony_ci mlog(ML_ERROR, "bad system_dir_blkno: 0\n"); 236562306a36Sopenharmony_ci } else if (le16_to_cpu(di->id2.i_super.s_max_slots) > OCFS2_MAX_SLOTS) { 236662306a36Sopenharmony_ci mlog(ML_ERROR, 236762306a36Sopenharmony_ci "Superblock slots found greater than file system " 236862306a36Sopenharmony_ci "maximum: found %u, max %u\n", 236962306a36Sopenharmony_ci le16_to_cpu(di->id2.i_super.s_max_slots), 237062306a36Sopenharmony_ci OCFS2_MAX_SLOTS); 237162306a36Sopenharmony_ci } else { 237262306a36Sopenharmony_ci /* found it! */ 237362306a36Sopenharmony_ci status = 0; 237462306a36Sopenharmony_ci } 237562306a36Sopenharmony_ci } 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ciout: 237862306a36Sopenharmony_ci if (status && status != -EAGAIN) 237962306a36Sopenharmony_ci mlog_errno(status); 238062306a36Sopenharmony_ci return status; 238162306a36Sopenharmony_ci} 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_cistatic int ocfs2_check_volume(struct ocfs2_super *osb) 238462306a36Sopenharmony_ci{ 238562306a36Sopenharmony_ci int status; 238662306a36Sopenharmony_ci int dirty; 238762306a36Sopenharmony_ci int local; 238862306a36Sopenharmony_ci struct ocfs2_dinode *local_alloc = NULL; /* only used if we 238962306a36Sopenharmony_ci * recover 239062306a36Sopenharmony_ci * ourselves. */ 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_ci /* Init our journal object. */ 239362306a36Sopenharmony_ci status = ocfs2_journal_init(osb, &dirty); 239462306a36Sopenharmony_ci if (status < 0) { 239562306a36Sopenharmony_ci mlog(ML_ERROR, "Could not initialize journal!\n"); 239662306a36Sopenharmony_ci goto finally; 239762306a36Sopenharmony_ci } 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci /* Now that journal has been initialized, check to make sure 240062306a36Sopenharmony_ci entire volume is addressable. */ 240162306a36Sopenharmony_ci status = ocfs2_journal_addressable(osb); 240262306a36Sopenharmony_ci if (status) 240362306a36Sopenharmony_ci goto finally; 240462306a36Sopenharmony_ci 240562306a36Sopenharmony_ci /* If the journal was unmounted cleanly then we don't want to 240662306a36Sopenharmony_ci * recover anything. Otherwise, journal_load will do that 240762306a36Sopenharmony_ci * dirty work for us :) */ 240862306a36Sopenharmony_ci if (!dirty) { 240962306a36Sopenharmony_ci status = ocfs2_journal_wipe(osb->journal, 0); 241062306a36Sopenharmony_ci if (status < 0) { 241162306a36Sopenharmony_ci mlog_errno(status); 241262306a36Sopenharmony_ci goto finally; 241362306a36Sopenharmony_ci } 241462306a36Sopenharmony_ci } else { 241562306a36Sopenharmony_ci printk(KERN_NOTICE "ocfs2: File system on device (%s) was not " 241662306a36Sopenharmony_ci "unmounted cleanly, recovering it.\n", osb->dev_str); 241762306a36Sopenharmony_ci } 241862306a36Sopenharmony_ci 241962306a36Sopenharmony_ci local = ocfs2_mount_local(osb); 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_ci /* will play back anything left in the journal. */ 242262306a36Sopenharmony_ci status = ocfs2_journal_load(osb->journal, local, dirty); 242362306a36Sopenharmony_ci if (status < 0) { 242462306a36Sopenharmony_ci mlog(ML_ERROR, "ocfs2 journal load failed! %d\n", status); 242562306a36Sopenharmony_ci goto finally; 242662306a36Sopenharmony_ci } 242762306a36Sopenharmony_ci 242862306a36Sopenharmony_ci if (osb->s_mount_opt & OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT) 242962306a36Sopenharmony_ci jbd2_journal_set_features(osb->journal->j_journal, 243062306a36Sopenharmony_ci JBD2_FEATURE_COMPAT_CHECKSUM, 0, 243162306a36Sopenharmony_ci JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); 243262306a36Sopenharmony_ci else 243362306a36Sopenharmony_ci jbd2_journal_clear_features(osb->journal->j_journal, 243462306a36Sopenharmony_ci JBD2_FEATURE_COMPAT_CHECKSUM, 0, 243562306a36Sopenharmony_ci JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); 243662306a36Sopenharmony_ci 243762306a36Sopenharmony_ci if (dirty) { 243862306a36Sopenharmony_ci /* recover my local alloc if we didn't unmount cleanly. */ 243962306a36Sopenharmony_ci status = ocfs2_begin_local_alloc_recovery(osb, 244062306a36Sopenharmony_ci osb->slot_num, 244162306a36Sopenharmony_ci &local_alloc); 244262306a36Sopenharmony_ci if (status < 0) { 244362306a36Sopenharmony_ci mlog_errno(status); 244462306a36Sopenharmony_ci goto finally; 244562306a36Sopenharmony_ci } 244662306a36Sopenharmony_ci /* we complete the recovery process after we've marked 244762306a36Sopenharmony_ci * ourselves as mounted. */ 244862306a36Sopenharmony_ci } 244962306a36Sopenharmony_ci 245062306a36Sopenharmony_ci status = ocfs2_load_local_alloc(osb); 245162306a36Sopenharmony_ci if (status < 0) { 245262306a36Sopenharmony_ci mlog_errno(status); 245362306a36Sopenharmony_ci goto finally; 245462306a36Sopenharmony_ci } 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci if (dirty) { 245762306a36Sopenharmony_ci /* Recovery will be completed after we've mounted the 245862306a36Sopenharmony_ci * rest of the volume. */ 245962306a36Sopenharmony_ci osb->local_alloc_copy = local_alloc; 246062306a36Sopenharmony_ci local_alloc = NULL; 246162306a36Sopenharmony_ci } 246262306a36Sopenharmony_ci 246362306a36Sopenharmony_ci /* go through each journal, trylock it and if you get the 246462306a36Sopenharmony_ci * lock, and it's marked as dirty, set the bit in the recover 246562306a36Sopenharmony_ci * map and launch a recovery thread for it. */ 246662306a36Sopenharmony_ci status = ocfs2_mark_dead_nodes(osb); 246762306a36Sopenharmony_ci if (status < 0) { 246862306a36Sopenharmony_ci mlog_errno(status); 246962306a36Sopenharmony_ci goto finally; 247062306a36Sopenharmony_ci } 247162306a36Sopenharmony_ci 247262306a36Sopenharmony_ci status = ocfs2_compute_replay_slots(osb); 247362306a36Sopenharmony_ci if (status < 0) 247462306a36Sopenharmony_ci mlog_errno(status); 247562306a36Sopenharmony_ci 247662306a36Sopenharmony_cifinally: 247762306a36Sopenharmony_ci kfree(local_alloc); 247862306a36Sopenharmony_ci 247962306a36Sopenharmony_ci if (status) 248062306a36Sopenharmony_ci mlog_errno(status); 248162306a36Sopenharmony_ci return status; 248262306a36Sopenharmony_ci} 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_ci/* 248562306a36Sopenharmony_ci * The routine gets called from dismount or close whenever a dismount on 248662306a36Sopenharmony_ci * volume is requested and the osb open count becomes 1. 248762306a36Sopenharmony_ci * It will remove the osb from the global list and also free up all the 248862306a36Sopenharmony_ci * initialized resources and fileobject. 248962306a36Sopenharmony_ci */ 249062306a36Sopenharmony_cistatic void ocfs2_delete_osb(struct ocfs2_super *osb) 249162306a36Sopenharmony_ci{ 249262306a36Sopenharmony_ci /* This function assumes that the caller has the main osb resource */ 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ci /* ocfs2_initializer_super have already created this workqueue */ 249562306a36Sopenharmony_ci if (osb->ocfs2_wq) 249662306a36Sopenharmony_ci destroy_workqueue(osb->ocfs2_wq); 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci ocfs2_free_slot_info(osb); 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci kfree(osb->osb_orphan_wipes); 250162306a36Sopenharmony_ci kfree(osb->slot_recovery_generations); 250262306a36Sopenharmony_ci /* FIXME 250362306a36Sopenharmony_ci * This belongs in journal shutdown, but because we have to 250462306a36Sopenharmony_ci * allocate osb->journal at the middle of ocfs2_initialize_super(), 250562306a36Sopenharmony_ci * we free it here. 250662306a36Sopenharmony_ci */ 250762306a36Sopenharmony_ci kfree(osb->journal); 250862306a36Sopenharmony_ci kfree(osb->local_alloc_copy); 250962306a36Sopenharmony_ci kfree(osb->uuid_str); 251062306a36Sopenharmony_ci kfree(osb->vol_label); 251162306a36Sopenharmony_ci ocfs2_put_dlm_debug(osb->osb_dlm_debug); 251262306a36Sopenharmony_ci memset(osb, 0, sizeof(struct ocfs2_super)); 251362306a36Sopenharmony_ci} 251462306a36Sopenharmony_ci 251562306a36Sopenharmony_ci/* Depending on the mount option passed, perform one of the following: 251662306a36Sopenharmony_ci * Put OCFS2 into a readonly state (default) 251762306a36Sopenharmony_ci * Return EIO so that only the process errs 251862306a36Sopenharmony_ci * Fix the error as if fsck.ocfs2 -y 251962306a36Sopenharmony_ci * panic 252062306a36Sopenharmony_ci */ 252162306a36Sopenharmony_cistatic int ocfs2_handle_error(struct super_block *sb) 252262306a36Sopenharmony_ci{ 252362306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(sb); 252462306a36Sopenharmony_ci int rv = 0; 252562306a36Sopenharmony_ci 252662306a36Sopenharmony_ci ocfs2_set_osb_flag(osb, OCFS2_OSB_ERROR_FS); 252762306a36Sopenharmony_ci pr_crit("On-disk corruption discovered. " 252862306a36Sopenharmony_ci "Please run fsck.ocfs2 once the filesystem is unmounted.\n"); 252962306a36Sopenharmony_ci 253062306a36Sopenharmony_ci if (osb->s_mount_opt & OCFS2_MOUNT_ERRORS_PANIC) { 253162306a36Sopenharmony_ci panic("OCFS2: (device %s): panic forced after error\n", 253262306a36Sopenharmony_ci sb->s_id); 253362306a36Sopenharmony_ci } else if (osb->s_mount_opt & OCFS2_MOUNT_ERRORS_CONT) { 253462306a36Sopenharmony_ci pr_crit("OCFS2: Returning error to the calling process.\n"); 253562306a36Sopenharmony_ci rv = -EIO; 253662306a36Sopenharmony_ci } else { /* default option */ 253762306a36Sopenharmony_ci rv = -EROFS; 253862306a36Sopenharmony_ci if (sb_rdonly(sb) && (ocfs2_is_soft_readonly(osb) || ocfs2_is_hard_readonly(osb))) 253962306a36Sopenharmony_ci return rv; 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci pr_crit("OCFS2: File system is now read-only.\n"); 254262306a36Sopenharmony_ci sb->s_flags |= SB_RDONLY; 254362306a36Sopenharmony_ci ocfs2_set_ro_flag(osb, 0); 254462306a36Sopenharmony_ci } 254562306a36Sopenharmony_ci 254662306a36Sopenharmony_ci return rv; 254762306a36Sopenharmony_ci} 254862306a36Sopenharmony_ci 254962306a36Sopenharmony_ciint __ocfs2_error(struct super_block *sb, const char *function, 255062306a36Sopenharmony_ci const char *fmt, ...) 255162306a36Sopenharmony_ci{ 255262306a36Sopenharmony_ci struct va_format vaf; 255362306a36Sopenharmony_ci va_list args; 255462306a36Sopenharmony_ci 255562306a36Sopenharmony_ci va_start(args, fmt); 255662306a36Sopenharmony_ci vaf.fmt = fmt; 255762306a36Sopenharmony_ci vaf.va = &args; 255862306a36Sopenharmony_ci 255962306a36Sopenharmony_ci /* Not using mlog here because we want to show the actual 256062306a36Sopenharmony_ci * function the error came from. */ 256162306a36Sopenharmony_ci printk(KERN_CRIT "OCFS2: ERROR (device %s): %s: %pV", 256262306a36Sopenharmony_ci sb->s_id, function, &vaf); 256362306a36Sopenharmony_ci 256462306a36Sopenharmony_ci va_end(args); 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci return ocfs2_handle_error(sb); 256762306a36Sopenharmony_ci} 256862306a36Sopenharmony_ci 256962306a36Sopenharmony_ci/* Handle critical errors. This is intentionally more drastic than 257062306a36Sopenharmony_ci * ocfs2_handle_error, so we only use for things like journal errors, 257162306a36Sopenharmony_ci * etc. */ 257262306a36Sopenharmony_civoid __ocfs2_abort(struct super_block *sb, const char *function, 257362306a36Sopenharmony_ci const char *fmt, ...) 257462306a36Sopenharmony_ci{ 257562306a36Sopenharmony_ci struct va_format vaf; 257662306a36Sopenharmony_ci va_list args; 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_ci va_start(args, fmt); 257962306a36Sopenharmony_ci 258062306a36Sopenharmony_ci vaf.fmt = fmt; 258162306a36Sopenharmony_ci vaf.va = &args; 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci printk(KERN_CRIT "OCFS2: abort (device %s): %s: %pV", 258462306a36Sopenharmony_ci sb->s_id, function, &vaf); 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci va_end(args); 258762306a36Sopenharmony_ci 258862306a36Sopenharmony_ci /* We don't have the cluster support yet to go straight to 258962306a36Sopenharmony_ci * hard readonly in here. Until then, we want to keep 259062306a36Sopenharmony_ci * ocfs2_abort() so that we can at least mark critical 259162306a36Sopenharmony_ci * errors. 259262306a36Sopenharmony_ci * 259362306a36Sopenharmony_ci * TODO: This should abort the journal and alert other nodes 259462306a36Sopenharmony_ci * that our slot needs recovery. */ 259562306a36Sopenharmony_ci 259662306a36Sopenharmony_ci /* Force a panic(). This stinks, but it's better than letting 259762306a36Sopenharmony_ci * things continue without having a proper hard readonly 259862306a36Sopenharmony_ci * here. */ 259962306a36Sopenharmony_ci if (!ocfs2_mount_local(OCFS2_SB(sb))) 260062306a36Sopenharmony_ci OCFS2_SB(sb)->s_mount_opt |= OCFS2_MOUNT_ERRORS_PANIC; 260162306a36Sopenharmony_ci ocfs2_handle_error(sb); 260262306a36Sopenharmony_ci} 260362306a36Sopenharmony_ci 260462306a36Sopenharmony_ci/* 260562306a36Sopenharmony_ci * Void signal blockers, because in-kernel sigprocmask() only fails 260662306a36Sopenharmony_ci * when SIG_* is wrong. 260762306a36Sopenharmony_ci */ 260862306a36Sopenharmony_civoid ocfs2_block_signals(sigset_t *oldset) 260962306a36Sopenharmony_ci{ 261062306a36Sopenharmony_ci int rc; 261162306a36Sopenharmony_ci sigset_t blocked; 261262306a36Sopenharmony_ci 261362306a36Sopenharmony_ci sigfillset(&blocked); 261462306a36Sopenharmony_ci rc = sigprocmask(SIG_BLOCK, &blocked, oldset); 261562306a36Sopenharmony_ci BUG_ON(rc); 261662306a36Sopenharmony_ci} 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_civoid ocfs2_unblock_signals(sigset_t *oldset) 261962306a36Sopenharmony_ci{ 262062306a36Sopenharmony_ci int rc = sigprocmask(SIG_SETMASK, oldset, NULL); 262162306a36Sopenharmony_ci BUG_ON(rc); 262262306a36Sopenharmony_ci} 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_cimodule_init(ocfs2_init); 262562306a36Sopenharmony_cimodule_exit(ocfs2_exit); 2626