From 96471b7a11cff1ad1234ce32c294e556378faacb Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Mon, 11 Oct 2004 15:51:24 +0100 Subject: [PATCH] NTFS: Add fs/ntfs/mft.c::try_map_mft_record() which fails with -EALREADY if the mft record is already locked and otherwise behaves the same way as fs/ntfs/mft.c::map_mft_record(). Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 3 +++ fs/ntfs/mft.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ fs/ntfs/mft.h | 1 + 3 files changed, 55 insertions(+) diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 91b23be8c7dbc..c3ff4343a74b7 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -70,6 +70,9 @@ ToDo/Notes: mft record dirty as well as the page itself. - Fix compiler warnings on x86-64 in fs/ntfs/dir.c. (Randy Dunlap, slightly modified by me) + - Add fs/ntfs/mft.c::try_map_mft_record() which fails with -EALREADY if + the mft record is already locked and otherwise behaves the same way + as fs/ntfs/mft.c::map_mft_record(). 2.1.20 - Fix two stupid bugs introduced in 2.1.18 release. diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index c74ae7d72c3fa..01e44140ac392 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -114,6 +114,57 @@ err_out: return (void*)page; } +/** + * try_map_mft_record - attempt to map, pin and lock an mft record + * @ni: ntfs inode whose MFT record to map + * + * First, attempt to take the mrec_lock semaphore. If the semaphore is already + * taken by someone else, return the error code -EALREADY. Otherwise continue + * as described below. + * + * The page of the record is mapped using map_mft_record_page() before being + * returned to the caller. + * + * This in turn uses ntfs_map_page() to get the page containing the wanted mft + * record (it in turn calls read_cache_page() which reads it in from disk if + * necessary, increments the use count on the page so that it cannot disappear + * under us and returns a reference to the page cache page). + * + * The mft record is now ours and we return a pointer to it. You need to check + * the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return + * the error code. + * + * For further details see the description of map_mft_record() below. + */ +MFT_RECORD *try_map_mft_record(ntfs_inode *ni) +{ + MFT_RECORD *m; + + ntfs_debug("Entering for mft_no 0x%lx.", ni->mft_no); + + /* Make sure the ntfs inode doesn't go away. */ + atomic_inc(&ni->count); + + /* + * Serialize access to this mft record. If someone else is already + * holding the lock, abort instead of waiting for the lock. + */ + if (unlikely(down_trylock(&ni->mrec_lock))) { + ntfs_debug("Mft record is already locked, aborting."); + atomic_dec(&ni->count); + return ERR_PTR(-EALREADY); + } + + m = map_mft_record_page(ni); + if (likely(!IS_ERR(m))) + return m; + + up(&ni->mrec_lock); + atomic_dec(&ni->count); + ntfs_error(ni->vol->sb, "Failed with error code %lu.", -PTR_ERR(m)); + return m; +} + /** * map_mft_record - map, pin and lock an mft record * @ni: ntfs inode whose MFT record to map diff --git a/fs/ntfs/mft.h b/fs/ntfs/mft.h index 924f87abff8b9..fddc92e21d900 100644 --- a/fs/ntfs/mft.h +++ b/fs/ntfs/mft.h @@ -29,6 +29,7 @@ #include "inode.h" +extern MFT_RECORD *try_map_mft_record(ntfs_inode *ni); extern MFT_RECORD *map_mft_record(ntfs_inode *ni); extern void unmap_mft_record(ntfs_inode *ni); -- 2.53.0