aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/attrib.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ntfs/attrib.c')
-rw-r--r--fs/ntfs/attrib.c87
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 */
138LCN 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);
150retry_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