[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-ntfs-cvs
Subject:    [Linux-NTFS-cvs] CVS: ntfs-driver-tng/linux/fs/ntfs aops.c,1.44,1.45 attraops.c,1.8,1.9 attrib.h,1.1
From:       Anton Altaparmakov <antona () users ! sourceforge ! net>
Date:       2002-01-28 7:01:19
[Download RAW message or body]


Changes by: antona

Update of /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs
In directory usw-pr-cvs1:/tmp/cvs-serv4307/linux/fs/ntfs

Modified Files:
	aops.c attraops.c attrib.h compress.c dir.c inode.c inode.h 
	mft.c namei.c ntfs.h super.c types.h volume.h 
Log Message:
The BIG update. Almost a rewrite of the whole driver. Divorce ntfs_inode from struct \
inode almost completely to allow extent inodes to exist without a struct inode \
associated with their ntfs_inode (this is the 2nd change requested by Al Viro). See \
ChangeLog for more details.


Index: aops.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/aops.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -U2 -r1.44 -r1.45
--- aops.c	2002/01/25 00:32:24	1.44
+++ aops.c	2002/01/28 07:01:17	1.45
@@ -78,9 +78,9 @@
  * doesn't really matter for the moment.
  */
-int ntfs_file_get_block(struct inode *vfs_ino, const sector_t blk,
+int ntfs_file_get_block(struct inode *vi, const sector_t blk,
 		struct buffer_head *bh, const int create)
 {
-	ntfs_inode *ntfs_ino = NTFS_I(vfs_ino);
-	struct super_block *sb = vfs_ino->i_sb;
+	ntfs_inode *ni = NTFS_I(vi);
+	struct super_block *sb = vi->i_sb;
 	ntfs_volume *vol = NTFS_SB(sb);
 	run_list *rl;
@@ -91,8 +91,8 @@
 	MFT_RECORD *mrec;
 
-	// ntfs_debug("Entering for blk 0x%lx.\n", blk);
+	//ntfs_debug("Entering for blk 0x%lx.\n", blk);
 	//printk(KERN_DEBUG "NTFS: " __FUNCTION__ "(): Entering for blk "
 	//		"0x%lx.\n", blk);
-	bh->b_dev = vfs_ino->i_dev;
+	bh->b_dev = vi->i_dev;
 	bh->b_blocknr = -1;
 	bh->b_state &= ~(1UL << BH_Mapped);
@@ -103,5 +103,5 @@
 	 * only relevant when we start handling attribute lists and extents.
 	 */
-	if (!ntfs_ino->run_list)
+	if (!ni->run_list)
 		goto map_run_list;
 have_run_list:
@@ -134,5 +134,5 @@
 
 	/* Convert the vcn to the corresponding logical cluster number (lcn). */
-	lcn = vcn_to_lcn(ntfs_ino->run_list, vcn);
+	lcn = vcn_to_lcn(ni->run_list, vcn);
 	if (lcn < -1) {
 		if (create)
@@ -168,10 +168,10 @@
 
 	/* Map, pin and lock the mft record for reading. */
-	mrec = map_mft_record(READ, vfs_ino);
+	mrec = map_mft_record(READ, ni);
 	if (IS_ERR(mrec))
 		return PTR_ERR(mrec);
 
 	/* Initialize the search context. */
-	err = get_attr_search_ctx(&ctx, vfs_ino, mrec);
+	err = get_attr_search_ctx(&ctx, ni, mrec);
 	if (err)
 		goto unm_err_out;
@@ -189,5 +189,5 @@
 
 	/* Unlock, unpin and release the mft record. */
-	unmap_mft_record(READ, vfs_ino);
+	unmap_mft_record(READ, ni);
 
 	/* If an error occured, return it. */
@@ -196,5 +196,5 @@
 
 	/* Everything ok, set the run list. */
-	ntfs_ino->run_list = rl;
+	ni->run_list = rl;
 
 	/* We now have the run list and can continue. */
@@ -205,5 +205,5 @@
 unm_err_out:
 	/* Unlock, unpin and release the mft record. */
-	unmap_mft_record(READ, vfs_ino);
+	unmap_mft_record(READ, ni);
 	return err;
 }
@@ -230,6 +230,6 @@
 {
 	s64 attr_pos;
-	struct inode *vfs_ino;
-	ntfs_inode *ntfs_ino;
+	struct inode *vi;
+	ntfs_inode *ni;
 	char *page_addr;
 	u32 attr_len;
@@ -251,17 +251,17 @@
 	 * must check it is not NULL before doing so.
 	 */
-	vfs_ino = page->mapping->host;
-	ntfs_ino = NTFS_I(vfs_ino);
+	vi = page->mapping->host;
+	ni = NTFS_I(vi);
 
 	/* Is the unnamed $DATA attribute resident? */
-	if (test_bit(NI_NonResident, &ntfs_ino->state)) {
+	if (test_bit(NI_NonResident, &ni->state)) {
 		/* Attribute is not resident. */
 
 		/* If the file is encrypted, we deny access, just like NT4. */
-		if (test_bit(NI_Encrypted, &ntfs_ino->state)) {
+		if (test_bit(NI_Encrypted, &ni->state)) {
 			err = -EACCES;
 			goto unl_err_out;
 		}
-		if (!test_bit(NI_Compressed, &ntfs_ino->state))
+		if (!test_bit(NI_Compressed, &ni->state))
 			/* Normal data stream, use generic functionality. */
 			return block_read_full_page(page, ntfs_file_get_block);
@@ -278,5 +278,5 @@
 
 	/* Map, pin and lock the mft record for reading. */
-	mrec = map_mft_record(READ, vfs_ino);
+	mrec = map_mft_record(READ, ni);
 	if (IS_ERR(mrec)) {
 		err = PTR_ERR(mrec);
@@ -284,5 +284,5 @@
 	}
 
-	err = get_attr_search_ctx(&ctx, vfs_ino, mrec);
+	err = get_attr_search_ctx(&ctx, ni, mrec);
 	if (err)
 		goto unm_dec_unl_err_out;
@@ -328,5 +328,5 @@
 unm_dec_unl_err_out:
 	/* Unlock, unpin and release the mft record. */
-	unmap_mft_record(READ, vfs_ino);
+	unmap_mft_record(READ, ni);
 dec_unl_err_out:
 	/* Release the inode. - Shouldn't be needed as the page is locked. */
@@ -509,12 +509,10 @@
 	if (!PageError(page)) {
 		char *addr;
-		ntfs_inode *ntfs_ino;
 		unsigned int i, recs, nr_err = 0;
 		u32 rec_size;
 
-		ntfs_ino = NTFS_I(page->mapping->host);
 		addr = kmap_atomic(page, KM_BIO_IRQ);
-		recs = PAGE_CACHE_SIZE / ntfs_ino->index_block_size;
-		rec_size = ntfs_ino->index_block_size;
+		rec_size = NTFS_I(page->mapping->host)->index_block_size;
+		recs = PAGE_CACHE_SIZE / rec_size;
 		for (i = 0; i < recs; i++) {
 			if (!post_read_mst_fixup((NTFS_RECORD*)(addr +
@@ -559,6 +557,6 @@
 	VCN vcn;
 	LCN lcn;
-	struct inode *vfs_ino;
-	ntfs_inode *ntfs_ino;
+	struct inode *vi;
+	ntfs_inode *ni;
 	struct super_block *sb;
 	ntfs_volume *vol;
@@ -576,8 +574,8 @@
 	 * with the page.
 	 */
-	vfs_ino = page->mapping->host;
-	ntfs_ino = NTFS_I(vfs_ino);
-	sb = vfs_ino->i_sb;
-	vol = NTFS_SB(sb);
+	vi = page->mapping->host;
+	ni = NTFS_I(vi);
+	sb = vi->i_sb;
+	vol = ni->vol;
 
 	/* We need to create buffers for the page so we can do low level io. */
@@ -590,5 +588,5 @@
 	nr_bu = blocks = PAGE_CACHE_SIZE >> blocksize_bits;
 	iblock = page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
-	lblock = (vfs_ino->i_size + blocksize - 1) >> blocksize_bits;
+	lblock = (vi->i_size + blocksize - 1) >> blocksize_bits;
 	bh = head = page->buffers;
 	if (!bh)
@@ -596,5 +594,5 @@
 #ifdef DEBUG
 	/* FIXME: Kludge for now. Later we want on demand run list loading. */
-	if (!ntfs_ino->run_list)
+	if (!ni->run_list)
 		panic("NTFS: Index run list has been unmapped! This is a "
 				"very serious bug! Cannot continue...");
@@ -610,5 +608,6 @@
 			/* Is the block within the allowed limits? */
 			if (iblock < lblock) {
-				/* Convert iblock into corresponding vcn and offset. */
+				/* Convert iblock into corresponding vcn and
+				 * offset. */
 				vcn = (VCN)iblock << blocksize_bits >>
 						vol->cluster_size_bits;
@@ -616,10 +615,13 @@
 						vol->cluster_size_mask;
 				/* Convert the vcn to the corresponding lcn. */
-				lcn = vcn_to_lcn(ntfs_ino->run_list, vcn);
+				lcn = vcn_to_lcn(ni->run_list, vcn);
 				if (lcn >= 0) {
-					/* Setup buffer head to correct block. */
-					bh->b_dev = vfs_ino->i_dev;
-					bh->b_blocknr = ((lcn << vol->cluster_size_bits)
-						+ vcn_ofs) >> blocksize_bits;
+					/* Setup buffer head to correct
+					 * block. */
+					bh->b_dev = vi->i_dev;
+					bh->b_blocknr = ((lcn <<
+							vol->cluster_size_bits)
+							+ vcn_ofs) >>
+							blocksize_bits;
 					bh->b_state |= (1UL << BH_Mapped);
 					arr[nr++] = bh;
@@ -628,12 +630,13 @@
 				ntfs_error(sb, "vcn_to_lcn() failed with "
 						"error code %Li.", -lcn);
-				// FIXME: Depending on vol->on_errors, do something.
+				// FIXME: Depending on vol->on_errors, do
+				// something.
 			}
 			/*
-			 * Either iblock was outside lblock limits or vcn_to_lcn()
-			 * returned error. Just zero that portion of the page and set
-			 * the buffer uptodate.
+			 * Either iblock was outside lblock limits or
+			 * vcn_to_lcn() returned error. Just zero that portion
+			 * of the page and set the buffer uptodate.
 			 */
-			bh->b_dev = vfs_ino->i_dev;
+			bh->b_dev = vi->i_dev;
 			bh->b_blocknr = -1UL;
 			memset(kmap(page) + i * blocksize, 0, blocksize);

Index: attraops.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/attraops.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -U2 -r1.8 -r1.9
--- attraops.c	2001/11/21 21:19:06	1.8
+++ attraops.c	2002/01/28 07:01:17	1.9
@@ -6,5 +6,5 @@
  */
 typedef struct {
-	struct inode *a_vfs_ino;
+	ntfs_inode *a_ni;
 	ntfs_volume *a_vol;
 	atomic_t a_count;

Index: attrib.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/attrib.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -U2 -r1.10 -r1.11
--- attrib.h	2002/01/06 03:24:58	1.10
+++ attrib.h	2002/01/28 07:01:17	1.11
@@ -58,7 +58,7 @@
 	ATTR_RECORD *attr;
 	BOOL is_first;
-	struct inode *vfs_ino;
+	ntfs_inode *ntfs_ino;
 	ATTR_LIST_ENTRY *al_entry;
-	struct inode *base_vfs_ino;
+	ntfs_inode *base_ntfs_ino;
 	MFT_RECORD *base_mrec;
 	ATTR_RECORD *base_attr;
@@ -82,5 +82,5 @@
 }
 
-extern int get_attr_search_ctx(attr_search_context **ctx, struct inode *vfs_ino,
+extern int get_attr_search_ctx(attr_search_context **ctx, ntfs_inode *ni,
 		MFT_RECORD *mrec);
 extern void put_attr_search_ctx(attr_search_context *ctx);

Index: compress.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/compress.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -U2 -r1.22 -r1.23
--- compress.c	2002/01/24 05:02:25	1.22
+++ compress.c	2002/01/28 07:01:17	1.23
@@ -419,8 +419,8 @@
 {
 	struct address_space *mapping = page->mapping;
-	struct inode *vfs_ino = mapping->host;
-	ntfs_inode *ntfs_ino = NTFS_I(vfs_ino);
-	struct super_block *sb = vfs_ino->i_sb;
-	ntfs_volume *vol = NTFS_SB(sb);
+	struct inode *vi = mapping->host;
+	ntfs_inode *ni = NTFS_I(vi);
+	struct super_block *sb = vi->i_sb;
+	ntfs_volume *vol = ni->vol;
 	kdev_t dev = sb->s_dev;
 	unsigned long block_size = sb->s_blocksize;
@@ -430,5 +430,5 @@
 	unsigned long offset, index = page->index;
 	run_list *rl;
-	u32 cb_size = ntfs_ino->compression_block_size;
+	u32 cb_size = ni->compression_block_size;
 	u64 cb_size_mask = cb_size - 1UL;
 	VCN vcn;
@@ -445,5 +445,5 @@
 	/* Number of compression blocks (cbs) in the wanted vcn range. */
 	unsigned int nr_cbs = (end_vcn - start_vcn) << vol->cluster_size_bits
-			>> ntfs_ino->compression_block_size_bits;
+			>> ni->compression_block_size_bits;
 	/*
 	 * Number of pages required to store the uncompressed data from all
@@ -478,5 +478,5 @@
 	 * as it should be a very seldom occurence...
 	 */
-	rl = ntfs_ino->run_list;
+	rl = ni->run_list;
 	if (unlikely(!rl))
 		goto map_run_list;
@@ -501,6 +501,6 @@
 	 * cache, alignment guarantees keep all the below much simpler. (-8
 	 */
-	max_page = ((vfs_ino->i_size + PAGE_CACHE_SIZE - 1) >>
-			PAGE_CACHE_SHIFT) - offset;
+	max_page = ((vi->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) -
+			offset;
 	if (nr_pages < max_page)
 		max_page = nr_pages;
@@ -533,5 +533,5 @@
 	cur_page = 0;
 	cur_ofs = 0;
-	cb_clusters = ntfs_ino->compression_block_clusters;
+	cb_clusters = ni->compression_block_clusters;
 do_next_cb:
 	nr_cbs--;
@@ -847,5 +847,5 @@
 
 	/* Map, pin and lock the mft record for reading. */
-	mrec = map_mft_record(READ, vfs_ino);
+	mrec = map_mft_record(READ, ni);
 	if (IS_ERR(mrec)) {
 		SetPageError(page);
@@ -854,5 +854,5 @@
 	}
 
-	err = get_attr_search_ctx(&ctx, vfs_ino, mrec);
+	err = get_attr_search_ctx(&ctx, ni, mrec);
 	if (err)
 		goto get_ctx_err_out;
@@ -862,5 +862,5 @@
 		put_attr_search_ctx(ctx);
 get_ctx_err_out:
-		unmap_mft_record(READ, vfs_ino);
+		unmap_mft_record(READ, ni);
 		SetPageError(page);
 		UnlockPage(page);
@@ -874,5 +874,5 @@
 
 	/* Unlock, unpin and release the mft record. */
-	unmap_mft_record(READ, vfs_ino);
+	unmap_mft_record(READ, ni);
 
 	/* If an error occured, return it. */
@@ -884,5 +884,5 @@
 
 	/* Everything ok, set the run list. */
-	ntfs_ino->run_list = rl;
+	ni->run_list = rl;
 
 	/* We now have the run list and can continue. */

Index: dir.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/dir.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -U2 -r1.31 -r1.32
--- dir.c	2001/12/16 19:04:36	1.31
+++ dir.c	2002/01/28 07:01:17	1.32
@@ -27,11 +27,11 @@
 
 /**
- * ntfs_lookup_ino_by_name - find an inode in a directory given its name
- * @dir_ino:	inode of the directory in which to search for the name
+ * ntfs_lookup_inode_by_name - find an inode in a directory given its name
+ * @dir_ni:	ntfs inode of the directory in which to search for the name
  * @uname:	Unicode name for which to search in the directory
  * @uname_len:	length of the name @uname in Unicode characters
  *
- * Look for an inode with name @uname in the directory with inode @dir_ino.
- * ntfs_lookup_ino_by_name() walks the contents of the directory looking for
+ * Look for an inode with name @uname in the directory with inode @dir_ni.
+ * ntfs_lookup_inode_by_name() walks the contents of the directory looking for
  * the Unicode name. If the name is found in the directory, the corresponding
  * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it
@@ -39,16 +39,16 @@
  *
  * On error, a negative value is returned corresponding to the error code. In
- * particular if the inode is not found -ENOENT is returned. No that you can't
- * just check the return value for being negative, you have to check the inode
- * number for being negative which you can extract using MREC(return value).
+ * particular if the inode is not found -ENOENT is returned. Note that you
+ * can't just check the return value for being negative, you have to check the
+ * inode number for being negative which you can extract using MREC(return
+ * value).
  *
  * Note, @uname_len does not include the (optional) terminating NULL character.
  */
-u64 ntfs_lookup_ino_by_name(struct inode *dir_ino, const uchar_t *uname,
+u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
 		const int uname_len)
 {
-	struct super_block *sb = dir_ino->i_sb;
-	ntfs_volume *vol = NTFS_SB(sb);
-	ntfs_inode *ntfs_dir_ino;
+	ntfs_volume *vol = dir_ni->vol;
+	struct super_block *sb = vol->sb;
 	MFT_RECORD *m;
 	INDEX_ROOT *ir;
@@ -66,9 +66,9 @@
 
 	/* Get hold of the mft record for the directory. */
-	m = map_mft_record(READ, dir_ino);
+	m = map_mft_record(READ, dir_ni);
 	if (IS_ERR(m))
 		goto map_err_out;
 
-	err = get_attr_search_ctx(&ctx, dir_ino, m);
+	err = get_attr_search_ctx(&ctx, dir_ni, m);
 	if (err)
 		goto unm_err_out;
@@ -78,5 +78,5 @@
 			NULL, 0, ctx)) {
 		ntfs_error(sb, "Index root attribute missing in directory "
-				"inode %li.", dir_ino->i_ino);
+				"inode %Li.", dir_ni->mft_no);
 		err = -EIO;
 		goto put_unm_err_out;
@@ -131,5 +131,5 @@
 			mref = le64_to_cpu(ie->indexed_file);
 			put_attr_search_ctx(ctx);
-			unmap_mft_record(READ, dir_ino);
+			unmap_mft_record(READ, dir_ni);
 			return mref;
 		}
@@ -182,15 +182,14 @@
 	} /* Child node present, descend into it. */
 	/* Consistency check: Verify that an index allocation exists. */
-	if (!NInoIndexAllocPresent(NTFS_I(dir_ino))) {
+	if (!NInoIndexAllocPresent(dir_ni)) {
 		ntfs_error(sb, "No index allocation attribute but index entry "
-				"requires one. Directory inode %li is corrupt "
-				"or driver bug.", dir_ino->i_ino);
+				"requires one. Directory inode %Li is corrupt "
+				"or driver bug.", dir_ni->mft_no);
 		err = -EIO;
 		goto put_unm_err_out;
 	}
-	ntfs_dir_ino = NTFS_I(dir_ino);
 	/* Get the starting vcn of the index_block holding the child node. */
 	vcn = sle64_to_cpup((char*)ie + le16_to_cpu(ie->length) - 8);
-	ia_mapping = dir_ino->i_mapping;
+	ia_mapping = dir_ni->inode->i_mapping;
 descend_into_child_node:
 	/*
@@ -199,5 +198,5 @@
 	 * disk if necessary.
 	 */
-	if (vol->cluster_size <= ntfs_dir_ino->index_block_size)
+	if (vol->cluster_size <= dir_ni->index_block_size)
 		page = ntfs_map_page(ia_mapping, vcn << vol->cluster_size_bits
 				>> PAGE_CACHE_SHIFT);
@@ -208,5 +207,5 @@
 fast_descend_into_child_node:
 	/* Get to the index allocation block. */
-	if (vol->cluster_size <= ntfs_dir_ino->index_block_size)
+	if (vol->cluster_size <= dir_ni->index_block_size)
 		ia = (INDEX_ALLOCATION*)(kaddr + ((vcn <<
 				vol->cluster_size_bits) & ~PAGE_CACHE_MASK));
@@ -217,5 +216,5 @@
 	if ((char*)ia < kaddr || (char*)ia > kaddr + PAGE_CACHE_SIZE) {
 		ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
-				"inode %li or driver bug.", dir_ino->i_ino);
+				"inode %Li or driver bug.", dir_ni->mft_no);
 		err = -EIO;
 		goto unm_unm_err_out;
@@ -223,36 +222,36 @@
 	if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
 		ntfs_error(sb, "Actual VCN (%Li) of index buffer is different "
-				"from expected VCN (%Li). Directory inode %li "
+				"from expected VCN (%Li). Directory inode %Li "
 				"is corrupt or driver bug.",
 				sle64_to_cpu(ia->index_block_vcn), vcn,
-				dir_ino->i_ino);
+				dir_ni->mft_no);
 		err = -EIO;
 		goto unm_unm_err_out;
 	}
 	if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
-			ntfs_dir_ino->index_block_size) {
-		ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %li "
+			dir_ni->index_block_size) {
+		ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %Li "
 				"has a size (%u) differing from the directory "
-				"specified size (%u). Directory inode %li is "
-				"corrupt or driver bug.", vcn, dir_ino->i_ino,
+				"specified size (%u). Directory inode is "
+				"corrupt or driver bug.", vcn, dir_ni->mft_no,
 				le32_to_cpu(ia->index.allocated_size) + 0x18,
-				ntfs_dir_ino->index_block_size, dir_ino->i_ino);
+				dir_ni->index_block_size);
 		err = -EIO;
 		goto unm_unm_err_out;
 	}
-	index_end = (char*)ia + ntfs_dir_ino->index_block_size;
+	index_end = (char*)ia + dir_ni->index_block_size;
 	if (index_end > kaddr + PAGE_CACHE_SIZE) {
-		ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %li "
+		ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %Li "
 				"crosses page boundary. Impossible! Cannot "
 				"access! This is probably a bug in the "
-				"driver.", vcn, dir_ino->i_ino);
+				"driver.", vcn, dir_ni->mft_no);
 		err = -EIO;
 		goto unm_unm_err_out;
 	}
 	index_end = (char*)&ia->index + le32_to_cpu(ia->index.index_length);
-	if (index_end > (char*)ia + ntfs_dir_ino->index_block_size) {
+	if (index_end > (char*)ia + dir_ni->index_block_size) {
 		ntfs_error(sb, "Size of index buffer (VCN %Li) of directory "
-				"inode %li exceeds maximum size.", vcn,
-				dir_ino->i_ino);
+				"inode %Li exceeds maximum size.", vcn,
+				dir_ni->mft_no);
 		err = -EIO;
 		goto unm_unm_err_out;
@@ -273,5 +272,5 @@
 				index_end) {
 			ntfs_error(sb, "Index entry out of bounds in "
-					"directory inode %li.", dir_ino->i_ino);
+					"directory inode %Li.", dir_ni->mft_no);
 			err = -EIO;
 			goto unm_unm_err_out;
@@ -309,5 +308,5 @@
 			ntfs_unmap_page(page);
 			put_attr_search_ctx(ctx);
-			unmap_mft_record(READ, dir_ino);
+			unmap_mft_record(READ, dir_ni);
 			return mref;
 		}
@@ -357,6 +356,6 @@
 		if ((ia->index.flags & NODE_MASK) == LEAF_NODE) {
 			ntfs_error(sb, "Index entry with child node found in "
-					"a leaf node in directory inode %li.",
-					dir_ino->i_ino);
+					"a leaf node in directory inode %Li.",
+					dir_ni->mft_no);
 			err = -EIO;
 			goto unm_unm_err_out;
@@ -377,5 +376,5 @@
 		}
 		ntfs_error(sb, "Negative child node vcn in directory inode "
-				"%li.", dir_ino->i_ino);
+				"%Li.", dir_ni->mft_no);
 		err = -EIO;
 		goto unm_unm_err_out;
@@ -389,5 +388,5 @@
 	put_attr_search_ctx(ctx);
 unm_err_out:
-	unmap_mft_record(READ, dir_ino);
+	unmap_mft_record(READ, dir_ni);
 	return ERR_MREF(err);
 map_err_out:
@@ -493,5 +492,5 @@
 	attr_search_context *ctx;
 
-	ntfs_debug("Entering for inode 0x%lx, f_pos 0x%Lx.\n", vdir->i_ino,
+	ntfs_debug("Entering for inode 0x%Lx, f_pos 0x%Lx.\n", ndir->mft_no,
 			filp->f_pos);
 	rc = err = 0;
@@ -502,5 +501,5 @@
 	if (!filp->f_pos) {
 		ntfs_debug("Calling filldir for . with len 1, f_pos 0x0, "
-				"inode 0x%lx, DT_DIR.\n", vdir->i_ino);
+				"inode 0x%Lx, DT_DIR.\n", ndir->mft_no);
 		rc = filldir(dirent, ".", 1, filp->f_pos, vdir->i_ino, DT_DIR);
 		if (rc)
@@ -510,6 +509,6 @@
 	if (filp->f_pos == 1) {
 		ntfs_debug("Calling filldir for .. with len 2, f_pos 0x1, "
-				"inode 0x%lx, DT_DIR.\n",
-				filp->f_dentry->d_parent->d_inode->i_ino);
+				"inode 0x%Lx, DT_DIR.\n",
+				filp->f_dentry->d_parent->d_inode->mft_no);
 		rc = filldir(dirent, "..", 2, filp->f_pos,
 				filp->f_dentry->d_parent->d_inode->i_ino,
@@ -520,5 +519,5 @@
 	}
 	/* Get hold of the mft record for the directory. */
-	m = map_mft_record(READ, vdir);
+	m = map_mft_record(READ, ndir);
 	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
@@ -526,5 +525,5 @@
 	}
 
-	err = get_attr_search_ctx(&ctx, vdir, m);
+	err = get_attr_search_ctx(&ctx, ndir, m);
 	if (err)
 		goto unm_err_out;
@@ -548,5 +547,5 @@
 			NULL, 0, ctx)) {
 		ntfs_error(sb, "Index root attribute missing in directory "
-				"inode %li.", vdir->i_ino);
+				"inode %Li.", ndir->mft_no);
 		err = -EIO;
 		goto kf_unm_err_out;
@@ -608,5 +607,5 @@
 				NULL, 0, ctx)) {
 			ntfs_error(sb, "Index bitmap attribute missing in "
-					"directory inode %li.", vdir->i_ino);
+					"directory inode %Li.", ndir->mft_no);
 			err = -EIO;
 			goto kf_unm_err_out;
