diff options
Diffstat (limited to 'fs/ntfs')
-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 { |