Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/include
In directory usw-pr-cvs1:/tmp/cvs-serv32418/include
Modified Files:
types.h
Log Message:
Add a description and structure for holding attributes in memory. No code to
use it yet but it's a start. The design is geared with the ideas of making
searching for attributes and using/implementing the search context as easy as
possible, integrating the attributes into their mft_entries and maintining a
fast sync volume path.
Comments welcome.
Index: types.h
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/include/types.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -U2 -r1.2 -r1.3
--- types.h 2001/04/11 14:29:11 1.2
+++ types.h 2001/04/12 22:37:20 1.3
@@ -122,10 +122,12 @@
Note, the list members are mft_entry
struct pointers. */
- int nr_mft_entries; /* Number of mft_entries. */
- struct list_head dirty_mft_entries; /* Linked list of all loaded mft
- records which are dirty. */
- int nr_dirty_mft_entries; /* Number of dirty mft_entries. */
- struct list_head v_list; /* Anchor for list of all mounted
- volumes. */
+ int nr_mft_entries; /* Number of mft entries. */
+ struct list_head dirty_mft_entries; /* Linked list of all dirty mft
+ records. */
+ int nr_dirty_mft_entries; /* Number of dirty mft_entries. */
+ struct list_head dirty_attrs; /* List of all dirty (non-resident)
+ attributes. */
+ int nr_dirty_attrs; /* Number of dirty_attrs. */
+ struct list_head v_list; /* Anchor for mounted volumes list. */
} ntfs_volume;
@@ -266,17 +268,157 @@
*/
+typedef union {
+ __u8; /* Unnamed __u8 to serve as default when just using
+ a_val without specifying any of the below. */
+ STANDARD_INFORMATION std_inf;
+ ATTR_LIST_ENTRY al_entry;
+ FILENAME_ATTR filename;
+ OBJECT_ID_ATTR obj_id;
+ SECURITY_DESCRIPTOR_ATTR sec_desc;
+ VOLUME_NAME vol_name;
+ VOLUME_INFORMATION vol_inf;
+ DATA_ATTR data;
+ INDEX_ROOT index_root;
+ INDEX_BLOCK index_blk;
+ BITMAP_ATTR bmp;
+ REPARSE_POINT reparse;
+ EA_INFORMATION ea_inf;
+ EA_ATTR ea;
+ PROPERTY_SET property_set;
+ LOGGED_UTILITY_STREAM logged_util_stream;
+ EFS_ATTR efs;
+} attr_val;
+
struct _ntfs_file;
typedef struct _ntfs_file ntfs_file;
+struct _mft_entry;
+typedef struct _mft_entry mft_entry;
+
+/**
+ * attr - structure describing an attribute in memory
+ * @a_rec: actual attribute record
+ * @a_val: attribute value (points into @a_rec if resident)
+ * @a_run_list: run list of the attribute value (if non-resident)
+ * @a_attr_list: attribute list attribute in @m_base_entry
+ * @a_attr_list_entry: attribute list entry of this attribute in @a_attr_list
+ * @a_flags: flags describing the status of the attribute
+ * @a_count: usage count of the attribute
+ * @a_dirty_list: anchor for the dirty_attrs list of the volume
+ * @a_vol: volume the attribute belongs to
+ * @m_entry: mft entry the attribute is contained in
+ * @m_base_entry: base mft entry holding @a_run_list
+ *
+ * @a_rec points to the ATTR_RECORD for the attribute. This field is always
+ * valid as it is used to determine which attribute is held in this entry.
+ *
+ * @a_val points to the attribute value of the attribute and will either point
+ * into @a_rec (resident attribute) or it will point to a especially for it
+ * allocated memory which has to be freed when the attribute is unmapped. @a_val
+ * is only valid when the mapped flag is set in @a_flags.
+ *
+ * It is important to note that @a_val contains only the mapped portion of the
+ * attribute value which is indicated by a lcn >= 0 in the run list.
+ *
+ * If lcn is -1, @a_val does contain this portion of the value, but it is all
+ * zero, and there is no storage allocated for it (it is a sparse run). When
+ * writing it to disk it is checked for being zero again and if it is, the
+ * (zero) data is not written to disk, but a sparse entry is saved in the
+ * mapping pairs array. If it is not zero stotare is allocated on disk and the
+ * data is written. The run list and mapping pairs array is then updated to
+ * reflect this and lcn is no longer -1.
+ *
+ * If lcn is -2, the corresponding bit of the attribute value is only contained
+ * in @a_val (and is set to zero but is in fact invalid data), if it is located
+ * in between two existing lcn >= 0 containing run list entries. I.e. if you
+ * find lcn == -2 in the first or last run list entry in @a_run_list, @a_val
+ * does not contain this data at all! So translation has to occur to correct
+ * the offset when reading/writing. If a user request the attribute value as a
+ * whole, then we will automatically insert all extents into @a_run_list and
+ * @a_val.
+ *
+ * @a_run_list will not necessarily hold the complete run_list. Should the vcn
+ * being looked for not be present in @a_run_list, it should be checked for
+ * other extents before returning out of bounds error. A special case is when
+ * the lcn is found to be -2 which means that there are one or more extents of
+ * the length specified (if this is not the last run list entry, i.e. length is
+ * not 0) but they haven't been inserted into the attribute.
+ *
+ * Note, that @a_run_list may be NULL which means that the run list has not
+ * been extracted from @a_rec (yet). This can only happen when the attribute
+ * value is not mapped. If mapped, @a_run_list must be valid.
+ *
+ * @a_attr_list and @a_attr_list_entry are used to point to the attribute list
+ * attribute describing this attribute and to the attribute list entry within
+ * the attribute list attribute which describes this attribute. These fields
+ * are only valid if the in_attr_list flag is set in @a_flags.
+ *
+ * The following flags are defined for @a_flags:
+ * dirty - Attribute is dirty. Needs to be written to disk.
+ * mapped - Attribute value is mapped. If not mapped @a_val and
+ * @a_dirty_list are not defined.
+ * error - There was some kind of error on I/O so it is possible
+ * that one or more of the other fields are corrupt.
+ * nonresident - Attribute is not resident. If resident, @a_run_list,
+ * @a_dirty_list and @m_base_entry are not defined (0).
+ * in_attr_list - Attribute is described by the attribute list attribute
+ * @a_attr_list, the entry describing it is
+ * @a_attr_list_entry, and this points into @a_attr_list.
+ * in_ext_record - Attribute is described by the attribute list
+ * attribute and it is stored in an extension record
+ * (pointed to by @m_entry) rather than in the base mft
+ * record. This is redundant in the sense that if you
+ * compare @m_entry with @m_base_entry and they are not
+ * equal this implies the same as this flag.
+ *
+ * @a_count is the number of times the attribute value has been mapped. When it
+ * reaches zero it may be safely unmapped (after being synced if dirty). This
+ * can be done at any point in time. Remember, we only free() the memory if the
+ * attribute is non resident! Once the value is unmapped, it is also safe to
+ * free() @a_run_list.
+ *
+ * @a_dirty_list anchors the attribute entry into the dirty_attrs list of
+ * @a_vol. Used when syncing the volume to be able to quickly walk all dirty
+ * attributes and sync them as well. Only applies to non-resident attributes
+ * as resident ones are covered by virtue of being contained inside their
+ * mft entries (@m_entry) which are dirty and synced to disk, anyway.
+ *
+ * @a_vol is the volume the attribute belongs to. This is just so lookups are
+ * quicker. Otherwise it could be obtained from @m_entry->m_vol.
+ *
+ * @m_entry points to the mft entry in which the attribute is held. If the
+ * attribute is in the base mft record, @m_entry is also the base mft record
+ * and @m_base_entry equals @m_entry. If the attribute is located in an
+ * extension mft record, @m_base_entry points to the mft entry of the base mft
+ * record and in_ext_record flag is set in @a_flags.
+ *
+ * Note, we don't store the file this attribute belongs to, as this information
+ * is irrelevant for all intents and purposes and can be obtained from
+ * @m_entry->m_file should it be needed at some point.
+ */
typedef struct {
+ ATTR_RECORD *a_rec;
+ run_list a_run_list;
+ attr_val *a_val;
+ unsigned int a_flags;
+ unsigned int a_count;
+ struct list_head a_dirty_list;
+ ntfs_volume *a_vol;
+ mft_entry *m_entry;
+ mft_entry *m_base_entry;
+} attr;
+
+struct _mft_entry {
MFT_RECORD *m_rec;
unsigned int m_flags;
MFT_REF m_ref;
unsigned int m_count;
+ attr **m_attrs;
+ int nr_m_attrs;
ntfs_file *m_file;
struct list_head m_list;
struct list_head m_dirty_list;
ntfs_volume *m_vol;
-} mft_entry;
+};
struct _ntfs_file {
@@ -288,5 +430,4 @@
ntfs_volume *f_vol;
};
-
#endif /* defined NTFS_TYPES_H */
|