diff options
author | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2022-10-11 19:19:36 +0200 |
---|---|---|
committer | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2022-11-14 17:50:48 +0100 |
commit | ec5fc72013762500867c9cef96fed89dc7161832 (patch) | |
tree | 1a7b889fe1a3d168eb1453666f5755274a429f11 /fs/ntfs3/super.c | |
parent | fs/ntfs3: Fix wrong if in hdr_first_de (diff) | |
download | linux-ec5fc72013762500867c9cef96fed89dc7161832.tar.xz linux-ec5fc72013762500867c9cef96fed89dc7161832.zip |
fs/ntfs3: Improve checking of bad clusters
Added new function wnd_set_used_safe.
Load $BadClus before $AttrDef instead of before $Bitmap.
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Diffstat (limited to 'fs/ntfs3/super.c')
-rw-r--r-- | fs/ntfs3/super.c | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 59a831bd0c9b..ef4ea3f21905 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -930,7 +930,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) struct block_device *bdev = sb->s_bdev; struct inode *inode; struct ntfs_inode *ni; - size_t i, tt; + size_t i, tt, bad_len, bad_frags; CLST vcn, lcn, len; struct ATTRIB *attr; const struct VOLUME_INFO *info; @@ -1100,30 +1100,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) sbi->mft.ni = ni; - /* Load $BadClus. */ - ref.low = cpu_to_le32(MFT_REC_BADCLUST); - ref.seq = cpu_to_le16(MFT_REC_BADCLUST); - inode = ntfs_iget5(sb, &ref, &NAME_BADCLUS); - if (IS_ERR(inode)) { - ntfs_err(sb, "Failed to load $BadClus."); - err = PTR_ERR(inode); - goto out; - } - - ni = ntfs_i(inode); - - for (i = 0; run_get_entry(&ni->file.run, i, &vcn, &lcn, &len); i++) { - if (lcn == SPARSE_LCN) - continue; - - if (!sbi->bad_clusters) - ntfs_notice(sb, "Volume contains bad blocks"); - - sbi->bad_clusters += len; - } - - iput(inode); - /* Load $Bitmap. */ ref.low = cpu_to_le32(MFT_REC_BITMAP); ref.seq = cpu_to_le16(MFT_REC_BITMAP); @@ -1161,6 +1137,44 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) if (err) goto out; + /* Load $BadClus. */ + ref.low = cpu_to_le32(MFT_REC_BADCLUST); + ref.seq = cpu_to_le16(MFT_REC_BADCLUST); + inode = ntfs_iget5(sb, &ref, &NAME_BADCLUS); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + ntfs_err(sb, "Failed to load $BadClus (%d).", err); + goto out; + } + + ni = ntfs_i(inode); + bad_len = bad_frags = 0; + for (i = 0; run_get_entry(&ni->file.run, i, &vcn, &lcn, &len); i++) { + if (lcn == SPARSE_LCN) + continue; + + bad_len += len; + bad_frags += 1; + if (sb_rdonly(sb)) + continue; + + if (wnd_set_used_safe(&sbi->used.bitmap, lcn, len, &tt) || tt) { + /* Bad blocks marked as free in bitmap. */ + ntfs_set_state(sbi, NTFS_DIRTY_ERROR); + } + } + if (bad_len) { + /* + * Notice about bad blocks. + * In normal cases these blocks are marked as used in bitmap. + * And we never allocate space in it. + */ + ntfs_notice(sb, + "Volume contains %zu bad blocks in %zu fragments.", + bad_len, bad_frags); + } + iput(inode); + /* Load $AttrDef. */ ref.low = cpu_to_le32(MFT_REC_ATTR); ref.seq = cpu_to_le16(MFT_REC_ATTR); |