From b9e6be22b85f3534720a1d85cbea6063180a7ef6 Mon Sep 17 00:00:00 2001
From: Anton Altaparmakov <aia21@cantab.net>
Date: Thu, 27 Jun 2002 14:28:05 +0100
Subject: [PATCH] NTFS: 2.0.13 - Use iget5_locked() in preparation for fake
 inodes and small cleanups. - Remove nr_mft_bits and the now superfluous union
 with nr_mft_records   from ntfs_volume structure. - Remove nr_lcn_bits and
 the now superfluous union with nr_clusters   from ntfs_volume structure. -
 Use iget5_locked() and friends instead of conventional iget(). Wrap   the
 call in fs/ntfs/inode.c::ntfs_iget() and update callers of iget()   to use
 ntfs_iget(). Leave only one iget() call at mount time so we   don't need an
 ntfs_iget_mount(). - Change fs/ntfs/inode.c::ntfs_new_extent_inode() to take
 mft_no as an   additional argument.

---
 Documentation/filesystems/ntfs.txt |   3 +
 fs/ntfs/ChangeLog                  |  17 +-
 fs/ntfs/Makefile                   |   2 +-
 fs/ntfs/inode.c                    | 254 ++++++++++++++++++++++++++---
 fs/ntfs/inode.h                    |   6 +-
 fs/ntfs/mft.c                      |   3 +-
 fs/ntfs/namei.c                    |  24 +--
 fs/ntfs/super.c                    | 108 ++++++------
 fs/ntfs/volume.h                   |  17 +-
 9 files changed, 321 insertions(+), 113 deletions(-)

diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
index b2ee0cd9a863..4827bc2cda6f 100644
--- a/Documentation/filesystems/ntfs.txt
+++ b/Documentation/filesystems/ntfs.txt
@@ -247,6 +247,9 @@ ChangeLog
 
 Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
 
+2.0.13:
+	- Internal changes towards using iget5_locked() in preparation for
+	  fake inodes and small cleanups to ntfs_volume structure.
 2.0.12:
 	- Internal cleanups in address space operations made possible by the
 	  changes introduced in the previous release.
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 4e3d51fee2bd..e921ef9d19ff 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -22,10 +22,25 @@ ToDo:
 	  based attribute i/o is further developed.
 	- CLEANUP: Modularising code in aops.c a bit, e.g. a-la get_block(),
 	  will be cleaner and make code reuse easier.
+	- Modify ntfs_read_locked_inode() to return an error code and update
+	  callers, i.e. ntfs_iget(), to pass that error code up instead of just
+	  using -EIO.
 	- Enable NFS exporting of NTFS.
-	- Use iget5_locked() and friends instead of conventional iget().
 	- Use fake inodes for address space i/o.
 
+2.0.13 - Use iget5_locked() in preparation for fake inodes and small cleanups.
+
+	- Remove nr_mft_bits and the now superfluous union with nr_mft_records
+	  from ntfs_volume structure.
+	- Remove nr_lcn_bits and the now superfluous union with nr_clusters
+	  from ntfs_volume structure.
+	- Use iget5_locked() and friends instead of conventional iget(). Wrap
+	  the call in fs/ntfs/inode.c::ntfs_iget() and update callers of iget()
+	  to use ntfs_iget(). Leave only one iget() call at mount time so we
+	  don't need an ntfs_iget_mount().
+	- Change fs/ntfs/inode.c::ntfs_new_extent_inode() to take mft_no as an
+	  additional argument.
+
 2.0.12 - Initial cleanup of address space operations following 2.0.11 changes.
 
 	- Merge fs/ntfs/aops.c::end_buffer_read_mst_async() and
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile
index b6211f4d9e8d..e6fe82353289 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.12\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.13\"
 
 ifeq ($(CONFIG_NTFS_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 2b040e07135e..1af023c419d1 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -24,6 +24,178 @@
 
 #include "ntfs.h"
 #include "dir.h"
+#include "inode.h"
+#include "attrib.h"
+
+/**
+ * ntfs_attr - ntfs in memory attribute structure
+ * @mft_no:	mft record number of the base mft record of this attribute
+ * @name:	Unicode name of the attribute (NULL if unnamed)
+ * @name_len:	length of @name in Unicode characters (0 if unnamed)
+ * @type:	attribute type (see layout.h)
+ *
+ * This structure exists only to provide a small structure for the
+ * ntfs_iget()/ntfs_test_inode()/ntfs_init_locked_inode() mechanism.
+ *
+ * NOTE: Elements are ordered by size to make the structure as compact as
+ * possible on all architectures.
+ */
+typedef struct {
+	unsigned long mft_no;
+	uchar_t *name;
+	u32 name_len;
+	ATTR_TYPES type;
+} ntfs_attr;
+
+/**
+ * ntfs_test_inode - compare two (possibly fake) inodes for equality
+ * @vi:		vfs inode which to test
+ * @na:		ntfs attribute which is being tested with
+ *
+ * Compare the ntfs attribute embedded in the ntfs specific part of the vfs
+ * inode @vi for equality with the ntfs attribute @na.
+ *
+ * If searching for the normal file/directory inode, set @na->type to AT_UNUSED.
+ * @na->name and @na->name_len are then ignored.
+ *
+ * Return 1 if the attributes match and 0 if not.
+ *
+ * NOTE: This function runs with the inode_lock spin lock held so it is not
+ * allowed to sleep.
+ */
+static int ntfs_test_inode(struct inode *vi, ntfs_attr *na)
+{
+	ntfs_inode *ni;
+
+	if (vi->i_ino != na->mft_no)
+		return 0;
+	ni = NTFS_I(vi);
+	/* If !NInoAttr(ni), @vi is a normal file or directory inode. */
+	if (likely(!NInoAttr(ni))) {
+		/* If not looking for a normal inode this is a mismatch. */
+		if (unlikely(na->type != AT_UNUSED))
+			return 0;
+	} else {
+		/* A fake inode describing an attribute. */
+		if (ni->type != na->type)
+			return 0;
+		if (ni->name_len != na->name_len)
+			return 0;
+		if (na->name_len && memcmp(ni->name, na->name,
+				na->name_len * sizeof(uchar_t)))
+			return 0;
+	}
+	/* Match! */
+	return 1;
+}
+
+/**
+ * ntfs_init_locked_inode - initialize an inode
+ * @vi:		vfs inode to initialize
+ * @na:		ntfs attribute which to initialize @vi to
+ *
+ * Initialize the vfs inode @vi with the values from the ntfs attribute @na in
+ * order to enable ntfs_test_inode() to do its work.
+ *
+ * If initializing the normal file/directory inode, set @na->type to AT_UNUSED.
+ * In that case, @na->name and @na->name_len should be set to NULL and 0,
+ * respectively. Although that is not strictly necessary as
+ * ntfs_read_inode_locked() will fill them in later.
+ *
+ * Return 0 on success and -errno on error.
+ *
+ * NOTE: This function runs with the inode_lock spin lock held so it is not
+ * allowed to sleep. (Hence the GFP_ATOMIC allocation.)
+ */
+static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na)
+{
+	ntfs_inode *ni = NTFS_I(vi);
+
+	vi->i_ino = na->mft_no;
+	ni->type = na->type;
+	ni->name = na->name;
+	ni->name_len = na->name_len;
+	/* If initializing a normal inode, we are done. */
+	if (likely(na->type == AT_UNUSED))
+		return 0;
+	/* It is a fake inode. */
+	NInoSetAttr(ni);
+	/*
+	 * We have I30 global constant as an optimization as it is the name
+	 * in >99.9% of named attributes! The other <0.1% incur a GFP_ATOMIC
+	 * allocation but that is ok. And most attributes are unnamed anyway,
+	 * thus the fraction of named attributes with name != I30 is actually
+	 * absolutely tiny.
+	 */
+	if (na->name && na->name_len && na->name != I30) {
+		unsigned int i;
+
+		i = na->name_len * sizeof(uchar_t);
+		ni->name = (uchar_t*)kmalloc(i + sizeof(uchar_t), GFP_ATOMIC);
+		if (!ni->name)
+			return -ENOMEM;
+		memcpy(ni->name, na->name, i);
+		ni->name[i] = cpu_to_le16('\0');
+	}
+	return 0;
+}
+
+typedef int (*test_t)(struct inode *, void *);
+typedef int (*set_t)(struct inode *, void *);
+static void ntfs_read_locked_inode(struct inode *vi);
+
+/**
+ * ntfs_iget - obtain a struct inode corresponding to a specific normal inode
+ * @sb:		super block of mounted volume
+ * @mft_no:	mft record number / inode number to obtain
+ *
+ * Obtain the struct inode corresponding to a specific normal inode (i.e. a
+ * file or directory).
+ *
+ * If the inode is in the cache, it is just returned with an increased
+ * reference count. Otherwise, a new struct inode is allocated and initialized,
+ * and finally ntfs_read_locked_inode() is called to read in the inode and
+ * fill in the remainder of the inode structure.
+ *
+ * Return the struct inode on success. Check the return value with IS_ERR() and
+ * if true, the function failed and the error code is obtained from PTR_ERR().
+ */
+struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no)
+{
+	struct inode *vi;
+	ntfs_attr na;
+
+	na.mft_no = mft_no;
+	na.type = AT_UNUSED;
+	na.name = NULL;
+	na.name_len = 0;
+
+	vi = iget5_locked(sb, mft_no, (test_t)ntfs_test_inode,
+			(set_t)ntfs_init_locked_inode, &na);
+	if (!vi)
+		return ERR_PTR(-ENOMEM);
+
+	/* If this is a freshly allocated inode, need to read it now. */
+	if (vi->i_state & I_NEW) {
+		ntfs_read_locked_inode(vi);
+		unlock_new_inode(vi);
+	}
+#if 0
+	// TODO: Enable this and do the follow up cleanup, i.e. remove all the
+	// bad inode checks. -- BUT: Do we actually want to do this? -- It may
+	// result in repeated attemps to read a bad inode which is not
+	// desirable. (AIA)
+	/*
+	 * There is no point in keeping bad inodes around. This also simplifies
+	 * things in that we never need to check for bad inodes elsewhere.
+	 */
+	if (is_bad_inode(vi)) {
+		iput(vi);
+		vi = ERR_PTR(-EIO);
+	}
+#endif
+	return vi;
+}
 
 struct inode *ntfs_alloc_big_inode(struct super_block *sb)
 {
@@ -32,12 +204,12 @@ struct inode *ntfs_alloc_big_inode(struct super_block *sb)
 	ntfs_debug("Entering.");
 	ni = (ntfs_inode *)kmem_cache_alloc(ntfs_big_inode_cache,
 			SLAB_NOFS);
-	if (!ni) {
-		ntfs_error(sb, "Allocation of NTFS big inode structure "
-				"failed.");
-		return NULL;
+	if (likely(ni != NULL)) {
+		ni->state = 0;
+		return VFS_I(ni);
 	}
-	return VFS_I(ni);
+	ntfs_error(sb, "Allocation of NTFS big inode structure failed.");
+	return NULL;
 }
 
 void ntfs_destroy_big_inode(struct inode *inode)
@@ -49,14 +221,17 @@ void ntfs_destroy_big_inode(struct inode *inode)
 	kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode));
 }
 
-ntfs_inode *ntfs_alloc_extent_inode(void)
+static ntfs_inode *ntfs_alloc_extent_inode(void)
 {
 	ntfs_inode *ni = (ntfs_inode *)kmem_cache_alloc(ntfs_inode_cache,
 			SLAB_NOFS);
 	ntfs_debug("Entering.");
-	if (unlikely(!ni))
-		ntfs_error(NULL, "Allocation of NTFS inode structure failed.");
-	return ni;
+	if (likely(ni != NULL)) {
+		ni->state = 0;
+		return ni;
+	}
+	ntfs_error(NULL, "Allocation of NTFS inode structure failed.");
+	return NULL;
 }
 
 void ntfs_destroy_extent_inode(ntfs_inode *ni)
@@ -68,27 +243,42 @@ void ntfs_destroy_extent_inode(ntfs_inode *ni)
 
 /**
  * __ntfs_init_inode - initialize ntfs specific part of an inode
+ * @sb:		super block of mounted volume
+ * @ni:		freshly allocated ntfs inode which to initialize
  *
  * Initialize an ntfs inode to defaults.
  *
+ * NOTE: ni->mft_no, ni->state, ni->type, ni->name, and ni->name_len are left
+ * untouched. Make sure to initialize them elsewhere.
+ *
  * Return zero on success and -ENOMEM on error.
  */
 static void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
 {
 	ntfs_debug("Entering.");
-	memset(ni, 0, sizeof(ntfs_inode));
+	ni->initialized_size = ni->allocated_size = 0;
+	ni->seq_no = 0;
 	atomic_set(&ni->count, 1);
-	ni->vol = NULL;
+	ni->vol = NTFS_SB(sb);
 	init_run_list(&ni->run_list);
 	init_rwsem(&ni->mrec_lock);
 	atomic_set(&ni->mft_count, 0);
 	ni->page = NULL;
+	ni->page_ofs = 0;
+	ni->attr_list_size = 0;
 	ni->attr_list = NULL;
 	init_run_list(&ni->attr_list_rl);
+	ni->_IDM(index_block_size) = 0;
+	ni->_IDM(index_vcn_size) = 0;
+	ni->_IDM(bmp_size) = 0;
+	ni->_IDM(bmp_initialized_size) = 0;
+	ni->_IDM(bmp_allocated_size) = 0;
 	init_run_list(&ni->_IDM(bmp_rl));
+	ni->_IDM(index_block_size_bits) = 0;
+	ni->_IDM(index_vcn_size_bits) = 0;
 	init_MUTEX(&ni->extent_lock);
+	ni->nr_extents = 0;
 	ni->_INE(base_ntfs_ino) = NULL;
-	ni->vol = NTFS_SB(sb);
 	return;
 }
 
@@ -102,13 +292,18 @@ static void ntfs_init_big_inode(struct inode *vi)
 	return;
 }
 
-ntfs_inode *ntfs_new_extent_inode(struct super_block *sb)
+ntfs_inode *ntfs_new_extent_inode(struct super_block *sb, unsigned long mft_no)
 {
 	ntfs_inode *ni = ntfs_alloc_extent_inode();
 
 	ntfs_debug("Entering.");
-	if (ni)
+	if (likely(ni != NULL)) {
 		__ntfs_init_inode(sb, ni);
+		ni->mft_no = mft_no;
+		ni->type = AT_UNUSED;
+		ni->name = NULL;
+		ni->name_len = 0;
+	}
 	return ni;
 }
 
@@ -189,18 +384,20 @@ static int ntfs_is_extended_system_file(attr_search_context *ctx)
 }
 
 /**
- * ntfs_read_inode - read an inode from its device
+ * ntfs_read_locked_inode - read an inode from its device
  * @vi:		inode to read
  *
- * ntfs_read_inode() is called from the VFS iget() function to read the inode
+ * ntfs_read_locked_inode() is called from the ntfs_iget() to read the inode
  * described by @vi into memory from the device.
  *
  * The only fields in @vi that we need to/can look at when the function is
  * called are i_sb, pointing to the mounted device's super block, and i_ino,
- * the number of the inode to load.
+ * the number of the inode to load. If this is a fake inode, i.e. NInoAttr(),
+ * then the fields type, name, and name_len are also valid, and describe the
+ * attribute which this fake inode represents.
  *
- * ntfs_read_inode() maps, pins and locks the mft record number i_ino for
- * reading and sets up the necessary @vi fields as well as initializing
+ * ntfs_read_locked_inode() maps, pins and locks the mft record number i_ino
+ * for reading and sets up the necessary @vi fields as well as initializing
  * the ntfs inode.
  *
  * Q: What locks are held when the function is called?
@@ -209,9 +406,9 @@ static int ntfs_is_extended_system_file(attr_search_context *ctx)
  *    i_flags is set to 0 and we have no business touching it. Only an ioctl()
  *    is allowed to write to them. We should of course be honouring them but
  *    we need to do that using the IS_* macros defined in include/linux/fs.h.
- *    In any case ntfs_read_inode() has nothing to do with i_flags at all.
+ *    In any case ntfs_read_locked_inode() has nothing to do with i_flags.
  */
