diff options
Diffstat (limited to 'fs/ntfs/attrib.c')
-rw-r--r-- | fs/ntfs/attrib.c | 87 |
1 files changed, 87 insertions, 0 deletions
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 |