super.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,070 行 · 第 1/5 页

C
2,070
字号
#else /* NTFS_RW */	/*	 * For the read-write compiled driver, if we are remounting read-write,	 * make sure there are no volume errors and that no unsupported volume	 * flags are set.  Also, empty the logfile journal as it would become	 * stale as soon as something is written to the volume and mark the	 * volume dirty so that chkdsk is run if the volume is not umounted	 * cleanly.  Finally, mark the quotas out of date so Windows rescans	 * the volume on boot and updates them.	 *	 * When remounting read-only, mark the volume clean if no volume errors	 * have occured.	 */	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {		static const char *es = ".  Cannot remount read-write.";		/* Remounting read-write. */		if (NVolErrors(vol)) {			ntfs_error(sb, "Volume has errors and is read-only%s",					es);			return -EROFS;		}		if (vol->vol_flags & VOLUME_IS_DIRTY) {			ntfs_error(sb, "Volume is dirty and read-only%s", es);			return -EROFS;		}		if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) {			ntfs_error(sb, "Volume has unsupported flags set and "					"is read-only%s", es);			return -EROFS;		}		if (ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) {			ntfs_error(sb, "Failed to set dirty bit in volume "					"information flags%s", es);			return -EROFS;		}#if 0		// TODO: Enable this code once we start modifying anything that		//	 is different between NTFS 1.2 and 3.x...		/* Set NT4 compatibility flag on newer NTFS version volumes. */		if ((vol->major_ver > 1)) {			if (ntfs_set_volume_flags(vol, VOLUME_MOUNTED_ON_NT4)) {				ntfs_error(sb, "Failed to set NT4 "						"compatibility flag%s", es);				NVolSetErrors(vol);				return -EROFS;			}		}#endif		if (!ntfs_empty_logfile(vol->logfile_ino)) {			ntfs_error(sb, "Failed to empty journal $LogFile%s",					es);			NVolSetErrors(vol);			return -EROFS;		}		if (!ntfs_mark_quotas_out_of_date(vol)) {			ntfs_error(sb, "Failed to mark quotas out of date%s",					es);			NVolSetErrors(vol);			return -EROFS;		}	} else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {		/* Remounting read-only. */		if (!NVolErrors(vol)) {			if (ntfs_clear_volume_flags(vol, VOLUME_IS_DIRTY))				ntfs_warning(sb, "Failed to clear dirty bit "						"in volume information "						"flags.  Run chkdsk.");		}	}#endif /* NTFS_RW */	// TODO: Deal with *flags.	if (!parse_options(vol, opt))		return -EINVAL;	ntfs_debug("Done.");	return 0;}/** * is_boot_sector_ntfs - check whether a boot sector is a valid NTFS boot sector * @sb:		Super block of the device to which @b belongs. * @b:		Boot sector of device @sb to check. * @silent:	If TRUE, all output will be silenced. * * is_boot_sector_ntfs() checks whether the boot sector @b is a valid NTFS boot * sector. Returns TRUE if it is valid and FALSE if not. * * @sb is only needed for warning/error output, i.e. it can be NULL when silent * is TRUE. */static BOOL is_boot_sector_ntfs(const struct super_block *sb,		const NTFS_BOOT_SECTOR *b, const BOOL silent){	/*	 * Check that checksum == sum of u32 values from b to the checksum	 * field. If checksum is zero, no checking is done.	 */	if ((void*)b < (void*)&b->checksum && b->checksum) {		le32 *u;		u32 i;		for (i = 0, u = (le32*)b; u < (le32*)(&b->checksum); ++u)			i += le32_to_cpup(u);		if (le32_to_cpu(b->checksum) != i)			goto not_ntfs;	}	/* Check OEMidentifier is "NTFS    " */	if (b->oem_id != magicNTFS)		goto not_ntfs;	/* Check bytes per sector value is between 256 and 4096. */	if (le16_to_cpu(b->bpb.bytes_per_sector) < 0x100 ||			le16_to_cpu(b->bpb.bytes_per_sector) > 0x1000)		goto not_ntfs;	/* Check sectors per cluster value is valid. */	switch (b->bpb.sectors_per_cluster) {	case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:		break;	default:		goto not_ntfs;	}	/* Check the cluster size is not above 65536 bytes. */	if ((u32)le16_to_cpu(b->bpb.bytes_per_sector) *			b->bpb.sectors_per_cluster > 0x10000)		goto not_ntfs;	/* Check reserved/unused fields are really zero. */	if (le16_to_cpu(b->bpb.reserved_sectors) ||			le16_to_cpu(b->bpb.root_entries) ||			le16_to_cpu(b->bpb.sectors) ||			le16_to_cpu(b->bpb.sectors_per_fat) ||			le32_to_cpu(b->bpb.large_sectors) || b->bpb.fats)		goto not_ntfs;	/* Check clusters per file mft record value is valid. */	if ((u8)b->clusters_per_mft_record < 0xe1 ||			(u8)b->clusters_per_mft_record > 0xf7)		switch (b->clusters_per_mft_record) {		case 1: case 2: case 4: case 8: case 16: case 32: case 64:			break;		default:			goto not_ntfs;		}	/* Check clusters per index block value is valid. */	if ((u8)b->clusters_per_index_record < 0xe1 ||			(u8)b->clusters_per_index_record > 0xf7)		switch (b->clusters_per_index_record) {		case 1: case 2: case 4: case 8: case 16: case 32: case 64:			break;		default:			goto not_ntfs;		}	/*	 * Check for valid end of sector marker. We will work without it, but	 * many BIOSes will refuse to boot from a bootsector if the magic is	 * incorrect, so we emit a warning.	 */	if (!silent && b->end_of_sector_marker != cpu_to_le16(0xaa55))		ntfs_warning(sb, "Invalid end of sector marker.");	return TRUE;not_ntfs:	return FALSE;}/** * read_ntfs_boot_sector - read the NTFS boot sector of a device * @sb:		super block of device to read the boot sector from * @silent:	if true, suppress all output * * Reads the boot sector from the device and validates it. If that fails, tries * to read the backup boot sector, first from the end of the device a-la NT4 and * later and then from the middle of the device a-la NT3.51 and before. * * If a valid boot sector is found but it is not the primary boot sector, we * repair the primary boot sector silently (unless the device is read-only or * the primary boot sector is not accessible). * * NOTE: To call this function, @sb must have the fields s_dev, the ntfs super * block (u.ntfs_sb), nr_blocks and the device flags (s_flags) initialized * to their respective values. * * Return the unlocked buffer head containing the boot sector or NULL on error. */static struct buffer_head *read_ntfs_boot_sector(struct super_block *sb,		const int silent){	const char *read_err_str = "Unable to read %s boot sector.";	struct buffer_head *bh_primary, *bh_backup;	long nr_blocks = NTFS_SB(sb)->nr_blocks;	/* Try to read primary boot sector. */	if ((bh_primary = sb_bread(sb, 0))) {		if (is_boot_sector_ntfs(sb, (NTFS_BOOT_SECTOR*)				bh_primary->b_data, silent))			return bh_primary;		if (!silent)			ntfs_error(sb, "Primary boot sector is invalid.");	} else if (!silent)		ntfs_error(sb, read_err_str, "primary");	if (!(NTFS_SB(sb)->on_errors & ON_ERRORS_RECOVER)) {		if (bh_primary)			brelse(bh_primary);		if (!silent)			ntfs_error(sb, "Mount option errors=recover not used. "					"Aborting without trying to recover.");		return NULL;	}	/* Try to read NT4+ backup boot sector. */	if ((bh_backup = sb_bread(sb, nr_blocks - 1))) {		if (is_boot_sector_ntfs(sb, (NTFS_BOOT_SECTOR*)				bh_backup->b_data, silent))			goto hotfix_primary_boot_sector;		brelse(bh_backup);	} else if (!silent)		ntfs_error(sb, read_err_str, "backup");	/* Try to read NT3.51- backup boot sector. */	if ((bh_backup = sb_bread(sb, nr_blocks >> 1))) {		if (is_boot_sector_ntfs(sb, (NTFS_BOOT_SECTOR*)				bh_backup->b_data, silent))			goto hotfix_primary_boot_sector;		if (!silent)			ntfs_error(sb, "Could not find a valid backup boot "					"sector.");		brelse(bh_backup);	} else if (!silent)		ntfs_error(sb, read_err_str, "backup");	/* We failed. Cleanup and return. */	if (bh_primary)		brelse(bh_primary);	return NULL;hotfix_primary_boot_sector:	if (bh_primary) {		/*		 * If we managed to read sector zero and the volume is not		 * read-only, copy the found, valid backup boot sector to the		 * primary boot sector.		 */		if (!(sb->s_flags & MS_RDONLY)) {			ntfs_warning(sb, "Hot-fix: Recovering invalid primary "					"boot sector from backup copy.");			memcpy(bh_primary->b_data, bh_backup->b_data,					sb->s_blocksize);			mark_buffer_dirty(bh_primary);			sync_dirty_buffer(bh_primary);			if (buffer_uptodate(bh_primary)) {				brelse(bh_backup);				return bh_primary;			}			ntfs_error(sb, "Hot-fix: Device write error while "					"recovering primary boot sector.");		} else {			ntfs_warning(sb, "Hot-fix: Recovery of primary boot "					"sector failed: Read-only mount.");		}		brelse(bh_primary);	}	ntfs_warning(sb, "Using backup boot sector.");	return bh_backup;}/** * parse_ntfs_boot_sector - parse the boot sector and store the data in @vol * @vol:	volume structure to initialise with data from boot sector * @b:		boot sector to parse * * Parse the ntfs boot sector @b and store all imporant information therein in * the ntfs super block @vol. Return TRUE on success and FALSE on error. */static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b){	unsigned int sectors_per_cluster_bits, nr_hidden_sects;	int clusters_per_mft_record, clusters_per_index_record;	s64 ll;	vol->sector_size = le16_to_cpu(b->bpb.bytes_per_sector);	vol->sector_size_bits = ffs(vol->sector_size) - 1;	ntfs_debug("vol->sector_size = %i (0x%x)", vol->sector_size,			vol->sector_size);	ntfs_debug("vol->sector_size_bits = %i (0x%x)", vol->sector_size_bits,			vol->sector_size_bits);	if (vol->sector_size != vol->sb->s_blocksize)		ntfs_warning(vol->sb, "The boot sector indicates a sector size "				"different from the device sector size.");	ntfs_debug("sectors_per_cluster = 0x%x", b->bpb.sectors_per_cluster);	sectors_per_cluster_bits = ffs(b->bpb.sectors_per_cluster) - 1;	ntfs_debug("sectors_per_cluster_bits = 0x%x",			sectors_per_cluster_bits);	nr_hidden_sects = le32_to_cpu(b->bpb.hidden_sectors);	ntfs_debug("number of hidden sectors = 0x%x", nr_hidden_sects);	vol->cluster_size = vol->sector_size << sectors_per_cluster_bits;	vol->cluster_size_mask = vol->cluster_size - 1;	vol->cluster_size_bits = ffs(vol->cluster_size) - 1;	ntfs_debug("vol->cluster_size = %i (0x%x)", vol->cluster_size,			vol->cluster_size);	ntfs_debug("vol->cluster_size_mask = 0x%x", vol->cluster_size_mask);	ntfs_debug("vol->cluster_size_bits = %i (0x%x)",			vol->cluster_size_bits, vol->cluster_size_bits);	if (vol->sector_size > vol->cluster_size) {		ntfs_error(vol->sb, "Sector sizes above the cluster size are "				"not supported. Sorry.");		return FALSE;	}	if (vol->sb->s_blocksize > vol->cluster_size) {		ntfs_error(vol->sb, "Cluster sizes smaller than the device "				"sector size are not supported. Sorry.");		return FALSE;	}	clusters_per_mft_record = b->clusters_per_mft_record;	ntfs_debug("clusters_per_mft_record = %i (0x%x)",			clusters_per_mft_record, clusters_per_mft_record);	if (clusters_per_mft_record > 0)		vol->mft_record_size = vol->cluster_size <<				(ffs(clusters_per_mft_record) - 1);	else		/*		 * When mft_record_size < cluster_size, clusters_per_mft_record		 * = -log2(mft_record_size) bytes. mft_record_size normaly is		 * 1024 bytes, which is encoded as 0xF6 (-10 in decimal).		 */		vol->mft_record_size = 1 << -clusters_per_mft_record;	vol->mft_record_size_mask = vol->mft_record_size - 1;	vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;	ntfs_debug("vol->mft_record_size = %i (0x%x)", vol->mft_record_size,			vol->mft_record_size);	ntfs_debug("vol->mft_record_size_mask = 0x%x",			vol->mft_record_size_mask);	ntfs_debug("vol->mft_record_size_bits = %i (0x%x)",			vol->mft_record_size_bits, vol->mft_record_size_bits);	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);	/*	 * 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 is beyond end of volume. Weird.");		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 is beyond end of volume. "				"Weird.");		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;}

⌨️ 快捷键说明

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