-void ntfs_read_inode(struct inode *vi)
+static void ntfs_read_locked_inode(struct inode *vi)
 {
 	ntfs_volume *vol = NTFS_SB(vi->i_sb);
 	ntfs_inode *ni;
@@ -661,7 +858,7 @@ void ntfs_read_inode(struct inode *vi)
 		vi->i_fop = &ntfs_dir_ops;
 		vi->i_mapping->a_ops = &ntfs_dir_aops;
 	} else {
-		/* It is a file: find first extent of unnamed data attribute. */
+		/* It is a file. */
 		reinit_attr_search_ctx(ctx);
 
 		/* Setup the data attribute, even if not present. */
@@ -669,6 +866,7 @@ void ntfs_read_inode(struct inode *vi)
 		ni->name = NULL;
 		ni->name_len = 0;
 
+		/* Find first extent of the unnamed data attribute. */
 		if (!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx)) {
 			vi->i_size = ni->initialized_size =
 					ni->allocated_size = 0LL;
@@ -877,15 +1075,17 @@ void ntfs_read_inode_mount(struct inode *vi)
 
 	ntfs_debug("Entering.");
 
-	/* Initialize the ntfs specific part of @vi. */
-	ntfs_init_big_inode(vi);
-	ni = NTFS_I(vi);
 	if (vi->i_ino != FILE_MFT) {
 		ntfs_error(sb, "Called for inode 0x%lx but only inode %d "
 				"allowed.", vi->i_ino, FILE_MFT);
 		goto err_out;
 	}
 
+	/* Initialize the ntfs specific part of @vi. */
+	ntfs_init_big_inode(vi);
+
+	ni = NTFS_I(vi);
+
 	/* Setup the data attribute. It is special as it is mst protected. */
 	NInoSetNonResident(ni);
 	NInoSetMstProtected(ni);
@@ -1158,7 +1358,7 @@ void ntfs_read_inode_mount(struct inode *vi)
 				ntfs_error(sb, "$MFT is too big! Aborting.");
 				goto put_err_out;
 			}
-			vol->_VMM(nr_mft_records) = ll;
+			vol->nr_mft_records = ll;
 			/*
 			 * We have got the first extent of the run_list for
 			 * $MFT which means it is now relatively safe to call
@@ -1184,7 +1384,7 @@ void ntfs_read_inode_mount(struct inode *vi)
 			 * ntfs_read_inode() on extents of $MFT/$DATA. But lets
 			 * hope this never happens...
 			 */
-			ntfs_read_inode(vi);
+			ntfs_read_locked_inode(vi);
 			if (is_bad_inode(vi)) {
 				ntfs_error(sb, "ntfs_read_inode() of $MFT "
 						"failed. BUG or corrupt $MFT. "
diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h
index 2c97dd2b353e..0025b9026633 100644
--- a/fs/ntfs/inode.h
+++ b/fs/ntfs/inode.h
@@ -231,14 +231,16 @@ static inline struct inode *VFS_I(ntfs_inode *ni)
 	return &((big_ntfs_inode*)ni)->vfs_inode;
 }
 
+extern struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no);
+
 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_extent_inode(struct super_block *sb);
+extern ntfs_inode *ntfs_new_extent_inode(struct super_block *sb,
+		unsigned long mft_no);
 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);
 
 extern void ntfs_dirty_inode(struct inode *vi);
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index bede95895c11..efece0f373a6 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -417,14 +417,13 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
 		return m;
 	}
 	/* Record wasn't there. Get a new ntfs inode and initialize it. */
-	ni = ntfs_new_extent_inode(base_ni->vol->sb);
+	ni = ntfs_new_extent_inode(base_ni->vol->sb, mft_no);
 	if (!ni) {
 		up(&base_ni->extent_lock);
 		atomic_dec(&base_ni->count);
 		return ERR_PTR(-ENOMEM);
 	}
 	ni->vol = base_ni->vol;
-	ni->mft_no = mft_no;
 	ni->seq_no = seq_no;
 	ni->nr_extents = -1;
 	ni->_INE(base_ntfs_ino) = base_ni;
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index 87b31ccd22bd..060e2c27f00d 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -38,8 +38,8 @@
  * supplying the name of the inode in @dent->d_name.name. ntfs_lookup()
  * converts the name to Unicode and walks the contents of the directory inode
  * @dir_ino looking for the converted Unicode name. If the name is found in the
