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

Commit 271849a9 authored by Anton Altaparmakov's avatar Anton Altaparmakov
Browse files

NTFS: Add fs/ntfs/attrib.[hc]::ntfs_attr_vcn_to_lcn_nolock() used by the new


      write code.

Signed-off-by: default avatarAnton Altaparmakov <aia21@cantab.net>
parent 7e693073
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -88,8 +88,10 @@ ToDo/Notes:
	  checked and set in the ntfs inode as done for compressed files and
	  the compressed size needs to be used for vfs inode->i_blocks instead
	  of the allocated size, again, as done for compressed files.
	- Add AT_EA in addition to AT_DATA to whitelist for being allowed to
	  be non-resident in fs/ntfs/attrib.c::ntfs_attr_can_be_non_resident().
	- Add AT_EA in addition to AT_DATA to whitelist for being allowed to be
	  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.

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

+87 −0
Original line number Diff line number Diff line
@@ -105,6 +105,93 @@ int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
	return err;
}

/**
 * ntfs_attr_vcn_to_lcn_nolock - convert a vcn into a lcn given an ntfs inode
 * @ni:			ntfs inode of the attribute whose runlist to search
 * @vcn:		vcn to convert
 * @write_locked:	true if the runlist is locked for writing
 *
 * Find the virtual cluster number @vcn in the runlist of the ntfs attribute
 * described by the ntfs inode @ni and return the corresponding logical cluster
 * number (lcn).
 *
 * 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.
 *
 * Since lcns must be >= 0, we use negative return codes with special meaning:
 *
 * Return code	Meaning / Description
 * ==========================================
 *  LCN_HOLE	Hole / not allocated on disk.
 *  LCN_ENOENT	There is no such vcn in the runlist, i.e. @vcn is out of bounds.
 *  LCN_ENOMEM	Not enough memory to map runlist.
 *  LCN_EIO	Critical error (runlist/file is corrupt, i/o error, etc).
 *
 * 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.
 */
LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
		const BOOL write_locked)
{
	LCN lcn;
	BOOL is_retry = FALSE;

	ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.",
			ni->mft_no, (unsigned long long)vcn,
			write_locked ? "write" : "read");
	BUG_ON(!ni);
	BUG_ON(!NInoNonResident(ni));
	BUG_ON(vcn < 0);
retry_remap:
	/* Convert vcn to lcn.  If that fails map the runlist and retry once. */
	lcn = ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn);
	if (likely(lcn >= LCN_HOLE)) {
		ntfs_debug("Done, lcn 0x%llx.", (long long)lcn);
		return lcn;
	}
	if (lcn != LCN_RL_NOT_MAPPED) {
		if (lcn != LCN_ENOENT)
			lcn = LCN_EIO;
	} else if (!is_retry) {
		int err;

		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) {
			up_write(&ni->runlist.lock);
			down_read(&ni->runlist.lock);
		}
		if (likely(!err)) {
			is_retry = TRUE;
			goto retry_remap;
		}
		if (err == -ENOENT)
			lcn = LCN_ENOENT;
		else if (err == -ENOMEM)
			lcn = LCN_ENOMEM;
		else
			lcn = LCN_EIO;
	}
	if (lcn != LCN_ENOENT)
		ntfs_error(ni->vol->sb, "Failed with error code %lli.",
				(long long)lcn);
	return lcn;
}

/**
 * ntfs_find_vcn_nolock - find a vcn in the runlist described by an ntfs inode
 * @ni:			ntfs inode describing the runlist to search
+4 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * attrib.h - Defines for attribute handling in NTFS Linux kernel driver.
 *	      Part of the Linux-NTFS project.
 *
 * Copyright (c) 2001-2004 Anton Altaparmakov
 * Copyright (c) 2001-2005 Anton Altaparmakov
 * Copyright (c) 2002 Richard Russon
 *
 * This program/include file is free software; you can redistribute it and/or
@@ -63,6 +63,9 @@ typedef struct {
extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn);
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);