Skip to content

Commit 338f379

Browse files
author
Matthew Wilcox (Oracle)
committed
fs: Convert vfs_dedupe_file_range_compare to folios
We still only operate on a single page of data at a time due to using kmap(). A more complex implementation would work on each page in a folio, but it's not clear that such a complex implementation would be worthwhile. Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: William Kucharski <[email protected]>
1 parent 1613fac commit 338f379

File tree

1 file changed

+55
-61
lines changed

1 file changed

+55
-61
lines changed

fs/remap_range.c

Lines changed: 55 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -146,119 +146,113 @@ static int generic_remap_check_len(struct inode *inode_in,
146146
}
147147

148148
/* Read a page's worth of file data into the page cache. */
149-
static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset)
149+
static struct folio *vfs_dedupe_get_folio(struct inode *inode, loff_t pos)
150150
{
151-
struct page *page;
151+
struct folio *folio;
152152

153-
page = read_mapping_page(inode->i_mapping, offset >> PAGE_SHIFT, NULL);
154-
if (IS_ERR(page))
155-
return page;
156-
if (!PageUptodate(page)) {
157-
put_page(page);
153+
folio = read_mapping_folio(inode->i_mapping, pos >> PAGE_SHIFT, NULL);
154+
if (IS_ERR(folio))
155+
return folio;
156+
if (!folio_test_uptodate(folio)) {
157+
folio_put(folio);
158158
return ERR_PTR(-EIO);
159159
}
160-
return page;
160+
return folio;
161161
}
162162

163163
/*
164-
* Lock two pages, ensuring that we lock in offset order if the pages are from
165-
* the same file.
164+
* Lock two folios, ensuring that we lock in offset order if the folios
165+
* are from the same file.
166166
*/
167-
static void vfs_lock_two_pages(struct page *page1, struct page *page2)
167+
static void vfs_lock_two_folios(struct folio *folio1, struct folio *folio2)
168168
{
169169
/* Always lock in order of increasing index. */
170-
if (page1->index > page2->index)
171-
swap(page1, page2);
170+
if (folio1->index > folio2->index)
171+
swap(folio1, folio2);
172172

173-
lock_page(page1);
174-
if (page1 != page2)
175-
lock_page(page2);
173+
folio_lock(folio1);
174+
if (folio1 != folio2)
175+
folio_lock(folio2);
176176
}
177177

178-
/* Unlock two pages, being careful not to unlock the same page twice. */
179-
static void vfs_unlock_two_pages(struct page *page1, struct page *page2)
178+
/* Unlock two folios, being careful not to unlock the same folio twice. */
179+
static void vfs_unlock_two_folios(struct folio *folio1, struct folio *folio2)
180180
{
181-
unlock_page(page1);
182-
if (page1 != page2)
183-
unlock_page(page2);
181+
folio_unlock(folio1);
182+
if (folio1 != folio2)
183+
folio_unlock(folio2);
184184
}
185185

186186
/*
187187
* Compare extents of two files to see if they are the same.
188188
* Caller must have locked both inodes to prevent write races.
189189
*/
190190
static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
191-
struct inode *dest, loff_t destoff,
191+
struct inode *dest, loff_t dstoff,
192192
loff_t len, bool *is_same)
193193
{
194-
loff_t src_poff;
195-
loff_t dest_poff;
196-
void *src_addr;
197-
void *dest_addr;
198-
struct page *src_page;
199-
struct page *dest_page;
200-
loff_t cmp_len;
201-
bool same;
202-
int error;
203-
204-
error = -EINVAL;
205-
same = true;
194+
bool same = true;
195+
int error = -EINVAL;
196+
206197
while (len) {
207-
src_poff = srcoff & (PAGE_SIZE - 1);
208-
dest_poff = destoff & (PAGE_SIZE - 1);
209-
cmp_len = min(PAGE_SIZE - src_poff,
210-
PAGE_SIZE - dest_poff);
198+
struct folio *src_folio, *dst_folio;
199+
void *src_addr, *dst_addr;
200+
loff_t cmp_len = min(PAGE_SIZE - offset_in_page(srcoff),
201+
PAGE_SIZE - offset_in_page(dstoff));
202+
211203
cmp_len = min(cmp_len, len);
212204
if (cmp_len <= 0)
213205
goto out_error;
214206

215-
src_page = vfs_dedupe_get_page(src, srcoff);
216-
if (IS_ERR(src_page)) {
217-
error = PTR_ERR(src_page);
207+
src_folio = vfs_dedupe_get_folio(src, srcoff);
208+
if (IS_ERR(src_folio)) {
209+
error = PTR_ERR(src_folio);
218210
goto out_error;
219211
}
220-
dest_page = vfs_dedupe_get_page(dest, destoff);
221-
if (IS_ERR(dest_page)) {
222-
error = PTR_ERR(dest_page);
223-
put_page(src_page);
212+
dst_folio = vfs_dedupe_get_folio(dest, dstoff);
213+
if (IS_ERR(dst_folio)) {
214+
error = PTR_ERR(dst_folio);
215+
folio_put(src_folio);
224216
goto out_error;
225217
}
226218

227-
vfs_lock_two_pages(src_page, dest_page);
219+
vfs_lock_two_folios(src_folio, dst_folio);
228220

229221
/*
230-
* Now that we've locked both pages, make sure they're still
222+
* Now that we've locked both folios, make sure they're still
231223
* mapped to the file data we're interested in. If not,
232224
* someone is invalidating pages on us and we lose.
233225
*/
234-
if (!PageUptodate(src_page) || !PageUptodate(dest_page) ||
235-
src_page->mapping != src->i_mapping ||
236-
dest_page->mapping != dest->i_mapping) {
226+
if (!folio_test_uptodate(src_folio) || !folio_test_uptodate(dst_folio) ||
227+
src_folio->mapping != src->i_mapping ||
228+
dst_folio->mapping != dest->i_mapping) {
237229
same = false;
238230
goto unlock;
239231
}
240232

241-
src_addr = kmap_atomic(src_page);
242-
dest_addr = kmap_atomic(dest_page);
233+
src_addr = kmap_local_folio(src_folio,
234+
offset_in_folio(src_folio, srcoff));
235+
dst_addr = kmap_local_folio(dst_folio,
236+
offset_in_folio(dst_folio, dstoff));
243237

244-
flush_dcache_page(src_page);
245-
flush_dcache_page(dest_page);
238+
flush_dcache_folio(src_folio);
239+
flush_dcache_folio(dst_folio);
246240

247-
if (memcmp(src_addr + src_poff, dest_addr + dest_poff, cmp_len))
241+
if (memcmp(src_addr, dst_addr, cmp_len))
248242
same = false;
249243

250-
kunmap_atomic(dest_addr);
251-
kunmap_atomic(src_addr);
244+
kunmap_local(dst_addr);
245+
kunmap_local(src_addr);
252246
unlock:
253-
vfs_unlock_two_pages(src_page, dest_page);
254-
put_page(dest_page);
255-
put_page(src_page);
247+
vfs_unlock_two_folios(src_folio, dst_folio);
248+
folio_put(dst_folio);
249+
folio_put(src_folio);
256250

257251
if (!same)
258252
break;
259253

260254
srcoff += cmp_len;
261-
destoff += cmp_len;
255+
dstoff += cmp_len;
262256
len -= cmp_len;
263257
}
264258

0 commit comments

Comments
 (0)