@@ -656,5 +655,5 @@
 	if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) {
 		ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
-				"inode %li or driver bug.", vdir->i_ino);
+				"inode %Li or driver bug.", ndir->mft_no);
 		err = -EIO;
 		goto unm_dir_err_out;
@@ -670,9 +669,9 @@
 			ntfs_error(sb, "Actual VCN (%Li) of index buffer is "
 					"different from expected VCN (%Li). "
-					"Directory inode %li is corrupt or "
+					"Directory inode %Li is corrupt or "
 					"driver bug. ",
 					sle64_to_cpu(ia->index_block_vcn),
 					ia_pos >> vol->cluster_size_bits,
-					vdir->i_ino);
+					ndir->mft_no);
 			err = -EIO;
 			goto unm_dir_err_out;
@@ -684,9 +683,9 @@
 			ntfs_error(sb, "Actual VCN (%Li) of index buffer is "
 					"different from expected VCN (%Li). "
-					"Directory inode %li is corrupt or "
+					"Directory inode %Li is corrupt or "
 					"driver bug.",
 					sle64_to_cpu(ia->index_block_vcn),
 					ia_pos >> vol->sector_size_bits,
-					vdir->i_ino);
+					ndir->mft_no);
 			err = -EIO;
 			goto unm_dir_err_out;
