[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