📄 super.c
字号:
#ifdef OCFS2_ORACORE_WORKAROUNDS if (opts & OCFS2_MOUNT_COMPAT_OCFS) seq_printf(s, ",datavolume");#endif 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); if (osb->osb_commit_interval) seq_printf(s, ",commit=%u", (unsigned) (osb->osb_commit_interval / HZ)); if (osb->local_alloc_size != OCFS2_DEFAULT_LOCAL_ALLOC_SIZE) seq_printf(s, ",localalloc=%d", osb->local_alloc_size); if (opts & OCFS2_MOUNT_LOCALFLOCKS) seq_printf(s, ",localflocks,"); 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 inline 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_inode_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);#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 = 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_inode_unlock(inode, 0); status = 0;bail: if (inode) iput(inode); mlog_exit(status); return status;}#ifdef STATFS_TAKES_SBstatic int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf){ return _ocfs2_statfs(sb->s_root, buf);}#elsestatic int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf){ return _ocfs2_statfs(dentry, buf);}#endifstatic void ocfs2_inode_init_once(void *data, struct kmem_cache *cachep, unsigned long flags){ 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_inode_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 = kapi_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_dlm_init(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; } /* 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;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); 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. */ mutex_lock(&osb->recovery_lock); osb->disable_recovery = 1; mutex_unlock(&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 * complete. */ flush_workqueue(ocfs2_wq); ocfs2_journal_shutdown(osb); ocfs2_sync_blockdev(sb); /* No dlm means we've failed during mount, so skip all the * steps which depended on that to complete. */ if (osb->dlm) { tmp = ocfs2_super_lock(osb, 1); if (tmp < 0) { mlog_errno(tmp); return; } } if (osb->slot_num != OCFS2_INVALID_SLOT) ocfs2_put_slot(osb); if (osb->dlm) ocfs2_super_unlock(osb, 1); ocfs2_release_system_inodes(osb); if (osb->dlm) ocfs2_dlm_shutdown(osb); debugfs_remove(osb->osb_debug_root); if (!mnt_err) ocfs2_stop_heartbeat(osb); atomic_set(&osb->vol_state, VOLUME_DISMOUNTED); if (ocfs2_mount_local(osb)) snprintf(nodestr, sizeof(nodestr), "local"); else snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num); printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %s)\n", osb->dev_str, nodestr); ocfs2_delete_osb(osb); kfree(osb); sb->s_dev = 0; sb->s_fs_info = NULL;}static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uuid, unsigned uuid_bytes){ int i, ret; char *ptr; BUG_ON(uuid_bytes != OCFS2_VOL_UUID_LEN); osb->uuid_str = kzalloc(OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL); if (osb->uuid_str == NULL) return -ENOMEM; for (i = 0, ptr = osb->uuid_str; i < OCFS2_VOL_UUID_LEN; i++) { /* print with null */ ret = snprintf(ptr, 3, "%02X", uuid[i]); if (ret != 2) /* drop super cleans up */ return -EINVAL; /* then only advance past the last char */ ptr += 2; } return 0;}static int ocfs2_initialize_super(struct super_block *sb, struct buffer_head *bh, int sector_size){ int status; int i, cbits, bbits; struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; struct inode *inode = NULL; struct ocfs2_journal *journal; __le32 uuid_net_key; struct ocfs2_super *osb; mlog_entry_void(); osb = kzalloc(sizeof(struct ocfs2_super), GFP_KERNEL); if (!osb) { status = -ENOMEM; mlog_errno(status); goto bail; } sb->s_fs_info = osb; sb->s_op = &ocfs2_sops; sb->s_export_op = &ocfs2_export_ops; osb->osb_locking_proto = ocfs2_locking_protocol; sb->s_time_gran = 1; sb->s_flags |= MS_NOATIME; /* this is needed to support O_LARGEFILE */ cbits = le32_to_cpu(di->id2.i_super.s_clustersize_bits);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -