Commit 67bb1037 authored by Anton Altaparmakov's avatar Anton Altaparmakov
Browse files

NTFS: Fixup handling of sparse, compressed, and encrypted attributes in


      fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode().
Signed-off-by: default avatarAnton Altaparmakov <aia21@cantab.net>
parent 1c7d469d
......@@ -75,6 +75,8 @@ ToDo/Notes:
which leads to lock reversal.
- Truncate {a,c,m}time to the ntfs supported time granularity when
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
many bug fixes, cleanups, and enhancements...
......
......@@ -1013,41 +1013,50 @@ skip_large_dir_stuff:
}
a = ctx->attr;
/* Setup the state. */
if (a->non_resident) {
NInoSetNonResident(ni);
if (a->flags & (ATTR_COMPRESSION_MASK |
ATTR_IS_SPARSE)) {
if (a->flags & ATTR_COMPRESSION_MASK) {
NInoSetCompressed(ni);
if (vol->cluster_size > 4096) {
ntfs_error(vi->i_sb, "Found "
if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
if (a->flags & ATTR_COMPRESSION_MASK) {
NInoSetCompressed(ni);
if (vol->cluster_size > 4096) {
ntfs_error(vi->i_sb, "Found "
"compressed data 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 or corrupt "
"file.");
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)
NInoSetSparse(ni);
}
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 !=
4) {
ntfs_error(vi->i_sb, "Found "
"nonstandard compression unit "
"(%u instead of 4). Cannot "
"handle this.",
a->data.non_resident.
compression_unit);
"nonstandard "
"compression unit (%u "
"instead of 4). "
"Cannot handle this.",
a->data.non_resident.
compression_unit);
err = -EOPNOTSUPP;
goto unm_err_out;
}
......@@ -1065,14 +1074,6 @@ skip_large_dir_stuff:
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;
}
NInoSetEncrypted(ni);
}
if (a->data.non_resident.lowest_vcn) {
ntfs_error(vi->i_sb, "First extent of $DATA "
"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))
goto unm_err_out;
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) {
/* Ensure the attribute name is placed before the value. */
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.");
goto unm_err_out;
}
if (NInoMstProtected(ni) || a->flags) {
if (NInoMstProtected(ni)) {
ntfs_error(vi->i_sb, "Found mst protected attribute "
"or attribute with non-zero flags but "
"the attribute is resident. Please "
"report you saw this message to "
"but the attribute is resident. "
"Please report you saw this message to "
"linux-ntfs-dev@lists.sourceforge.net");
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.");
goto unm_err_out;
}
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;
}
}
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 ((NInoCompressed(ni) || NInoSparse(ni)) &&
ni->type != AT_INDEX_ROOT) {
if (a->data.non_resident.compression_unit != 4) {
ntfs_error(vi->i_sb, "Found nonstandard "
"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(
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) {
ntfs_error(vi->i_sb, "First extent of attribute has "
"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;
else
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;
else
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.
*/
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.");
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 |
ATTR_IS_SPARSE)) {
ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index "
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment