aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-03-03 09:43:43 -0500
committerAnton Altaparmakov <aia21@cantab.net>2005-05-05 06:15:46 -0400
commit9451f8519c5e6d5d064c30033fc3d4ce77de321c (patch)
tree104eedf065c4091838a27f6e674875a035c30820 /fs
parent413826868fb49d200b741bcaeaf58ea5c5e45321 (diff)
NTFS: Correct sparse file handling. The compressed values need to be
checked and set in the ntfs inode as done for compressed files and the compressed size needs to be used for vfs inode->i_blocks instead of the allocated size, again, as done for compressed files. Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs')
-rw-r--r--fs/ntfs/ChangeLog4
-rw-r--r--fs/ntfs/inode.c172
-rw-r--r--fs/ntfs/layout.h15
3 files changed, 94 insertions, 97 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index cf21e0571b68..cd348f0b90e5 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -84,6 +84,10 @@ ToDo/Notes:
84 - Make fs/ntfs/namei.c::ntfs_get_{parent,dentry} static and move the 84 - Make fs/ntfs/namei.c::ntfs_get_{parent,dentry} static and move the
85 definition of ntfs_export_ops from fs/ntfs/super.c to namei.c. Also, 85 definition of ntfs_export_ops from fs/ntfs/super.c to namei.c. Also,
86 declare ntfs_export_ops in fs/ntfs/ntfs.h. 86 declare ntfs_export_ops in fs/ntfs/ntfs.h.
87 - Correct sparse file handling. The compressed values need to be
88 checked and set in the ntfs inode as done for compressed files and
89 the compressed size needs to be used for vfs inode->i_blocks instead
90 of the allocated size, again, as done for compressed files.
87 91
882.1.22 - Many bug and race fixes and error handling improvements. 922.1.22 - Many bug and race fixes and error handling improvements.
89 93
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 7ae647c640bb..f7bee8d014d9 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1016,26 +1016,31 @@ skip_large_dir_stuff:
1016 /* Setup the state. */ 1016 /* Setup the state. */
1017 if (a->non_resident) { 1017 if (a->non_resident) {
1018 NInoSetNonResident(ni); 1018 NInoSetNonResident(ni);
1019 if (a->flags & ATTR_COMPRESSION_MASK) { 1019 if (a->flags & (ATTR_COMPRESSION_MASK |
1020 NInoSetCompressed(ni); 1020 ATTR_IS_SPARSE)) {
1021 if (vol->cluster_size > 4096) { 1021 if (a->flags & ATTR_COMPRESSION_MASK) {
1022 ntfs_error(vi->i_sb, "Found " 1022 NInoSetCompressed(ni);
1023 "compressed data but " 1023 if (vol->cluster_size > 4096) {
1024 "compression is disabled due " 1024 ntfs_error(vi->i_sb, "Found "
1025 "to cluster size (%i) > 4kiB.", 1025 "compressed data but "
1026 vol->cluster_size); 1026 "compression is "
1027 goto unm_err_out; 1027 "disabled due to "
1028 } 1028 "cluster size (%i) > "
1029 if ((a->flags & ATTR_COMPRESSION_MASK) 1029 "4kiB.",
1030 != ATTR_IS_COMPRESSED) { 1030 vol->cluster_size);
1031 ntfs_error(vi->i_sb, "Found " 1031 goto unm_err_out;
1032 "unknown compression method or " 1032 }
1033 "corrupt file."); 1033 if ((a->flags & ATTR_COMPRESSION_MASK)
1034 goto unm_err_out; 1034 != ATTR_IS_COMPRESSED) {
1035 ntfs_error(vi->i_sb, "Found "
1036 "unknown compression "
1037 "method or corrupt "
1038 "file.");
1039 goto unm_err_out;
1040 }
1035 } 1041 }
1036 ni->itype.compressed.block_clusters = 1U << 1042 if (a->flags & ATTR_IS_SPARSE)
1037 a->data.non_resident. 1043 NInoSetSparse(ni);
1038 compression_unit;
1039 if (a->data.non_resident.compression_unit != 1044 if (a->data.non_resident.compression_unit !=
1040 4) { 1045 4) {
1041 ntfs_error(vi->i_sb, "Found " 1046 ntfs_error(vi->i_sb, "Found "
@@ -1047,12 +1052,19 @@ skip_large_dir_stuff:
1047 err = -EOPNOTSUPP; 1052 err = -EOPNOTSUPP;
1048 goto unm_err_out; 1053 goto unm_err_out;
1049 } 1054 }
1055 ni->itype.compressed.block_clusters = 1U <<
1056 a->data.non_resident.
1057 compression_unit;
1050 ni->itype.compressed.block_size = 1U << ( 1058 ni->itype.compressed.block_size = 1U << (
1051 a->data.non_resident. 1059 a->data.non_resident.
1052 compression_unit + 1060 compression_unit +
1053 vol->cluster_size_bits); 1061 vol->cluster_size_bits);
1054 ni->itype.compressed.block_size_bits = ffs( 1062 ni->itype.compressed.block_size_bits = ffs(
1055 ni->itype.compressed.block_size) - 1; 1063 ni->itype.compressed.
1064 block_size) - 1;
1065 ni->itype.compressed.size = sle64_to_cpu(
1066 a->data.non_resident.
1067 compressed_size);
1056 } 1068 }
1057 if (a->flags & ATTR_IS_ENCRYPTED) { 1069 if (a->flags & ATTR_IS_ENCRYPTED) {
1058 if (a->flags & ATTR_COMPRESSION_MASK) { 1070 if (a->flags & ATTR_COMPRESSION_MASK) {
@@ -1062,27 +1074,19 @@ skip_large_dir_stuff:
1062 } 1074 }
1063 NInoSetEncrypted(ni); 1075 NInoSetEncrypted(ni);
1064 } 1076 }
1065 if (a->flags & ATTR_IS_SPARSE)
1066 NInoSetSparse(ni);
1067 if (a->data.non_resident.lowest_vcn) { 1077 if (a->data.non_resident.lowest_vcn) {
1068 ntfs_error(vi->i_sb, "First extent of $DATA " 1078 ntfs_error(vi->i_sb, "First extent of $DATA "
1069 "attribute has non zero " 1079 "attribute has non zero "
1070 "lowest_vcn."); 1080 "lowest_vcn.");
1071 goto unm_err_out; 1081 goto unm_err_out;
1072 } 1082 }
1073 /* Setup all the sizes. */
1074 vi->i_size = sle64_to_cpu( 1083 vi->i_size = sle64_to_cpu(
1075 a->data.non_resident.data_size); 1084 a->data.non_resident.data_size);
1076 ni->initialized_size = sle64_to_cpu( 1085 ni->initialized_size = sle64_to_cpu(
1077 a->data.non_resident.initialized_size); 1086 a->data.non_resident.initialized_size);
1078 ni->allocated_size = sle64_to_cpu( 1087 ni->allocated_size = sle64_to_cpu(
1079 a->data.non_resident.allocated_size); 1088 a->data.non_resident.allocated_size);
1080 if (NInoCompressed(ni))
1081 ni->itype.compressed.size = sle64_to_cpu(
1082 a->data.non_resident.
1083 compressed_size);
1084 } else { /* Resident attribute. */ 1089 } else { /* Resident attribute. */
1085 /* Setup all the sizes. */
1086 vi->i_size = ni->initialized_size = le32_to_cpu( 1090 vi->i_size = ni->initialized_size = le32_to_cpu(
1087 a->data.resident.value_length); 1091 a->data.resident.value_length);
1088 ni->allocated_size = le32_to_cpu(a->length) - 1092 ni->allocated_size = le32_to_cpu(a->length) -
@@ -1120,11 +1124,10 @@ no_data_attr_special_case:
1120 * sizes of all non-resident attributes present to give us the Linux 1124 * sizes of all non-resident attributes present to give us the Linux
1121 * correct size that should go into i_blocks (after division by 512). 1125 * correct size that should go into i_blocks (after division by 512).
1122 */ 1126 */
1123 if (S_ISDIR(vi->i_mode) || !NInoCompressed(ni)) 1127 if (S_ISREG(vi->i_mode) && (NInoCompressed(ni) || NInoSparse(ni)))
1124 vi->i_blocks = ni->allocated_size >> 9;
1125 else
1126 vi->i_blocks = ni->itype.compressed.size >> 9; 1128 vi->i_blocks = ni->itype.compressed.size >> 9;
1127 1129 else
1130 vi->i_blocks = ni->allocated_size >> 9;
1128 ntfs_debug("Done."); 1131 ntfs_debug("Done.");
1129 return 0; 1132 return 0;
1130 1133
@@ -1226,14 +1229,13 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1226 "linux-ntfs-dev@lists.sourceforge.net"); 1229 "linux-ntfs-dev@lists.sourceforge.net");
1227 goto unm_err_out; 1230 goto unm_err_out;
1228 } 1231 }
1229 /* Resident attribute. Setup all the sizes. */
1230 vi->i_size = ni->initialized_size = le32_to_cpu( 1232 vi->i_size = ni->initialized_size = le32_to_cpu(
1231 a->data.resident.value_length); 1233 a->data.resident.value_length);
1232 ni->allocated_size = le32_to_cpu(a->length) - 1234 ni->allocated_size = le32_to_cpu(a->length) -
1233 le16_to_cpu(a->data.resident.value_offset); 1235 le16_to_cpu(a->data.resident.value_offset);
1234 if (vi->i_size > ni->allocated_size) { 1236 if (vi->i_size > ni->allocated_size) {
1235 ntfs_error(vi->i_sb, "Resident data attribute is " 1237 ntfs_error(vi->i_sb, "Resident attribute is corrupt "
1236 "corrupt (size exceeds allocation)."); 1238 "(size exceeds allocation).");
1237 goto unm_err_out; 1239 goto unm_err_out;
1238 } 1240 }
1239 } else { 1241 } else {
@@ -1249,43 +1251,50 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1249 "the mapping pairs array."); 1251 "the mapping pairs array.");
1250 goto unm_err_out; 1252 goto unm_err_out;
1251 } 1253 }
1252 if (a->flags & ATTR_COMPRESSION_MASK) { 1254 if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
1255 if (a->flags & ATTR_COMPRESSION_MASK) {
1256 NInoSetCompressed(ni);
1257 if ((ni->type != AT_DATA) || (ni->type ==
1258 AT_DATA && ni->name_len)) {
1259 ntfs_error(vi->i_sb, "Found compressed "
1260 "non-data or named "
1261 "data attribute. "
1262 "Please report you "
1263 "saw this message to "
1264 "linux-ntfs-dev@lists."
1265 "sourceforge.net");
1266 goto unm_err_out;
1267 }
1268 if (vol->cluster_size > 4096) {
1269 ntfs_error(vi->i_sb, "Found compressed "
1270 "attribute but "
1271 "compression is "
1272 "disabled due to "
1273 "cluster size (%i) > "
1274 "4kiB.",
1275 vol->cluster_size);
1276 goto unm_err_out;
1277 }
1278 if ((a->flags & ATTR_COMPRESSION_MASK) !=
1279 ATTR_IS_COMPRESSED) {
1280 ntfs_error(vi->i_sb, "Found unknown "
1281 "compression method.");
1282 goto unm_err_out;
1283 }
1284 }
1253 if (NInoMstProtected(ni)) { 1285 if (NInoMstProtected(ni)) {
1254 ntfs_error(vi->i_sb, "Found mst protected " 1286 ntfs_error(vi->i_sb, "Found mst protected "
1255 "attribute but the attribute " 1287 "attribute but the attribute "
1256 "is compressed. Please report " 1288 "is %s. Please report you "
1257 "you saw this message to " 1289 "saw this message to "
1258 "linux-ntfs-dev@lists."
1259 "sourceforge.net");
1260 goto unm_err_out;
1261 }
1262 NInoSetCompressed(ni);
1263 if ((ni->type != AT_DATA) || (ni->type == AT_DATA &&
1264 ni->name_len)) {
1265 ntfs_error(vi->i_sb, "Found compressed "
1266 "non-data or named data "
1267 "attribute. Please report "
1268 "you saw this message to "
1269 "linux-ntfs-dev@lists." 1290 "linux-ntfs-dev@lists."
1270 "sourceforge.net"); 1291 "sourceforge.net",
1271 goto unm_err_out; 1292 NInoCompressed(ni) ?
1272 } 1293 "compressed" : "sparse");
1273 if (vol->cluster_size > 4096) {
1274 ntfs_error(vi->i_sb, "Found compressed "
1275 "attribute but compression is "
1276 "disabled due to cluster size "
1277 "(%i) > 4kiB.",
1278 vol->cluster_size);
1279 goto unm_err_out;
1280 }
1281 if ((a->flags & ATTR_COMPRESSION_MASK) !=
1282 ATTR_IS_COMPRESSED) {
1283 ntfs_error(vi->i_sb, "Found unknown "
1284 "compression method.");
1285 goto unm_err_out; 1294 goto unm_err_out;
1286 } 1295 }
1287 ni->itype.compressed.block_clusters = 1U << 1296 if (a->flags & ATTR_IS_SPARSE)
1288 a->data.non_resident.compression_unit; 1297 NInoSetSparse(ni);
1289 if (a->data.non_resident.compression_unit != 4) { 1298 if (a->data.non_resident.compression_unit != 4) {
1290 ntfs_error(vi->i_sb, "Found nonstandard " 1299 ntfs_error(vi->i_sb, "Found nonstandard "
1291 "compression unit (%u instead " 1300 "compression unit (%u instead "
@@ -1295,11 +1304,15 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1295 err = -EOPNOTSUPP; 1304 err = -EOPNOTSUPP;
1296 goto unm_err_out; 1305 goto unm_err_out;
1297 } 1306 }
1307 ni->itype.compressed.block_clusters = 1U <<
1308 a->data.non_resident.compression_unit;
1298 ni->itype.compressed.block_size = 1U << ( 1309 ni->itype.compressed.block_size = 1U << (
1299 a->data.non_resident.compression_unit + 1310 a->data.non_resident.compression_unit +
1300 vol->cluster_size_bits); 1311 vol->cluster_size_bits);
1301 ni->itype.compressed.block_size_bits = ffs( 1312 ni->itype.compressed.block_size_bits = ffs(
1302 ni->itype.compressed.block_size) - 1; 1313 ni->itype.compressed.block_size) - 1;
1314 ni->itype.compressed.size = sle64_to_cpu(
1315 a->data.non_resident.compressed_size);
1303 } 1316 }
1304 if (a->flags & ATTR_IS_ENCRYPTED) { 1317 if (a->flags & ATTR_IS_ENCRYPTED) {
1305 if (a->flags & ATTR_COMPRESSION_MASK) { 1318 if (a->flags & ATTR_COMPRESSION_MASK) {
@@ -1318,34 +1331,17 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1318 } 1331 }
1319 NInoSetEncrypted(ni); 1332 NInoSetEncrypted(ni);
1320 } 1333 }
1321 if (a->flags & ATTR_IS_SPARSE) {
1322 if (NInoMstProtected(ni)) {
1323 ntfs_error(vi->i_sb, "Found mst protected "
1324 "attribute but the attribute "
1325 "is sparse. Please report "
1326 "you saw this message to "
1327 "linux-ntfs-dev@lists."
1328 "sourceforge.net");
1329 goto unm_err_out;
1330 }
1331 NInoSetSparse(ni);
1332 }
1333 if (a->data.non_resident.lowest_vcn) { 1334 if (a->data.non_resident.lowest_vcn) {
1334 ntfs_error(vi->i_sb, "First extent of attribute has " 1335 ntfs_error(vi->i_sb, "First extent of attribute has "
1335 "non-zero lowest_vcn."); 1336 "non-zero lowest_vcn.");
1336 goto unm_err_out; 1337 goto unm_err_out;
1337 } 1338 }
1338 /* Setup all the sizes. */
1339 vi->i_size = sle64_to_cpu(a->data.non_resident.data_size); 1339 vi->i_size = sle64_to_cpu(a->data.non_resident.data_size);
1340 ni->initialized_size = sle64_to_cpu( 1340 ni->initialized_size = sle64_to_cpu(
1341 a->data.non_resident.initialized_size); 1341 a->data.non_resident.initialized_size);
1342 ni->allocated_size = sle64_to_cpu( 1342 ni->allocated_size = sle64_to_cpu(
1343 a->data.non_resident.allocated_size); 1343 a->data.non_resident.allocated_size);
1344 if (NInoCompressed(ni))
1345 ni->itype.compressed.size = sle64_to_cpu(
1346 a->data.non_resident.compressed_size);
1347 } 1344 }
1348
1349 /* Setup the operations for this attribute inode. */ 1345 /* Setup the operations for this attribute inode. */
1350 vi->i_op = NULL; 1346 vi->i_op = NULL;
1351 vi->i_fop = NULL; 1347 vi->i_fop = NULL;
@@ -1353,12 +1349,10 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1353 vi->i_mapping->a_ops = &ntfs_mst_aops; 1349 vi->i_mapping->a_ops = &ntfs_mst_aops;
1354 else 1350 else
1355 vi->i_mapping->a_ops = &ntfs_aops; 1351 vi->i_mapping->a_ops = &ntfs_aops;
1356 1352 if (NInoCompressed(ni) || NInoSparse(ni))
1357 if (!NInoCompressed(ni))
1358 vi->i_blocks = ni->allocated_size >> 9;
1359 else
1360 vi->i_blocks = ni->itype.compressed.size >> 9; 1353 vi->i_blocks = ni->itype.compressed.size >> 9;
1361 1354 else
1355 vi->i_blocks = ni->allocated_size >> 9;
1362 /* 1356 /*
1363 * Make sure the base inode doesn't go away and attach it to the 1357 * Make sure the base inode doesn't go away and attach it to the
1364 * attribute inode. 1358 * attribute inode.
@@ -1643,7 +1637,6 @@ skip_large_index_stuff:
1643 vi->i_fop = NULL; 1637 vi->i_fop = NULL;
1644 vi->i_mapping->a_ops = &ntfs_mst_aops; 1638 vi->i_mapping->a_ops = &ntfs_mst_aops;
1645 vi->i_blocks = ni->allocated_size >> 9; 1639 vi->i_blocks = ni->allocated_size >> 9;
1646
1647 /* 1640 /*
1648 * Make sure the base inode doesn't go away and attach it to the 1641 * Make sure the base inode doesn't go away and attach it to the
1649 * index inode. 1642 * index inode.
@@ -1728,7 +1721,6 @@ int ntfs_read_inode_mount(struct inode *vi)
1728 ni->type = AT_DATA; 1721 ni->type = AT_DATA;
1729 ni->name = NULL; 1722 ni->name = NULL;
1730 ni->name_len = 0; 1723 ni->name_len = 0;
1731
1732 /* 1724 /*
1733 * This sets up our little cheat allowing us to reuse the async read io 1725 * This sets up our little cheat allowing us to reuse the async read io
1734 * completion handler for directories. 1726 * completion handler for directories.
diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h
index 7cb8806d4559..8d1f1326612f 100644
--- a/fs/ntfs/layout.h
+++ b/fs/ntfs/layout.h
@@ -749,10 +749,11 @@ typedef struct {
749 record header aligned to 8-byte boundary. */ 749 record header aligned to 8-byte boundary. */
750/* 34*/ u8 compression_unit; /* The compression unit expressed 750/* 34*/ u8 compression_unit; /* The compression unit expressed
751 as the log to the base 2 of the number of 751 as the log to the base 2 of the number of
752 clusters in a compression unit. 0 means not 752 clusters in a compression unit. 0 means not
753 compressed. (This effectively limits the 753 compressed. (This effectively limits the
754 compression unit size to be a power of two 754 compression unit size to be a power of two
755 clusters.) WinNT4 only uses a value of 4. */ 755 clusters.) WinNT4 only uses a value of 4.
756 Sparse files also have this set to 4. */
756/* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */ 757/* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */
757/* The sizes below are only used when lowest_vcn is zero, as otherwise it would 758/* The sizes below are only used when lowest_vcn is zero, as otherwise it would
758 be difficult to keep them up-to-date.*/ 759 be difficult to keep them up-to-date.*/
@@ -772,10 +773,10 @@ typedef struct {
772 data_size. */ 773 data_size. */
773/* sizeof(uncompressed attr) = 64*/ 774/* sizeof(uncompressed attr) = 64*/
774/* 64*/ sle64 compressed_size; /* Byte size of the attribute 775/* 64*/ sle64 compressed_size; /* Byte size of the attribute
775 value after compression. Only present when 776 value after compression. Only present when
776 compressed. Always is a multiple of the 777 compressed or sparse. Always is a multiple of
777 cluster size. Represents the actual amount of 778 the cluster size. Represents the actual amount
778 disk space being used on the disk. */ 779 of disk space being used on the disk. */
779/* sizeof(compressed attr) = 72*/ 780/* sizeof(compressed attr) = 72*/
780 } __attribute__ ((__packed__)) non_resident; 781 } __attribute__ ((__packed__)) non_resident;
781 } __attribute__ ((__packed__)) data; 782 } __attribute__ ((__packed__)) data;