aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ntfs/ChangeLog2
-rw-r--r--fs/ntfs/inode.c215
2 files changed, 116 insertions, 101 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 9c5af9c8a8af..ed8d00150931 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -75,6 +75,8 @@ ToDo/Notes:
75 which leads to lock reversal. 75 which leads to lock reversal.
76 - Truncate {a,c,m}time to the ntfs supported time granularity when 76 - Truncate {a,c,m}time to the ntfs supported time granularity when
77 updating the times in the inode in ntfs_setattr(). 77 updating the times in the inode in ntfs_setattr().
78 - Fixup handling of sparse, compressed, and encrypted attributes in
79 fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode().
78 80
792.1.23 - Implement extension of resident files and make writing safe as well as 812.1.23 - Implement extension of resident files and make writing safe as well as
80 many bug fixes, cleanups, and enhancements... 82 many bug fixes, cleanups, and enhancements...
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 89d844f69244..dc4bbe3acf5c 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1013,41 +1013,50 @@ skip_large_dir_stuff:
1013 } 1013 }
1014 a = ctx->attr; 1014 a = ctx->attr;
1015 /* Setup the state. */ 1015 /* Setup the state. */
1016 if (a->non_resident) { 1016 if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
1017 NInoSetNonResident(ni); 1017 if (a->flags & ATTR_COMPRESSION_MASK) {
1018 if (a->flags & (ATTR_COMPRESSION_MASK | 1018 NInoSetCompressed(ni);
1019 ATTR_IS_SPARSE)) { 1019 if (vol->cluster_size > 4096) {
1020 if (a->flags & ATTR_COMPRESSION_MASK) { 1020 ntfs_error(vi->i_sb, "Found "
1021 NInoSetCompressed(ni);
1022 if (vol->cluster_size > 4096) {
1023 ntfs_error(vi->i_sb, "Found "
1024 "compressed data but " 1021 "compressed data but "
1025 "compression is " 1022 "compression is "
1026 "disabled due to " 1023 "disabled due to "
1027 "cluster size (%i) > " 1024 "cluster size (%i) > "
1028 "4kiB.", 1025 "4kiB.",
1029 vol->cluster_size); 1026 vol->cluster_size);
1030 goto unm_err_out; 1027 goto unm_err_out;
1031 } 1028 }
1032 if ((a->flags & ATTR_COMPRESSION_MASK) 1029 if ((a->flags & ATTR_COMPRESSION_MASK)
1033 != ATTR_IS_COMPRESSED) { 1030 != ATTR_IS_COMPRESSED) {
1034 ntfs_error(vi->i_sb, "Found " 1031 ntfs_error(vi->i_sb, "Found unknown "
1035 "unknown compression " 1032 "compression method "
1036 "method or corrupt " 1033 "or corrupt file.");
1037 "file."); 1034 goto unm_err_out;
1038 goto unm_err_out;
1039 }
1040 } 1035 }
1041 if (a->flags & ATTR_IS_SPARSE) 1036 }
1042 NInoSetSparse(ni); 1037 if (a->flags & ATTR_IS_SPARSE)
1038 NInoSetSparse(ni);
1039 }
1040 if (a->flags & ATTR_IS_ENCRYPTED) {
1041 if (NInoCompressed(ni)) {
1042 ntfs_error(vi->i_sb, "Found encrypted and "
1043 "compressed data.");
1044 goto unm_err_out;
1045 }
1046 NInoSetEncrypted(ni);
1047 }
1048 if (a->non_resident) {
1049 NInoSetNonResident(ni);
1050 if (NInoCompressed(ni) || NInoSparse(ni)) {
1043 if (a->data.non_resident.compression_unit != 1051 if (a->data.non_resident.compression_unit !=
1044 4) { 1052 4) {
1045 ntfs_error(vi->i_sb, "Found " 1053 ntfs_error(vi->i_sb, "Found "
1046 "nonstandard compression unit " 1054 "nonstandard "
1047 "(%u instead of 4). Cannot " 1055 "compression unit (%u "
1048 "handle this.", 1056 "instead of 4). "
1049 a->data.non_resident. 1057 "Cannot handle this.",
1050 compression_unit); 1058 a->data.non_resident.
1059 compression_unit);
1051 err = -EOPNOTSUPP; 1060 err = -EOPNOTSUPP;
1052 goto unm_err_out; 1061 goto unm_err_out;
1053 } 1062 }
@@ -1065,14 +1074,6 @@ skip_large_dir_stuff:
1065 a->data.non_resident. 1074 a->data.non_resident.
1066 compressed_size); 1075 compressed_size);
1067 } 1076 }
1068 if (a->flags & ATTR_IS_ENCRYPTED) {
1069 if (a->flags & ATTR_COMPRESSION_MASK) {
1070 ntfs_error(vi->i_sb, "Found encrypted "
1071 "and compressed data.");
1072 goto unm_err_out;
1073 }
1074 NInoSetEncrypted(ni);
1075 }
1076 if (a->data.non_resident.lowest_vcn) { 1077 if (a->data.non_resident.lowest_vcn) {
1077 ntfs_error(vi->i_sb, "First extent of $DATA " 1078 ntfs_error(vi->i_sb, "First extent of $DATA "
1078 "attribute has non zero " 1079 "attribute has non zero "
@@ -1212,6 +1213,75 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1212 if (unlikely(err)) 1213 if (unlikely(err))
1213 goto unm_err_out; 1214 goto unm_err_out;
1214 a = ctx->attr; 1215 a = ctx->attr;
1216 if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
1217 if (a->flags & ATTR_COMPRESSION_MASK) {
1218 NInoSetCompressed(ni);
1219 if ((ni->type != AT_DATA) || (ni->type == AT_DATA &&
1220 ni->name_len)) {
1221 ntfs_error(vi->i_sb, "Found compressed "
1222 "non-data or named data "
1223 "attribute. Please report "
1224 "you saw this message to "
1225 "linux-ntfs-dev@lists."
1226 "sourceforge.net");
1227 goto unm_err_out;
1228 }
1229 if (vol->cluster_size > 4096) {
1230 ntfs_error(vi->i_sb, "Found compressed "
1231 "attribute but compression is "
1232 "disabled due to cluster size "
1233 "(%i) > 4kiB.",
1234 vol->cluster_size);
1235 goto unm_err_out;
1236 }
1237 if ((a->flags & ATTR_COMPRESSION_MASK) !=
1238 ATTR_IS_COMPRESSED) {
1239 ntfs_error(vi->i_sb, "Found unknown "
1240 "compression method.");
1241 goto unm_err_out;
1242 }
1243 }
1244 /*
1245 * The encryption flag set in an index root just means to
1246 * compress all files.
1247 */
1248 if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {
1249 ntfs_error(vi->i_sb, "Found mst protected attribute "
1250 "but the attribute is %s. Please "
1251 "report you saw this message to "
1252 "linux-ntfs-dev@lists.sourceforge.net",
1253 NInoCompressed(ni) ? "compressed" :
1254 "sparse");
1255 goto unm_err_out;
1256 }
1257 if (a->flags & ATTR_IS_SPARSE)
1258 NInoSetSparse(ni);
1259 }
1260 if (a->flags & ATTR_IS_ENCRYPTED) {
1261 if (NInoCompressed(ni)) {
1262 ntfs_error(vi->i_sb, "Found encrypted and compressed "
1263 "data.");
1264 goto unm_err_out;
1265 }
1266 /*
1267 * The encryption flag set in an index root just means to
1268 * encrypt all files.
1269 */
1270 if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {
1271 ntfs_error(vi->i_sb, "Found mst protected attribute "
1272 "but the attribute is encrypted. "
1273 "Please report you saw this message "
1274 "to linux-ntfs-dev@lists.sourceforge."
1275 "net");
1276 goto unm_err_out;
1277 }
1278 if (ni->type != AT_DATA) {
1279 ntfs_error(vi->i_sb, "Found encrypted non-data "
1280 "attribute.");
1281 goto unm_err_out;
1282 }
1283 NInoSetEncrypted(ni);
1284 }
1215 if (!a->non_resident) { 1285 if (!a->non_resident) {
1216 /* Ensure the attribute name is placed before the value. */ 1286 /* Ensure the attribute name is placed before the value. */
1217 if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= 1287 if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >=
@@ -1220,11 +1290,10 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1220 "the attribute value."); 1290 "the attribute value.");
1221 goto unm_err_out; 1291 goto unm_err_out;
1222 } 1292 }
1223 if (NInoMstProtected(ni) || a->flags) { 1293 if (NInoMstProtected(ni)) {
1224 ntfs_error(vi->i_sb, "Found mst protected attribute " 1294 ntfs_error(vi->i_sb, "Found mst protected attribute "
1225 "or attribute with non-zero flags but " 1295 "but the attribute is resident. "
1226 "the attribute is resident. Please " 1296 "Please report you saw this message to "
1227 "report you saw this message to "
1228 "linux-ntfs-dev@lists.sourceforge.net"); 1297 "linux-ntfs-dev@lists.sourceforge.net");
1229 goto unm_err_out; 1298 goto unm_err_out;
1230 } 1299 }
@@ -1250,50 +1319,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1250 "the mapping pairs array."); 1319 "the mapping pairs array.");
1251 goto unm_err_out; 1320 goto unm_err_out;
1252 } 1321 }
1253 if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) { 1322 if ((NInoCompressed(ni) || NInoSparse(ni)) &&
1254 if (a->flags & ATTR_COMPRESSION_MASK) { 1323 ni->type != AT_INDEX_ROOT) {
1255 NInoSetCompressed(ni);
1256 if ((ni->type != AT_DATA) || (ni->type ==
1257 AT_DATA && ni->name_len)) {
1258 ntfs_error(vi->i_sb, "Found compressed "
1259 "non-data or named "
1260 "data attribute. "
1261 "Please report you "
1262 "saw this message to "
1263 "linux-ntfs-dev@lists."
1264 "sourceforge.net");
1265 goto unm_err_out;
1266 }
1267 if (vol->cluster_size > 4096) {
1268 ntfs_error(vi->i_sb, "Found compressed "
1269 "attribute but "
1270 "compression is "
1271 "disabled due to "
1272 "cluster size (%i) > "
1273 "4kiB.",
1274 vol->cluster_size);
1275 goto unm_err_out;
1276 }
1277 if ((a->flags & ATTR_COMPRESSION_MASK) !=
1278 ATTR_IS_COMPRESSED) {
1279 ntfs_error(vi->i_sb, "Found unknown "
1280 "compression method.");
1281 goto unm_err_out;
1282 }
1283 }
1284 if (NInoMstProtected(ni)) {
1285 ntfs_error(vi->i_sb, "Found mst protected "
1286 "attribute but the attribute "
1287 "is %s. Please report you "
1288 "saw this message to "
1289 "linux-ntfs-dev@lists."
1290 "sourceforge.net",
1291 NInoCompressed(ni) ?
1292 "compressed" : "sparse");
1293 goto unm_err_out;
1294 }
1295 if (a->flags & ATTR_IS_SPARSE)
1296 NInoSetSparse(ni);
1297 if (a->data.non_resident.compression_unit != 4) { 1324 if (a->data.non_resident.compression_unit != 4) {
1298 ntfs_error(vi->i_sb, "Found nonstandard " 1325 ntfs_error(vi->i_sb, "Found nonstandard "
1299 "compression unit (%u instead " 1326 "compression unit (%u instead "
@@ -1313,23 +1340,6 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1313 ni->itype.compressed.size = sle64_to_cpu( 1340 ni->itype.compressed.size = sle64_to_cpu(
1314 a->data.non_resident.compressed_size); 1341 a->data.non_resident.compressed_size);
1315 } 1342 }
1316 if (a->flags & ATTR_IS_ENCRYPTED) {
1317 if (a->flags & ATTR_COMPRESSION_MASK) {
1318 ntfs_error(vi->i_sb, "Found encrypted and "
1319 "compressed data.");
1320 goto unm_err_out;
1321 }
1322 if (NInoMstProtected(ni)) {
1323 ntfs_error(vi->i_sb, "Found mst protected "
1324 "attribute but the attribute "
1325 "is encrypted. Please report "
1326 "you saw this message to "
1327 "linux-ntfs-dev@lists."
1328 "sourceforge.net");
1329 goto unm_err_out;
1330 }
1331 NInoSetEncrypted(ni);
1332 }
1333 if (a->data.non_resident.lowest_vcn) { 1343 if (a->data.non_resident.lowest_vcn) {
1334 ntfs_error(vi->i_sb, "First extent of attribute has " 1344 ntfs_error(vi->i_sb, "First extent of attribute has "
1335 "non-zero lowest_vcn."); 1345 "non-zero lowest_vcn.");
@@ -1348,12 +1358,12 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
1348 vi->i_mapping->a_ops = &ntfs_mst_aops; 1358 vi->i_mapping->a_ops = &ntfs_mst_aops;
1349 else 1359 else
1350 vi->i_mapping->a_ops = &ntfs_aops; 1360 vi->i_mapping->a_ops = &ntfs_aops;
1351 if (NInoCompressed(ni) || NInoSparse(ni)) 1361 if ((NInoCompressed(ni) || NInoSparse(ni)) && ni->type != AT_INDEX_ROOT)
1352 vi->i_blocks = ni->itype.compressed.size >> 9; 1362 vi->i_blocks = ni->itype.compressed.size >> 9;
1353 else 1363 else
1354 vi->i_blocks = ni->allocated_size >> 9; 1364 vi->i_blocks = ni->allocated_size >> 9;
1355 /* 1365 /*
1356 * Make sure the base inode doesn't go away and attach it to the 1366 * Make sure the base inode does not go away and attach it to the
1357 * attribute inode. 1367 * attribute inode.
1358 */ 1368 */
1359 igrab(base_vi); 1369 igrab(base_vi);
@@ -1480,7 +1490,10 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
1480 "after the attribute value."); 1490 "after the attribute value.");
1481 goto unm_err_out; 1491 goto unm_err_out;
1482 } 1492 }
1483 /* Compressed/encrypted/sparse index root is not allowed. */ 1493 /*
1494 * Compressed/encrypted/sparse index root is not allowed, except for
1495 * directories of course but those are not dealt with here.
1496 */
1484 if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED | 1497 if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED |
1485 ATTR_IS_SPARSE)) { 1498 ATTR_IS_SPARSE)) {
1486 ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index " 1499 ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index "