From 3ccc7384db3d762e834dfdae13c1d6434b2fdeab Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Thu, 23 Mar 2006 15:03:11 +0000 Subject: NTFS: Fix a buggette in an "should be impossible" case handling where we continued the attribute lookup loop instead of aborting it. Signed-off-by: Anton Altaparmakov --- fs/ntfs/attrib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/ntfs/attrib.c') diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 9480a0526cd..a92b9e9db91 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1,7 +1,7 @@ /** * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. * - * Copyright (c) 2001-2005 Anton Altaparmakov + * Copyright (c) 2001-2006 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -1048,7 +1048,7 @@ do_next_attr_loop: le32_to_cpu(ctx->mrec->bytes_allocated)) break; if (a->type == AT_END) - continue; + break; if (!a->length) break; if (al_entry->instance != a->instance) -- cgit v1.2.3-70-g09d2 From a0646a1f04f1ec4c7514e5b00496b54e054a2c99 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Thu, 23 Mar 2006 15:53:03 +0000 Subject: NTFS: Add support for sparse files which have a compression unit of 0. Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 1 + fs/ntfs/attrib.c | 25 +++++++++++++------- fs/ntfs/inode.c | 68 ++++++++++++++++++++++++++++++++++++------------------- fs/ntfs/layout.h | 19 ++++++++++------ 4 files changed, 75 insertions(+), 38 deletions(-) (limited to 'fs/ntfs/attrib.c') diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 548d9059a69..b5774233ef1 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -31,6 +31,7 @@ ToDo/Notes: - Fix comparison of $MFT and $MFTMirr to not bail out when there are unused, invalid mft records which are the same in both $MFT and $MFTMirr. + - Add support for sparse files which have a compression unit of 0. 2.1.26 - Minor bug fixes and updates. diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index a92b9e9db91..7a568eb7d80 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1695,7 +1695,9 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) a->data.non_resident.initialized_size = cpu_to_sle64(attr_size); if (NInoSparse(ni) || NInoCompressed(ni)) { - a->data.non_resident.compression_unit = 4; + a->data.non_resident.compression_unit = 0; + if (NInoCompressed(ni) || vol->major_ver < 3) + a->data.non_resident.compression_unit = 4; a->data.non_resident.compressed_size = a->data.non_resident.allocated_size; } else @@ -1714,13 +1716,20 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) ni->allocated_size = new_size; if (NInoSparse(ni) || NInoCompressed(ni)) { ni->itype.compressed.size = ni->allocated_size; - ni->itype.compressed.block_size = 1U << - (a->data.non_resident.compression_unit + - vol->cluster_size_bits); - ni->itype.compressed.block_size_bits = - ffs(ni->itype.compressed.block_size) - 1; - ni->itype.compressed.block_clusters = 1U << - a->data.non_resident.compression_unit; + if (a->data.non_resident.compression_unit) { + ni->itype.compressed.block_size = 1U << (a->data. + non_resident.compression_unit + + vol->cluster_size_bits); + ni->itype.compressed.block_size_bits = + ffs(ni->itype.compressed.block_size) - + 1; + ni->itype.compressed.block_clusters = 1U << + a->data.non_resident.compression_unit; + } else { + ni->itype.compressed.block_size = 0; + ni->itype.compressed.block_size_bits = 0; + ni->itype.compressed.block_clusters = 0; + } vi->i_blocks = ni->itype.compressed.size >> 9; } else vi->i_blocks = ni->allocated_size >> 9; diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 55263b7de9c..ae341922f42 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -1,7 +1,7 @@ /** * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. * - * Copyright (c) 2001-2005 Anton Altaparmakov + * Copyright (c) 2001-2006 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -24,8 +24,10 @@ #include #include #include +#include #include "aops.h" +#include "attrib.h" #include "dir.h" #include "debug.h" #include "inode.h" @@ -1064,10 +1066,10 @@ skip_large_dir_stuff: if (a->non_resident) { NInoSetNonResident(ni); if (NInoCompressed(ni) || NInoSparse(ni)) { - if (a->data.non_resident.compression_unit != - 4) { + if (NInoCompressed(ni) && a->data.non_resident. + compression_unit != 4) { ntfs_error(vi->i_sb, "Found " - "nonstandard " + "non-standard " "compression unit (%u " "instead of 4). " "Cannot handle this.", @@ -1076,16 +1078,26 @@ skip_large_dir_stuff: err = -EOPNOTSUPP; goto unm_err_out; } - ni->itype.compressed.block_clusters = 1U << - a->data.non_resident. - compression_unit; - ni->itype.compressed.block_size = 1U << ( - a->data.non_resident. - compression_unit + - vol->cluster_size_bits); - ni->itype.compressed.block_size_bits = ffs( - ni->itype.compressed. - block_size) - 1; + if (a->data.non_resident.compression_unit) { + ni->itype.compressed.block_size = 1U << + (a->data.non_resident. + compression_unit + + vol->cluster_size_bits); + ni->itype.compressed.block_size_bits = + ffs(ni->itype. + compressed. + block_size) - 1; + ni->itype.compressed.block_clusters = + 1U << a->data. + non_resident. + compression_unit; + } else { + ni->itype.compressed.block_size = 0; + ni->itype.compressed.block_size_bits = + 0; + ni->itype.compressed.block_clusters = + 0; + } ni->itype.compressed.size = sle64_to_cpu( a->data.non_resident. compressed_size); @@ -1338,8 +1350,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) goto unm_err_out; } if (NInoCompressed(ni) || NInoSparse(ni)) { - if (a->data.non_resident.compression_unit != 4) { - ntfs_error(vi->i_sb, "Found nonstandard " + if (NInoCompressed(ni) && a->data.non_resident. + compression_unit != 4) { + ntfs_error(vi->i_sb, "Found non-standard " "compression unit (%u instead " "of 4). Cannot handle this.", a->data.non_resident. @@ -1347,13 +1360,22 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) err = -EOPNOTSUPP; goto unm_err_out; } - ni->itype.compressed.block_clusters = 1U << - a->data.non_resident.compression_unit; - ni->itype.compressed.block_size = 1U << ( - a->data.non_resident.compression_unit + - vol->cluster_size_bits); - ni->itype.compressed.block_size_bits = ffs( - ni->itype.compressed.block_size) - 1; + if (a->data.non_resident.compression_unit) { + ni->itype.compressed.block_size = 1U << + (a->data.non_resident. + compression_unit + + vol->cluster_size_bits); + ni->itype.compressed.block_size_bits = + ffs(ni->itype.compressed. + block_size) - 1; + ni->itype.compressed.block_clusters = 1U << + a->data.non_resident. + compression_unit; + } else { + ni->itype.compressed.block_size = 0; + ni->itype.compressed.block_size_bits = 0; + ni->itype.compressed.block_clusters = 0; + } ni->itype.compressed.size = sle64_to_cpu( a->data.non_resident.compressed_size); } diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index bb408d4dcbb..f4283e12070 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h @@ -769,7 +769,7 @@ typedef struct { compressed. (This effectively limits the compression unit size to be a power of two clusters.) WinNT4 only uses a value of 4. - Sparse files also have this set to 4. */ + Sparse files have this set to 0 on XPSP2. */ /* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */ /* The sizes below are only used when lowest_vcn is zero, as otherwise it would be difficult to keep them up-to-date.*/ @@ -1076,16 +1076,21 @@ typedef struct { /* 20*/ sle64 last_access_time; /* Time this mft record was last accessed. */ /* 28*/ sle64 allocated_size; /* Byte size of on-disk allocated space - for the data attribute. So for - normal $DATA, this is the + for the unnamed data attribute. So + for normal $DATA, this is the allocated_size from the unnamed $DATA attribute and for compressed and/or sparse $DATA, this is the compressed_size from the unnamed - $DATA attribute. NOTE: This is a - multiple of the cluster size. */ -/* 30*/ sle64 data_size; /* Byte size of actual data in data - attribute. */ + $DATA attribute. For a directory or + other inode without an unnamed $DATA + attribute, this is always 0. NOTE: + This is a multiple of the cluster + size. */ +/* 30*/ sle64 data_size; /* Byte size of actual data in unnamed + data attribute. For a directory or + other inode without an unnamed $DATA + attribute, this is always 0. */ /* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ /* 3c*/ union { /* 3c*/ struct { -- cgit v1.2.3-70-g09d2 From f95c4018fd4b0bdef9b1bcb4eac7056e2a07282a Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Thu, 23 Mar 2006 15:59:32 +0000 Subject: NTFS: Remove all the make_bad_inode() calls. This should only be called from read inode and new inode code paths. Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 2 ++ fs/ntfs/aops.c | 1 - fs/ntfs/attrib.c | 6 ------ fs/ntfs/file.c | 13 +------------ fs/ntfs/mft.c | 1 + fs/ntfs/mft.h | 5 +---- 6 files changed, 5 insertions(+), 23 deletions(-) (limited to 'fs/ntfs/attrib.c') diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index b5774233ef1..13e70d4e2fd 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -32,6 +32,8 @@ ToDo/Notes: unused, invalid mft records which are the same in both $MFT and $MFTMirr. - Add support for sparse files which have a compression unit of 0. + - Remove all the make_bad_inode() calls. This should only be called + from read inode and new inode code paths. 2.1.26 - Minor bug fixes and updates. diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 7c7e313620f..1cf105b9920 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -1530,7 +1530,6 @@ err_out: "error %i.", err); SetPageError(page); NVolSetErrors(ni->vol); - make_bad_inode(vi); } unlock_page(page); if (ctx) diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 7a568eb7d80..1663f5c3c6a 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -2438,16 +2438,12 @@ undo_alloc: "chkdsk to recover.", IS_ERR(m) ? "restore attribute search context" : "truncate attribute runlist"); - make_bad_inode(vi); - make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); } else if (mp_rebuilt) { if (ntfs_attr_record_resize(m, a, attr_len)) { ntfs_error(vol->sb, "Failed to restore attribute " "record in error code path. Run " "chkdsk to recover."); - make_bad_inode(vi); - make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); } else /* if (success) */ { if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( @@ -2460,8 +2456,6 @@ undo_alloc: "mapping pairs array in error " "code path. Run chkdsk to " "recover."); - make_bad_inode(vi); - make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); } flush_dcache_mft_record_page(ctx->ntfs_ino); diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 2e5ba0c535d..f5d057e4acc 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -1207,8 +1207,6 @@ rl_not_mapped_enoent: "attribute runlist in error code " "path. Run chkdsk to recover the " "lost cluster."); - make_bad_inode(vi); - make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); } else /* if (success) */ { status.runlist_merged = 0; @@ -1239,8 +1237,6 @@ rl_not_mapped_enoent: ntfs_error(vol->sb, "Failed to restore attribute " "record in error code path. Run " "chkdsk to recover."); - make_bad_inode(vi); - make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); } else /* if (success) */ { if (ntfs_mapping_pairs_build(vol, (u8*)a + @@ -1253,8 +1249,6 @@ rl_not_mapped_enoent: "mapping pairs array in error " "code path. Run chkdsk to " "recover."); - make_bad_inode(vi); - make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); } flush_dcache_mft_record_page(ctx->ntfs_ino); @@ -1623,11 +1617,8 @@ err_out: unmap_mft_record(base_ni); ntfs_error(vi->i_sb, "Failed to update initialized_size/i_size (error " "code %i).", err); - if (err != -ENOMEM) { + if (err != -ENOMEM) NVolSetErrors(ni->vol); - make_bad_inode(VFS_I(base_ni)); - make_bad_inode(vi); - } return err; } @@ -1802,8 +1793,6 @@ err_out: ntfs_error(vi->i_sb, "Resident attribute commit write failed " "with error %i.", err); NVolSetErrors(ni->vol); - make_bad_inode(VFS_I(base_ni)); - make_bad_inode(vi); } if (ctx) ntfs_attr_put_search_ctx(ctx); diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 6499aafc225..7254391b0e5 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -93,6 +93,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni) "Run chkdsk.", ni->mft_no); ntfs_unmap_page(page); page = ERR_PTR(-EIO); + NVolSetErrors(vol); } err_out: ni->page = NULL; diff --git a/fs/ntfs/mft.h b/fs/ntfs/mft.h index 407de2cef1d..639cd1bab08 100644 --- a/fs/ntfs/mft.h +++ b/fs/ntfs/mft.h @@ -97,10 +97,7 @@ extern int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync); * uptodate. * * On success, clean the mft record and return 0. On error, leave the mft - * record dirty and return -errno. The caller should call make_bad_inode() on - * the base inode to ensure no more access happens to this inode. We do not do - * it here as the caller may want to finish writing other extent mft records - * first to minimize on-disk metadata inconsistencies. + * record dirty and return -errno. */ static inline int write_mft_record(ntfs_inode *ni, MFT_RECORD *m, int sync) { -- cgit v1.2.3-70-g09d2