diff options
Diffstat (limited to 'fs/ntfs/inode.c')
| -rw-r--r-- | fs/ntfs/inode.c | 227 |
1 files changed, 121 insertions, 106 deletions
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 886214a77f90..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 " |
| @@ -2430,16 +2443,18 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 2430 | * We skipped the truncate but must still update | 2443 | * We skipped the truncate but must still update |
| 2431 | * timestamps. | 2444 | * timestamps. |
| 2432 | */ | 2445 | */ |
| 2433 | ia_valid |= ATTR_MTIME|ATTR_CTIME; | 2446 | ia_valid |= ATTR_MTIME | ATTR_CTIME; |
| 2434 | } | 2447 | } |
| 2435 | } | 2448 | } |
| 2436 | |||
| 2437 | if (ia_valid & ATTR_ATIME) | 2449 | if (ia_valid & ATTR_ATIME) |
| 2438 | vi->i_atime = attr->ia_atime; | 2450 | vi->i_atime = timespec_trunc(attr->ia_atime, |
| 2451 | vi->i_sb->s_time_gran); | ||
| 2439 | if (ia_valid & ATTR_MTIME) | 2452 | if (ia_valid & ATTR_MTIME) |
| 2440 | vi->i_mtime = attr->ia_mtime; | 2453 | vi->i_mtime = timespec_trunc(attr->ia_mtime, |
| 2454 | vi->i_sb->s_time_gran); | ||
| 2441 | if (ia_valid & ATTR_CTIME) | 2455 | if (ia_valid & ATTR_CTIME) |
| 2442 | vi->i_ctime = attr->ia_ctime; | 2456 | vi->i_ctime = timespec_trunc(attr->ia_ctime, |
| 2457 | vi->i_sb->s_time_gran); | ||
| 2443 | mark_inode_dirty(vi); | 2458 | mark_inode_dirty(vi); |
| 2444 | out: | 2459 | out: |
| 2445 | return err; | 2460 | return err; |
