Notes on the storage of attributes. =================================== Resident attributes =================== Resident attributes are small enough to be stored in the mft record itself. When an attribute becomes too big to fit in the mft record or when the number of attributes grows so large that there is no more space in the mft record, the largest attribute(s) is(are) made non-resident. (Note, that some attributes cannot be non-resident.) Non-resident attributes ======================= Non-resident attributes contain only their non-resident attribute header in the mft record and the actual attribute value is stored anywhere on the volume (but not in other mft records). The value of the attribute is saved as a sequence of clusters, named virtual clusters, beginning at virtual cluster number (vcn) zero. Each vcn corresponds to a cluster on the volume, or a logical cluster number (lcn). The lcns on the volume begin with lcn zero for the very first cluster on the volume. The location of the attribute value is described by the mapping pairs array present in the non-resident attribute header structure. The mapping pairs array contains, in compressed form, the mapping between the attribute's vcns and the corresponding lcns on the volume. When the mapping pairs array of a non-resident attribute becomes too large to fit in the mft record or when there are so many attributes in the mft record that, even though all attributes that can be non-resident have been made non-resident, they still do not fit in the mft record, the larger non-resident attributes are moved away from the mft record to make space. This is done by moving whole non-resident attribute header structures to other mft records and/or by splitting the mapping pairs array of attributes into several non-resident attribute headers, each containing a chunk of the original mapping pairs array. These non-resident attribute headers each describing the same attribute value (but different parts of it) are called extents. Attribute list attribute ======================== The attribute list attribute is then added to the base mft record to describe the location of each attribute. The attribute list attribute lists all attributes that belong to this mft record (with the exception of itself). Each entry in the attribute list describes the attribute listed and in which mft record its attribute header can be found. For resident attributes this will be the same number as the base mft record in which the attribute list attribute is located itself. For non-resident attributes, this will be another mft record, called an extension mft record. Naturally, all extension mft records point back to their base mft record. Only one attribute is stored in an extension mft record, even if the attribute is very small. At least this is the case with Windows NT4 SP6a driver. Should the mapping pairs array of an attribute become so large as to not fit into an extenstion mft record, even though its attribute is the only attribute in this extension record, then the attribute is splitt into several extents. The first extent starts at vcn 0 and has its lowest vcn value set to zero and continues up to its highest vcn value. This is determined by splitting up the mapping pairs array into chunks which just fit into an extension mft record each. Thus the first mapping pairs array chunk will determine the value of the highest vcn for the first extent. The attribute list will contain an entry for this extent. Then, a second extent is created which has its lowest vcn value set to the highest vcn of the previous extent + 1 and the next chunk of the mapping pairs array is inserted into this extent. Again, an entry for this extent is placed into the attribute list, and so on, until the whole non-resident attribute's mapping pairs array has been accomodated. Should the attribute list become too big to fit inside the base mft record it is made non-resident. However, it's maximum value size is determined by the Windows cache manager to be 256kb (the size of a VACB). Also, the mapping pairs array of the attribute list has to fit inside the base mft record, as an attribute list can't be described by itself and attribute lists are not allowed to be nested. Compressed attributes ===================== The attribute value of each $DATA attribute can be compressed to save space. If this is the case, the ATTR_IS_COMPRESSED flag is set. See the discussion on compression in include/attrib.h for more details. FIXME: The discussion belongs here! (AIA) Sparse attributes (NTFS 3.0+) ============================= The attribute value of each $DATA attribute can be sparse to save space. If this is the case, the ATTR_IS_SPARSE flag is set. Note, that compressed attributes are by definition sparse, as well as compressed, without having the ATTR_IS_SPARSE flag set. See the discussion on compression in include/attrib.h for more details. FIXME: The discussion belongs here! (AIA) Encrypted attributes (NTFS 3.0+) ================================ Since NTFS 3.0, the attribute value of each $DATA attribute can be encrypted, to protect the contents from spying eyes. If this is the case, the ATTR_IS_ENCRYPTED flag is set. FIXME: Write notes on attribute encryption. The discussions from the articles "Inside the Encrypting File System" in Windows NT magazine (?) are very good starting points. (AIA)