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 + -
显示快捷键?