Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0c1cc0e authored by Anton Altaparmakov's avatar Anton Altaparmakov
Browse files

NTFS: - Fix bug in fs/ntfs/attrib.c::ntfs_find_vcn_nolock() where after


        dropping the read lock and taking the write lock we were not checking
        whether someone else did not already do the work we wanted to do.
      - Rename ntfs_find_vcn_nolock() to ntfs_attr_find_vcn_nolock().
      - Tidy up some comments in fs/ntfs/runlist.c.
      - Add LCN_ENOMEM and LCN_EIO definitions to fs/ntfs/runlist.h.

Signed-off-by: default avatarAnton Altaparmakov <aia21@cantab.net>
parent 271849a9
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -92,6 +92,11 @@ ToDo/Notes:
	  non-resident in fs/ntfs/attrib.c::ntfs_attr_can_be_non_resident().
	- Add fs/ntfs/attrib.c::ntfs_attr_vcn_to_lcn_nolock() used by the new
	  write code.
	- Fix bug in fs/ntfs/attrib.c::ntfs_find_vcn_nolock() where after
	  dropping the read lock and taking the write lock we were not checking
	  whether someone else did not already do the work we wanted to do.
	- Rename fs/ntfs/attrib.c::ntfs_find_vcn_nolock() to
	  ntfs_attr_find_vcn_nolock() and update all callers.

2.1.22 - Many bug and race fixes and error handling improvements.

+17 −12
Original line number Diff line number Diff line
@@ -193,19 +193,19 @@ LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
}

/**
 * ntfs_find_vcn_nolock - find a vcn in the runlist described by an ntfs inode
 * ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode
 * @ni:			ntfs inode describing the runlist to search
 * @vcn:		vcn to find
 * @write_locked:	true if the runlist is locked for writing
 *
 * Find the virtual cluster number @vcn in the runlist described by the ntfs
 * inode @ni and return the address of the runlist element containing the @vcn.
 * The runlist is left locked and the caller has to unlock it.  In the error
 * case, the runlist is left in the same locking state as on entry.
 *
 * Note if @write_locked is FALSE the lock may be dropped inside the function
 * so you cannot rely on the runlist still being the same when this function
 * returns.
 * If the @vcn is not mapped yet, the attempt is made to map the attribute
 * extent containing the @vcn and the vcn to lcn conversion is retried.
 *
 * If @write_locked is true the caller has locked the runlist for writing and
 * if false for reading.
 *
 * Note you need to distinguish between the lcn of the returned runlist element
 * being >= 0 and LCN_HOLE.  In the later case you have to return zeroes on
@@ -221,13 +221,12 @@ LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
 *	-ENOMEM - Not enough memory to map runlist.
 *	-EIO	- Critical error (runlist/file is corrupt, i/o error, etc).
 *
 * Locking: - The runlist must be unlocked on entry.
 *	    - On failing return, the runlist is unlocked.
 *	    - On successful return, the runlist is locked.  If @need_write us
 *	      true, it is locked for writing.  Otherwise is is locked for
 *	      reading.
 * Locking: - The runlist must be locked on entry and is left locked on return.
 *	    - If @write_locked is FALSE, i.e. the runlist is locked for reading,
 *	      the lock may be dropped inside the function so you cannot rely on
 *	      the runlist still being the same when this function returns.
 */
runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
		const BOOL write_locked)
{
	runlist_element *rl;
@@ -268,6 +267,12 @@ runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
		if (!write_locked) {
			up_read(&ni->runlist.lock);
			down_write(&ni->runlist.lock);
			if (unlikely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) !=
					LCN_RL_NOT_MAPPED)) {
				up_write(&ni->runlist.lock);
				down_read(&ni->runlist.lock);
				goto retry_remap;
			}
		}
		err = ntfs_map_runlist_nolock(ni, vcn);
		if (!write_locked) {
+2 −2
Original line number Diff line number Diff line
@@ -66,8 +66,8 @@ extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
		const BOOL write_locked);

extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
		const BOOL write_locked);
extern runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni,
		const VCN vcn, const BOOL write_locked);

int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
		const u32 name_len, const IGNORE_CASE_BOOL ic,
+2 −2
Original line number Diff line number Diff line
@@ -850,7 +850,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,

	/* This returns with ni->runlist locked for reading on success. */
	down_read(&ni->runlist.lock);
	rl = ntfs_find_vcn_nolock(ni, start_vcn, FALSE);
	rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE);
	if (IS_ERR(rl)) {
		if (!is_rollback)
			ntfs_error(vol->sb, "Failed to find first runlist "
@@ -904,7 +904,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,

			/* Attempt to map runlist. */
			vcn = rl->vcn;
			rl = ntfs_find_vcn_nolock(ni, vcn, FALSE);
			rl = ntfs_attr_find_vcn_nolock(ni, vcn, FALSE);
			if (IS_ERR(rl)) {
				err = PTR_ERR(rl);
				if (!is_rollback)
+3 −3
Original line number Diff line number Diff line
@@ -1297,7 +1297,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
	read_lock_irqsave(&mftbmp_ni->size_lock, flags);
	ll = mftbmp_ni->allocated_size;
	read_unlock_irqrestore(&mftbmp_ni->size_lock, flags);
	rl = ntfs_find_vcn_nolock(mftbmp_ni,
	rl = ntfs_attr_find_vcn_nolock(mftbmp_ni,
			(ll - 1) >> vol->cluster_size_bits, TRUE);
	if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) {
		up_write(&mftbmp_ni->runlist.lock);
@@ -1727,8 +1727,8 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
	read_lock_irqsave(&mft_ni->size_lock, flags);
	ll = mft_ni->allocated_size;
	read_unlock_irqrestore(&mft_ni->size_lock, flags);
	rl = ntfs_find_vcn_nolock(mft_ni, (ll - 1) >> vol->cluster_size_bits,
			TRUE);
	rl = ntfs_attr_find_vcn_nolock(mft_ni,
			(ll - 1) >> vol->cluster_size_bits, TRUE);
	if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) {
		up_write(&mft_ni->runlist.lock);
		ntfs_error(vol->sb, "Failed to determine last allocated "
Loading