@@ -695,11 +694,11 @@
 	if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
 			ndir->index_block_size) {
-		ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %li "
+		ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %Li "
 				"has a size (%u) differing from the directory "
-				"specified size (%u). Directory inode %li is "
+				"specified size (%u). Directory inode is "
 				"corrupt or driver bug.", ia_pos >>
-				vol->cluster_size_bits, vdir->i_ino,
+				vol->cluster_size_bits, ndir->mft_no,
 				le32_to_cpu(ia->index.allocated_size) + 0x18,
-				ndir->index_block_size, vdir->i_ino);
+				ndir->index_block_size);
 		err = -EIO;
 		goto unm_dir_err_out;
@@ -707,9 +706,9 @@
 	index_end = (u8*)ia + ndir->index_block_size;
 	if (index_end > kaddr + PAGE_CACHE_SIZE) {
-		ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %li "
+		ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %Li "
 				"crosses page boundary. Impossible! Cannot "
 				"access! This is probably a bug in the "
 				"driver.", ia_pos >> vol->cluster_size_bits,
-				vdir->i_ino);
+				ndir->mft_no);
 		err = -EIO;
 		goto unm_dir_err_out;
@@ -719,6 +718,6 @@
 	if (index_end > (u8*)ia + ndir->index_block_size) {
 		ntfs_error(sb, "Size of index buffer (VCN %Li) of directory "
-				"inode %li exceeds maximum size.", ia_pos >>
-				vol->cluster_size_bits, vdir->i_ino);
+				"inode %Li exceeds maximum size.", ia_pos >>
+				vol->cluster_size_bits, ndir->mft_no);
 		err = -EIO;
 		goto unm_dir_err_out;
