⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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;		}		tmp = ocfs2_request_umount_vote(osb);		if (tmp < 0)			mlog_errno(tmp);	}	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_unregister_net_handlers(osb);		ocfs2_dlm_shutdown(osb);	}	ocfs2_clear_hb_callbacks(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 buffer_head *bitmap_bh = 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;	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);	bbits = le32_to_cpu(di->id2.i_super.s_blocksize_bits);	sb->s_maxbytes = ocfs2_max_file_offset(bbits, cbits);	osb->sb = sb;	/* Save off for ocfs2_rw_direct */	osb->s_sectsize_bits = blksize_bits(sector_size);	BUG_ON(!osb->s_sectsize_bits);	osb->net_response_ids = 0;	spin_lock_init(&osb->net_response_lock);	INIT_LIST_HEAD(&osb->net_response_list);	INIT_LIST_HEAD(&osb->osb_net_handlers);	init_waitqueue_head(&osb->recovery_event);	spin_lock_init(&osb->vote_task_lock);	init_waitqueue_head(&osb->vote_event);	osb->vote_work_sequence = 0;	osb->vote_wake_sequence = 0;	INIT_LIST_HEAD(&osb->blocked_lock_list);	osb->blocked_lock_count = 0;	INIT_LIST_HEAD(&osb->vote_list);	spin_lock_init(&osb->osb_lock);	atomic_set(&osb->alloc_stats.moves, 0);	atomic_set(&osb->alloc_stats.local_data, 0);	atomic_set(&osb->alloc_stats.bitmap_data, 0);	atomic_set(&osb->alloc_stats.bg_allocs, 0);	atomic_set(&osb->alloc_stats.bg_extends, 0);	ocfs2_init_node_maps(osb);	snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",		 MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));	mutex_init(&osb->recovery_lock);	osb->disable_recovery = 0;	osb->recovery_thread_task = NULL;	init_waitqueue_head(&osb->checkpoint_event);	atomic_set(&osb->needs_checkpoint, 0);	osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;	osb->node_num = O2NM_INVALID_NODE_NUM;	osb->slot_num = OCFS2_INVALID_SLOT;	osb->local_alloc_state = OCFS2_LA_UNUSED;	osb->local_alloc_bh = NULL;	ocfs2_setup_hb_callbacks(osb);	init_waitqueue_head(&osb->osb_mount_event);	osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL);	if (!osb->vol_label) {		mlog(ML_ERROR, "unable to alloc vol label\n");		status = -ENOMEM;		goto bail;	}	osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots);	if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) {		mlog(ML_ERROR, "Invalid number of node slots (%u)\n",		     osb->max_slots);		status = -EINVAL;		goto bail;	}	mlog(0, "max_slots for this device: %u\n", osb->max_slots);	init_waitqueue_head(&osb->osb_wipe_event);	osb->osb_orphan_wipes = kcalloc(osb->max_slots,					sizeof(*osb->osb_orphan_wipes),					GFP_KERNEL);	if (!osb->osb_orphan_wipes) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	osb->s_feature_compat =		le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_compat);	osb->s_feature_ro_compat =		le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_ro_compat);	osb->s_feature_incompat =		le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_incompat);	if ((i = OCFS2_HAS_INCOMPAT_FEATURE(osb->sb, ~OCFS2_FEATURE_INCOMPAT_SUPP))) {		mlog(ML_ERROR, "couldn't mount because of unsupported "		     "optional features (%x).\n", i);		status = -EINVAL;		goto bail;	}	if (!(osb->sb->s_flags & MS_RDONLY) &&	    (i = OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, ~OCFS2_FEATURE_RO_COMPAT_SUPP))) {		mlog(ML_ERROR, "couldn't mount RDWR because of "		     "unsupported optional features (%x).\n", i);		status = -EINVAL;		goto bail;	}	get_random_bytes(&osb->s_next_generation, sizeof(u32));	/* FIXME	 * This should be done in ocfs2_journal_init(), but unknown	 * ordering issues will cause the filesystem to crash.	 * If anyone wants to figure out what part of the code	 * refers to osb->journal before ocfs2_journal_init() is run,	 * be my guest.	 */	/* initialize our journal structure */	journal = kzalloc(sizeof(struct ocfs2_journal), GFP_KERNEL);	if (!journal) {		mlog(ML_ERROR, "unable to alloc journal\n");		status = -ENOMEM;		goto bail;	}	osb->journal = journal;	journal->j_osb = osb;	atomic_set(&journal->j_num_trans, 0);	init_rwsem(&journal->j_trans_barrier);	init_waitqueue_head(&journal->j_checkpointed);	spin_lock_init(&journal->j_lock);	journal->j_trans_id = (unsigned long) 1;	INIT_LIST_HEAD(&journal->j_la_cleanups);	INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery);	journal->j_state = OCFS2_JOURNAL_FREE;	/* get some pseudo constants for clustersize bits */	osb->s_clustersize_bits =		le32_to_cpu(di->id2.i_super.s_clustersize_bits);	osb->s_clustersize = 1 << osb->s_clustersize_bits;	mlog(0, "clusterbits=%d\n", osb->s_clustersize_bits);	if (osb->s_clustersize < OCFS2_MIN_CLUSTERSIZE ||	    osb->s_clustersize > OCFS2_MAX_CLUSTERSIZE) {		mlog(ML_ERROR, "Volume has invalid cluster size (%d)\n",		     osb->s_clustersize);		status = -EINVAL;		goto bail;	}	if (ocfs2_clusters_to_blocks(osb->sb, le32_to_cpu(di->i_clusters) - 1)	    > (u32)~0UL) {		mlog(ML_ERROR, "Volume might try to write to blocks beyond "		     "what jbd can address in 32 bits.\n");		status = -EINVAL;		goto bail;	}	if (ocfs2_setup_osb_uuid(osb, di->id2.i_super.s_uuid,				 sizeof(di->id2.i_super.s_uuid))) {		mlog(ML_ERROR, "Out of memory trying to setup our uuid.\n");		status = -ENOMEM;		goto bail;	}	memcpy(&uuid_net_key, di->id2.i_super.s_uuid, sizeof(uuid_net_key));	osb->net_key = le32_to_cpu(uuid_net_key);	strncpy(osb->vol_label, di->id2.i_super.s_label, 63);	osb->vol_label[63] = '\0';	osb->root_blkno = le64_to_cpu(di->id2.i_super.s_root_blkno);	osb->system_dir_blkno = le64_to_cpu(di->id2.i_super.s_system_dir_blkno);	osb->first_cluster_group_blkno =		le64_to_cpu(di->id2.i_super.s_first_cluster_group);	osb->fs_generation = le32_to_cpu(di->i_fs_generation);	mlog(0, "vol_label: %s\n", osb->vol_label);	mlog(0, "uuid: %s\n", osb->uuid_str);	mlog(0, "root_blkno=%llu, system_dir_blkno=%llu\n",	     (unsigned long long)osb->root_blkno,	     (unsigned long long)osb->system_dir_blkno);	osb->osb_dlm_debug = ocfs2_new_dlm_debug();	if (!osb->osb_dlm_debug) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	atomic_set(&osb->vol_state, VOLUME_INIT);	/* load root, system_dir, and all global system inodes */	status = ocfs2_init_global_system_inodes(osb);	if (status < 0) {		mlog_errno(status);		goto bail;	}	/*	 * global bitmap	 */	inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE,					    OCFS2_INVALID_SLOT);	if (!inode) {		status = -EINVAL;		mlog_errno(status);		goto bail;	}	osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno;	/* We don't have a cluster lock on the bitmap here because	 * we're only interested in static information and the extra	 * complexity at mount time isn't worht it. Don't pass the	 * inode in to the read function though as we don't want it to	 * be put in the cache. */	status = ocfs2_read_block(osb, osb->bitmap_blkno, &bitmap_bh, 0,				  NULL);	iput(inode);	if (status < 0) {		mlog_errno(status);		goto bail;	}	di = (struct ocfs2_dinode *) bitmap_bh->b_data;	osb->bitmap_cpg = le16_to_cpu(di->id2.i_chain.cl_cpg);	brelse(bitmap_bh);	mlog(0, "cluster bitmap inode: %llu, clusters per group: %u\n",	     (unsigned long long)osb->bitmap_blkno, osb->bitmap_cpg);	status = ocfs2_init_slot_info(osb);	if (status < 0) {		mlog_errno(status);		goto bail;	}bail:	mlog_exit(status);	return status;}/* * will return: -EAGAIN if it is ok to keep searching for superblocks *              -EINVAL if there is a bad superblock *              0 on success */static int ocfs2_verify_volume(struct ocfs2_dinode *di,			       struct buffer_head *bh,			       u32 blksz){	int status = -EAGAIN;	mlog_entry_void();	if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE,		   strlen(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0) {		status = -EINVAL;		if ((1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits)) != blksz) {			mlog(ML_ERROR, "found superblock with incorrect block "			     "size: found %u, should be %u\n",			     1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits),			       blksz);		} else if (le16_to_cpu(di->id2.i_super.s_major_rev_level) !=			   OCFS2_MAJOR_REV_LEVEL ||			   le16_to_cpu(di->id2.i_super.s_minor_rev_level) !=			   OCFS2_MINOR_REV_LEVEL) {			mlog(ML_ERROR, "found superblock with bad version: "			     "found %u.%u, should be %u.%u\n",			     le16_to_cpu(di->id2.i_super.s_major_rev_level),			     le16_to_cpu(di->id2.i_super.s_minor_rev_level),			     OCFS2_MAJOR_REV_LEVEL,			     OCFS2_MINOR_REV_LEVEL);		} else if (bh->b_blocknr != le64_to_cpu(di->i_blkno)) {			mlog(ML_ERROR, "bad block number on superblock: "			     "found %llu, should be %llu\n",			     (unsigned long long)le64_to_cpu(di->i_blkno),			     (unsigned long long)bh->b_blocknr);		} else if (le32_to_cpu(di->id2.i_super.s_clustersize_bits) < 12 ||			    le32_to_cpu(di->id2.i_super.s_clustersize_bits) > 20) {			mlog(ML_ERROR, "bad cluster size found: %u\n",			     1 << le32_to_cpu(di->id2.i_super.s_clustersize_bits));		} else if (!le64_to_cpu(di->id2.i_super.s_root_blkno)) {			mlog(ML_ERROR, "bad root_blkno: 0\n");		} else if (!le64_to_cpu(di->id2.i_super.s_system_dir_blkno)) {			mlog(ML_ERROR, "bad system_dir_blkno: 0\n");		} else if (le16_to_cpu(di->id2.i_super.s_max_slots) > OCFS2_MAX_SLOTS) {			mlog(ML_ERROR,			     "Superblock slots found greater than file system "			     "maximum: found %u, max %u\n",			     le16_to_cpu(di->id2.i_super.s_max_slots),			     OCFS2_MAX_SLOTS);		} else {			/* found it! */			status = 0;		}	}	mlog_exit(status);	return status;}static int ocfs2_check_volume(struct ocfs2_super *osb){	int status;	int dirty;	int local;	struct ocfs2_dinode *local_alloc = NULL; /* only used if we						  * recover						  * ourselves. */	mlog_entry_void();	/* Init our journal object. */	status = ocfs2_journal_init(osb->journal, &dirty);	if (status < 0) {		mlog(ML_ERROR, "Could not initialize journal!\n");		goto finally;	}	/* If the journal was unmounted cleanly then we don't want to	 * recover anything. Otherwise, journal_load will do that	 * dirty work for us :) */	if (!dirty) {		status = ocfs2_journal_wipe(osb->journal, 0);		if (status < 0) {			mlog_errno(status);			goto finally;		}	} else {		mlog(ML_NOTICE, "File system was not unmounted cleanly, "		     "recovering volume.\n");	}	local = ocfs2_mount_local(osb);	/* will play back anything left in the journal. */	ocfs2_journal_load(osb->journal, local);	if (dirty) {		/* recover my local alloc if we didn't unmount cleanly. */		status = ocfs2_begin_local_alloc_recovery(osb,							  osb->slot_num,							  &local_alloc);		if (status < 0) {			mlog_errno(status);			goto finally;		}		/* we complete the recovery process after we've marked		 * ourselves as mounted. */	}	mlog(0, "Journal loaded.\n");	status = ocfs2_load_local_alloc(osb);	if (status < 0) {		mlog_errno(status);		goto finally;	}	if (dirty) {		/* Recovery will be completed after we've mounted the		 * rest of the volume. */		osb->dirty = 1;		osb->local_alloc_copy = local_alloc;		local_alloc = NULL;	}	/* go through each journal, trylock it and if you get the	 * lock, and it's marked as dirty, set the bit in the recover	 * map and launch a recovery thread for it. */	status = ocfs2_mark_dead_nodes(osb);	if (status < 0)		mlog_errno(status);finally:	if (local_alloc)		kfree(local_alloc);	mlog_exit(status);	return status;}/* * The routine gets called from dismount or close whenever a dismount on * volume is requested and the osb open count becomes 1. * It will remove the osb from the global list and also free up all the * initialized resources and fileobject. */static void ocfs2_delete_osb(struct ocfs2_super *osb){	mlog_entry_void();	/* This function assumes that the caller has the main osb resource */	if (osb->slot_info)		ocfs2_free_slot_info(osb->slot_info);	kfree(osb->osb_orphan_wipes);	/* FIXME	 * This belongs in journal shutdown, but because we have to	 * allocate osb->journal at the start of ocfs2_initalize_osb(),	 * we free it here.	 */	kfree(osb->journal);	if (osb->local_alloc_copy)		kfree(osb->local_alloc_copy);	kfree(osb->uuid_str);	ocfs2_put_dlm_debug(osb->osb_dlm_debug);	memset(osb, 0, sizeof(struct ocfs2_super));	mlog_exit_void();}/* Put OCFS2 into a readonly state, or (if the user specifies it), * panic(). We do not support continue-on-error operation. */static void ocfs2_handle_error(struct super_block *sb){	struct ocfs2_super *osb = OCFS2_SB(sb);	if (osb->s_mount_opt & OCFS2_MOUNT_ERRORS_PANIC)		panic("OCFS2: (device %s): panic forced after error\n",		      sb->s_id);	ocfs2_set_osb_flag(osb, OCFS2_OSB_ERROR_FS);	if (sb->s_flags & MS_RDONLY &&	    (ocfs2_is_soft_readonly(osb) ||	     ocfs2_is_hard_readonly(osb)))		return;	printk(KERN_CRIT "File system is now read-only due to the potential "	       "of on-disk corruption. Please run fsck.ocfs2 once the file "	       "system is unmounted.\n");	sb->s_flags |= MS_RDONLY;	ocfs2_set_ro_flag(osb, 0);}static char error_buf[1024];void __ocfs2_error(struct super_block *sb,		   const char *function,		   const char *fmt, ...){	va_list args;	va_start(args, fmt);	vsnprintf(error_buf, sizeof(error_buf), fmt, args);	va_end(args);	/* Not using mlog here because we want to show the actual	 * function the error came from. */	printk(KERN_CRIT "OCFS2: ERROR (device %s): %s: %s\n",	       sb->s_id, function, error_buf);	ocfs2_handle_error(sb);}/* Handle critical errors. This is intentionally more drastic than * ocfs2_handle_error, so we only use for things like journal errors, * etc. */void __ocfs2_abort(struct super_block* sb,		   const char *function,		   const char *fmt, ...){	va_list args;	va_start(args, fmt);	vsnprintf(error_buf, sizeof(error_buf), fmt, args);	va_end(args);	printk(KERN_CRIT "OCFS2: abort (device %s): %s: %s\n",	       sb->s_id, function, error_buf);	/* We don't have the cluster support yet to go straight to	 * hard readonly in here. Until then, we want to keep	 * ocfs2_abort() so that we can at least mark critical	 * errors.	 *	 * TODO: This should abort the journal and alert other nodes	 * that our slot needs recovery. */	/* Force a panic(). This stinks, but it's better than letting	 * things continue without having a proper hard readonly	 * here. */	OCFS2_SB(sb)->s_mount_opt |= OCFS2_MOUNT_ERRORS_PANIC;	ocfs2_handle_error(sb);}module_init(ocfs2_init);module_exit(ocfs2_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -