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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		ntfs_error(vol->sb, "Mft record size (%i) is smaller than the "				"sector size (%i).  This is not supported.  "				"Sorry.", vol->mft_record_size,				vol->sector_size);		return false;	}	clusters_per_index_record = b->clusters_per_index_record;	ntfs_debug("clusters_per_index_record = %i (0x%x)",			clusters_per_index_record, clusters_per_index_record);	if (clusters_per_index_record > 0)		vol->index_record_size = vol->cluster_size <<				(ffs(clusters_per_index_record) - 1);	else		/*		 * When index_record_size < cluster_size,		 * clusters_per_index_record = -log2(index_record_size) bytes.		 * index_record_size normaly equals 4096 bytes, which is		 * encoded as 0xF4 (-12 in decimal).		 */		vol->index_record_size = 1 << -clusters_per_index_record;	vol->index_record_size_mask = vol->index_record_size - 1;	vol->index_record_size_bits = ffs(vol->index_record_size) - 1;	ntfs_debug("vol->index_record_size = %i (0x%x)",			vol->index_record_size, vol->index_record_size);	ntfs_debug("vol->index_record_size_mask = 0x%x",			vol->index_record_size_mask);	ntfs_debug("vol->index_record_size_bits = %i (0x%x)",			vol->index_record_size_bits,			vol->index_record_size_bits);	/* We cannot support index record sizes below the sector size. */	if (vol->index_record_size < vol->sector_size) {		ntfs_error(vol->sb, "Index record size (%i) is smaller than "				"the sector size (%i).  This is not "				"supported.  Sorry.", vol->index_record_size,				vol->sector_size);		return false;	}	/*	 * Get the size of the volume in clusters and check for 64-bit-ness.	 * Windows currently only uses 32 bits to save the clusters so we do	 * the same as it is much faster on 32-bit CPUs.	 */	ll = sle64_to_cpu(b->number_of_sectors) >> sectors_per_cluster_bits;	if ((u64)ll >= 1ULL << 32) {		ntfs_error(vol->sb, "Cannot handle 64-bit clusters.  Sorry.");		return false;	}	vol->nr_clusters = ll;	ntfs_debug("vol->nr_clusters = 0x%llx", (long long)vol->nr_clusters);	/*	 * On an architecture where unsigned long is 32-bits, we restrict the	 * volume size to 2TiB (2^41). On a 64-bit architecture, the compiler	 * will hopefully optimize the whole check away.	 */	if (sizeof(unsigned long) < 8) {		if ((ll << vol->cluster_size_bits) >= (1ULL << 41)) {			ntfs_error(vol->sb, "Volume size (%lluTiB) is too "					"large for this architecture.  "					"Maximum supported is 2TiB.  Sorry.",					(unsigned long long)ll >> (40 -					vol->cluster_size_bits));			return false;		}	}	ll = sle64_to_cpu(b->mft_lcn);	if (ll >= vol->nr_clusters) {		ntfs_error(vol->sb, "MFT LCN (%lli, 0x%llx) is beyond end of "				"volume.  Weird.", (unsigned long long)ll,				(unsigned long long)ll);		return false;	}	vol->mft_lcn = ll;	ntfs_debug("vol->mft_lcn = 0x%llx", (long long)vol->mft_lcn);	ll = sle64_to_cpu(b->mftmirr_lcn);	if (ll >= vol->nr_clusters) {		ntfs_error(vol->sb, "MFTMirr LCN (%lli, 0x%llx) is beyond end "				"of volume.  Weird.", (unsigned long long)ll,				(unsigned long long)ll);		return false;	}	vol->mftmirr_lcn = ll;	ntfs_debug("vol->mftmirr_lcn = 0x%llx", (long long)vol->mftmirr_lcn);#ifdef NTFS_RW	/*	 * Work out the size of the mft mirror in number of mft records. If the	 * cluster size is less than or equal to the size taken by four mft	 * records, the mft mirror stores the first four mft records. If the	 * cluster size is bigger than the size taken by four mft records, the	 * mft mirror contains as many mft records as will fit into one	 * cluster.	 */	if (vol->cluster_size <= (4 << vol->mft_record_size_bits))		vol->mftmirr_size = 4;	else		vol->mftmirr_size = vol->cluster_size >>				vol->mft_record_size_bits;	ntfs_debug("vol->mftmirr_size = %i", vol->mftmirr_size);#endif /* NTFS_RW */	vol->serial_no = le64_to_cpu(b->volume_serial_number);	ntfs_debug("vol->serial_no = 0x%llx",			(unsigned long long)vol->serial_no);	return true;}/** * ntfs_setup_allocators - initialize the cluster and mft allocators * @vol:	volume structure for which to setup the allocators * * Setup the cluster (lcn) and mft allocators to the starting values. */static void ntfs_setup_allocators(ntfs_volume *vol){#ifdef NTFS_RW	LCN mft_zone_size, mft_lcn;#endif /* NTFS_RW */	ntfs_debug("vol->mft_zone_multiplier = 0x%x",			vol->mft_zone_multiplier);#ifdef NTFS_RW	/* Determine the size of the MFT zone. */	mft_zone_size = vol->nr_clusters;	switch (vol->mft_zone_multiplier) {  /* % of volume size in clusters */	case 4:		mft_zone_size >>= 1;			/* 50%   */		break;	case 3:		mft_zone_size = (mft_zone_size +				(mft_zone_size >> 1)) >> 2;	/* 37.5% */		break;	case 2:		mft_zone_size >>= 2;			/* 25%   */		break;	/* case 1: */	default:		mft_zone_size >>= 3;			/* 12.5% */		break;	}	/* Setup the mft zone. */	vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn;	ntfs_debug("vol->mft_zone_pos = 0x%llx",			(unsigned long long)vol->mft_zone_pos);	/*	 * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs	 * source) and if the actual mft_lcn is in the expected place or even	 * further to the front of the volume, extend the mft_zone to cover the	 * beginning of the volume as well.  This is in order to protect the	 * area reserved for the mft bitmap as well within the mft_zone itself.	 * On non-standard volumes we do not protect it as the overhead would	 * be higher than the speed increase we would get by doing it.	 */	mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size;	if (mft_lcn * vol->cluster_size < 16 * 1024)		mft_lcn = (16 * 1024 + vol->cluster_size - 1) /				vol->cluster_size;	if (vol->mft_zone_start <= mft_lcn)		vol->mft_zone_start = 0;	ntfs_debug("vol->mft_zone_start = 0x%llx",			(unsigned long long)vol->mft_zone_start);	/*	 * Need to cap the mft zone on non-standard volumes so that it does	 * not point outside the boundaries of the volume.  We do this by	 * halving the zone size until we are inside the volume.	 */	vol->mft_zone_end = vol->mft_lcn + mft_zone_size;	while (vol->mft_zone_end >= vol->nr_clusters) {		mft_zone_size >>= 1;		vol->mft_zone_end = vol->mft_lcn + mft_zone_size;	}	ntfs_debug("vol->mft_zone_end = 0x%llx",			(unsigned long long)vol->mft_zone_end);	/*	 * Set the current position within each data zone to the start of the	 * respective zone.	 */	vol->data1_zone_pos = vol->mft_zone_end;	ntfs_debug("vol->data1_zone_pos = 0x%llx",			(unsigned long long)vol->data1_zone_pos);	vol->data2_zone_pos = 0;	ntfs_debug("vol->data2_zone_pos = 0x%llx",			(unsigned long long)vol->data2_zone_pos);	/* Set the mft data allocation position to mft record 24. */	vol->mft_data_pos = 24;	ntfs_debug("vol->mft_data_pos = 0x%llx",			(unsigned long long)vol->mft_data_pos);#endif /* NTFS_RW */}#ifdef NTFS_RW/** * load_and_init_mft_mirror - load and setup the mft mirror inode for a volume * @vol:	ntfs super block describing device whose mft mirror to load * * Return 'true' on success or 'false' on error. */static bool load_and_init_mft_mirror(ntfs_volume *vol){	struct inode *tmp_ino;	ntfs_inode *tmp_ni;	ntfs_debug("Entering.");	/* Get mft mirror inode. */	tmp_ino = ntfs_iget(vol->sb, FILE_MFTMirr);	if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {		if (!IS_ERR(tmp_ino))			iput(tmp_ino);		/* Caller will display error message. */		return false;	}	/*	 * Re-initialize some specifics about $MFTMirr's inode as	 * ntfs_read_inode() will have set up the default ones.	 */	/* Set uid and gid to root. */	tmp_ino->i_uid = tmp_ino->i_gid = 0;	/* Regular file.  No access for anyone. */	tmp_ino->i_mode = S_IFREG;	/* No VFS initiated operations allowed for $MFTMirr. */	tmp_ino->i_op = &ntfs_empty_inode_ops;	tmp_ino->i_fop = &ntfs_empty_file_ops;	/* Put in our special address space operations. */	tmp_ino->i_mapping->a_ops = &ntfs_mst_aops;	tmp_ni = NTFS_I(tmp_ino);	/* The $MFTMirr, like the $MFT is multi sector transfer protected. */	NInoSetMstProtected(tmp_ni);	NInoSetSparseDisabled(tmp_ni);	/*	 * Set up our little cheat allowing us to reuse the async read io	 * completion handler for directories.	 */	tmp_ni->itype.index.block_size = vol->mft_record_size;	tmp_ni->itype.index.block_size_bits = vol->mft_record_size_bits;	vol->mftmirr_ino = tmp_ino;	ntfs_debug("Done.");	return true;}/** * check_mft_mirror - compare contents of the mft mirror with the mft * @vol:	ntfs super block describing device whose mft mirror to check * * Return 'true' on success or 'false' on error. * * Note, this function also results in the mft mirror runlist being completely * mapped into memory.  The mft mirror write code requires this and will BUG() * should it find an unmapped runlist element. */static bool check_mft_mirror(ntfs_volume *vol){	struct super_block *sb = vol->sb;	ntfs_inode *mirr_ni;	struct page *mft_page, *mirr_page;	u8 *kmft, *kmirr;	runlist_element *rl, rl2[2];	pgoff_t index;	int mrecs_per_page, i;	ntfs_debug("Entering.");	/* Compare contents of $MFT and $MFTMirr. */	mrecs_per_page = PAGE_CACHE_SIZE / vol->mft_record_size;	BUG_ON(!mrecs_per_page);	BUG_ON(!vol->mftmirr_size);	mft_page = mirr_page = NULL;	kmft = kmirr = NULL;	index = i = 0;	do {		u32 bytes;		/* Switch pages if necessary. */		if (!(i % mrecs_per_page)) {			if (index) {				ntfs_unmap_page(mft_page);				ntfs_unmap_page(mirr_page);			}			/* Get the $MFT page. */			mft_page = ntfs_map_page(vol->mft_ino->i_mapping,					index);			if (IS_ERR(mft_page)) {				ntfs_error(sb, "Failed to read $MFT.");				return false;			}			kmft = page_address(mft_page);			/* Get the $MFTMirr page. */			mirr_page = ntfs_map_page(vol->mftmirr_ino->i_mapping,					index);			if (IS_ERR(mirr_page)) {				ntfs_error(sb, "Failed to read $MFTMirr.");				goto mft_unmap_out;			}			kmirr = page_address(mirr_page);			++index;		}		/* Do not check the record if it is not in use. */		if (((MFT_RECORD*)kmft)->flags & MFT_RECORD_IN_USE) {			/* Make sure the record is ok. */			if (ntfs_is_baad_recordp((le32*)kmft)) {				ntfs_error(sb, "Incomplete multi sector "						"transfer detected in mft "						"record %i.", i);mm_unmap_out:				ntfs_unmap_page(mirr_page);mft_unmap_out:				ntfs_unmap_page(mft_page);				return false;			}		}		/* Do not check the mirror record if it is not in use. */		if (((MFT_RECORD*)kmirr)->flags & MFT_RECORD_IN_USE) {			if (ntfs_is_baad_recordp((le32*)kmirr)) {				ntfs_error(sb, "Incomplete multi sector "						"transfer detected in mft "						"mirror record %i.", i);				goto mm_unmap_out;			}		}		/* Get the amount of data in the current record. */		bytes = le32_to_cpu(((MFT_RECORD*)kmft)->bytes_in_use);		if (bytes < sizeof(MFT_RECORD_OLD) ||				bytes > vol->mft_record_size ||				ntfs_is_baad_recordp((le32*)kmft)) {			bytes = le32_to_cpu(((MFT_RECORD*)kmirr)->bytes_in_use);			if (bytes < sizeof(MFT_RECORD_OLD) ||					bytes > vol->mft_record_size ||					ntfs_is_baad_recordp((le32*)kmirr))				bytes = vol->mft_record_size;		}		/* Compare the two records. */		if (memcmp(kmft, kmirr, bytes)) {			ntfs_error(sb, "$MFT and $MFTMirr (record %i) do not "					"match.  Run ntfsfix or chkdsk.", i);			goto mm_unmap_out;		}		kmft += vol->mft_record_size;		kmirr += vol->mft_record_size;	} while (++i < vol->mftmirr_size);	/* Release the last pages. */	ntfs_unmap_page(mft_page);	ntfs_unmap_page(mirr_page);	/* Construct the mft mirror runlist by hand. */	rl2[0].vcn = 0;	rl2[0].lcn = vol->mftmirr_lcn;	rl2[0].length = (vol->mftmirr_size * vol->mft_record_size +			vol->cluster_size - 1) / vol->cluster_size;	rl2[1].vcn = rl2[0].length;	rl2[1].lcn = LCN_ENOENT;	rl2[1].length = 0;	/*	 * Because we have just read all of the mft mirror, we know we have	 * mapped the full runlist for it.	 */	mirr_ni = NTFS_I(vol->mftmirr_ino);	down_read(&mirr_ni->runlist.lock);	rl = mirr_ni->runlist.rl;	/* Compare the two runlists.  They must be identical. */	i = 0;	do {		if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn ||				rl2[i].length != rl[i].length) {			ntfs_error(sb, "$MFTMirr location mismatch.  "					"Run chkdsk.");			up_read(&mirr_ni->runlist.lock);			return false;		}	} while (rl2[i++].length);	up_read(&mirr_ni->runlist.lock);	ntfs_debug("Done.");	return true;}/** * load_and_check_logfile - load and check the logfile inode for a volume * @vol:	ntfs super block describing device whose logfile to load * * Return 'true' on success or 'false' on error. */static bool load_and_check_logfile(ntfs_volume *vol,		RESTART_PAGE_HEADER **rp){	struct inode *tmp_ino;	ntfs_debug("Entering.");	tmp_ino = ntfs_iget(vol->sb, FILE_LogFile);	if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {		if (!IS_ERR(tmp_ino))			iput(tmp_ino);		/* Caller will display error message. */		return false;	}	if (!ntfs_check_logfile(tmp_ino, rp)) {		iput(tmp_ino);		/* ntfs_check_logfile() will have displayed error output. */		return false;	}	NInoSetSparseDisabled(NTFS_I(tmp_ino));	vol->logfile_ino = tmp_ino;	ntfs_debug("Done.");	return true;}#define NTFS_HIBERFIL_HEADER_SIZE	4096/**

⌨️ 快捷键说明

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