📄 super.c
字号:
"mount was not specified.\n"); goto read_super_error; } /* You should not be able to start a local heartbeat * on a readonly device. */ if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { status = -EROFS; mlog(ML_ERROR, "Local heartbeat specified on readonly " "device.\n"); goto read_super_error; } status = ocfs2_check_journals_nolocks(osb); if (status < 0) { if (status == -EROFS) mlog(ML_ERROR, "Recovery required on readonly " "file system, but write access is " "unavailable.\n"); else 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) " "with %s data mode.\n", osb->dev_str, nodestr, osb->slot_num, osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK ? "writeback" : "ordered"); atomic_set(&osb->vol_state, VOLUME_MOUNTED); wake_up(&osb->osb_mount_event); 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;}static 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);}static 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|FS_RENAME_DOES_D_MOVE, .next = NULL};static int ocfs2_parse_options(struct super_block *sb, char *options, struct mount_options *mopt, int is_remount){ int status; char *p; mlog_entry("remount: %d, options: \"%s\"\n", is_remount, options ? options : "(none)"); mopt->mount_opt = 0; mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; mopt->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: mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL; break; case Opt_hb_none: mopt->mount_opt &= ~OCFS2_MOUNT_HB_LOCAL; break; case Opt_barrier: if (match_int(&args[0], &option)) { status = 0; goto bail; } if (option) mopt->mount_opt |= OCFS2_MOUNT_BARRIER; else mopt->mount_opt &= ~OCFS2_MOUNT_BARRIER; break; case Opt_intr: mopt->mount_opt &= ~OCFS2_MOUNT_NOINTR; break; case Opt_nointr: mopt->mount_opt |= OCFS2_MOUNT_NOINTR; break; case Opt_err_panic: mopt->mount_opt |= OCFS2_MOUNT_ERRORS_PANIC; break; case Opt_err_ro: mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_PANIC; break; case Opt_data_ordered: mopt->mount_opt &= ~OCFS2_MOUNT_DATA_WRITEBACK; break; case Opt_data_writeback: mopt->mount_opt |= OCFS2_MOUNT_DATA_WRITEBACK; break; case Opt_atime_quantum: if (match_int(&args[0], &option)) { status = 0; goto bail; } if (option >= 0) mopt->atime_quantum = option; break; case Opt_slot: option = 0; if (match_int(&args[0], &option)) { status = 0; goto bail; } if (option) mopt->slot = (s16)option; break; 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 ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt){ struct ocfs2_super *osb = OCFS2_SB(mnt->mnt_sb); unsigned long opts = osb->s_mount_opt; if (opts & OCFS2_MOUNT_HB_LOCAL) seq_printf(s, ",_netdev,heartbeat=local"); else seq_printf(s, ",heartbeat=none"); if (opts & OCFS2_MOUNT_NOINTR) seq_printf(s, ",nointr"); if (opts & OCFS2_MOUNT_DATA_WRITEBACK) seq_printf(s, ",data=writeback"); else seq_printf(s, ",data=ordered"); if (opts & OCFS2_MOUNT_BARRIER) seq_printf(s, ",barrier=1"); if (opts & OCFS2_MOUNT_ERRORS_PANIC) seq_printf(s, ",errors=panic"); else seq_printf(s, ",errors=remount-ro"); if (osb->preferred_slot != OCFS2_INVALID_SLOT) seq_printf(s, ",preferred_slot=%d", osb->preferred_slot); if (osb->s_atime_quantum != OCFS2_DEFAULT_ATIME_QUANTUM) seq_printf(s, ",atime_quantum=%u", osb->s_atime_quantum); return 0;}static int __init ocfs2_init(void){ int status; mlog_entry_void(); ocfs2_print_version(); 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; } ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL); if (!ocfs2_debugfs_root) { status = -EFAULT; mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n"); }leave: if (status < 0) { ocfs2_free_mem_caches(); exit_ocfs2_uptodate_cache(); } 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); } debugfs_remove(ocfs2_debugfs_root); ocfs2_free_mem_caches(); unregister_filesystem(&ocfs2_fs_type); 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();}static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf){ 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", dentry->d_sb, buf); osb = OCFS2_SB(dentry->d_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, &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); buf->f_type = OCFS2_SUPER_MAGIC; buf->f_bsize = dentry->d_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(struct kmem_cache *cachep, void *data){ struct ocfs2_inode_info *oi = data; 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_io_markers); oi->ip_created_trans = 0; oi->ip_last_trans = 0; oi->ip_dir_start_lookup = 0; init_rwsem(&oi->ip_alloc_sem); mutex_init(&oi->ip_io_mutex); oi->ip_blkno = 0ULL; oi->ip_clusters = 0; ocfs2_lock_res_init_once(&oi->ip_rw_lockres); ocfs2_lock_res_init_once(&oi->ip_meta_lockres); ocfs2_lock_res_init_once(&oi->ip_data_lockres); ocfs2_lock_res_init_once(&oi->ip_open_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| SLAB_MEM_SPREAD), ocfs2_inode_init_once); if (!ocfs2_inode_cachep) return -ENOMEM; return 0;}static void ocfs2_free_mem_caches(void){ if (ocfs2_inode_cachep) kmem_cache_destroy(ocfs2_inode_cachep); ocfs2_inode_cachep = 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 leave; 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 leave; /* 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);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_shutdown_local_alloc(osb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -