Loading fs/ntfs/ChangeLog +4 −2 Original line number Diff line number Diff line Loading @@ -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. Loading fs/ntfs/attrib.c +87 −0 Original line number Diff line number Diff line Loading @@ -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 Loading fs/ntfs/attrib.h +4 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading
fs/ntfs/ChangeLog +4 −2 Original line number Diff line number Diff line Loading @@ -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. Loading
fs/ntfs/attrib.c +87 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
fs/ntfs/attrib.h +4 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading