if ((prev_ia_pos & PAGE_CACHE_MASK) != (ia_pos & PAGE_CACHE_MASK)) { 
if ((prev_ia_pos & (s64)PAGE_CACHE_MASK) != (ia_pos & (s64)PAGE_CACHE_MASK)) { 
static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir){	s64 ia_pos, ia_start, prev_ia_pos, bmp_pos;	loff_t fpos, i_size;	struct inode *bmp_vi, *vdir = filp->f_dentry->d_inode;	struct super_block *sb = vdir->i_sb;	ntfs_inode *ndir = NTFS_I(vdir);	ntfs_volume *vol = NTFS_SB(sb);	MFT_RECORD *m;	INDEX_ROOT *ir = NULL;	INDEX_ENTRY *ie;	INDEX_ALLOCATION *ia;	u8 *name = NULL;	int rc, err, ir_pos, cur_bmp_pos;	struct address_space *ia_mapping, *bmp_mapping;	struct page *bmp_page = NULL, *ia_page = NULL;	u8 *kaddr, *bmp, *index_end;	ntfs_attr_search_ctx *ctx;	fpos = filp->f_pos;	ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.",			vdir->i_ino, fpos);	rc = err = 0;	/* Are we at end of dir yet? */	i_size = i_size_read(vdir);	if (fpos >= i_size + vol->mft_record_size)		goto done;	/* Emulate . and .. for all directories. */	if (!fpos) {		ntfs_debug("Calling filldir for . with len 1, fpos 0x0, "				"inode 0x%lx, DT_DIR.", vdir->i_ino);		rc = filldir(dirent, ".", 1, fpos, vdir->i_ino, DT_DIR);		if (rc)			goto done;		fpos++;	}	if (fpos == 1) {		ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, "				"inode 0x%lx, DT_DIR.",				parent_ino(filp->f_dentry));		rc = filldir(dirent, "..", 2, fpos,				parent_ino(filp->f_dentry), DT_DIR);		if (rc)			goto done;		fpos++;	}	m = NULL;	ctx = NULL;	/*	 * Allocate a buffer to store the current name being processed	 * converted to format determined by current NLS.	 */	name = (u8*)kmalloc(NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1,			GFP_NOFS);	if (unlikely(!name)) {		err = -ENOMEM;		goto err_out;	}	/* Are we jumping straight into the index allocation attribute? */	if (fpos >= vol->mft_record_size)		goto skip_index_root;	/* Get hold of the mft record for the directory. */	m = map_mft_record(ndir);	if (IS_ERR(m)) {		err = PTR_ERR(m);		m = NULL;		goto err_out;	}	ctx = ntfs_attr_get_search_ctx(ndir, m);	if (unlikely(!ctx)) {		err = -ENOMEM;		goto err_out;	}	/* Get the offset into the index root attribute. */	ir_pos = (s64)fpos;	/* Find the index root attribute in the mft record. */	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,			0, ctx);	if (unlikely(err)) {		ntfs_error(sb, "Index root attribute missing in directory "				"inode 0x%lx.", vdir->i_ino);		goto err_out;	}	/*	 * Copy the index root attribute value to a buffer so that we can put	 * the search context and unmap the mft record before calling the	 * filldir() callback.  We need to do this because of NFSd which calls	 * ->lookup() from its filldir callback() and this causes NTFS to	 * deadlock as ntfs_lookup() maps the mft record of the directory and	 * we have got it mapped here already.  The only solution is for us to	 * unmap the mft record here so that a call to ntfs_lookup() is able to	 * map the mft record without deadlocking.	 */	rc = le32_to_cpu(ctx->attr->data.resident.value_length);	ir = (INDEX_ROOT*)kmalloc(rc, GFP_NOFS);	if (unlikely(!ir)) {		err = -ENOMEM;		goto err_out;	}	/* Copy the index root value (it has been verified in read_inode). */	memcpy(ir, (u8*)ctx->attr +			le16_to_cpu(ctx->attr->data.resident.value_offset), rc);	ntfs_attr_put_search_ctx(ctx);	unmap_mft_record(ndir);	ctx = NULL;	m = NULL;	index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);	/* The first index entry. */	ie = (INDEX_ENTRY*)((u8*)&ir->index +			le32_to_cpu(ir->index.entries_offset));	/*	 * Loop until we exceed valid memory (corruption case) or until we	 * reach the last entry or until filldir tells us it has had enough	 * or signals an error (both covered by the rc test).	 */	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {		ntfs_debug("In index root, offset 0x%zx.", (u8*)ie - (u8*)ir);		/* Bounds checks. */		if (unlikely((u8*)ie < (u8*)ir || (u8*)ie +				sizeof(INDEX_ENTRY_HEADER) > index_end ||				(u8*)ie + le16_to_cpu(ie->key_length) >				index_end))			goto err_out;		/* The last entry cannot contain a name. */		if (ie->flags & INDEX_ENTRY_END)			break;		/* Skip index root entry if continuing previous readdir. */		if (ir_pos > (u8*)ie - (u8*)ir)			continue;		/* Advance the position even if going to skip the entry. */		fpos = (u8*)ie - (u8*)ir;		/* Submit the name to the filldir callback. */		rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent,				filldir);		if (rc) {			kfree(ir);			goto abort;		}	}	/* We are done with the index root and can free the buffer. */	kfree(ir);	ir = NULL;	/* If there is no index allocation attribute we are finished. */	if (!NInoIndexAllocPresent(ndir))		goto EOD;	/* Advance fpos to the beginning of the index allocation. */	fpos = vol->mft_record_size;skip_index_root:	kaddr = NULL;	prev_ia_pos = -1LL;	/* Get the offset into the index allocation attribute. */	ia_pos = (s64)fpos - vol->mft_record_size;	ia_mapping = vdir->i_mapping;	bmp_vi = ndir->itype.index.bmp_ino;	if (unlikely(!bmp_vi)) {		ntfs_debug("Inode 0x%lx, regetting index bitmap.", vdir->i_ino);		bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);		if (IS_ERR(bmp_vi)) {			ntfs_error(sb, "Failed to get bitmap attribute.");			err = PTR_ERR(bmp_vi);			goto err_out;		}		ndir->itype.index.bmp_ino = bmp_vi;	}	bmp_mapping = bmp_vi->i_mapping;	/* Get the starting bitmap bit position and sanity check it. */	bmp_pos = ia_pos >> ndir->itype.index.block_size_bits;	if (unlikely(bmp_pos >> 3 >= i_size_read(bmp_vi))) {		ntfs_error(sb, "Current index allocation position exceeds "				"index bitmap size.");		goto err_out;	}	/* Get the starting bit position in the current bitmap page. */	cur_bmp_pos = bmp_pos & ((PAGE_CACHE_SIZE * 8) - 1);	bmp_pos &= ~(u64)((PAGE_CACHE_SIZE * 8) - 1);get_next_bmp_page:	ntfs_debug("Reading bitmap with page index 0x%llx, bit ofs 0x%llx",			(unsigned long long)bmp_pos >> (3 + PAGE_CACHE_SHIFT),			(unsigned long long)bmp_pos &			(unsigned long long)((PAGE_CACHE_SIZE * 8) - 1));	bmp_page = ntfs_map_page(bmp_mapping,			bmp_pos >> (3 + PAGE_CACHE_SHIFT));	if (IS_ERR(bmp_page)) {		ntfs_error(sb, "Reading index bitmap failed.");		err = PTR_ERR(bmp_page);		bmp_page = NULL;		goto err_out;	}	bmp = (u8*)page_address(bmp_page);	/* Find next index block in use. */	while (!(bmp[cur_bmp_pos >> 3] & (1 << (cur_bmp_pos & 7)))) {find_next_index_buffer:		cur_bmp_pos++;		/*		 * If we have reached the end of the bitmap page, get the next		 * page, and put away the old one.		 */		if (unlikely((cur_bmp_pos >> 3) >= PAGE_CACHE_SIZE)) {			ntfs_unmap_page(bmp_page);			bmp_pos += PAGE_CACHE_SIZE * 8;			cur_bmp_pos = 0;			goto get_next_bmp_page;		}		/* If we have reached the end of the bitmap, we are done. */		if (unlikely(((bmp_pos + cur_bmp_pos) >> 3) >= i_size))			goto unm_EOD;		ia_pos = (bmp_pos + cur_bmp_pos) <<				ndir->itype.index.block_size_bits;	}	ntfs_debug("Handling index buffer 0x%llx.",			(unsigned long long)bmp_pos + cur_bmp_pos);	/* If the current index buffer is in the same page we reuse the page. */	if ((prev_ia_pos & PAGE_CACHE_MASK) != (ia_pos & PAGE_CACHE_MASK)) {		prev_ia_pos = ia_pos;		if (likely(ia_page != NULL)) {			unlock_page(ia_page);			ntfs_unmap_page(ia_page);		}		/*		 * Map the page cache page containing the current ia_pos,		 * reading it from disk if necessary.		 */		ia_page = ntfs_map_page(ia_mapping, ia_pos >> PAGE_CACHE_SHIFT);		if (IS_ERR(ia_page)) {			ntfs_error(sb, "Reading index allocation data failed.");			err = PTR_ERR(ia_page);			ia_page = NULL;			goto err_out;		}		lock_page(ia_page);		kaddr = (u8*)page_address(ia_page);	}	/* Get the current index buffer. */	ia = (INDEX_ALLOCATION*)(kaddr + (ia_pos & ~PAGE_CACHE_MASK &			~(s64)(ndir->itype.index.block_size - 1)));	/* Bounds checks. */	if (unlikely((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE)) {		ntfs_error(sb, "Out of bounds check failed. Corrupt directory "				"inode 0x%lx or driver bug.", vdir->i_ino);		goto err_out;	}	/* Catch multi sector transfer fixup errors. */	if (unlikely(!ntfs_is_indx_record(ia->magic))) {		ntfs_error(sb, "Directory index record with vcn 0x%llx is "				"corrupt.  Corrupt inode 0x%lx.  Run chkdsk.",				(unsigned long long)ia_pos >>				ndir->itype.index.vcn_size_bits, vdir->i_ino);		goto err_out;	}	if (unlikely(sle64_to_cpu(ia->index_block_vcn) != (ia_pos &			~(s64)(ndir->itype.index.block_size - 1)) >>			ndir->itype.index.vcn_size_bits)) {		ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is "				"different from expected VCN (0x%llx). "				"Directory inode 0x%lx is corrupt or driver "				"bug. ", (unsigned long long)				sle64_to_cpu(ia->index_block_vcn),				(unsigned long long)ia_pos >>				ndir->itype.index.vcn_size_bits, vdir->i_ino);		goto err_out;	}	if (unlikely(le32_to_cpu(ia->index.allocated_size) + 0x18 !=			ndir->itype.index.block_size)) {		ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode "				"0x%lx has a size (%u) differing from the "				"directory specified size (%u). Directory "				"inode is corrupt or driver bug.",				(unsigned long long)ia_pos >>				ndir->itype.index.vcn_size_bits, vdir->i_ino,				le32_to_cpu(ia->index.allocated_size) + 0x18,				ndir->itype.index.block_size);		goto err_out;	}	index_end = (u8*)ia + ndir->itype.index.block_size;	if (unlikely(index_end > kaddr + PAGE_CACHE_SIZE)) {		ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode "				"0x%lx crosses page boundary. Impossible! "				"Cannot access! This is probably a bug in the "				"driver.", (unsigned long long)ia_pos >>				ndir->itype.index.vcn_size_bits, vdir->i_ino);		goto err_out;	}	ia_start = ia_pos & ~(s64)(ndir->itype.index.block_size - 1);	index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);	if (unlikely(index_end > (u8*)ia + ndir->itype.index.block_size)) {		ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory "				"inode 0x%lx exceeds maximum size.",				(unsigned long long)ia_pos >>				ndir->itype.index.vcn_size_bits, vdir->i_ino);		goto err_out;	}	/* The first index entry in this index buffer. */	ie = (INDEX_ENTRY*)((u8*)&ia->index +			le32_to_cpu(ia->index.entries_offset));	/*	 * Loop until we exceed valid memory (corruption case) or until we	 * reach the last entry or until filldir tells us it has had enough	 * or signals an error (both covered by the rc test).	 */	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {		ntfs_debug("In index allocation, offset 0x%llx.",				(unsigned long long)ia_start +				(unsigned long long)((u8*)ie - (u8*)ia));		/* Bounds checks. */		if (unlikely((u8*)ie < (u8*)ia || (u8*)ie +				sizeof(INDEX_ENTRY_HEADER) > index_end ||				(u8*)ie + le16_to_cpu(ie->key_length) >				index_end))			goto err_out;		/* The last entry cannot contain a name. */		if (ie->flags & INDEX_ENTRY_END)			break;		/* Skip index block entry if continuing previous readdir. */		if (ia_pos - ia_start > (u8*)ie - (u8*)ia)			continue;		/* Advance the position even if going to skip the entry. */		fpos = (u8*)ie - (u8*)ia +				(sle64_to_cpu(ia->index_block_vcn) <<				ndir->itype.index.vcn_size_bits) +				vol->mft_record_size;		/*		 * Submit the name to the @filldir callback.  Note,		 * ntfs_filldir() drops the lock on @ia_page but it retakes it		 * before returning, unless a non-zero value is returned in		 * which case the page is left unlocked.		 */		rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent,				filldir);		if (rc) {			/* @ia_page is already unlocked in this case. */			ntfs_unmap_page(ia_page);			ntfs_unmap_page(bmp_page);			goto abort;		}	}	goto find_next_index_buffer;unm_EOD:	if (ia_page) {		unlock_page(ia_page);		ntfs_unmap_page(ia_page);	}	ntfs_unmap_page(bmp_page);EOD:	/* We are finished, set fpos to EOD. */	fpos = i_size + vol->mft_record_size;abort:	kfree(name);done:#ifdef DEBUG	if (!rc)		ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos);	else		ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.",				rc, fpos);#endif	filp->f_pos = fpos;	return 0;err_out:	if (bmp_page)		ntfs_unmap_page(bmp_page);	if (ia_page) {		unlock_page(ia_page);		ntfs_unmap_page(ia_page);	}	kfree(ir);	kfree(name);	if (ctx)		ntfs_attr_put_search_ctx(ctx);	if (m)		unmap_mft_record(ndir);	if (!err)		err = -EIO;	ntfs_debug("Failed. Returning error code %i.", -err);	filp->f_pos = fpos;	return err;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/3bd1f4a173a3445f9919c21e775de2d8b9deacf8/dir.c/clean/fs/ntfs/dir.c