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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static inline int ntfs_set_volume_flags(ntfs_volume *vol, VOLUME_FLAGS flags){	flags &= VOLUME_FLAGS_MASK;	return ntfs_write_volume_flags(vol, vol->vol_flags | flags);}/** * ntfs_clear_volume_flags - clear bits in the volume information flags * @vol:	ntfs volume on which to modify the flags * @flags:	flags to clear on the volume * * Clear the bits in @flags in the volume information flags on the volume @vol. * * Return 0 on success and -errno on error. */static inline int ntfs_clear_volume_flags(ntfs_volume *vol, VOLUME_FLAGS flags){	flags &= VOLUME_FLAGS_MASK;	flags = vol->vol_flags & cpu_to_le16(~le16_to_cpu(flags));	return ntfs_write_volume_flags(vol, flags);}#endif /* NTFS_RW *//** * ntfs_remount - change the mount options of a mounted ntfs filesystem * @sb:		superblock of mounted ntfs filesystem * @flags:	remount flags * @opt:	remount options string * * Change the mount options of an already mounted ntfs filesystem. * * NOTE:  The VFS sets the @sb->s_flags remount flags to @flags after * ntfs_remount() returns successfully (i.e. returns 0).  Otherwise, * @sb->s_flags are not changed. */static int ntfs_remount(struct super_block *sb, int *flags, char *opt){	ntfs_volume *vol = NTFS_SB(sb);	ntfs_debug("Entering with remount options string: %s", opt);#ifndef NTFS_RW	/* For read-only compiled driver, enforce read-only flag. */	*flags |= MS_RDONLY;#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_MODIFIED_BY_CHKDSK) {			ntfs_error(sb, "Volume has been modified by chkdsk "					"and is read-only%s", es);			return -EROFS;		}		if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) {			ntfs_error(sb, "Volume has unsupported flags set "					"(0x%x) and is read-only%s",					(unsigned)le16_to_cpu(vol->vol_flags),					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;		}		if (!ntfs_stamp_usnjrnl(vol)) {			ntfs_error(sb, "Failed to stamp transation log "					"($UsnJrnl)%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.  We will work when	 * the checksum test fails, since some utilities update the boot sector	 * ignoring the checksum which leaves the checksum out-of-date.  We	 * report a warning if this is the case.	 */	if ((void*)b < (void*)&b->checksum && b->checksum && !silent) {		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)			ntfs_warning(sb, "Invalid boot sector checksum.");	}	/* 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 the maximum (64kiB). */	if ((u32)le16_to_cpu(b->bpb.bytes_per_sector) *			b->bpb.sectors_per_cluster > NTFS_MAX_CLUSTER_SIZE)		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 != const_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;	sector_t 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.  Note we only copy the actual boot		 * sector structure, not the actual whole device sector as that		 * may be bigger and would potentially damage the $Boot system		 * file (FIXME: Would be nice to know if the backup boot sector		 * on a large sector device contains the whole boot loader or		 * just the first 512 bytes).		 */		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,					NTFS_BLOCK_SIZE);			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_error(vol->sb, "Sector size (%i) is smaller than the "				"device block size (%lu).  This is not "				"supported.  Sorry.", vol->sector_size,				vol->sb->s_blocksize);		return false;	}	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", vol->cluster_size_bits);	if (vol->cluster_size < vol->sector_size) {		ntfs_error(vol->sb, "Cluster size (%i) is smaller than the "				"sector size (%i).  This is not supported.  "				"Sorry.", vol->cluster_size, vol->sector_size);		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);	/*	 * We cannot support mft record sizes above the PAGE_CACHE_SIZE since	 * we store $MFT/$DATA, the table of mft records in the page cache.	 */	if (vol->mft_record_size > PAGE_CACHE_SIZE) {		ntfs_error(vol->sb, "Mft record size (%i) exceeds the "				"PAGE_CACHE_SIZE on your system (%lu).  "				"This is not supported.  Sorry.",				vol->mft_record_size, PAGE_CACHE_SIZE);		return false;	}	/* We cannot support mft record sizes below the sector size. */	if (vol->mft_record_size < vol->sector_size) {

⌨️ 快捷键说明

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