diff options
| author | Anton Altaparmakov <aia21@cantab.net> | 2002-06-25 21:13:24 +0100 |
|---|---|---|
| committer | Anton Altaparmakov <aia21@cantab.net> | 2002-06-25 21:13:24 +0100 |
| commit | 6bb39cd9762daad5489c20a5296afb01e2ac0b8a (patch) | |
| tree | a538e57978151e420082dd4d9df71b18dd3d0f5c /fs | |
| parent | 242550337893dd5542fcd793115f87e4fd49494c (diff) | |
NTFS: 2.0.11 - Initial preparations for fake inode based attribute i/o.
- Move definition of ntfs_inode_state_bits to fs/ntfs/inode.h and
do some macro magic (adapted from include/linux/buffer_head.h) to
expand all the helper functions NInoFoo(), NInoSetFoo(), and
NInoClearFoo().
- Add new flag to ntfs_inode_state_bits: NI_Sparse.
- Add new fields to ntfs_inode structure to allow use of fake inodes
for attribute i/o: type, name, name_len. Also add new state bits:
NI_Attr, which, if set, indicates the inode is a fake inode, and
NI_MstProtected, which, if set, indicates the attribute uses multi
sector transfer protection, i.e. fixups need to be applied after
reads and before/after writes.
- Rename fs/ntfs/inode.c::ntfs_{new,clear,destroy}_inode() to
ntfs_{new,clear,destroy}_extent_inode() and update callers.
- Use ntfs_clear_extent_inode() in fs/ntfs/inode.c::__ntfs_clear_inode()
instead of ntfs_destroy_extent_inode().
- Cleanup memory deallocations in {__,}ntfs_clear_{,big_}inode().
- Make all operations on ntfs inode state bits use the NIno* functions.
- Set up the new ntfs inode fields and state bits in
fs/ntfs/inode.c::ntfs_read_inode() and add appropriate cleanup of
allocated memory to __ntfs_clear_inode().
- Cleanup ntfs_inode structure a bit for better ordering of elements
w.r.t. their size to allow better packing of the structure in memory.
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/ntfs/ChangeLog | 34 | ||||
| -rw-r--r-- | fs/ntfs/Makefile | 2 | ||||
| -rw-r--r-- | fs/ntfs/dir.c | 2 | ||||
| -rw-r--r-- | fs/ntfs/dir.h | 2 | ||||
| -rw-r--r-- | fs/ntfs/inode.c | 133 | ||||
| -rw-r--r-- | fs/ntfs/inode.h | 129 | ||||
| -rw-r--r-- | fs/ntfs/mft.c | 12 | ||||
| -rw-r--r-- | fs/ntfs/ntfs.h | 35 | ||||
| -rw-r--r-- | fs/ntfs/super.c | 9 |
9 files changed, 249 insertions, 109 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 2cb1bc02bd7e..1c7804c61ce1 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -21,7 +21,34 @@ ToDo: several copies of almost identicall functions and the functions are quite big. Modularising them a bit, e.g. a-la get_block(), will make them cleaner and make code reuse easier. - - Want to use dummy inodes for address space i/o. + - Enable NFS exporting of NTFS. + - Use iget5_locked() and friends instead of conventional iget(). + - Use fake inodes for address space i/o. + +2.0.11 - Initial preparations for fake inode based attribute i/o. + + - Move definition of ntfs_inode_state_bits to fs/ntfs/inode.h and + do some macro magic (adapted from include/linux/buffer_head.h) to + expand all the helper functions NInoFoo(), NInoSetFoo(), and + NInoClearFoo(). + - Add new flag to ntfs_inode_state_bits: NI_Sparse. + - Add new fields to ntfs_inode structure to allow use of fake inodes + for attribute i/o: type, name, name_len. Also add new state bits: + NI_Attr, which, if set, indicates the inode is a fake inode, and + NI_MstProtected, which, if set, indicates the attribute uses multi + sector transfer protection, i.e. fixups need to be applied after + reads and before/after writes. + - Rename fs/ntfs/inode.c::ntfs_{new,clear,destroy}_inode() to + ntfs_{new,clear,destroy}_extent_inode() and update callers. + - Use ntfs_clear_extent_inode() in fs/ntfs/inode.c::__ntfs_clear_inode() + instead of ntfs_destroy_extent_inode(). + - Cleanup memory deallocations in {__,}ntfs_clear_{,big_}inode(). + - Make all operations on ntfs inode state bits use the NIno* functions. + - Set up the new ntfs inode fields and state bits in + fs/ntfs/inode.c::ntfs_read_inode() and add appropriate cleanup of + allocated memory to __ntfs_clear_inode(). + - Cleanup ntfs_inode structure a bit for better ordering of elements + w.r.t. their size to allow better packing of the structure in memory. 2.0.10 - There can only be 2^32 - 1 inodes on an NTFS volume. @@ -38,7 +65,10 @@ ToDo: - Change decompression engine to use a single buffer protected by a spin lock instead of per-CPU buffers. (Rusty Russell) - - Switch to using the new KM_BIO_SRC_IRQ for atomic kmaps. (Andrew + - Do not update cb_pos when handling a partial final page during + decompression of a sparse compression block, as the value is later + reset without being read/used. (Rusty Russell) + - Switch to using the new KM_BIO_SRC_IRQ for atomic kmap()s. (Andrew Morton) - Change buffer size in ntfs_readdir()/ntfs_filldir() to use NLS_MAX_CHARSET_SIZE which makes the buffers almost 1kiB each but diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index febb47c6509a..f89830b3ff14 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \ mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o -EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.10\" +EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.11\" ifeq ($(CONFIG_NTFS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 2d4cc586f3a1..06e34fa6ffe0 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -27,7 +27,7 @@ /** * The little endian Unicode string $I30 as a global constant. */ -const uchar_t I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'), +uchar_t I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'), const_cpu_to_le16('3'), const_cpu_to_le16('0'), const_cpu_to_le16(0) }; diff --git a/fs/ntfs/dir.h b/fs/ntfs/dir.h index 1b1586ac9564..7b8ebee5d8c2 100644 --- a/fs/ntfs/dir.h +++ b/fs/ntfs/dir.h @@ -38,7 +38,7 @@ typedef struct { } __attribute__ ((__packed__)) ntfs_name; /* The little endian Unicode string $I30 as a global constant. */ -extern const uchar_t I30[5]; +extern uchar_t I30[5]; extern MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname, const int uname_len, ntfs_name **res); diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 4e30cf3637eb..2b040e07135e 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -49,7 +49,7 @@ void ntfs_destroy_big_inode(struct inode *inode) kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode)); } -ntfs_inode *ntfs_alloc_inode(void) +ntfs_inode *ntfs_alloc_extent_inode(void) { ntfs_inode *ni = (ntfs_inode *)kmem_cache_alloc(ntfs_inode_cache, SLAB_NOFS); @@ -59,7 +59,7 @@ ntfs_inode *ntfs_alloc_inode(void) return ni; } -void ntfs_destroy_inode(ntfs_inode *ni) +void ntfs_destroy_extent_inode(ntfs_inode *ni) { ntfs_debug("Entering."); BUG_ON(atomic_read(&ni->mft_count) || !atomic_dec_and_test(&ni->count)); @@ -102,9 +102,9 @@ static void ntfs_init_big_inode(struct inode *vi) return; } -ntfs_inode *ntfs_new_inode(struct super_block *sb) +ntfs_inode *ntfs_new_extent_inode(struct super_block *sb) { - ntfs_inode *ni = ntfs_alloc_inode(); + ntfs_inode *ni = ntfs_alloc_extent_inode(); ntfs_debug("Entering."); if (ni) @@ -239,7 +239,8 @@ void ntfs_read_inode(struct inode *vi) /* * Initialize the ntfs specific part of @vi special casing - * FILE_MFT which we need to do at mount time. + * FILE_MFT which we need to do at mount time. This also sets + * ni->mft_no to vi->i_ino. */ if (vi->i_ino != FILE_MFT) ntfs_init_big_inode(vi); @@ -358,13 +359,14 @@ void ntfs_read_inode(struct inode *vi) if (vi->i_ino == FILE_MFT) goto skip_attr_list_load; ntfs_debug("Attribute list found in inode 0x%lx.", vi->i_ino); - ni->state |= 1 << NI_AttrList; + NInoSetAttrList(ni); if (ctx->attr->flags & ATTR_IS_ENCRYPTED || - ctx->attr->flags & ATTR_COMPRESSION_MASK) { + ctx->attr->flags & ATTR_COMPRESSION_MASK || + ctx->attr->flags & ATTR_IS_SPARSE) { ntfs_error(vi->i_sb, "Attribute list attribute is " - "compressed/encrypted. Not allowed. " - "Corrupt inode. You should run " - "chkdsk."); + "compressed/encrypted/sparse. Not " + "allowed. Corrupt inode. You should " + "run chkdsk."); goto put_unm_err_out; } /* Now allocate memory for the attribute list. */ @@ -377,7 +379,7 @@ void ntfs_read_inode(struct inode *vi) goto ec_put_unm_err_out; } if (ctx->attr->non_resident) { - ni->state |= 1 << NI_AttrListNonResident; + NInoSetAttrListNonResident(ni); if (ctx->attr->_ANR(lowest_vcn)) { ntfs_error(vi->i_sb, "Attribute list has non " "zero lowest_vcn. Inode is " @@ -459,7 +461,7 @@ skip_attr_list_load: * encrypted. */ if (ctx->attr->flags & ATTR_COMPRESSION_MASK) - ni->state |= 1 << NI_Compressed; + NInoSetCompressed(ni); if (ctx->attr->flags & ATTR_IS_ENCRYPTED) { if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { ntfs_error(vi->i_sb, "Found encrypted and " @@ -467,8 +469,10 @@ skip_attr_list_load: "allowed."); goto put_unm_err_out; } - ni->state |= 1 << NI_Encrypted; + NInoSetEncrypted(ni); } + if (ctx->attr->flags & ATTR_IS_SPARSE) + NInoSetSparse(ni); ir = (INDEX_ROOT*)((char*)ctx->attr + le16_to_cpu(ctx->attr->_ARA(value_offset))); ir_end = (char*)ir + le32_to_cpu(ctx->attr->_ARA(value_length)); @@ -530,12 +534,19 @@ skip_attr_list_load: ni->_IDM(index_vcn_size) = vol->sector_size; ni->_IDM(index_vcn_size_bits) = vol->sector_size_bits; } + + /* Setup the index allocation attribute, even if not present. */ + NInoSetMstProtected(ni); + ni->type = AT_INDEX_ALLOCATION; + ni->name = I30; + ni->name_len = 4; + if (!(ir->index.flags & LARGE_INDEX)) { /* No index allocation. */ vi->i_size = ni->initialized_size = 0; goto skip_large_dir_stuff; } /* LARGE_INDEX: Index allocation present. Setup state. */ - ni->state |= 1 << NI_NonResident; + NInoSetIndexAllocPresent(ni); /* Find index allocation attribute. */ reinit_attr_search_ctx(ctx); if (!lookup_attr(AT_INDEX_ALLOCATION, I30, 4, CASE_SENSITIVE, @@ -555,6 +566,11 @@ skip_attr_list_load: "is encrypted."); goto put_unm_err_out; } + if (ctx->attr->flags & ATTR_IS_SPARSE) { + ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " + "is sparse."); + goto put_unm_err_out; + } if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " "is compressed."); @@ -581,13 +597,13 @@ skip_attr_list_load: goto put_unm_err_out; } if (ctx->attr->flags & (ATTR_COMPRESSION_MASK | - ATTR_IS_ENCRYPTED)) { + ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) { ntfs_error(vi->i_sb, "$BITMAP attribute is compressed " - "and/or encrypted."); + "and/or encrypted and/or sparse."); goto put_unm_err_out; } if (ctx->attr->non_resident) { - ni->state |= 1 << NI_BmpNonResident; + NInoSetBmpNonResident(ni); if (ctx->attr->_ANR(lowest_vcn)) { ntfs_error(vi->i_sb, "First extent of $BITMAP " "attribute has non zero " @@ -647,6 +663,12 @@ skip_large_dir_stuff: } else { /* It is a file: find first extent of unnamed data attribute. */ reinit_attr_search_ctx(ctx); + + /* Setup the data attribute, even if not present. */ + ni->type = AT_DATA; + ni->name = NULL; + ni->name_len = 0; + if (!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx)) { vi->i_size = ni->initialized_size = ni->allocated_size = 0LL; @@ -675,9 +697,9 @@ skip_large_dir_stuff: } /* Setup the state. */ if (ctx->attr->non_resident) { - ni->state |= 1 << NI_NonResident; + NInoSetNonResident(ni); if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { - ni->state |= 1 << NI_Compressed; + NInoSetCompressed(ni); if (vol->cluster_size > 4096) { ntfs_error(vi->i_sb, "Found " "compressed data but " @@ -707,8 +729,9 @@ skip_large_dir_stuff: goto ec_put_unm_err_out; } ni->_ICF(compression_block_size) = 1U << ( - ctx->attr->_ANR(compression_unit) - + vol->cluster_size_bits); + ctx->attr->_ANR( + compression_unit) + + vol->cluster_size_bits); ni->_ICF(compression_block_size_bits) = ffs( ni->_ICF(compression_block_size)) - 1; } @@ -718,8 +741,10 @@ skip_large_dir_stuff: "and compressed data."); goto put_unm_err_out; } - ni->state |= 1 << NI_Encrypted; + NInoSetEncrypted(ni); } + if (ctx->attr->flags & ATTR_IS_SPARSE) + NInoSetSparse(ni); if (ctx->attr->_ANR(lowest_vcn)) { ntfs_error(vi->i_sb, "First extent of $DATA " "attribute has non zero " @@ -861,6 +886,13 @@ void ntfs_read_inode_mount(struct inode *vi) goto err_out; } + /* Setup the data attribute. It is special as it is mst protected. */ + NInoSetNonResident(ni); + NInoSetMstProtected(ni); + ni->type = AT_DATA; + ni->name = NULL; + ni->name_len = 0; + /* * This sets up our little cheat allowing us to reuse the async io * completion handler for directories. @@ -930,13 +962,14 @@ void ntfs_read_inode_mount(struct inode *vi) u8 *al_end; ntfs_debug("Attribute list attribute found in $MFT."); - ni->state |= 1 << NI_AttrList; + NInoSetAttrList(ni); if (ctx->attr->flags & ATTR_IS_ENCRYPTED || - ctx->attr->flags & ATTR_COMPRESSION_MASK) { + ctx->attr->flags & ATTR_COMPRESSION_MASK || + ctx->attr->flags & ATTR_IS_SPARSE) { ntfs_error(sb, "Attribute list attribute is " - "compressed/encrypted. Not allowed. " - "$MFT is corrupt. You should run " - "chkdsk."); + "compressed/encrypted/sparse. Not " + "allowed. $MFT is corrupt. You should " + "run chkdsk."); goto put_err_out; } /* Now allocate memory for the attribute list. */ @@ -948,7 +981,7 @@ void ntfs_read_inode_mount(struct inode *vi) goto put_err_out; } if (ctx->attr->non_resident) { - ni->state |= 1 << NI_AttrListNonResident; + NInoSetAttrListNonResident(ni); if (ctx->attr->_ANR(lowest_vcn)) { ntfs_error(sb, "Attribute list has non zero " "lowest_vcn. $MFT is corrupt. " @@ -1071,11 +1104,13 @@ void ntfs_read_inode_mount(struct inode *vi) } /* $MFT must be uncompressed and unencrypted. */ if (attr->flags & ATTR_COMPRESSION_MASK || - attr->flags & ATTR_IS_ENCRYPTED) { - ntfs_error(sb, "$MFT must be uncompressed and " - "unencrypted but a compressed/" - "encrypted extent was found. " - "$MFT is corrupt. Run chkdsk."); + attr->flags & ATTR_IS_ENCRYPTED || + attr->flags & ATTR_IS_SPARSE) { + ntfs_error(sb, "$MFT must be uncompressed, " + "non-sparse, and unencrypted but a " + "compressed/sparse/encrypted extent " + "was found. $MFT is corrupt. Run " + "chkdsk."); goto put_err_out; } /* @@ -1296,29 +1331,42 @@ void __ntfs_clear_inode(ntfs_inode *ni) // FIXME: Handle dirty case for each extent inode! for (i = 0; i < ni->nr_extents; i++) - ntfs_destroy_inode(ni->_INE(extent_ntfs_inos)[i]); + ntfs_clear_extent_inode(ni->_INE(extent_ntfs_inos)[i]); kfree(ni->_INE(extent_ntfs_inos)); } /* Free all alocated memory. */ down_write(&ni->run_list.lock); - ntfs_free(ni->run_list.rl); - ni->run_list.rl = NULL; + if (ni->run_list.rl) { + ntfs_free(ni->run_list.rl); + ni->run_list.rl = NULL; + } up_write(&ni->run_list.lock); - ntfs_free(ni->attr_list); + if (ni->attr_list) { + ntfs_free(ni->attr_list); + ni->attr_list = NULL; + } down_write(&ni->attr_list_rl.lock); - ntfs_free(ni->attr_list_rl.rl); - ni->attr_list_rl.rl = NULL; + if (ni->attr_list_rl.rl) { + ntfs_free(ni->attr_list_rl.rl); + ni->attr_list_rl.rl = NULL; + } up_write(&ni->attr_list_rl.lock); + + if (ni->name_len && ni->name != I30) { + /* Catch bugs... */ + BUG_ON(!ni->name); + kfree(ni->name); + } } -void ntfs_clear_inode(ntfs_inode *ni) +void ntfs_clear_extent_inode(ntfs_inode *ni) { __ntfs_clear_inode(ni); /* Bye, bye... */ - ntfs_destroy_inode(ni); + ntfs_destroy_extent_inode(ni); } /** @@ -1339,7 +1387,8 @@ void ntfs_clear_big_inode(struct inode *vi) if (S_ISDIR(vi->i_mode)) { down_write(&ni->_IDM(bmp_rl).lock); - ntfs_free(ni->_IDM(bmp_rl).rl); + if (ni->_IDM(bmp_rl).rl) + ntfs_free(ni->_IDM(bmp_rl).rl); up_write(&ni->_IDM(bmp_rl).lock); } return; diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h index b8bb212fed93..2c97dd2b353e 100644 --- a/fs/ntfs/inode.h +++ b/fs/ntfs/inode.h @@ -3,7 +3,7 @@ * the Linux-NTFS project. * * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (C) 2002 Richard Russon. + * Copyright (c) 2002 Richard Russon. * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -26,6 +26,7 @@ #include <linux/seq_file.h> +#include "layout.h" #include "volume.h" typedef struct _ntfs_inode ntfs_inode; @@ -38,21 +39,39 @@ struct _ntfs_inode { s64 initialized_size; /* Copy from $DATA/$INDEX_ALLOCATION. */ s64 allocated_size; /* Copy from $DATA/$INDEX_ALLOCATION. */ unsigned long state; /* NTFS specific flags describing this inode. - See fs/ntfs/ntfs.h:ntfs_inode_state_bits. */ + See ntfs_inode_state_bits below. */ unsigned long mft_no; /* Number of the mft record / inode. */ u16 seq_no; /* Sequence number of the mft record. */ atomic_t count; /* Inode reference count for book keeping. */ ntfs_volume *vol; /* Pointer to the ntfs volume of this inode. */ + /* + * If NInoAttr() is true, the below fields describe the attribute which + * this fake inode belongs to. The actual inode of this attribute is + * pointed to by base_ntfs_ino and nr_extents is always set to -1 (see + * below). For real inodes, we also set the type (AT_DATA for files and + * AT_INDEX_ALLOCATION for directories), with the name = NULL and + * name_len = 0 for files and name = I30 (global constant) and + * name_len = 4 for directories. + */ + ATTR_TYPES type; /* Attribute type of this fake inode. */ + uchar_t *name; /* Attribute name of this fake inode. */ + u32 name_len; /* Attribute name length of this fake inode. */ run_list run_list; /* If state has the NI_NonResident bit set, the run list of the unnamed data attribute (if a file) or of the index allocation - attribute (directory). If run_list.rl is - NULL, the run list has not been read in or - has been unmapped. If NI_NonResident is - clear, the unnamed data attribute is - resident (file) or there is no $I30 index - allocation attribute (directory). In that - case run_list.rl is always NULL.*/ + attribute (directory) or of the attribute + described by the fake inode (if NInoAttr()). + If run_list.rl is NULL, the run list has not + been read in yet or has been unmapped. If + NI_NonResident is clear, the attribute is + resident (file and fake inode) or there is + no $I30 index allocation attribute + (small directory). In the latter case + run_list.rl is always NULL.*/ + /* + * The following fields are only valid for real inodes and extent + * inodes. + */ struct rw_semaphore mrec_lock; /* Lock for serializing access to the mft record belonging to this inode. */ atomic_t mft_count; /* Mapping reference count for book keeping. */ @@ -74,17 +93,18 @@ struct _ntfs_inode { union { struct { /* It is a directory or $MFT. */ u32 index_block_size; /* Size of an index block. */ - u8 index_block_size_bits; /* Log2 of the above. */ u32 index_vcn_size; /* Size of a vcn in this directory index. */ - u8 index_vcn_size_bits; /* Log2 of the above. */ s64 bmp_size; /* Size of the $I30 bitmap. */ s64 bmp_initialized_size; /* Copy from $I30 bitmap. */ s64 bmp_allocated_size; /* Copy from $I30 bitmap. */ run_list bmp_rl; /* Run list for the $I30 bitmap if it is non-resident. */ + u8 index_block_size_bits; /* Log2 of the above. */ + u8 index_vcn_size_bits; /* Log2 of the above. */ } SN(idm); - struct { /* It is a compressed file. */ + struct { /* It is a compressed file or fake inode. */ + s64 compressed_size; /* Copy from $DATA. */ u32 compression_block_size; /* Size of a compression block (cb). */ u8 compression_block_size_bits; /* Log2 of the size of @@ -92,13 +112,13 @@ struct _ntfs_inode { u8 compression_block_clusters; /* Number of clusters per compression block. */ - s64 compressed_size; /* Copy from $DATA. */ } SN(icf); } SN(idc); struct semaphore extent_lock; /* Lock for accessing/modifying the below . */ s32 nr_extents; /* For a base mft record, the number of attached extent - inodes (0 if none), for extent records this is -1. */ + inodes (0 if none), for extent records and for fake + inodes describing an attribute this is -1. */ union { /* This union is only used if nr_extents != 0. */ ntfs_inode **extent_ntfs_inos; /* For nr_extents > 0, array of the ntfs inodes of the extent @@ -107,7 +127,9 @@ struct _ntfs_inode { been loaded. */ ntfs_inode *base_ntfs_ino; /* For nr_extents == -1, the ntfs inode of the base mft - record. */ + record. For fake inodes, the + real (base) inode to which + the attribute belongs. */ } SN(ine); }; @@ -115,6 +137,79 @@ struct _ntfs_inode { #define _ICF(X) SC(idc.icf,X) #define _INE(X) SC(ine,X) +/* + * Defined bits for the state field in the ntfs_inode structure. + * (f) = files only, (d) = directories only, (a) = attributes/fake inodes only + */ +typedef enum { + NI_Dirty, /* 1: Mft record needs to be written to disk. */ + NI_AttrList, /* 1: Mft record contains an attribute list. */ + NI_AttrListNonResident, /* 1: Attribute list is non-resident. Implies + NI_AttrList is set. */ + + NI_Attr, /* 1: Fake inode for attribute i/o. + 0: Real inode or extent inode. */ + + NI_MstProtected, /* 1: Attribute is protected by MST fixups. + 0: Attribute is not protected by fixups. */ + NI_NonResident, /* 1: Unnamed data attr is non-resident (f). + 1: Attribute is non-resident (a). */ + NI_IndexAllocPresent = NI_NonResident, /* 1: $I30 index alloc attr is + present (d). */ + NI_Compressed, /* 1: Unnamed data attr is compressed (f). + 1: Create compressed files by default (d). + 1: Attribute is compressed (a). */ + NI_Encrypted, /* 1: Unnamed data attr is encrypted (f). + 1: Create encrypted files by default (d). + 1: Attribute is encrypted (a). */ + NI_Sparse, /* 1: Unnamed data attr is sparse (f). + 1: Create sparse files by default (d). + 1: Attribute is sparse (a). */ + NI_BmpNonResident, /* 1: $I30 bitmap attr is non resident (d). */ +} ntfs_inode_state_bits; + +/* + * NOTE: We should be adding dirty mft records to a list somewhere and they + * should be independent of the (ntfs/vfs) inode structure so that an inode can + * be removed but the record can be left dirty for syncing later. + */ + +/* + * Macro tricks to expand the NInoFoo(), NInoSetFoo(), and NInoClearFoo() + * functions. + */ +#define NINO_FNS(flag) \ +static inline int NIno##flag(ntfs_inode *ni) \ +{ \ + return test_bit(NI_##flag, &(ni)->state); \ +} \ +static inline void NInoSet##flag(ntfs_inode *ni) \ +{ \ + set_bit(NI_##flag, &(ni)->state); \ +} \ +static inline void NInoClear##flag(ntfs_inode *ni) \ +{ \ + clear_bit(NI_##flag, &(ni)->state); \ +} + +/* Emit the ntfs inode bitops functions. */ +NINO_FNS(Dirty) +NINO_FNS(AttrList) +NINO_FNS(AttrListNonResident) +NINO_FNS(Attr) +NINO_FNS(MstProtected) +NINO_FNS(NonResident) +NINO_FNS(IndexAllocPresent) +NINO_FNS(Compressed) +NINO_FNS(Encrypted) +NINO_FNS(Sparse) +NINO_FNS(BmpNonResident) + +/* + * The full structure containing a ntfs_inode and a vfs struct inode. Used for + * all real and fake inodes but not for extent inodes which lack the vfs struct + * inode. + */ typedef struct { ntfs_inode ntfs_inode; struct inode vfs_inode; /* The vfs inode structure. */ @@ -140,8 +235,8 @@ extern struct inode *ntfs_alloc_big_inode(struct super_block *sb); extern void ntfs_destroy_big_inode(struct inode *inode); extern void ntfs_clear_big_inode(struct inode *vi); -extern ntfs_inode *ntfs_new_inode(struct super_block *sb); -extern void ntfs_clear_inode(ntfs_inode *ni); +extern ntfs_inode *ntfs_new_extent_inode(struct super_block *sb); +extern void ntfs_clear_extent_inode(ntfs_inode *ni); extern void ntfs_read_inode(struct inode *vi); extern void ntfs_read_inode_mount(struct inode *vi); diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 9e3a4e666356..0a8e360b4ad3 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -334,9 +334,9 @@ void unmap_mft_record(const int rw, ntfs_inode *ni) /* * If pure ntfs_inode, i.e. no vfs inode attached, we leave it to - * ntfs_clear_inode() in the extent inode case, and to the caller in - * the non-extent, yet pure ntfs inode case, to do the actual tear - * down of all structures and freeing of all allocated memory. + * ntfs_clear_extent_inode() in the extent inode case, and to the + * caller in the non-extent, yet pure ntfs inode case, to do the actual + * tear down of all structures and freeing of all allocated memory. */ return; } @@ -417,7 +417,7 @@ map_err_out: return m; } /* Record wasn't there. Get a new ntfs inode and initialize it. */ - ni = ntfs_new_inode(base_ni->vol->sb); + ni = ntfs_new_extent_inode(base_ni->vol->sb); if (!ni) { up(&base_ni->extent_lock); atomic_dec(&base_ni->count); @@ -433,7 +433,7 @@ map_err_out: if (IS_ERR(m)) { up(&base_ni->extent_lock); atomic_dec(&base_ni->count); - ntfs_clear_inode(ni); + ntfs_clear_extent_inode(ni); goto map_err_out; } /* Verify the sequence number. */ @@ -479,7 +479,7 @@ unm_err_out: * release it or we will leak memory. */ if (destroy_ni) - ntfs_clear_inode(ni); + ntfs_clear_extent_inode(ni); return m; } diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index e29a1a90a353..1ecf909f735f 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h @@ -53,41 +53,6 @@ typedef enum { NTFS_MAX_NAME_LEN = 255, } NTFS_CONSTANTS; -/* - * Defined bits for the state field in the ntfs_inode structure. - * (f) = files only, (d) = directories only - */ -typedef enum { - NI_Dirty, /* 1: Mft record needs to be written to disk. */ - NI_AttrList, /* 1: Mft record contains an attribute list. */ - NI_AttrListNonResident, /* 1: Attribute list is non-resident. Implies - NI_AttrList is set. */ - NI_NonResident, /* 1: Unnamed data attr is non-resident (f). - 1: $I30 index alloc attr is present (d). */ - NI_Compressed, /* 1: Unnamed data attr is compressed (f). - 1: Create compressed files by default (d). */ - NI_Encrypted, /* 1: Unnamed data attr is encrypted (f). - 1: Create encrypted files by default (d). */ - NI_BmpNonResident, /* 1: $I30 bitmap attr is non resident (d). */ -} ntfs_inode_state_bits; - -/* - * NOTE: We should be adding dirty mft records to a list somewhere and they - * should be independent of the (ntfs/vfs) inode structure so that an inode can - * be removed but the record can be left dirty for syncing later. - */ - -#define NInoDirty(n_ino) test_bit(NI_Dirty, &(n_ino)->state) -#define NInoSetDirty(n_ino) set_bit(NI_Dirty, &(n_ino)->state) -#define NInoClearDirty(n_ino) clear_bit(NI_Dirty, &(n_ino)->state) - -#define NInoAttrList(n_ino) test_bit(NI_AttrList, &(n_ino)->state) -#define NInoNonResident(n_ino) test_bit(NI_NonResident, &(n_ino)->state) -#define NInoIndexAllocPresent(n_ino) test_bit(NI_NonResident, &(n_ino)->state) -#define NInoCompressed(n_ino) test_bit(NI_Compressed, &(n_ino)->state) -#define NInoEncrypted(n_ino) test_bit(NI_Encrypted, &(n_ino)->state) -#define NInoBmpNonResident(n_ino) test_bit(NI_BmpNonResident, &(n_ino)->state) - /* Global variables. */ /* Slab caches (from super.c). */ diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index fa58e6a9defa..50632b950fb8 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -1709,10 +1709,11 @@ cond_iput_mft_ino_err_out_now: } #undef OGIN /* - * This is needed to get ntfs_clear_inode() called for each inode we - * have ever called iget()/iput() on, otherwise we A) leak resources - * and B) a subsequent mount fails automatically due to iget() never - * calling down into our ntfs_read_inode{_mount}() methods again... + * This is needed to get ntfs_clear_extent_inode() called for each + * inode we have ever called iget()/iput() on, otherwise we A) leak + * resources and B) a subsequent mount fails automatically due to + * iget() never calling down into our ntfs_read_inode{_mount}() methods + * again... */ if (invalidate_inodes(sb)) { ntfs_error(sb, "Busy inodes left. This is most likely a NTFS " |
