📄 super.c
字号:
mlog_errno(status); goto read_super_error; } ocfs2_set_ro_flag(osb, 1); printk(KERN_NOTICE "Readonly device detected. No cluster " "services will be utilized for this mount. Recovery " "will be skipped.\n"); } if (!ocfs2_is_hard_readonly(osb)) { if (sb->s_flags & MS_RDONLY) ocfs2_set_ro_flag(osb, 0); } status = ocfs2_verify_heartbeat(osb); if (status < 0) { mlog_errno(status); goto read_super_error; } osb->osb_debug_root = debugfs_create_dir(osb->uuid_str, ocfs2_debugfs_root); if (!osb->osb_debug_root) { status = -EINVAL; mlog(ML_ERROR, "Unable to create per-mount debugfs root.\n"); goto read_super_error; } status = ocfs2_mount_volume(sb); if (osb->root_inode) inode = igrab(osb->root_inode); if (status < 0) goto read_super_error; if (!inode) { status = -EIO; mlog_errno(status); goto read_super_error; } root = d_alloc_root(inode); if (!root) { status = -ENOMEM; mlog_errno(status); goto read_super_error; } sb->s_root = root; ocfs2_complete_mount_recovery(osb); if (ocfs2_mount_local(osb)) snprintf(nodestr, sizeof(nodestr), "local"); else snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num); printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %s, slot %d)\n", osb->dev_str, nodestr, osb->slot_num); atomic_set(&osb->vol_state, VOLUME_MOUNTED); wake_up(&osb->osb_mount_event);#ifdef HAS_MS_LOOP_NO_AOPS /* OCFS2's prepare and commit write operations don't do any locking. */ sb->s_flags |= MS_LOOP_NO_AOPS;#endif mlog_exit(status); return status;read_super_error: if (bh != NULL) brelse(bh); if (inode) iput(inode); if (osb) { atomic_set(&osb->vol_state, VOLUME_DISABLED); wake_up(&osb->osb_mount_event); ocfs2_dismount_volume(sb, 1); } mlog_exit(status); return status;}#ifdef GET_SB_RETURNS_SBstatic struct super_block *ocfs2_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data){ return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super);}#elsestatic int ocfs2_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt){ return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super, mnt);}#endifstatic struct file_system_type ocfs2_fs_type = { .owner = THIS_MODULE, .name = "ocfs2", .get_sb = ocfs2_get_sb, /* is this called when we mount * the fs? */ .kill_sb = kill_block_super, /* set to the generic one * right now, but do we * need to change that? */ .fs_flags = FS_REQUIRES_DEV, .next = NULL};static int ocfs2_parse_options(struct super_block *sb, char *options, unsigned long *mount_opt, s16 *slot, int is_remount){ int status; char *p; mlog_entry("remount: %d, options: \"%s\"\n", is_remount, options ? options : "(none)"); *mount_opt = 0; *slot = OCFS2_INVALID_SLOT; if (!options) { status = 1; goto bail; } while ((p = strsep(&options, ",")) != NULL) { int token, option; substring_t args[MAX_OPT_ARGS]; if (!*p) continue; token = match_token(p, tokens, args); switch (token) { case Opt_hb_local: *mount_opt |= OCFS2_MOUNT_HB_LOCAL; break; case Opt_hb_none: *mount_opt &= ~OCFS2_MOUNT_HB_LOCAL; break; case Opt_barrier: if (match_int(&args[0], &option)) { status = 0; goto bail; } if (option) *mount_opt |= OCFS2_MOUNT_BARRIER; else *mount_opt &= ~OCFS2_MOUNT_BARRIER; break; case Opt_intr: *mount_opt &= ~OCFS2_MOUNT_NOINTR; break; case Opt_nointr: *mount_opt |= OCFS2_MOUNT_NOINTR; break; case Opt_err_panic: *mount_opt |= OCFS2_MOUNT_ERRORS_PANIC; break; case Opt_err_ro: *mount_opt &= ~OCFS2_MOUNT_ERRORS_PANIC; break; case Opt_slot: option = 0; if (match_int(&args[0], &option)) { status = 0; goto bail; } if (option) *slot = (s16)option; break;#ifdef OCFS2_ORACORE_WORKAROUNDS case Opt_datavolume: if (is_remount) { mlog(ML_ERROR, "Cannot specifiy datavolume " "on remount.\n"); status = 0; goto bail; } *mount_opt |= OCFS2_MOUNT_COMPAT_OCFS; break;#endif default: mlog(ML_ERROR, "Unrecognized mount option \"%s\" " "or missing value\n", p); status = 0; goto bail; } } status = 1;bail: mlog_exit(status); return status;}static int __init ocfs2_init(void){ int status; mlog_entry_void(); ocfs2_print_version(); if (init_ocfs2_extent_maps()) return -ENOMEM; status = init_ocfs2_uptodate_cache(); if (status < 0) { mlog_errno(status); goto leave; } status = ocfs2_initialize_mem_caches(); if (status < 0) { mlog_errno(status); goto leave; } ocfs2_wq = create_singlethread_workqueue("ocfs2_wq"); if (!ocfs2_wq) { status = -ENOMEM; goto leave; } spin_lock(&ocfs2_globals_lock); osb_id = 0; spin_unlock(&ocfs2_globals_lock); ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL); if (!ocfs2_debugfs_root) { status = -EFAULT; mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n"); } /* Initialize the proc interface */ ocfs2_proc_init();leave: if (status < 0) { ocfs2_free_mem_caches(); exit_ocfs2_uptodate_cache(); exit_ocfs2_extent_maps(); } mlog_exit(status); if (status >= 0) { return register_filesystem(&ocfs2_fs_type); } else return -1;}static void __exit ocfs2_exit(void){ mlog_entry_void(); if (ocfs2_wq) { flush_workqueue(ocfs2_wq); destroy_workqueue(ocfs2_wq); } ocfs2_free_mem_caches(); /* Deinit the proc interface */ ocfs2_proc_deinit(); debugfs_remove(ocfs2_debugfs_root); unregister_filesystem(&ocfs2_fs_type); exit_ocfs2_extent_maps(); exit_ocfs2_uptodate_cache(); mlog_exit_void();}static void ocfs2_put_super(struct super_block *sb){ mlog_entry("(0x%p)\n", sb); ocfs2_sync_blockdev(sb); ocfs2_dismount_volume(sb, 0); mlog_exit_void();}#ifdef STATFS_GETS_SBstatic int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf){#elsestatic int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf){ struct super_block *sb = dentry->d_sb;#endif struct ocfs2_super *osb; u32 numbits, freebits; int status; struct ocfs2_dinode *bm_lock; struct buffer_head *bh = NULL; struct inode *inode = NULL; mlog_entry("(%p, %p)\n", sb, buf); osb = OCFS2_SB(sb); inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, OCFS2_INVALID_SLOT); if (!inode) { mlog(ML_ERROR, "failed to get bitmap inode\n"); status = -EIO; goto bail; } status = ocfs2_meta_lock(inode, NULL, &bh, 0); if (status < 0) { mlog_errno(status); goto bail; } bm_lock = (struct ocfs2_dinode *) bh->b_data; numbits = le32_to_cpu(bm_lock->id1.bitmap1.i_total); freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used);#ifdef OCFS2_ORACORE_WORKAROUNDS if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS) buf->f_type = OCFS_SUPER_MAGIC; else#endif buf->f_type = OCFS2_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_namelen = OCFS2_MAX_FILENAME_LEN; buf->f_blocks = ((sector_t) numbits) * (osb->s_clustersize >> osb->sb->s_blocksize_bits); buf->f_bfree = ((sector_t) freebits) * (osb->s_clustersize >> osb->sb->s_blocksize_bits); buf->f_bavail = buf->f_bfree; buf->f_files = numbits; buf->f_ffree = freebits; brelse(bh); ocfs2_meta_unlock(inode, 0); status = 0;bail: if (inode) iput(inode); mlog_exit(status); return status;}static void ocfs2_inode_init_once(void *data, kmem_cache_t *cachep, unsigned long flags){ struct ocfs2_inode_info *oi = data; if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { oi->ip_flags = 0; oi->ip_open_count = 0; spin_lock_init(&oi->ip_lock); ocfs2_extent_map_init(&oi->vfs_inode); INIT_LIST_HEAD(&oi->ip_handle_list); INIT_LIST_HEAD(&oi->ip_io_markers); oi->ip_handle = NULL; oi->ip_created_trans = 0; oi->ip_last_trans = 0; oi->ip_dir_start_lookup = 0; init_rwsem(&oi->ip_alloc_sem); init_MUTEX(&(oi->ip_io_sem)); oi->ip_blkno = 0ULL; oi->ip_clusters = 0; oi->ip_mmu_private = 0LL; ocfs2_lock_res_init_once(&oi->ip_meta_lockres); ocfs2_lock_res_init_once(&oi->ip_data_lockres); ocfs2_metadata_cache_init(&oi->vfs_inode); inode_init_once(&oi->vfs_inode); }}static int ocfs2_initialize_mem_caches(void){ ocfs2_inode_cachep = kmem_cache_create("ocfs2_inode_cache", sizeof(struct ocfs2_inode_info), 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, ocfs2_inode_init_once, NULL); if (!ocfs2_inode_cachep) return -ENOMEM; ocfs2_lock_cache = kmem_cache_create("ocfs2_lock", sizeof(struct ocfs2_journal_lock), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!ocfs2_lock_cache) return -ENOMEM; return 0;}static void ocfs2_free_mem_caches(void){ if (ocfs2_inode_cachep) kmem_cache_destroy(ocfs2_inode_cachep); if (ocfs2_lock_cache) kmem_cache_destroy(ocfs2_lock_cache); ocfs2_inode_cachep = NULL; ocfs2_lock_cache = NULL;}static int ocfs2_get_sector(struct super_block *sb, struct buffer_head **bh, int block, int sect_size){ if (!sb_set_blocksize(sb, sect_size)) { mlog(ML_ERROR, "unable to set blocksize\n"); return -EIO; } *bh = sb_getblk(sb, block); if (!*bh) { mlog_errno(-EIO); return -EIO; } lock_buffer(*bh); if (!buffer_dirty(*bh)) clear_buffer_uptodate(*bh); unlock_buffer(*bh); ll_rw_block(READ, 1, bh); wait_on_buffer(*bh); return 0;}/* ocfs2 1.0 only allows one cluster and node identity per kernel image. */static int ocfs2_fill_local_node_info(struct ocfs2_super *osb){ int status; /* XXX hold a ref on the node while mounte? easy enough, if * desirable. */ if (ocfs2_mount_local(osb)) osb->node_num = 0; else osb->node_num = o2nm_this_node(); if (osb->node_num == O2NM_MAX_NODES) { mlog(ML_ERROR, "could not find this host's node number\n"); status = -ENOENT; goto bail; } mlog(0, "I am node %d\n", osb->node_num); status = 0;bail: return status;}static int ocfs2_mount_volume(struct super_block *sb){ int status = 0; int unlock_super = 0; struct ocfs2_super *osb = OCFS2_SB(sb); mlog_entry_void(); if (ocfs2_is_hard_readonly(osb)) goto out_add_proc; status = ocfs2_fill_local_node_info(osb); if (status < 0) { mlog_errno(status); goto leave; } status = ocfs2_register_hb_callbacks(osb); if (status < 0) { mlog_errno(status); goto leave; } status = ocfs2_dlm_init(osb); if (status < 0) { mlog_errno(status); goto leave; } /* requires vote_thread to be running. */ status = ocfs2_register_net_handlers(osb); if (status < 0) { mlog_errno(status); goto leave; } status = ocfs2_super_lock(osb, 1); if (status < 0) { mlog_errno(status); goto leave; } unlock_super = 1; /* This will load up the node map and add ourselves to it. */ status = ocfs2_find_slot(osb); if (status < 0) { mlog_errno(status); goto leave; } ocfs2_populate_mounted_map(osb); /* load all node-local system inodes */ status = ocfs2_init_local_system_inodes(osb); if (status < 0) { mlog_errno(status); goto leave; } status = ocfs2_check_volume(osb); if (status < 0) { mlog_errno(status); goto leave; } status = ocfs2_truncate_log_init(osb); if (status < 0) { mlog_errno(status); goto leave; } if (ocfs2_mount_local(osb)) goto out_add_proc; /* This should be sent *after* we recovered our journal as it * will cause other nodes to unmark us as needing * recovery. However, we need to send it *before* dropping the * super block lock as otherwise their recovery threads might * try to clean us up while we're live! */ status = ocfs2_request_mount_vote(osb); if (status < 0) mlog_errno(status);out_add_proc: /* Add proc entry for this volume */ ocfs2_proc_add_volume(osb);leave: if (unlock_super) ocfs2_super_unlock(osb, 1); mlog_exit(status); return status;}/* we can't grab the goofy sem lock from inside wait_event, so we use * memory barriers to make sure that we'll see the null task before * being woken up */static int ocfs2_recovery_thread_running(struct ocfs2_super *osb){ mb(); return osb->recovery_thread_task != NULL;}static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err){ int tmp; struct ocfs2_super *osb = NULL; char nodestr[8]; mlog_entry("(0x%p)\n", sb); BUG_ON(!sb); osb = OCFS2_SB(sb); BUG_ON(!osb); ocfs2_wait_for_okp_destruction(osb); ocfs2_shutdown_local_alloc(osb); ocfs2_truncate_log_shutdown(osb); /* disable any new recovery threads and wait for any currently * running ones to exit. Do this before setting the vol_state. */ down(&osb->recovery_lock); osb->disable_recovery = 1; up(&osb->recovery_lock); wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb)); /* At this point, we know that no more recovery threads can be * launched, so wait for any recovery completion work to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -