aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ntfs/ChangeLog6
-rw-r--r--fs/ntfs/attrib.c87
-rw-r--r--fs/ntfs/attrib.h5
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
942.1.22 - Many bug and race fixes and error handling improvements. 962.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 */
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
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 {
63extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn); 63extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn);
64extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn); 64extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
65 65
66extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
67 const BOOL write_locked);
68
66extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, 69extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
67 const BOOL write_locked); 70 const BOOL write_locked);
68 71