diff options
Diffstat (limited to 'fs/ntfs/attrib.c')
| -rw-r--r-- | fs/ntfs/attrib.c | 41 | 
1 files changed, 25 insertions, 16 deletions
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 3b9de404021..41859343a0c 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1376,19 +1376,6 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)  	err = ntfs_attr_record_resize(m, a, arec_size);  	if (unlikely(err))  		goto err_out; -	/* Setup the in-memory attribute structure to be non-resident. */ -	NInoSetNonResident(ni); -	ni->runlist.rl = rl; -	write_lock_irqsave(&ni->size_lock, flags); -	ni->allocated_size = new_size; -	write_unlock_irqrestore(&ni->size_lock, flags); -	/* -	 * FIXME: For now just clear all of these as we do not support them -	 * when writing. -	 */ -	NInoClearCompressed(ni); -	NInoClearSparse(ni); -	NInoClearEncrypted(ni);  	/*  	 * Convert the resident part of the attribute record to describe a  	 * non-resident attribute. @@ -1399,7 +1386,10 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)  		memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),  				a->name_length * sizeof(ntfschar));  	a->name_offset = cpu_to_le16(name_ofs); -	/* Update the flags to match the in-memory ones. */ +	/* +	 * FIXME: For now just clear all of these as we do not support them +	 * when writing. +	 */  	a->flags &= cpu_to_le16(0xffff & ~le16_to_cpu(ATTR_IS_SPARSE |  			ATTR_IS_ENCRYPTED | ATTR_COMPRESSION_MASK));  	/* Setup the fields specific to non-resident attributes. */ @@ -1422,6 +1412,25 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)  				err);  		goto undo_err_out;  	} +	/* Setup the in-memory attribute structure to be non-resident. */ +	/* +	 * FIXME: For now just clear all of these as we do not support them +	 * when writing. +	 */ +	NInoClearSparse(ni); +	NInoClearEncrypted(ni); +	NInoClearCompressed(ni); +	ni->runlist.rl = rl; +	write_lock_irqsave(&ni->size_lock, flags); +	ni->allocated_size = new_size; +	write_unlock_irqrestore(&ni->size_lock, flags); +	/* +	 * This needs to be last since the address space operations ->readpage +	 * and ->writepage can run concurrently with us as they are not +	 * serialized on i_sem.  Note, we are not allowed to fail once we flip +	 * this switch, which is another reason to do this last. +	 */ +	NInoSetNonResident(ni);  	/* Mark the mft record dirty, so it gets written back. */  	flush_dcache_mft_record_page(ctx->ntfs_ino);  	mark_mft_record_dirty(ctx->ntfs_ino); @@ -1431,6 +1440,7 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)  	if (page) {  		set_page_dirty(page);  		unlock_page(page); +		mark_page_accessed(page);  		page_cache_release(page);  	}  	ntfs_debug("Done."); @@ -1492,11 +1502,10 @@ undo_err_out:  		memcpy((u8*)a + mp_ofs, kaddr, attr_size);  		kunmap_atomic(kaddr, KM_USER0);  	} -	/* Finally setup the ntfs inode appropriately. */ +	/* Setup the allocated size in the ntfs inode in case it changed. */  	write_lock_irqsave(&ni->size_lock, flags);  	ni->allocated_size = arec_size - mp_ofs;  	write_unlock_irqrestore(&ni->size_lock, flags); -	NInoClearNonResident(ni);  	/* Mark the mft record dirty, so it gets written back. */  	flush_dcache_mft_record_page(ctx->ntfs_ino);  	mark_mft_record_dirty(ctx->ntfs_ino);  |