- * directory, the corresponding inode is loaded by calling iget() on its inode
- * number and the inode is associated with the dentry @dent via a call to
+ * directory, the corresponding inode is loaded by calling ntfs_iget() on its
+ * inode number and the inode is associated with the dentry @dent via a call to
  * d_add().
  *
  * If the name is not found in the directory, a NULL inode is inserted into the
@@ -111,9 +111,9 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
 	kmem_cache_free(ntfs_name_cache, uname);
 	if (!IS_ERR_MREF(mref)) {
 		dent_ino = MREF(mref);
-		ntfs_debug("Found inode 0x%lx. Calling iget.", dent_ino);
-		dent_inode = iget(vol->sb, dent_ino);
-		if (dent_inode) {
+		ntfs_debug("Found inode 0x%lx. Calling ntfs_iget.", dent_ino);
+		dent_inode = ntfs_iget(vol->sb, dent_ino);
+		if (likely(!IS_ERR(dent_inode))) {
 			/* Consistency check. */
 			if (MSEQNO(mref) == NTFS_I(dent_inode)->seq_no ||
 					dent_ino == FILE_MFT) {
@@ -132,16 +132,19 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
 			ntfs_error(vol->sb, "Found stale reference to inode "
 					"0x%lx (reference sequence number = "
 					"0x%x, inode sequence number = 0x%x, "
-					"returning -EACCES. Run chkdsk.",
+					"returning -EIO. Run chkdsk.",
 					dent_ino, MSEQNO(mref),
 					NTFS_I(dent_inode)->seq_no);
 			iput(dent_inode);
+			dent_inode = ERR_PTR(-EIO);
 		} else
-			ntfs_error(vol->sb, "iget(0x%lx) failed, returning "
-					"-EACCES.", dent_ino);
+			ntfs_error(vol->sb, "ntfs_iget(0x%lx) failed with "
+				   "error code %li.", dent_ino,
+				   PTR_ERR(dent_inode));
 		if (name)
 			kfree(name);
-		return ERR_PTR(-EACCES);
+		/* Return the error code. */
+		return (struct dentry *)dent_inode;
 	}
 	/* It is guaranteed that name is no longer allocated at this point. */
 	if (MREF_ERR(mref) == -ENOENT) {
@@ -256,7 +259,8 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
 		BUG_ON(real_dent->d_inode != dent_inode);
 		/*
 		 * Already have the inode and the dentry attached, decrement
-		 * the reference count to balance the iget() we did earlier on.
+		 * the reference count to balance the ntfs_iget() we did
+		 * earlier on.
 		 */
 		iput(dent_inode);
 		return real_dent;
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 50632b950fb8..94cc54668d87 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -605,17 +605,17 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
 				sizeof(unsigned long) * 4);
 		return FALSE;
 	}
-	vol->_VCL(nr_clusters) = ll;
-	ntfs_debug("vol->nr_clusters = 0x%Lx", (long long)vol->_VCL(nr_clusters));
+	vol->nr_clusters = ll;
+	ntfs_debug("vol->nr_clusters = 0x%Lx", (long long)vol->nr_clusters);
 	ll = sle64_to_cpu(b->mft_lcn);
-	if (ll >= vol->_VCL(nr_clusters)) {
+	if (ll >= vol->nr_clusters) {
 		ntfs_error(vol->sb, "MFT LCN is beyond end of volume. Weird.");
 		return FALSE;
 	}
 	vol->mft_lcn = ll;
 	ntfs_debug("vol->mft_lcn = 0x%Lx", (long long)vol->mft_lcn);
 	ll = sle64_to_cpu(b->mftmirr_lcn);
-	if (ll >= vol->_VCL(nr_clusters)) {
+	if (ll >= vol->nr_clusters) {
 		ntfs_error(vol->sb, "MFTMirr LCN is beyond end of volume. "
 				"Weird.");
 		return FALSE;
@@ -629,7 +629,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
 	 * Determine MFT zone size. This is not strictly the right place to do
 	 * this, but I am too lazy to create a function especially for it...
 	 */
-	vol->mft_zone_end = vol->_VCL(nr_clusters);
+	vol->mft_zone_end = vol->nr_clusters;
 	switch (vol->mft_zone_multiplier) {  /* % of volume size in clusters */
 	case 4:
 		vol->mft_zone_end = vol->mft_zone_end >> 1;	/* 50%   */
@@ -678,9 +678,9 @@ static BOOL load_and_init_upcase(ntfs_volume *vol)
 
 	ntfs_debug("Entering.");
 	/* Read upcase table and setup vol->upcase and vol->upcase_len. */
-	ino = iget(sb, FILE_UpCase);
-	if (!ino || is_bad_inode(ino)) {
-		if (ino)
+	ino = ntfs_iget(sb, FILE_UpCase);
+	if (IS_ERR(ino) || is_bad_inode(ino)) {
+		if (!IS_ERR(ino))
 			iput(ino);
 		goto upcase_failed;
 	}
@@ -848,7 +848,7 @@ static BOOL load_system_files(ntfs_volume *vol)
 			vol->mftbmp_allocated_size =
 					sle64_to_cpu(attr->_ANR(allocated_size));
 			/* Consistency check. */
-			if (vol->mftbmp_size < (vol->_VMM(nr_mft_records) + 7) >> 3) {
+			if (vol->mftbmp_size < (vol->nr_mft_records + 7) >> 3) {
 				ntfs_error(sb, "$MFT/$BITMAP is too short to "
 						"contain a complete mft "
 						"bitmap: impossible. $MFT is "
@@ -914,9 +914,9 @@ static BOOL load_system_files(ntfs_volume *vol)
 	// volume read-write...
 
 	/* Get mft mirror inode. */
-	vol->mftmirr_ino = iget(sb, FILE_MFTMirr);
-	if (!vol->mftmirr_ino || is_bad_inode(vol->mftmirr_ino)) {
-		if (is_bad_inode(vol->mftmirr_ino))
+	vol->mftmirr_ino = ntfs_iget(sb, FILE_MFTMirr);
+	if (IS_ERR(vol->mftmirr_ino) || is_bad_inode(vol->mftmirr_ino)) {
+		if (!IS_ERR(vol->mftmirr_ino))
 			iput(vol->mftmirr_ino);
 		ntfs_error(sb, "Failed to load $MFTMirr.");
 		return FALSE;
@@ -932,13 +932,13 @@ static BOOL load_system_files(ntfs_volume *vol)
 	 * need for any locking at this stage as we are already running
 	 * exclusively as we are mount in progress task.
 	 */
-	vol->lcnbmp_ino = iget(sb, FILE_Bitmap);
-	if (!vol->lcnbmp_ino || is_bad_inode(vol->lcnbmp_ino)) {
-		if (is_bad_inode(vol->lcnbmp_ino))
+	vol->lcnbmp_ino = ntfs_iget(sb, FILE_Bitmap);
+	if (IS_ERR(vol->lcnbmp_ino) || is_bad_inode(vol->lcnbmp_ino)) {
+		if (!IS_ERR(vol->lcnbmp_ino))
 			iput(vol->lcnbmp_ino);
 		goto bitmap_failed;
 	}
-	if ((vol->_VCL(nr_lcn_bits) + 7) >> 3 > vol->lcnbmp_ino->i_size) {
+	if ((vol->nr_clusters + 7) >> 3 > vol->lcnbmp_ino->i_size) {
 		iput(vol->lcnbmp_ino);
 bitmap_failed:
 		ntfs_error(sb, "Failed to load $Bitmap.");
@@ -948,9 +948,9 @@ static BOOL load_system_files(ntfs_volume *vol)
 	 * Get the volume inode and setup our cache of the volume flags and
 	 * version.
 	 */
-	vol->vol_ino = iget(sb, FILE_Volume);
-	if (!vol->vol_ino || is_bad_inode(vol->vol_ino)) {
-		if (is_bad_inode(vol->vol_ino))
+	vol->vol_ino = ntfs_iget(sb, FILE_Volume);
+	if (IS_ERR(vol->vol_ino) || is_bad_inode(vol->vol_ino)) {
+		if (!IS_ERR(vol->vol_ino))
 			iput(vol->vol_ino);
 volume_failed:
 		ntfs_error(sb, "Failed to load $Volume.");
@@ -993,9 +993,9 @@ static BOOL load_system_files(ntfs_volume *vol)
 	 * Get the inode for the logfile and empty it if this is a read-write
 	 * mount.
 	 */
-	tmp_ino = iget(sb, FILE_LogFile);
-	if (!tmp_ino || is_bad_inode(tmp_ino)) {
-		if (is_bad_inode(tmp_ino))
+	tmp_ino = ntfs_iget(sb, FILE_LogFile);
+	if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {
+		if (!IS_ERR(tmp_ino))
 			iput(tmp_ino);
 		ntfs_error(sb, "Failed to load $LogFile.");
 		// FIMXE: We only want to empty the thing so pointless bailing
@@ -1010,9 +1010,9 @@ static BOOL load_system_files(ntfs_volume *vol)
 	 * Get the inode for the attribute definitions file and parse the
 	 * attribute definitions.
 	 */ 
-	tmp_ino = iget(sb, FILE_AttrDef);
-	if (!tmp_ino || is_bad_inode(tmp_ino)) {
-		if (is_bad_inode(tmp_ino))
+	tmp_ino = ntfs_iget(sb, FILE_AttrDef);
+	if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {
+		if (!IS_ERR(tmp_ino))
 			iput(tmp_ino);
 		ntfs_error(sb, "Failed to load $AttrDef.");
 		goto iput_vol_bmp_mirr_err_out;
@@ -1020,9 +1020,9 @@ static BOOL load_system_files(ntfs_volume *vol)
 	// FIXME: Parse the attribute definitions.
 	iput(tmp_ino);
 	/* Get the root directory inode. */
-	vol->root_ino = iget(sb, FILE_root);
-	if (!vol->root_ino || is_bad_inode(vol->root_ino)) {
-		if (is_bad_inode(vol->root_ino))
+	vol->root_ino = ntfs_iget(sb, FILE_root);
+	if (IS_ERR(vol->root_ino) || is_bad_inode(vol->root_ino)) {
+		if (!IS_ERR(vol->root_ino))
 			iput(vol->root_ino);
 		ntfs_error(sb, "Failed to load root directory.");
 		goto iput_vol_bmp_mirr_err_out;
@@ -1032,18 +1032,18 @@ static BOOL load_system_files(ntfs_volume *vol)
 		return TRUE;
 	/* NTFS 3.0+ specific initialization. */
 	/* Get the security descriptors inode. */
-	vol->secure_ino = iget(sb, FILE_Secure);
-	if (!vol->secure_ino || is_bad_inode(vol->secure_ino)) {
-		if (is_bad_inode(vol->secure_ino))
+	vol->secure_ino = ntfs_iget(sb, FILE_Secure);
+	if (IS_ERR(vol->secure_ino) || is_bad_inode(vol->secure_ino)) {
+		if (!IS_ERR(vol->secure_ino))
 			iput(vol->secure_ino);
 		ntfs_error(sb, "Failed to load $Secure.");
 		goto iput_root_vol_bmp_mirr_err_out;
 	}
 	// FIXME: Initialize security.
 	/* Get the extended system files' directory inode. */
-	tmp_ino = iget(sb, FILE_Extend);
-	if (!tmp_ino || is_bad_inode(tmp_ino)) {
-		if (is_bad_inode(tmp_ino))
+	tmp_ino = ntfs_iget(sb, FILE_Extend);
+	if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {
+		if (!IS_ERR(tmp_ino))
 			iput(tmp_ino);
 		ntfs_error(sb, "Failed to load $Extend.");
 		goto iput_sec_root_vol_bmp_mirr_err_out;
@@ -1051,8 +1051,8 @@ static BOOL load_system_files(ntfs_volume *vol)
 	// FIXME: Do something. E.g. want to delete the $UsnJrnl if exists.
 	// Note we might be doing this at the wrong level; we might want to
 	// d_alloc_root() and then do a "normal" open(2) of $Extend\$UsnJrnl
-	// rather than using iget here, as we don't know the inode number for
-	// the files in $Extend directory.
+	// rather than using ntfs_iget here, as we don't know the inode number
+	// for the files in $Extend directory.
 	iput(tmp_ino);
 	return TRUE;
 iput_sec_root_vol_bmp_mirr_err_out:
@@ -1172,7 +1172,7 @@ s64 get_nr_free_clusters(ntfs_volume *vol)
 	 * Convert the number of bits into bytes rounded up, then convert into
 	 * multiples of PAGE_CACHE_SIZE.
 	 */
-	max_index = (vol->_VCL(nr_clusters) + 7) >> (3 + PAGE_CACHE_SHIFT);
+	max_index = (vol->nr_clusters + 7) >> (3 + PAGE_CACHE_SHIFT);
 	/* Use multiples of 4 bytes. */
 	max_size = PAGE_CACHE_SIZE >> 2;
 	ntfs_debug("Reading $BITMAP, max_index = 0x%lx, max_size = 0x%x.",
@@ -1211,7 +1211,7 @@ s64 get_nr_free_clusters(ntfs_volume *vol)
 		 * Get the multiples of 4 bytes in use in the final partial
 		 * page.
 		 */
-		max_size = ((((vol->_VCL(nr_clusters) + 7) >> 3) & ~PAGE_CACHE_MASK)
+		max_size = ((((vol->nr_clusters + 7) >> 3) & ~PAGE_CACHE_MASK)
 				+ 3) >> 2;
 		/* If there is a partial page go back and do it. */
 		if (max_size) {
@@ -1254,7 +1254,7 @@ unsigned long get_nr_free_mft_records(ntfs_volume *vol)
 	 * Convert the number of bits into bytes rounded up, then convert into
 	 * multiples of PAGE_CACHE_SIZE.
 	 */
-	max_index = (vol->_VMM(nr_mft_records) + 7) >> (3 + PAGE_CACHE_SHIFT);
+	max_index = (vol->nr_mft_records + 7) >> (3 + PAGE_CACHE_SHIFT);
 	/* Use multiples of 4 bytes. */
 	max_size = PAGE_CACHE_SIZE >> 2;
 	ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = "
@@ -1293,12 +1293,12 @@ unsigned long get_nr_free_mft_records(ntfs_volume *vol)
 		 * Get the multiples of 4 bytes in use in the final partial
 		 * page.
 		 */
-		max_size = ((((vol->_VMM(nr_mft_records) + 7) >> 3) &
+		max_size = ((((vol->nr_mft_records + 7) >> 3) &
 				~PAGE_CACHE_MASK) + 3) >> 2;
 		/* If there is a partial page go back and do it. */
 		if (max_size) {
 			/* Compensate for out of bounds zero bits. */
-			if ((i = vol->_VMM(nr_mft_records) & 31))
+			if ((i = vol->nr_mft_records & 31))
 				nr_free -= 32 - i;
 			ntfs_debug("Handling partial page, max_size = 0x%x",
 					max_size);
@@ -1345,7 +1345,7 @@ int ntfs_statfs(struct super_block *sb, struct statfs *sfs)
 	 * inodes are also stored in data blocs ($MFT is a file) this is just
 	 * the total clusters.
 	 */
-	sfs->f_blocks = vol->_VCL(nr_clusters) << vol->cluster_size_bits >>
+	sfs->f_blocks = vol->nr_clusters << vol->cluster_size_bits >>
 				PAGE_CACHE_SHIFT;
 	/* Free data blocks in file system in units of f_bsize. */
 	size	      = get_nr_free_clusters(vol) << vol->cluster_size_bits >>
@@ -1394,8 +1394,6 @@ struct super_operations ntfs_mount_sops = {
 struct super_operations ntfs_sops = {
 	alloc_inode:	ntfs_alloc_big_inode,	/* VFS: Allocate a new inode. */
 	destroy_inode:	ntfs_destroy_big_inode,	/* VFS: Deallocate an inode. */
-	read_inode:	ntfs_read_inode,	/* VFS: Load inode from disk,
-						   called from iget(). */
 	dirty_inode:	ntfs_dirty_inode,	/* VFS: Called from
 						   __mark_inode_dirty(). */
 	//write_inode:	NULL,		/* VFS: Write dirty inode to disk. */
@@ -1575,9 +1573,9 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	/*
 	 * Now load the metadata required for the page cache and our address
 	 * space operations to function. We do this by setting up a specialised
-	 * read_inode method and then just calling iget() to obtain the inode
-	 * for $MFT which is sufficient to allow our normal inode operations
-	 * and associated address space operations to function.
+	 * read_inode method and then just calling the normal iget() to obtain
+	 * the inode for $MFT which is sufficient to allow our normal inode
+	 * operations and associated address space operations to function.
 	 */
 	/*
 	 * Poison vol->mft_ino so we know whether iget() called into our
@@ -1601,9 +1599,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	 * Note: sb->s_op has already been set to &ntfs_sops by our specialized
 	 * ntfs_read_inode_mount() method when it was invoked by iget().
 	 */
-
 	down(&ntfs_lock);
-
 	/*
 	 * The current mount is a compression user if the cluster size is
 	 * less than or equal 4kiB.
@@ -1618,7 +1614,6 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 			goto iput_tmp_ino_err_out_now;
 		}
 	}
-
 	/*
 	 * Increment the number of mounts and generate the global default
 	 * upcase table if necessary. Also temporarily increment the number of
@@ -1629,12 +1624,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	ntfs_nr_upcase_users++;
 
 	up(&ntfs_lock);
-
 	/*
 	 * From now on, ignore @silent parameter. If we fail below this line,
 	 * it will be due to a corrupt fs or a system error, so we report it.
 	 */
-
 	/*
 	 * Open the system files with normal access functions and complete
 	 * setting up the ntfs super block.
@@ -1643,9 +1636,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 		ntfs_error(sb, "Failed to load system files.");
 		goto unl_upcase_iput_tmp_ino_err_out_now;
 	}
-
 	if ((sb->s_root = d_alloc_root(vol->root_ino))) {
-		/* We increment i_count simulating an iget(). */
+		/* We increment i_count simulating an ntfs_iget(). */
 		atomic_inc(&vol->root_ino->i_count);
 		ntfs_debug("Exiting, status successful.");
 		/* Release the default upcase if it has no users. */
@@ -1710,10 +1702,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 #undef OGIN
 	/*
 	 * 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...
+	 * inode we have ever called ntfs_iget()/iput() on, otherwise we A)
+	 * leak resources and B) a subsequent mount fails automatically due to
+	 * ntfs_iget() never calling down into our ntfs_read_locked_inode()
+	 * method again...
 	 */
 	if (invalidate_inodes(sb)) {
 		ntfs_error(sb, "Busy inodes left. This is most likely a NTFS "
diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h
index 01b429378fad..f289335df624 100644
--- a/fs/ntfs/volume.h
+++ b/fs/ntfs/volume.h
@@ -3,7 +3,7 @@
  *	      of 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
@@ -89,10 +89,8 @@ typedef struct {
 	u32 index_record_size;		/* in bytes */
 	u32 index_record_size_mask;	/* index_record_size - 1 */
 	u8 index_record_size_bits;	/* log2(index_record_size) */
-	union {
-		LCN nr_clusters;	/* Volume size in clusters. */
-		LCN nr_lcn_bits;	/* Number of bits in lcn bitmap. */
-	} SN(vcl);
+	LCN nr_clusters;		/* Volume size in clusters == number of
+					   bits in lcn bitmap. */
 	LCN mft_lcn;			/* Cluster location of mft data. */
 	LCN mftmirr_lcn;		/* Cluster location of copy of mft. */
 	u64 serial_no;			/* The volume serial number. */
@@ -104,10 +102,8 @@ typedef struct {
 	struct inode *mft_ino;		/* The VFS inode of $MFT. */
 	struct rw_semaphore mftbmp_lock; /* Lock for serializing accesses to the
 					    mft record bitmap ($MFT/$BITMAP). */
-	union {
-		unsigned long nr_mft_records; /* Number of mft records. */
-		unsigned long nr_mft_bits; /* Number of bits in mft bitmap. */
-	} SN(vmm);
+	unsigned long nr_mft_records;	/* Number of mft records == number of
+					   bits in mft bitmap. */
 	struct address_space mftbmp_mapping; /* Page cache for $MFT/$BITMAP. */
 	run_list mftbmp_rl;		/* Run list for $MFT/$BITMAP. */
 	s64 mftbmp_size;		/* Data size of $MFT/$BITMAP. */
@@ -128,8 +124,5 @@ typedef struct {
 	struct nls_table *nls_map;
 } ntfs_volume;
 
-#define _VCL(X)  SC(vcl,X)
-#define _VMM(X)  SC(vmm,X)
-
 #endif /* _LINUX_NTFS_VOLUME_H */
 
-- 
2.30.9