@@ -761,5 +760,5 @@
 abort:
 	put_attr_search_ctx(ctx);
-	unmap_mft_record(READ, vdir);
+	unmap_mft_record(READ, ndir);
 	kfree(name);
 done:
@@ -780,5 +779,5 @@
 	put_attr_search_ctx(ctx);
 unm_err_out:
-	unmap_mft_record(READ, vdir);
+	unmap_mft_record(READ, ndir);
 err_out:
 	ntfs_debug("Failed. Returning error code %i.\n", -err);

Index: inode.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/inode.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -U2 -r1.52 -r1.53
--- inode.c	2002/01/25 00:32:24	1.52
+++ inode.c	2002/01/28 07:01:17	1.53
@@ -1,3 +1,3 @@
-/*
+/**
  * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project.
  *
@@ -22,32 +22,55 @@
 #include <linux/pagemap.h>
 
+ntfs_inode *ntfs_new_inode(void)
+{
+	ntfs_inode *ni = kmem_cache_alloc(ntfs_inode_cache, SLAB_NOFS);
+	if (ni) {
[...1126 lines suppressed...]
+		kfree(ni->extent_ntfs_inos);
 	}
 	/* Free all alocated memory. */
-	vfs_ino->u.generic_ip = NULL;
-	ntfs_free(ntfs_ino->run_list);
-	ntfs_free(ntfs_ino->attr_list);
-	ntfs_free(ntfs_ino->attr_list_rl);
-	if (S_ISDIR(vfs_ino->i_mode))
-		ntfs_free(ntfs_ino->bmp_rl);
+	vi->u.generic_ip = NULL;
+	ntfs_free(ni->run_list);
+	ntfs_free(ni->attr_list);
+	ntfs_free(ni->attr_list_rl);
+	if (S_ISDIR(vi->i_mode))
+		ntfs_free(ni->bmp_rl);
 	/* Bye, bye... */
-	kmem_cache_free(ntfs_inode_cache, ntfs_ino);
+	ntfs_free_inode(ni);
 	return;
 }

Index: inode.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/inode.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -U2 -r1.8 -r1.9
--- inode.h	2001/12/16 19:04:36	1.8
+++ inode.h	2002/01/28 07:01:17	1.9
@@ -24,27 +24,7 @@
 #define _LINUX_NTFS_INODE_H
 
-/*
- * Clusters are signed 64-bit values on NTFS volumes. We define two types, LCN
- * and VCN, to allow for type checking and better code readability.
- */
-typedef s64 VCN;
-typedef s64 LCN;
+#include "volume.h"
 
