diff options
| -rw-r--r-- | fs/ntfs/ChangeLog | 1 | ||||
| -rw-r--r-- | fs/ntfs/attrib.c | 25 | ||||
| -rw-r--r-- | fs/ntfs/inode.c | 68 | ||||
| -rw-r--r-- | fs/ntfs/layout.h | 19 |
4 files changed, 75 insertions, 38 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 548d9059a697..b5774233ef1d 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
| @@ -31,6 +31,7 @@ ToDo/Notes: | |||
| 31 | - Fix comparison of $MFT and $MFTMirr to not bail out when there are | 31 | - Fix comparison of $MFT and $MFTMirr to not bail out when there are |
| 32 | unused, invalid mft records which are the same in both $MFT and | 32 | unused, invalid mft records which are the same in both $MFT and |
| 33 | $MFTMirr. | 33 | $MFTMirr. |
| 34 | - Add support for sparse files which have a compression unit of 0. | ||
| 34 | 35 | ||
| 35 | 2.1.26 - Minor bug fixes and updates. | 36 | 2.1.26 - Minor bug fixes and updates. |
| 36 | 37 | ||
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index a92b9e9db91d..7a568eb7d80f 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) | |||
| 1695 | a->data.non_resident.initialized_size = | 1695 | a->data.non_resident.initialized_size = |
| 1696 | cpu_to_sle64(attr_size); | 1696 | cpu_to_sle64(attr_size); |
| 1697 | if (NInoSparse(ni) || NInoCompressed(ni)) { | 1697 | if (NInoSparse(ni) || NInoCompressed(ni)) { |
| 1698 | a->data.non_resident.compression_unit = 4; | 1698 | a->data.non_resident.compression_unit = 0; |
| 1699 | if (NInoCompressed(ni) || vol->major_ver < 3) | ||
| 1700 | a->data.non_resident.compression_unit = 4; | ||
| 1699 | a->data.non_resident.compressed_size = | 1701 | a->data.non_resident.compressed_size = |
| 1700 | a->data.non_resident.allocated_size; | 1702 | a->data.non_resident.allocated_size; |
| 1701 | } else | 1703 | } else |
| @@ -1714,13 +1716,20 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) | |||
| 1714 | ni->allocated_size = new_size; | 1716 | ni->allocated_size = new_size; |
| 1715 | if (NInoSparse(ni) || NInoCompressed(ni)) { | 1717 | if (NInoSparse(ni) || NInoCompressed(ni)) { |
| 1716 | ni->itype.compressed.size = ni->allocated_size; | 1718 | ni->itype.compressed.size = ni->allocated_size; |
| 1717 | ni->itype.compressed.block_size = 1U << | 1719 | if (a->data.non_resident.compression_unit) { |
| 1718 | (a->data.non_resident.compression_unit + | 1720 | ni->itype.compressed.block_size = 1U << (a->data. |
| 1719 | vol->cluster_size_bits); | 1721 | non_resident.compression_unit + |
| 1720 | ni->itype.compressed.block_size_bits = | 1722 | vol->cluster_size_bits); |
| 1721 | ffs(ni->itype.compressed.block_size) - 1; | 1723 | ni->itype.compressed.block_size_bits = |
| 1722 | ni->itype.compressed.block_clusters = 1U << | 1724 | ffs(ni->itype.compressed.block_size) - |
| 1723 | a->data.non_resident.compression_unit; | 1725 | 1; |
| 1726 | ni->itype.compressed.block_clusters = 1U << | ||
| 1727 | a->data.non_resident.compression_unit; | ||
| 1728 | } else { | ||
| 1729 | ni->itype.compressed.block_size = 0; | ||
| 1730 | ni->itype.compressed.block_size_bits = 0; | ||
| 1731 | ni->itype.compressed.block_clusters = 0; | ||
| 1732 | } | ||
| 1724 | vi->i_blocks = ni->itype.compressed.size >> 9; | 1733 | vi->i_blocks = ni->itype.compressed.size >> 9; |
| 1725 | } else | 1734 | } else |
| 1726 | vi->i_blocks = ni->allocated_size >> 9; | 1735 | vi->i_blocks = ni->allocated_size >> 9; |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 55263b7de9c0..ae341922f423 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. | 2 | * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2006 Anton Altaparmakov |
| 5 | * | 5 | * |
| 6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
| @@ -24,8 +24,10 @@ | |||
| 24 | #include <linux/smp_lock.h> | 24 | #include <linux/smp_lock.h> |
| 25 | #include <linux/quotaops.h> | 25 | #include <linux/quotaops.h> |
| 26 | #include <linux/mount.h> | 26 | #include <linux/mount.h> |
| 27 | #include <linux/mutex.h> | ||
| 27 | 28 | ||
| 28 | #include "aops.h" | 29 | #include "aops.h" |
| 30 | #include "attrib.h" | ||
| 29 | #include "dir.h" | 31 | #include "dir.h" |
| 30 | #include "debug.h" | 32 | #include "debug.h" |
| 31 | #include "inode.h" | 33 | #include "inode.h" |
| @@ -1064,10 +1066,10 @@ skip_large_dir_stuff: | |||
| 1064 | if (a->non_resident) { | 1066 | if (a->non_resident) { |
| 1065 | NInoSetNonResident(ni); | 1067 | NInoSetNonResident(ni); |
| 1066 | if (NInoCompressed(ni) || NInoSparse(ni)) { | 1068 | if (NInoCompressed(ni) || NInoSparse(ni)) { |
| 1067 | if (a->data.non_resident.compression_unit != | 1069 | if (NInoCompressed(ni) && a->data.non_resident. |
| 1068 | 4) { | 1070 | compression_unit != 4) { |
| 1069 | ntfs_error(vi->i_sb, "Found " | 1071 | ntfs_error(vi->i_sb, "Found " |
| 1070 | "nonstandard " | 1072 | "non-standard " |
| 1071 | "compression unit (%u " | 1073 | "compression unit (%u " |
| 1072 | "instead of 4). " | 1074 | "instead of 4). " |
| 1073 | "Cannot handle this.", | 1075 | "Cannot handle this.", |
| @@ -1076,16 +1078,26 @@ skip_large_dir_stuff: | |||
| 1076 | err = -EOPNOTSUPP; | 1078 | err = -EOPNOTSUPP; |
| 1077 | goto unm_err_out; | 1079 | goto unm_err_out; |
| 1078 | } | 1080 | } |
| 1079 | ni->itype.compressed.block_clusters = 1U << | 1081 | if (a->data.non_resident.compression_unit) { |
| 1080 | a->data.non_resident. | 1082 | ni->itype.compressed.block_size = 1U << |
| 1081 | compression_unit; | 1083 | (a->data.non_resident. |
| 1082 | ni->itype.compressed.block_size = 1U << ( | 1084 | compression_unit + |
| 1083 | a->data.non_resident. | 1085 | vol->cluster_size_bits); |
| 1084 | compression_unit + | 1086 | ni->itype.compressed.block_size_bits = |
| 1085 | vol->cluster_size_bits); | 1087 | ffs(ni->itype. |
| 1086 | ni->itype.compressed.block_size_bits = ffs( | 1088 | compressed. |
| 1087 | ni->itype.compressed. | 1089 | block_size) - 1; |
| 1088 | block_size) - 1; | 1090 | ni->itype.compressed.block_clusters = |
| 1091 | 1U << a->data. | ||
| 1092 | non_resident. | ||
| 1093 | compression_unit; | ||
| 1094 | } else { | ||
| 1095 | ni->itype.compressed.block_size = 0; | ||
| 1096 | ni->itype.compressed.block_size_bits = | ||
| 1097 | 0; | ||
| 1098 | ni->itype.compressed.block_clusters = | ||
| 1099 | 0; | ||
| 1100 | } | ||
| 1089 | ni->itype.compressed.size = sle64_to_cpu( | 1101 | ni->itype.compressed.size = sle64_to_cpu( |
| 1090 | a->data.non_resident. | 1102 | a->data.non_resident. |
| 1091 | compressed_size); | 1103 | compressed_size); |
| @@ -1338,8 +1350,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
| 1338 | goto unm_err_out; | 1350 | goto unm_err_out; |
| 1339 | } | 1351 | } |
| 1340 | if (NInoCompressed(ni) || NInoSparse(ni)) { | 1352 | if (NInoCompressed(ni) || NInoSparse(ni)) { |
| 1341 | if (a->data.non_resident.compression_unit != 4) { | 1353 | if (NInoCompressed(ni) && a->data.non_resident. |
| 1342 | ntfs_error(vi->i_sb, "Found nonstandard " | 1354 | compression_unit != 4) { |
| 1355 | ntfs_error(vi->i_sb, "Found non-standard " | ||
| 1343 | "compression unit (%u instead " | 1356 | "compression unit (%u instead " |
| 1344 | "of 4). Cannot handle this.", | 1357 | "of 4). Cannot handle this.", |
| 1345 | a->data.non_resident. | 1358 | a->data.non_resident. |
| @@ -1347,13 +1360,22 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
| 1347 | err = -EOPNOTSUPP; | 1360 | err = -EOPNOTSUPP; |
| 1348 | goto unm_err_out; | 1361 | goto unm_err_out; |
| 1349 | } | 1362 | } |
| 1350 | ni->itype.compressed.block_clusters = 1U << | 1363 | if (a->data.non_resident.compression_unit) { |
| 1351 | a->data.non_resident.compression_unit; | 1364 | ni->itype.compressed.block_size = 1U << |
| 1352 | ni->itype.compressed.block_size = 1U << ( | 1365 | (a->data.non_resident. |
| 1353 | a->data.non_resident.compression_unit + | 1366 | compression_unit + |
| 1354 | vol->cluster_size_bits); | 1367 | vol->cluster_size_bits); |
| 1355 | ni->itype.compressed.block_size_bits = ffs( | 1368 | ni->itype.compressed.block_size_bits = |
| 1356 | ni->itype.compressed.block_size) - 1; | 1369 | ffs(ni->itype.compressed. |
| 1370 | block_size) - 1; | ||
| 1371 | ni->itype.compressed.block_clusters = 1U << | ||
| 1372 | a->data.non_resident. | ||
| 1373 | compression_unit; | ||
| 1374 | } else { | ||
| 1375 | ni->itype.compressed.block_size = 0; | ||
| 1376 | ni->itype.compressed.block_size_bits = 0; | ||
| 1377 | ni->itype.compressed.block_clusters = 0; | ||
| 1378 | } | ||
| 1357 | ni->itype.compressed.size = sle64_to_cpu( | 1379 | ni->itype.compressed.size = sle64_to_cpu( |
| 1358 | a->data.non_resident.compressed_size); | 1380 | a->data.non_resident.compressed_size); |
| 1359 | } | 1381 | } |
diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index bb408d4dcbb0..f4283e120709 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h | |||
| @@ -769,7 +769,7 @@ typedef struct { | |||
| 769 | compressed. (This effectively limits the | 769 | compressed. (This effectively limits the |
| 770 | compression unit size to be a power of two | 770 | compression unit size to be a power of two |
| 771 | clusters.) WinNT4 only uses a value of 4. | 771 | clusters.) WinNT4 only uses a value of 4. |
| 772 | Sparse files also have this set to 4. */ | 772 | Sparse files have this set to 0 on XPSP2. */ |
| 773 | /* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */ | 773 | /* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */ |
| 774 | /* The sizes below are only used when lowest_vcn is zero, as otherwise it would | 774 | /* The sizes below are only used when lowest_vcn is zero, as otherwise it would |
| 775 | be difficult to keep them up-to-date.*/ | 775 | be difficult to keep them up-to-date.*/ |
| @@ -1076,16 +1076,21 @@ typedef struct { | |||
| 1076 | /* 20*/ sle64 last_access_time; /* Time this mft record was last | 1076 | /* 20*/ sle64 last_access_time; /* Time this mft record was last |
| 1077 | accessed. */ | 1077 | accessed. */ |
| 1078 | /* 28*/ sle64 allocated_size; /* Byte size of on-disk allocated space | 1078 | /* 28*/ sle64 allocated_size; /* Byte size of on-disk allocated space |
| 1079 | for the data attribute. So for | 1079 | for the unnamed data attribute. So |
| 1080 | normal $DATA, this is the | 1080 | for normal $DATA, this is the |
| 1081 | allocated_size from the unnamed | 1081 | allocated_size from the unnamed |
| 1082 | $DATA attribute and for compressed | 1082 | $DATA attribute and for compressed |
| 1083 | and/or sparse $DATA, this is the | 1083 | and/or sparse $DATA, this is the |
| 1084 | compressed_size from the unnamed | 1084 | compressed_size from the unnamed |
| 1085 | $DATA attribute. NOTE: This is a | 1085 | $DATA attribute. For a directory or |
| 1086 | multiple of the cluster size. */ | 1086 | other inode without an unnamed $DATA |
| 1087 | /* 30*/ sle64 data_size; /* Byte size of actual data in data | 1087 | attribute, this is always 0. NOTE: |
| 1088 | attribute. */ | 1088 | This is a multiple of the cluster |
| 1089 | size. */ | ||
| 1090 | /* 30*/ sle64 data_size; /* Byte size of actual data in unnamed | ||
| 1091 | data attribute. For a directory or | ||
| 1092 | other inode without an unnamed $DATA | ||
| 1093 | attribute, this is always 0. */ | ||
| 1089 | /* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ | 1094 | /* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ |
| 1090 | /* 3c*/ union { | 1095 | /* 3c*/ union { |
| 1091 | /* 3c*/ struct { | 1096 | /* 3c*/ struct { |
