NTFS: Fixup handling of sparse, compressed, and encrypted attributes in
authorAnton Altaparmakov <aia21@cantab.net>
Thu, 8 Sep 2005 20:19:45 +0000 (21:19 +0100)
committerAnton Altaparmakov <aia21@cantab.net>
Thu, 8 Sep 2005 20:19:45 +0000 (21:19 +0100)
      fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode().

Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
fs/ntfs/ChangeLog
fs/ntfs/inode.c

index 9c5af9c8a8af52111d4ad02a9a94256de4f1cd81..ed8d00150931d52e5a849a9b7f3e1f4076698531 100644 (file)
@@ -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...
index 89d844f69244e90e05f920cf1bdc20a984e3dca2..dc4bbe3acf5cd2b66e60da0aa488fdb5e5833886 100644 (file)
@@ -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 "