-/**
- * run_list - in memory vcn to lcn mapping array
- * @vcn:	starting vcn of the current array element
- * @lcn:	starting lcn of the current array element
- * @length:	length in clusters of the current array element
- * 
- * The last vcn (in fact the last vcn + 1) is reached when length == 0.
- * 
- * When lcn == -1 this means that the count vcns starting at vcn are not 
- * physically allocated (i.e. this is a hole / data is sparse).
- */
-typedef struct {	/* In memory vcn to lcn mapping structure element. */
-	VCN vcn;	/* vcn = Starting virtual cluster number. */
-	LCN lcn;	/* lcn = Starting logical cluster number. */
-	s64 length;	/* Run length in clusters. */
-} run_list;
+typedef struct _ntfs_inode ntfs_inode;
 
 /*
@@ -52,9 +32,13 @@
  * fields already provided in the VFS inode.
  */
-typedef struct {
+struct _ntfs_inode {
 	struct inode *inode;	/* Pointer to the inode structure of this
-				   ntfs_inode. */
+				   ntfs_inode. NULL for extent inodes. */
 	unsigned long state;	/* NTFS specific flags describing this inode.
 				   See fs/ntfs/ntfs.h:ntfs_inode_state_bits. */
+	u64 mft_no;		/* Mft record number (inode number). */
+	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. */
 	run_list *run_list;	/* If state has the NI_NonResident bit set,
 				   the run list of the unnamed data attribute
@@ -69,10 +53,11 @@
 	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. */
 	struct page *page;	/* The page containing the mft record of the
 				   inode. This should only be touched by the
-				   (un)map_mft_record() functions. Do NOT touch
-				   from anywhere else or the ntfs divil will
-				   appear and take your heart out with a blunt
-				   spoon! You have been warned. (-8 */
+				   (un)map_mft_record*() functions. */
+	int page_ofs;		/* Offset into the page at which the mft record
+				   begins. This should only be touched by the
+				   (un)map_mft_record*() functions. */
 	/*
 	 * Attribute list support (only for use by the attribute lookup
@@ -107,18 +92,26 @@
 	s32 nr_extents;	/* The number of extent inodes, if this is a base
 			   mft record, -1 if this is an extent record, and
-			   0 if there are no extents (on which iget() has
-			   been called internally). */
+			   0 if there are no loaded extents. */
 	union {		/* This union is only used if nr_extents != 0. */
-		struct inode **extent_vfs_inos;	/* For nr_extents > 0, array of
-						   the vfs inodes of the extent
+		ntfs_inode **extent_ntfs_inos;	/* For nr_extents > 0, array of
+						   the ntfs inodes of the extent
 						   mft records belonging to
-						   this base inode for which
-						   iget() has been called
-						   internally. */
-		struct inode *base_vfs_ino;	/* For nr_extents == -1, the
+						   this base inode which have
+						   been loaded. */
+		ntfs_inode *base_ntfs_ino;	/* For nr_extents == -1, the
 						   vfs inode of the base mft
 						   record. */
 	};
-} ntfs_inode;
+};
+
+extern ntfs_inode *ntfs_new_inode(void);
+extern void ntfs_free_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);
+
+extern void ntfs_clear_inode(struct inode *ni);
 
 #endif /* _LINUX_NTFS_FS_INODE_H */

Index: mft.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/mft.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -U2 -r1.36 -r1.37
--- mft.c	2002/01/25 00:32:24	1.36
+++ mft.c	2002/01/28 07:01:17	1.37
@@ -80,14 +80,16 @@
  * We return 0 on success or -errno on error.
  */
