]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/filemap.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2018-2024 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <djwong@kernel.org>
11 #include <sys/types.h>
12 #include <sys/statvfs.h>
13 #include "libfrog/paths.h"
14 #include "xfs_scrub.h"
19 * These routines provide a simple interface to query the block
20 * mappings of the fork of a given inode via GETBMAPX and call a
21 * function to iterate each mapping result.
27 * Iterate all the extent block mappings between the key and fork end.
28 * Returns 0 or a positive error number.
31 scrub_iterate_filemaps(
32 struct scrub_ctx
*ctx
,
35 struct file_bmap
*key
,
36 scrub_bmap_iter_fn fn
,
42 struct file_bmap bmap
;
48 map
= calloc(BMAP_NR
, sizeof(struct getbmapx
));
52 map
->bmv_offset
= BTOBB(key
->bm_offset
);
53 map
->bmv_block
= BTOBB(key
->bm_physical
);
54 if (key
->bm_length
== 0)
55 map
->bmv_length
= ULLONG_MAX
;
57 map
->bmv_length
= BTOBB(key
->bm_length
);
58 map
->bmv_iflags
= BMV_IF_PREALLOC
| BMV_IF_NO_HOLES
;
61 getxattr_type
= XFS_IOC_FSGETXATTRA
;
62 map
->bmv_iflags
|= BMV_IF_ATTRFORK
;
65 map
->bmv_iflags
|= BMV_IF_COWFORK
;
66 getxattr_type
= FS_IOC_FSGETXATTR
;
69 getxattr_type
= FS_IOC_FSGETXATTR
;
75 ret
= ioctl(fd
, getxattr_type
, &fsx
);
81 if (fsx
.fsx_nextents
== 0)
84 map
->bmv_count
= min(fsx
.fsx_nextents
+ 1, BMAP_NR
);
86 while ((ret
= ioctl(fd
, XFS_IOC_GETBMAPX
, map
)) == 0) {
87 for (i
= 0, p
= &map
[i
+ 1]; i
< map
->bmv_entries
; i
++, p
++) {
88 bmap
.bm_offset
= BBTOB(p
->bmv_offset
);
89 bmap
.bm_physical
= BBTOB(p
->bmv_block
);
90 bmap
.bm_length
= BBTOB(p
->bmv_length
);
91 bmap
.bm_flags
= p
->bmv_oflags
;
92 ret
= fn(ctx
, fd
, whichfork
, &fsx
, &bmap
, arg
);
95 if (scrub_excessive_errors(ctx
))
99 if (map
->bmv_entries
== 0)
101 p
= map
+ map
->bmv_entries
;
102 if (p
->bmv_oflags
& BMV_OF_LAST
)
105 new_off
= p
->bmv_offset
+ p
->bmv_length
;
106 map
->bmv_length
-= new_off
- map
->bmv_offset
;
107 map
->bmv_offset
= new_off
;
113 * Pre-reflink filesystems don't know about CoW forks, so don't
114 * be too surprised if it fails.
116 if (whichfork
== XFS_COW_FORK
&& ret
== EINVAL
)