NTFS: Fixup handling of sparse, compressed, and encrypted attributes in
fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode(). Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
This commit is contained in:
parent
1c7d469d47
commit
67bb103725
@ -75,6 +75,8 @@ ToDo/Notes:
|
|||||||
which leads to lock reversal.
|
which leads to lock reversal.
|
||||||
- Truncate {a,c,m}time to the ntfs supported time granularity when
|
- Truncate {a,c,m}time to the ntfs supported time granularity when
|
||||||
updating the times in the inode in ntfs_setattr().
|
updating the times in the inode in ntfs_setattr().
|
||||||
|
- Fixup handling of sparse, compressed, and encrypted attributes in
|
||||||
|
fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode().
|
||||||
|
|
||||||
2.1.23 - Implement extension of resident files and make writing safe as well as
|
2.1.23 - Implement extension of resident files and make writing safe as well as
|
||||||
many bug fixes, cleanups, and enhancements...
|
many bug fixes, cleanups, and enhancements...
|
||||||
|
215
fs/ntfs/inode.c
215
fs/ntfs/inode.c
@ -1013,41 +1013,50 @@ static int ntfs_read_locked_inode(struct inode *vi)
|
|||||||
}
|
}
|
||||||
a = ctx->attr;
|
a = ctx->attr;
|
||||||
/* Setup the state. */
|
/* Setup the state. */
|
||||||
if (a->non_resident) {
|
if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
|
||||||
NInoSetNonResident(ni);
|
if (a->flags & ATTR_COMPRESSION_MASK) {
|
||||||
if (a->flags & (ATTR_COMPRESSION_MASK |
|
NInoSetCompressed(ni);
|
||||||
ATTR_IS_SPARSE)) {
|
if (vol->cluster_size > 4096) {
|
||||||
if (a->flags & ATTR_COMPRESSION_MASK) {
|
ntfs_error(vi->i_sb, "Found "
|
||||||
NInoSetCompressed(ni);
|
|
||||||
if (vol->cluster_size > 4096) {
|
|
||||||
ntfs_error(vi->i_sb, "Found "
|
|
||||||
"compressed data but "
|
"compressed data but "
|
||||||
"compression is "
|
"compression is "
|
||||||
"disabled due to "
|
"disabled due to "
|
||||||
"cluster size (%i) > "
|
"cluster size (%i) > "
|
||||||
"4kiB.",
|
"4kiB.",
|
||||||
vol->cluster_size);
|
vol->cluster_size);
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
|
||||||
if ((a->flags & ATTR_COMPRESSION_MASK)
|
|
||||||
!= ATTR_IS_COMPRESSED) {
|
|
||||||
ntfs_error(vi->i_sb, "Found "
|
|
||||||
"unknown compression "
|
|
||||||
"method or corrupt "
|
|
||||||
"file.");
|
|
||||||
goto unm_err_out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (a->flags & ATTR_IS_SPARSE)
|
if ((a->flags & ATTR_COMPRESSION_MASK)
|
||||||
NInoSetSparse(ni);
|
!= ATTR_IS_COMPRESSED) {
|
||||||
|
ntfs_error(vi->i_sb, "Found unknown "
|
||||||
|
"compression method "
|
||||||
|
"or corrupt file.");
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (a->flags & ATTR_IS_SPARSE)
|
||||||
|
NInoSetSparse(ni);
|
||||||
|
}
|
||||||
|
if (a->flags & ATTR_IS_ENCRYPTED) {
|
||||||
|
if (NInoCompressed(ni)) {
|
||||||
|
ntfs_error(vi->i_sb, "Found encrypted and "
|
||||||
|
"compressed data.");
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
NInoSetEncrypted(ni);
|
||||||
|
}
|
||||||
|
if (a->non_resident) {
|
||||||
|
NInoSetNonResident(ni);
|
||||||
|
if (NInoCompressed(ni) || NInoSparse(ni)) {
|
||||||
if (a->data.non_resident.compression_unit !=
|
if (a->data.non_resident.compression_unit !=
|
||||||
4) {
|
4) {
|
||||||
ntfs_error(vi->i_sb, "Found "
|
ntfs_error(vi->i_sb, "Found "
|
||||||
"nonstandard compression unit "
|
"nonstandard "
|
||||||
"(%u instead of 4). Cannot "
|
"compression unit (%u "
|
||||||
"handle this.",
|
"instead of 4). "
|
||||||
a->data.non_resident.
|
"Cannot handle this.",
|
||||||
compression_unit);
|
a->data.non_resident.
|
||||||
|
compression_unit);
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
}
|
||||||
@ -1065,14 +1074,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
|
|||||||
a->data.non_resident.
|
a->data.non_resident.
|
||||||
compressed_size);
|
compressed_size);
|
||||||
}
|
}
|
||||||
if (a->flags & ATTR_IS_ENCRYPTED) {
|
|
||||||
if (a->flags & ATTR_COMPRESSION_MASK) {
|
|
||||||
ntfs_error(vi->i_sb, "Found encrypted "
|
|
||||||
"and compressed data.");
|
|
||||||
goto unm_err_out;
|
|
||||||
}
|
|
||||||
NInoSetEncrypted(ni);
|
|
||||||
}
|
|
||||||
if (a->data.non_resident.lowest_vcn) {
|
if (a->data.non_resident.lowest_vcn) {
|
||||||
ntfs_error(vi->i_sb, "First extent of $DATA "
|
ntfs_error(vi->i_sb, "First extent of $DATA "
|
||||||
"attribute has non zero "
|
"attribute has non zero "
|
||||||
@ -1212,6 +1213,75 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
|
|||||||
if (unlikely(err))
|
if (unlikely(err))
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
a = ctx->attr;
|
a = ctx->attr;
|
||||||
|
if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
|
||||||
|
if (a->flags & ATTR_COMPRESSION_MASK) {
|
||||||
|
NInoSetCompressed(ni);
|
||||||
|
if ((ni->type != AT_DATA) || (ni->type == AT_DATA &&
|
||||||
|
ni->name_len)) {
|
||||||
|
ntfs_error(vi->i_sb, "Found compressed "
|
||||||
|
"non-data or named data "
|
||||||
|
"attribute. Please report "
|
||||||
|
"you saw this message to "
|
||||||
|
"linux-ntfs-dev@lists."
|
||||||
|
"sourceforge.net");
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
if (vol->cluster_size > 4096) {
|
||||||
|
ntfs_error(vi->i_sb, "Found compressed "
|
||||||
|
"attribute but compression is "
|
||||||
|
"disabled due to cluster size "
|
||||||
|
"(%i) > 4kiB.",
|
||||||
|
vol->cluster_size);
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
if ((a->flags & ATTR_COMPRESSION_MASK) !=
|
||||||
|
ATTR_IS_COMPRESSED) {
|
||||||
|
ntfs_error(vi->i_sb, "Found unknown "
|
||||||
|
"compression method.");
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The encryption flag set in an index root just means to
|
||||||
|
* compress all files.
|
||||||
|
*/
|
||||||
|
if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {
|
||||||
|
ntfs_error(vi->i_sb, "Found mst protected attribute "
|
||||||
|
"but the attribute is %s. Please "
|
||||||
|
"report you saw this message to "
|
||||||
|
"linux-ntfs-dev@lists.sourceforge.net",
|
||||||
|
NInoCompressed(ni) ? "compressed" :
|
||||||
|
"sparse");
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
if (a->flags & ATTR_IS_SPARSE)
|
||||||
|
NInoSetSparse(ni);
|
||||||
|
}
|
||||||
|
if (a->flags & ATTR_IS_ENCRYPTED) {
|
||||||
|
if (NInoCompressed(ni)) {
|
||||||
|
ntfs_error(vi->i_sb, "Found encrypted and compressed "
|
||||||
|
"data.");
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The encryption flag set in an index root just means to
|
||||||
|
* encrypt all files.
|
||||||
|
*/
|
||||||
|
if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {
|
||||||
|
ntfs_error(vi->i_sb, "Found mst protected attribute "
|
||||||
|
"but the attribute is encrypted. "
|
||||||
|
"Please report you saw this message "
|
||||||
|
"to linux-ntfs-dev@lists.sourceforge."
|
||||||
|
"net");
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
if (ni->type != AT_DATA) {
|
||||||
|
ntfs_error(vi->i_sb, "Found encrypted non-data "
|
||||||
|
"attribute.");
|
||||||
|
goto unm_err_out;
|
||||||
|
}
|
||||||
|
NInoSetEncrypted(ni);
|
||||||
|
}
|
||||||
if (!a->non_resident) {
|
if (!a->non_resident) {
|
||||||
/* Ensure the attribute name is placed before the value. */
|
/* Ensure the attribute name is placed before the value. */
|
||||||
if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >=
|
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)
|
|||||||
"the attribute value.");
|
"the attribute value.");
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
}
|
||||||
if (NInoMstProtected(ni) || a->flags) {
|
if (NInoMstProtected(ni)) {
|
||||||
ntfs_error(vi->i_sb, "Found mst protected attribute "
|
ntfs_error(vi->i_sb, "Found mst protected attribute "
|
||||||
"or attribute with non-zero flags but "
|
"but the attribute is resident. "
|
||||||
"the attribute is resident. Please "
|
"Please report you saw this message to "
|
||||||
"report you saw this message to "
|
|
||||||
"linux-ntfs-dev@lists.sourceforge.net");
|
"linux-ntfs-dev@lists.sourceforge.net");
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
}
|
||||||
@ -1250,50 +1319,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
|
|||||||
"the mapping pairs array.");
|
"the mapping pairs array.");
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
}
|
||||||
if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
|
if ((NInoCompressed(ni) || NInoSparse(ni)) &&
|
||||||
if (a->flags & ATTR_COMPRESSION_MASK) {
|
ni->type != AT_INDEX_ROOT) {
|
||||||
NInoSetCompressed(ni);
|
|
||||||
if ((ni->type != AT_DATA) || (ni->type ==
|
|
||||||
AT_DATA && ni->name_len)) {
|
|
||||||
ntfs_error(vi->i_sb, "Found compressed "
|
|
||||||
"non-data or named "
|
|
||||||
"data attribute. "
|
|
||||||
"Please report you "
|
|
||||||
"saw this message to "
|
|
||||||
"linux-ntfs-dev@lists."
|
|
||||||
"sourceforge.net");
|
|
||||||
goto unm_err_out;
|
|
||||||
}
|
|
||||||
if (vol->cluster_size > 4096) {
|
|
||||||
ntfs_error(vi->i_sb, "Found compressed "
|
|
||||||
"attribute but "
|
|
||||||
"compression is "
|
|
||||||
"disabled due to "
|
|
||||||
"cluster size (%i) > "
|
|
||||||
"4kiB.",
|
|
||||||
vol->cluster_size);
|
|
||||||
goto unm_err_out;
|
|
||||||
}
|
|
||||||
if ((a->flags & ATTR_COMPRESSION_MASK) !=
|
|
||||||
ATTR_IS_COMPRESSED) {
|
|
||||||
ntfs_error(vi->i_sb, "Found unknown "
|
|
||||||
"compression method.");
|
|
||||||
goto unm_err_out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (NInoMstProtected(ni)) {
|
|
||||||
ntfs_error(vi->i_sb, "Found mst protected "
|
|
||||||
"attribute but the attribute "
|
|
||||||
"is %s. Please report you "
|
|
||||||
"saw this message to "
|
|
||||||
"linux-ntfs-dev@lists."
|
|
||||||
"sourceforge.net",
|
|
||||||
NInoCompressed(ni) ?
|
|
||||||
"compressed" : "sparse");
|
|
||||||
goto unm_err_out;
|
|
||||||
}
|
|
||||||
if (a->flags & ATTR_IS_SPARSE)
|
|
||||||
NInoSetSparse(ni);
|
|
||||||
if (a->data.non_resident.compression_unit != 4) {
|
if (a->data.non_resident.compression_unit != 4) {
|
||||||
ntfs_error(vi->i_sb, "Found nonstandard "
|
ntfs_error(vi->i_sb, "Found nonstandard "
|
||||||
"compression unit (%u instead "
|
"compression unit (%u instead "
|
||||||
@ -1313,23 +1340,6 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
|
|||||||
ni->itype.compressed.size = sle64_to_cpu(
|
ni->itype.compressed.size = sle64_to_cpu(
|
||||||
a->data.non_resident.compressed_size);
|
a->data.non_resident.compressed_size);
|
||||||
}
|
}
|
||||||
if (a->flags & ATTR_IS_ENCRYPTED) {
|
|
||||||
if (a->flags & ATTR_COMPRESSION_MASK) {
|
|
||||||
ntfs_error(vi->i_sb, "Found encrypted and "
|
|
||||||
"compressed data.");
|
|
||||||
goto unm_err_out;
|
|
||||||
}
|
|
||||||
if (NInoMstProtected(ni)) {
|
|
||||||
ntfs_error(vi->i_sb, "Found mst protected "
|
|
||||||
"attribute but the attribute "
|
|
||||||
"is encrypted. Please report "
|
|
||||||
"you saw this message to "
|
|
||||||
"linux-ntfs-dev@lists."
|
|
||||||
"sourceforge.net");
|
|
||||||
goto unm_err_out;
|
|
||||||
}
|
|
||||||
NInoSetEncrypted(ni);
|
|
||||||
}
|
|
||||||
if (a->data.non_resident.lowest_vcn) {
|
if (a->data.non_resident.lowest_vcn) {
|
||||||
ntfs_error(vi->i_sb, "First extent of attribute has "
|
ntfs_error(vi->i_sb, "First extent of attribute has "
|
||||||
"non-zero lowest_vcn.");
|
"non-zero lowest_vcn.");
|
||||||
@ -1348,12 +1358,12 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
|
|||||||
vi->i_mapping->a_ops = &ntfs_mst_aops;
|
vi->i_mapping->a_ops = &ntfs_mst_aops;
|
||||||
else
|
else
|
||||||
vi->i_mapping->a_ops = &ntfs_aops;
|
vi->i_mapping->a_ops = &ntfs_aops;
|
||||||
if (NInoCompressed(ni) || NInoSparse(ni))
|
if ((NInoCompressed(ni) || NInoSparse(ni)) && ni->type != AT_INDEX_ROOT)
|
||||||
vi->i_blocks = ni->itype.compressed.size >> 9;
|
vi->i_blocks = ni->itype.compressed.size >> 9;
|
||||||
else
|
else
|
||||||
vi->i_blocks = ni->allocated_size >> 9;
|
vi->i_blocks = ni->allocated_size >> 9;
|
||||||
/*
|
/*
|
||||||
* Make sure the base inode doesn't go away and attach it to the
|
* Make sure the base inode does not go away and attach it to the
|
||||||
* attribute inode.
|
* attribute inode.
|
||||||
*/
|
*/
|
||||||
igrab(base_vi);
|
igrab(base_vi);
|
||||||
@ -1480,7 +1490,10 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
|
|||||||
"after the attribute value.");
|
"after the attribute value.");
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
}
|
||||||
/* Compressed/encrypted/sparse index root is not allowed. */
|
/*
|
||||||
|
* Compressed/encrypted/sparse index root is not allowed, except for
|
||||||
|
* directories of course but those are not dealt with here.
|
||||||
|
*/
|
||||||
if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED |
|
if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED |
|
||||||
ATTR_IS_SPARSE)) {
|
ATTR_IS_SPARSE)) {
|
||||||
ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index "
|
ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index "
|
||||||
|
Loading…
Reference in New Issue
Block a user