+#if 0
+// Can't do this as iget_map_mft_record no longer exists...
 int format_mft_record2(struct super_block *vfs_sb, const unsigned long inum,
 		MFT_RECORD *mft_rec)
 {
 	MFT_RECORD *m;
-	struct inode *vfs_ino;
+	ntfs_inode *ni;
 
 	if (mft_rec)
 		m = mft_rec;
 	else {
-		m = iget_map_mft_record(WRITE, vfs_sb, inum, &vfs_ino);
+		m = iget_map_mft_record(WRITE, vfs_sb, inum, &ni);
 		if (IS_ERR(m))
 			return PTR_ERR(m);
@@ -95,13 +97,15 @@
 	__format_mft_record(m, NTFS_SB(vfs_sb)->mft_record_size, inum);
 	if (!mft_rec) {
-		unmap_mft_record(WRITE, vfs_ino);
-		iput(vfs_ino);
+		// TODO: dirty mft record
+		unmap_mft_record(WRITE, ni);
+		// TODO: Do stuff to get rid of the ntfs_inode
 	}
 	return 0;
 }
+#endif
 
 /**
  * format_mft_record - initialize an empty mft record
- * @vfs_ino:	vfs inode of mft record
+ * @ni:		ntfs inode of mft record
  * @mft_rec:	mapped, pinned and locked mft record (optional)
  *
@@ -113,5 +117,5 @@
  * We return 0 on success or -errno on error.
  */
-int format_mft_record(struct inode *vfs_ino, MFT_RECORD *mft_rec)
+int format_mft_record(ntfs_inode *ni, MFT_RECORD *mft_rec)
 {
 	MFT_RECORD *m;
@@ -120,12 +124,11 @@
 		m = mft_rec;
 	else {
-		m = map_mft_record(WRITE, vfs_ino);
+		m = map_mft_record(WRITE, ni);
 		if (IS_ERR(m))
 			return PTR_ERR(m);
 	}
-	__format_mft_record(m, NTFS_SB(vfs_ino->i_sb)->mft_record_size,
-			vfs_ino->i_ino);
+	__format_mft_record(m, ni->vol->mft_record_size, ni->mft_no);
 	if (!mft_rec)
-		unmap_mft_record(WRITE, vfs_ino);
+		unmap_mft_record(WRITE, ni);
 	return 0;
 }
@@ -148,4 +151,5 @@
 	//ntfs_debug("Executing.\n");
 	//printk(KERN_DEBUG "NTFS: " __FUNCTION__ "(): Executing.\n");
+
 	mark_buffer_uptodate(bh, uptodate);
 	/* This is a temporary buffer used for page I/O. */
@@ -182,12 +186,10 @@
 	if (!PageError(page)) {
 		char *addr;
-		ntfs_volume *vol;
 		unsigned int i, recs, nr_err = 0;
 		u32 rec_size;
 
-		vol = NTFS_SB(page->mapping->host->i_sb);
 		addr = kmap_atomic(page, KM_BIO_IRQ);
-		recs = PAGE_CACHE_SIZE / vol->mft_record_size;
-		rec_size = vol->mft_record_size;
+		rec_size = NTFS_SB(page->mapping->host->i_sb)->mft_record_size;
+		recs = PAGE_CACHE_SIZE / rec_size;
 		for (i = 0; i < recs; i++) {
 			if (!post_read_mst_fixup((NTFS_RECORD*)(addr +
@@ -219,6 +221,6 @@
 	VCN vcn;
 	LCN lcn;
-	struct inode *vfs_ino;
-	ntfs_inode *ntfs_ino;
+	struct inode *vi;
+	ntfs_inode *ni;
 	struct super_block *sb;
 	ntfs_volume *vol;
@@ -234,7 +236,7 @@
 		PAGE_BUG(page);
 	/* Get the VFS and ntfs inodes as well as the super blocks for page. */
-	vfs_ino = page->mapping->host;
-	ntfs_ino = NTFS_I(vfs_ino);
-	sb = vfs_ino->i_sb;
+	vi = page->mapping->host;
+	ni = NTFS_I(vi);
+	sb = vi->i_sb;
 	vol = NTFS_SB(sb);
 
@@ -245,5 +247,5 @@
 	blocks = PAGE_CACHE_SIZE >> blocksize_bits;
 	iblock = page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
-	lblock = (vfs_ino->i_size + blocksize - 1) >> blocksize_bits;
+	lblock = (vi->i_size + blocksize - 1) >> blocksize_bits;
 	ntfs_debug("blocks = 0x%x, iblock = 0x%lx, lblock = 0x%lx.\n", blocks,
 			iblock, lblock);
@@ -251,5 +253,5 @@
 	BUG_ON(!bh);
 #ifdef DEBUG
-	if (!ntfs_ino->run_list)
+	if (!ni->run_list)
 		panic("NTFS: $MFT/$DATA run list has been unmapped! This is a "
 				"very serious bug! Cannot continue...");
@@ -270,8 +272,8 @@
 					vol->cluster_size_mask;
 			/* Convert the vcn to the corresponding lcn. */
-			lcn = vcn_to_lcn(ntfs_ino->run_list, vcn);
+			lcn = vcn_to_lcn(ni->run_list, vcn);
 			if (lcn >= 0) {
 				/* Setup buffer head to correct block. */
-				bh->b_dev = vfs_ino->i_dev;
+				bh->b_dev = vi->i_dev;
 				bh->b_blocknr = ((lcn << vol->cluster_size_bits)
 						+ vcn_ofs) >> blocksize_bits;
@@ -289,5 +291,5 @@
 		 * the buffer uptodate.
 		 */
-		bh->b_dev = vfs_ino->i_dev;
+		bh->b_dev = vi->i_dev;
 		bh->b_blocknr = -1UL;
 		bh->b_state &= ~(1UL << BH_Mapped);
@@ -344,5 +346,5 @@
  * map_mft_record - map, pin and lock an mft record
  * @rw:		map for read (rw = READ) or write (rw = WRITE)
- * @vfs_ino:	vfs inode whose MFT record to map
+ * @ni:		ntfs inode whose MFT record to map
  *
  * First, take the mrec_lock semaphore for reading or writing, depending on
@@ -394,19 +396,16 @@
  * write it out.
  */
-MFT_RECORD *map_mft_record(const int rw, struct inode *vfs_ino)
+/*
+ * This maps the page in which the mft record is situated and nothing else.
+ */
+static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
 {
-	ntfs_inode *ntfs_ino = NTFS_I(vfs_ino);
-	ntfs_volume *vol = NTFS_SB(vfs_ino->i_sb);
-	struct inode *mft_ino = vol->mft_ino;
+	ntfs_volume *vol = ni->vol;
+	struct inode *mft_vi = vol->mft_ino;
 	struct page *page;
 	unsigned long index, ofs, end_index;
 
-	ntfs_debug("Entering for i_ino 0x%lx, mapping for %s.\n",
-			vfs_ino->i_ino, rw == READ ? "READ" : "WRITE");
-	/* Serialize access to this mft record. */
-	if (rw == READ)
-		down_read(&ntfs_ino->mrec_lock);
-	else
-		down_write(&ntfs_ino->mrec_lock);
+	ntfs_debug("Entering for i_ino 0x%Lx.\n", ni->mft_no);
+	BUG_ON(atomic_read(&ni->mft_count) || ni->page);
 	/*
 	 * The index into the page cache and the offset within the page cache
@@ -415,13 +414,11 @@
 	 * here if the volume was that big...
 	 */
-	index = (s64)vfs_ino->i_ino << vol->mft_record_size_bits >>
-			PAGE_CACHE_SHIFT;
-	ofs = ((s64)vfs_ino->i_ino << vol->mft_record_size_bits) &
-			~PAGE_CACHE_MASK;
+	index = ni->mft_no << vol->mft_record_size_bits >> PAGE_CACHE_SHIFT;
+	ofs = (ni->mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK;
 	/* The maximum valid index into the page cache for $MFT's data. */
-	end_index = mft_ino->i_size >> PAGE_CACHE_SHIFT;
+	end_index = mft_vi->i_size >> PAGE_CACHE_SHIFT;
 	/* If the wanted index is out of bounds the mft record doesn't exist. */
 	if (index >= end_index) {
-		if (index > end_index || (mft_ino->i_size & ~PAGE_CACHE_MASK) <
+		if (index > end_index || (mft_vi->i_size & ~PAGE_CACHE_MASK) <
 				ofs + vol->mft_record_size) {
 			page = ERR_PTR(-ENOENT);
@@ -430,17 +427,69 @@
 	}
 	/* Read, map, and pin the page. */
-	page = ntfs_map_page(mft_ino->i_mapping, index);
+	page = ntfs_map_page(mft_vi->i_mapping, index);
 	if (!IS_ERR(page)) {
-		ntfs_ino->page = page;
+		atomic_inc(&ni->mft_count);
+		/* Setup the references in the ntfs_inode. */
+		ni->page = page;
+		ni->page_ofs = ofs;
 		ntfs_debug("Done.");
 		return page_address(page) + ofs;
 	}
 up_err_out:
+	/* Just in case... */
+	ni->page = NULL;
+	ni->page_ofs = 0;
+	ntfs_debug("Failed.");
+	return (void*)page;
+}
+
+static inline void unmap_mft_record_page(ntfs_inode *ni)
+{
+	BUG_ON(atomic_read(&ni->mft_count) || !ni->page);
+	// TODO: If dirty, blah...
+	ntfs_unmap_page(ni->page);
+	ni->page = NULL;
+	ni->page_ofs = 0;
+	return;
+}
+
+/*
+ * This downs the semaphore, bumps the map reference count and returns the mft
+ * record. If this is the first invocation, the record's page is first
+ * mapped.
+ */
+MFT_RECORD *map_mft_record(const int rw, ntfs_inode *ni)
+{
+	MFT_RECORD *m;
+
+	ntfs_debug("Entering for i_ino 0x%Lx, mapping for %s.\n",
+			ni->mft_no, rw == READ ? "READ" : "WRITE");
+	/* Make sure the ntfs inode doesn't go away. */
+	atomic_inc(&ni->count);
+	/* Serialize access to this mft record. */
+	if (rw == READ)
+		down_read(&ni->mrec_lock);
+	else
+		down_write(&ni->mrec_lock);
+	/* If already mapped just bump reference count and return it. */
+	if (atomic_read(&ni->mft_count)) {
+		BUG_ON(!ni->page);
+		atomic_inc(&ni->mft_count);
+		ntfs_debug("Done.");
+		return page_address(ni->page) + ni->page_ofs;
+	}
+	m = map_mft_record_page(ni);
+	if (!IS_ERR(m)) {
+		ntfs_debug("Done.");
+		return m;
+	}
 	/* Release the mft record lock and return the error code. */
 	if (rw == READ)
-		up_read(&ntfs_ino->mrec_lock);
+		up_read(&ni->mrec_lock);
 	else
-		up_write(&ntfs_ino->mrec_lock);
-	return (void*)page;
+		up_write(&ni->mrec_lock);
+	atomic_dec(&ni->count);
+	ntfs_debug("Failed.");
+	return m;
 }
 
@@ -466,4 +515,20 @@
  * that is omitted you will get busy inodes upon umount...
  */
+#if 0
+// this is no longer possible. iget() cannot be called as we may be loading
+// an ntfs inode which will never have a corresponding vfs inode counter part.
+// this is not going to be pretty. )-:
+// we need our own hash for ntfs inodes now, ugh. )-:
+// not having vfs inodes associated with all ntfs inodes is a bad mistake I am
+// getting the impression. this will in the end turn out uglier than just
+// having iget_no_wait().
+// my only hope is that we can get away without this functionality in the driver
+// altogether. we are ok for extent inodes already because we only handle them
+// via map_extent_mft_record().
+// if we really need it, we could have a list or hash of "pure ntfs inodes"
+// to cope with this situation, so the lookup would be:
+// look for the inode and if not present look for pure ntfs inode and if not
+// present add a new pure ntfs inode. under this scheme extent inodes have to
+// also be added to the list/hash of pure inodes.
 MFT_RECORD *iget_map_mft_record(const int rw, struct super_block *vfs_sb,
 		const unsigned long inum, struct inode **vfs_ino)
@@ -492,9 +557,10 @@
 	return mrec;
 }
+#endif
 
 /**
- * unmap_mft_record - release a mapped mft record after
+ * unmap_mft_record - release a mapped mft record
  * @rw:		unmap from read (@rw = READ) or write (@rw = WRITE)
- * @vfs_ino:	vfs inode whose MFT record to unmap
+ * @ni:		ntfs inode whose MFT record to unmap
  *
  * First, unmap the page (this is a NOP if highmem is not configured) and
@@ -511,17 +577,167 @@
  * NOTE: If caller had the mft record mapped for write and has modified it, it
  * is imperative to set the mft record dirty BEFORE calling unmap_mft_record().
+ *
+ * NOTE: This has to be done both for 'normal' mft records, and for extent mft
+ * records.
  */
-void unmap_mft_record(const int rw, struct inode *vfs_ino)
+void unmap_mft_record(const int rw, ntfs_inode *ni)
 {
-	ntfs_inode *ntfs_ino = NTFS_I(vfs_ino);
-	struct page *page = ntfs_ino->page;
+	struct page *page = ni->page;
+
+	BUG_ON(!atomic_read(&ni->mft_count) || !page);
 
-	ntfs_debug("Entering for i_ino 0x%lx, unmapping from %s.\n",
-			vfs_ino->i_ino, rw == READ ? "READ" : "WRITE");
-	ntfs_unmap_page(page);
+	ntfs_debug("Entering for mft_no 0x%Lx, unmapping from %s.\n",
+			ni->mft_no, rw == READ ? "READ" : "WRITE");
+	/* Only destroy the actual page mapping if this is the last one. */
+	if (atomic_dec_and_test(&ni->mft_count))
+		unmap_mft_record_page(ni);
 	if (rw == READ)
-		up_read(&ntfs_ino->mrec_lock);
+		up_read(&ni->mrec_lock);
 	else
-		up_write(&ntfs_ino->mrec_lock);
+		up_write(&ni->mrec_lock);
+	atomic_dec(&ni->count);
+	// FIXME: 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.
+	return;
+}
+
+/**
+ * map_extent_mft_record - load an extent inode and attach it to its base
+ * @base_ni:	base ntfs inode
+ * @mref:	mft reference of the extent inode to load (in little endian)
+ * @ntfs_ino:	on successful return, pointer to the ntfs_inode structure
+ *
+ * Load the extent mft record @mref and attach it to its base inode @base_ni.
+ * Return the mapped extent mft record if IS_ERR(result) is false. Otherwise
+ * PTR_ERR(result) gives the negative error code.
+ *
+ * On successful return, @ntfs_ino contains a pointer to the ntfs_inode
+ * structure of the mapped extent inode.
+ *
+ * Note, we always map for READ. We consider this lock as irrelevant because
+ * the base inode will be write locked in all cases when we want to write to
+ * an extent inode which already gurantees that there is no-one else accessing
+ * the extent inode.
+ */
+MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
+		ntfs_inode **ntfs_ino)
+{
+	MFT_RECORD *m;
+	ntfs_inode *ni = NULL;
+	ntfs_inode **extent_nis = NULL;
+	int i;
+	u64 mft_no = MREF_LE(mref);
+	u16 seq_no = MSEQNO_LE(mref);
+	BOOL destroy_ni = FALSE;
+
+	ntfs_debug("Mapping extent mft record 0x%Lx (base mft record 0x%Lx).\n",
+			mft_no, base_ni->mft_no);
+	/* Make sure the base ntfs inode doesn't go away. */
+	atomic_inc(&base_ni->count);
+	/*
+	 * Check if this extent inode has already been added to the base inode,
+	 * in which case just return it. If not found, add it to the base
+	 * inode before returning it.
+	 */
+	down(&base_ni->extent_lock);
+	if (base_ni->nr_extents > 0) {
+		extent_nis = base_ni->extent_ntfs_inos;
+		for (i = 0; i < base_ni->nr_extents; i++) {
+			if (mft_no != extent_nis[i]->mft_no)
+				continue;
+			ni = extent_nis[i];
+			/* Make sure the ntfs inode doesn't go away. */
+			atomic_inc(&ni->count);
+			break;
+		}
+	}
+	if (ni) {
+		up(&base_ni->extent_lock);
+		atomic_dec(&base_ni->count);
+		/* We found the record; just have to map and return it. */
+		m = map_mft_record(READ, ni);
+		/* Map mft record increments this on success. */
+		atomic_dec(&ni->count);
+		if (!IS_ERR(m)) {
+			/* Verify the sequence number. */
+			if (le16_to_cpu(m->sequence_number) == seq_no) {
+				ntfs_debug("Done 1.\n");
+				*ntfs_ino = ni;
+				return m;
+			}
+			unmap_mft_record(READ, ni);
+			ntfs_error(base_ni->vol->sb, "Found stale extent mft "
+					"reference! Corrupt file system. "
+					"Run chkdsk.");
+			return ERR_PTR(-EIO);
+		}
+map_err_out:
+		ntfs_error(base_ni->vol->sb, "Failed to map extent "
+				"mft record, error code %i.", -PTR_ERR(m));
+		return m;
+	}
+	/* Record wasn't there. Get a new ntfs inode and initialize it. */
+	ni = ntfs_new_inode();
+	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->base_ntfs_ino = base_ni;
+	/* Now load it. */
+	m = map_mft_record(READ, ni);
+	if (IS_ERR(m)) {
+		up(&base_ni->extent_lock);
+		atomic_dec(&base_ni->count);
+		goto map_err_out;
+	}
+	/* Verify the sequence number. */
+	if (le16_to_cpu(m->sequence_number) != seq_no) {
+		ntfs_error(base_ni->vol->sb, "Found stale extent mft "
+				"reference! Corrupt file system. Run chkdsk.");
+		destroy_ni = TRUE;
+		m = ERR_PTR(-EIO);
+		goto unm_err_out;
+	}
+	/* Attach extent inode to base inode, reallocating memory if needed. */
+	if (!(base_ni->nr_extents & ~3)) {
+		ntfs_inode **tmp;
+		int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
+		tmp = (ntfs_inode **)kmalloc(new_size, GFP_NOFS);
+		if (!tmp) {
+			ntfs_error(base_ni->vol->sb, "Failed to allocate "
+					"internal buffer.");
+			destroy_ni = TRUE;
+			m = ERR_PTR(-ENOMEM);
+			goto unm_err_out;
+		}
+		if (base_ni->extent_ntfs_inos) {
+			memcpy(tmp, base_ni->extent_ntfs_inos, new_size - 4);
+			kfree(base_ni->extent_ntfs_inos);
+		}
+		base_ni->extent_ntfs_inos = tmp;
+	}
+	base_ni->extent_ntfs_inos[base_ni->nr_extents++] = ni;
+	up(&base_ni->extent_lock);
+	atomic_dec(&base_ni->count);
+	ntfs_debug("Done 2.");
+	*ntfs_ino = ni;
+	return m;
+unm_err_out:
+	unmap_mft_record(READ, ni);
+	up(&base_ni->extent_lock);
+	atomic_dec(&base_ni->count);
+	/*
+	 * If the extent inode is not attached to the base inode we need to
+	 * terminate it with extreme prejudice or we will leak memory.
+	 */
+	if (destroy_ni)
+		ntfs_free_inode(ni);
+	return m;
 }
 

Index: namei.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/namei.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -U2 -r1.14 -r1.15
--- namei.c	2001/12/12 21:41:14	1.14
+++ namei.c	2002/01/28 07:01:17	1.15
@@ -62,5 +62,5 @@
 		return ERR_PTR(uname_len);
 	}
-	mref = ntfs_lookup_ino_by_name(dir_ino, uname, uname_len);
+	mref = ntfs_lookup_inode_by_name(NTFS_I(dir_ino), uname, uname_len);
 	kmem_cache_free(ntfs_name_cache, uname);
 	if (!IS_ERR_MREF(mref)) {

Index: ntfs.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/ntfs.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -U2 -r1.20 -r1.21
--- ntfs.h	2002/01/25 00:32:24	1.20
+++ ntfs.h	2002/01/28 07:01:17	1.21
@@ -37,12 +37,14 @@
 #include <linux/pagemap.h>
 #include <linux/smp.h>
+#include <asm/atomic.h>
 #include "debug.h"
 #include "malloc.h"
 #include "endian.h"
 #include "types.h"
-#include "inode.h"
 #include "volume.h"
+#include "inode.h"
 #include "layout.h"
 #include "attrib.h"
+#include "mft.h"
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -206,5 +208,5 @@
 
 /* From fs/ntfs/aops.c */
-extern int ntfs_file_get_block(struct inode *vfs_ino, const sector_t blk,
+extern int ntfs_file_get_block(struct inode *vi, const sector_t blk,
 		struct buffer_head *bh, const int create);
 
@@ -233,28 +235,13 @@
 extern inline time_t ntfs2utc(const s64 time);
 
-/* From fs/ntfs/inode.c */
-extern void ntfs_read_inode(struct inode *vfs_ino);
-extern void ntfs_read_inode_mount(struct inode *vfs_ino);
-extern void ntfs_dirty_inode(struct inode *vfs_ino);
-extern void ntfs_clear_inode(struct inode *vfs_ino);
-
 /* From fs/ntfs/dir.c */
-extern u64 ntfs_lookup_ino_by_name(struct inode *dir_ino, const uchar_t *uname,
+extern u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
 		const int uname_len);
 
-/* From fs/ntfs/mft.c */
-extern int format_mft_record(struct inode *vfs_ino, MFT_RECORD *m);
-extern int format_mft_record2(struct super_block *vfs_sb,
-		const unsigned long inum, MFT_RECORD *m);
-extern MFT_RECORD *map_mft_record(const int rw, struct inode *vfs_ino);
-extern MFT_RECORD *iget_map_mft_record(const int rw, struct super_block *vfs_sb,
-		const unsigned long inum, struct inode **vfs_ino);
-extern void unmap_mft_record(const int rw, struct inode *vfs_ino);
-
 /* From fs/ntfs/unistr.c */
 extern BOOL ntfs_are_names_equal(const uchar_t *s1, size_t s1_len,
-		     const uchar_t *s2, size_t s2_len,
-		     const IGNORE_CASE_BOOL ic,
-		     const uchar_t *upcase, const u32 upcase_size);
+		const uchar_t *s2, size_t s2_len,
+		const IGNORE_CASE_BOOL ic,
+		const uchar_t *upcase, const u32 upcase_size);
 extern int ntfs_collate_names(const uchar_t *name1, const u32 name1_len,
 		const uchar_t *name2, const u32 name2_len,
@@ -263,5 +250,5 @@
 extern int ntfs_ucsncmp(const uchar_t *s1, const uchar_t *s2, size_t n);
 extern int ntfs_ucsncasecmp(const uchar_t *s1, const uchar_t *s2, size_t n,
-		     const uchar_t *upcase, const u32 upcase_size);
+		const uchar_t *upcase, const u32 upcase_size);
 extern void ntfs_upcase_name(uchar_t *name, u32 name_len,
 		const uchar_t *upcase, const u32 upcase_len);

Index: super.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/super.c,v
retrieving revision 1.64
retrieving revision 1.65
diff -U2 -r1.64 -r1.65
--- super.c	2002/01/25 00:32:24	1.64
+++ super.c	2002/01/28 07:01:17	1.65
@@ -121,5 +121,5 @@
 		else NTFS_GETOPT_OPTIONS_ARRAY("errors", on_errors,
 				on_errors_arr)
-		else if (!strcmp(p, "nls")) {
+		else if (!strcmp(p, "nls") || !strcmp(p, "iocharset")) {
 			struct nls_table *old_nls;
 			if (!v || !*v)
@@ -753,10 +753,10 @@
 	 * the $MFT/$BITMAP attribute.
 	 */
-	m = map_mft_record(READ, vol->mft_ino);
+	m = map_mft_record(READ, NTFS_I(vol->mft_ino));
 	if (IS_ERR(m)) {
 		ntfs_error(sb, "Failed to map $MFT.");
 		return FALSE;
 	}
-	if (get_attr_search_ctx(&ctx, vol->mft_ino, m)) {
+	if (get_attr_search_ctx(&ctx, NTFS_I(vol->mft_ino), m)) {
 		ntfs_error(sb, "Failed to get attribute search context.");
 		goto unmap_err_out;
@@ -768,5 +768,5 @@
 		put_attr_search_ctx(ctx);
 unmap_err_out:
-		unmap_mft_record(READ, vol->mft_ino);
+		unmap_mft_record(READ, NTFS_I(vol->mft_ino));
 		return FALSE;
 	}
@@ -797,5 +797,5 @@
 	rl = decompress_mapping_pairs(vol, ctx->attr, NULL);
 	put_attr_search_ctx(ctx);
-	unmap_mft_record(READ, vol->mft_ino);
+	unmap_mft_record(READ, NTFS_I(vol->mft_ino));
 	if (IS_ERR(rl)) {
 		ntfs_error(sb, "decompress_mapping_pairs() failed with error "
@@ -856,5 +856,5 @@
 		goto iput_bmp_mirr_err_out;
 	}
-	m = map_mft_record(READ, vol->vol_ino);
+	m = map_mft_record(READ, NTFS_I(vol->vol_ino));
 	if (IS_ERR(m)) {
 iput_volume_failed:
@@ -862,5 +862,5 @@
 		goto volume_failed;
 	}
-	if (get_attr_search_ctx(&ctx, vol->vol_ino, m)) {
+	if (get_attr_search_ctx(&ctx, NTFS_I(vol->vol_ino), m)) {
 		ntfs_error(sb, "Failed to get attribute search context.");
 		goto get_ctx_vol_failed;
@@ -870,5 +870,5 @@
 		put_attr_search_ctx(ctx);
 get_ctx_vol_failed:
-		unmap_mft_record(READ, vol->vol_ino);
+		unmap_mft_record(READ, NTFS_I(vol->vol_ino));
 		goto iput_volume_failed;
 	}
@@ -881,5 +881,5 @@
 	vol->minor_ver = vi->minor_ver;
 	put_attr_search_ctx(ctx);
-	unmap_mft_record(READ, vol->vol_ino);
+	unmap_mft_record(READ, NTFS_I(vol->vol_ino));
 	printk(KERN_INFO "NTFS volume version %i.%i.\n", vol->major_ver,
 			vol->minor_ver);
@@ -1254,5 +1254,5 @@
 	 * Total data blocks in file system in units of f_bsize and since
 	 * inodes are also stored in data blocs ($MFT is a file) this is just
-	 * the total cluster.
+	 * the total clusters.
 	 */
 	sfs->f_blocks = vol->nr_clusters << vol->cluster_size_bits >>

Index: types.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/types.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -U2 -r1.1 -r1.2
--- types.h	2001/11/30 00:36:40	1.1
+++ types.h	2002/01/28 07:01:17	1.2
@@ -24,4 +24,31 @@
 #define _LINUX_NTFS_TYPES_H
 
+/* 2-byte Unicode character type. */
+typedef u16 uchar_t;
+
+/*
+ * Clusters are signed 64-bit values on NTFS volumes. We define two types, LCN
+ * and VCN, to allow for type checking and better code readability.
+ */
+typedef s64 VCN;
+typedef s64 LCN;
+
+/**
+ * run_list - in memory vcn to lcn mapping array
+ * @vcn:	starting vcn of the current array element
+ * @lcn:	starting lcn of the current array element
+ * @length:	length in clusters of the current array element
+ * 
+ * The last vcn (in fact the last vcn + 1) is reached when length == 0.
+ * 
+ * When lcn == -1 this means that the count vcns starting at vcn are not 
+ * physically allocated (i.e. this is a hole / data is sparse).
+ */
+typedef struct {	/* In memory vcn to lcn mapping structure element. */
+	VCN vcn;	/* vcn = Starting virtual cluster number. */
+	LCN lcn;	/* lcn = Starting logical cluster number. */
+	s64 length;	/* Run length in clusters. */
+} run_list;
+
 typedef enum {
 	FALSE = 0,

Index: volume.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/volume.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -U2 -r1.3 -r1.4
--- volume.h	2001/12/16 19:04:36	1.3
+++ volume.h	2002/01/28 07:01:17	1.4
@@ -24,6 +24,5 @@
 #define _LINUX_NTFS_VOLUME_H
 
-/* 2-byte Unicode character type. */
-typedef u16 uchar_t;
+#include "types.h"
 
 /*


_______________________________________________
Linux-NTFS-cvs mailing list
Linux-NTFS-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-ntfs-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic