diff options
| author | Anton Altaparmakov <aia21@cantab.net> | 2005-03-07 16:36:18 -0500 |
|---|---|---|
| committer | Anton Altaparmakov <aia21@cantab.net> | 2005-05-05 06:18:43 -0400 |
| commit | 271849a98849394ea85fa7caa8a1aaa2b3a849b7 (patch) | |
| tree | 08e932656e463845faaa3610059c67e16aa92b7d | |
| parent | 7e693073a940c7484c0c21e3e1603e29ce46f30c (diff) | |
NTFS: Add fs/ntfs/attrib.[hc]::ntfs_attr_vcn_to_lcn_nolock() used by the new
write code.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
| -rw-r--r-- | fs/ntfs/ChangeLog | 6 | ||||
| -rw-r--r-- | fs/ntfs/attrib.c | 87 | ||||
| -rw-r--r-- | fs/ntfs/attrib.h | 5 |
3 files changed, 95 insertions, 3 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 868871cb9c6e..4af6ae6ff12b 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
| @@ -88,8 +88,10 @@ ToDo/Notes: | |||
| 88 | checked and set in the ntfs inode as done for compressed files and | 88 | checked and set in the ntfs inode as done for compressed files and |
| 89 | the compressed size needs to be used for vfs inode->i_blocks instead | 89 | the compressed size needs to be used for vfs inode->i_blocks instead |
| 90 | of the allocated size, again, as done for compressed files. | 90 | of the allocated size, again, as done for compressed files. |
| 91 | - Add AT_EA in addition to AT_DATA to whitelist for being allowed to | 91 | - Add AT_EA in addition to AT_DATA to whitelist for being allowed to be |
| 92 | be non-resident in fs/ntfs/attrib.c::ntfs_attr_can_be_non_resident(). | 92 | non-resident in fs/ntfs/attrib.c::ntfs_attr_can_be_non_resident(). |
| 93 | - Add fs/ntfs/attrib.c::ntfs_attr_vcn_to_lcn_nolock() used by the new | ||
| 94 | write code. | ||
| 93 | 95 | ||
| 94 | 2.1.22 - Many bug and race fixes and error handling improvements. | 96 | 2.1.22 - Many bug and race fixes and error handling improvements. |
| 95 | 97 | ||
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index fa464fce2261..1610f1cd2862 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
| @@ -106,6 +106,93 @@ int ntfs_map_runlist(ntfs_inode *ni, VCN vcn) | |||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /** | 108 | /** |
| 109 | * ntfs_attr_vcn_to_lcn_nolock - convert a vcn into a lcn given an ntfs inode | ||
| 110 | * @ni: ntfs inode of the attribute whose runlist to search | ||
| 111 | * @vcn: vcn to convert | ||
| 112 | * @write_locked: true if the runlist is locked for writing | ||
| 113 | * | ||
| 114 | * Find the virtual cluster number @vcn in the runlist of the ntfs attribute | ||
| 115 | * described by the ntfs inode @ni and return the corresponding logical cluster | ||
| 116 | * number (lcn). | ||
| 117 | * | ||
| 118 | * If the @vcn is not mapped yet, the attempt is made to map the attribute | ||
| 119 | * extent containing the @vcn and the vcn to lcn conversion is retried. | ||
| 120 | * | ||
| 121 | * If @write_locked is true the caller has locked the runlist for writing and | ||
| 122 | * if false for reading. | ||
| 123 | * | ||
| 124 | * Since lcns must be >= 0, we use negative return codes with special meaning: | ||
| 125 | * | ||
| 126 | * Return code Meaning / Description | ||
| 127 | * ========================================== | ||
| 128 | * LCN_HOLE Hole / not allocated on disk. | ||
| 129 | * LCN_ENOENT There is no such vcn in the runlist, i.e. @vcn is out of bounds. | ||
| 130 | * LCN_ENOMEM Not enough memory to map runlist. | ||
| 131 | * LCN_EIO Critical error (runlist/file is corrupt, i/o error, etc). | ||
| 132 | * | ||
| 133 | * Locking: - The runlist must be locked on entry and is left locked on return. | ||
| 134 | * - If @write_locked is FALSE, i.e. the runlist is locked for reading, | ||
| 135 | * the lock may be dropped inside the function so you cannot rely on | ||
| 136 | * the runlist still being the same when this function returns. | ||
| 137 | */ | ||
| 138 | LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn, | ||
| 139 | const BOOL write_locked) | ||
| 140 | { | ||
| 141 | LCN lcn; | ||
| 142 | BOOL is_retry = FALSE; | ||
| 143 | |||
| 144 | ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.", | ||
| 145 | ni->mft_no, (unsigned long long)vcn, | ||
| 146 | write_locked ? "write" : "read"); | ||
| 147 | BUG_ON(!ni); | ||
| 148 | BUG_ON(!NInoNonResident(ni)); | ||
| 149 | BUG_ON(vcn < 0); | ||
| 150 | retry_remap: | ||
| 151 | /* Convert vcn to lcn. If that fails map the runlist and retry once. */ | ||
| 152 | lcn = ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn); | ||
| 153 | if (likely(lcn >= LCN_HOLE)) { | ||
| 154 | ntfs_debug("Done, lcn 0x%llx.", (long long)lcn); | ||
| 155 | return lcn; | ||
| 156 | } | ||
| 157 | if (lcn != LCN_RL_NOT_MAPPED) { | ||
| 158 | if (lcn != LCN_ENOENT) | ||
| 159 | lcn = LCN_EIO; | ||
| 160 | } else if (!is_retry) { | ||
| 161 | int err; | ||
| 162 | |||
| 163 | if (!write_locked) { | ||
| 164 | up_read(&ni->runlist.lock); | ||
| 165 | down_write(&ni->runlist.lock); | ||
| 166 | if (unlikely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) != | ||
| 167 | LCN_RL_NOT_MAPPED)) { | ||
| 168 | up_write(&ni->runlist.lock); | ||
| 169 | down_read(&ni->runlist.lock); | ||
| 170 | goto retry_remap; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | err = ntfs_map_runlist_nolock(ni, vcn); | ||
| 174 | if (!write_locked) { | ||
| 175 | up_write(&ni->runlist.lock); | ||
| 176 | down_read(&ni->runlist.lock); | ||
| 177 | } | ||
| 178 | if (likely(!err)) { | ||
| 179 | is_retry = TRUE; | ||
| 180 | goto retry_remap; | ||
| 181 | } | ||
| 182 | if (err == -ENOENT) | ||
| 183 | lcn = LCN_ENOENT; | ||
| 184 | else if (err == -ENOMEM) | ||
| 185 | lcn = LCN_ENOMEM; | ||
| 186 | else | ||
| 187 | lcn = LCN_EIO; | ||
| 188 | } | ||
| 189 | if (lcn != LCN_ENOENT) | ||
| 190 | ntfs_error(ni->vol->sb, "Failed with error code %lli.", | ||
| 191 | (long long)lcn); | ||
| 192 | return lcn; | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 109 | * ntfs_find_vcn_nolock - find a vcn in the runlist described by an ntfs inode | 196 | * ntfs_find_vcn_nolock - find a vcn in the runlist described by an ntfs inode |
| 110 | * @ni: ntfs inode describing the runlist to search | 197 | * @ni: ntfs inode describing the runlist to search |
| 111 | * @vcn: vcn to find | 198 | * @vcn: vcn to find |
diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h index 3eb451657025..75041c89c738 100644 --- a/fs/ntfs/attrib.h +++ b/fs/ntfs/attrib.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * attrib.h - Defines for attribute handling in NTFS Linux kernel driver. | 2 | * attrib.h - Defines for attribute handling in NTFS Linux kernel driver. |
| 3 | * Part of the Linux-NTFS project. | 3 | * Part of the Linux-NTFS project. |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2001-2004 Anton Altaparmakov | 5 | * Copyright (c) 2001-2005 Anton Altaparmakov |
| 6 | * Copyright (c) 2002 Richard Russon | 6 | * Copyright (c) 2002 Richard Russon |
| 7 | * | 7 | * |
| 8 | * This program/include file is free software; you can redistribute it and/or | 8 | * This program/include file is free software; you can redistribute it and/or |
| @@ -63,6 +63,9 @@ typedef struct { | |||
| 63 | extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn); | 63 | extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn); |
| 64 | extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn); | 64 | extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn); |
| 65 | 65 | ||
| 66 | extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn, | ||
| 67 | const BOOL write_locked); | ||
| 68 | |||
| 66 | extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, | 69 | extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, |
| 67 | const BOOL write_locked); | 70 | const BOOL write_locked); |
| 68 | 71 | ||
