]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/filemap.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
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_NO_DMAPI_READ
| BMV_IF_PREALLOC
|
62 getxattr_type
= XFS_IOC_FSGETXATTRA
;
63 map
->bmv_iflags
|= BMV_IF_ATTRFORK
;
66 map
->bmv_iflags
|= BMV_IF_COWFORK
;
67 getxattr_type
= FS_IOC_FSGETXATTR
;
70 getxattr_type
= FS_IOC_FSGETXATTR
;
76 ret
= ioctl(fd
, getxattr_type
, &fsx
);
82 if (fsx
.fsx_nextents
== 0)
85 map
->bmv_count
= min(fsx
.fsx_nextents
+ 1, BMAP_NR
);
87 while ((ret
= ioctl(fd
, XFS_IOC_GETBMAPX
, map
)) == 0) {
88 for (i
= 0, p
= &map
[i
+ 1]; i
< map
->bmv_entries
; i
++, p
++) {
89 bmap
.bm_offset
= BBTOB(p
->bmv_offset
);
90 bmap
.bm_physical
= BBTOB(p
->bmv_block
);
91 bmap
.bm_length
= BBTOB(p
->bmv_length
);
92 bmap
.bm_flags
= p
->bmv_oflags
;
93 ret
= fn(ctx
, fd
, whichfork
, &fsx
, &bmap
, arg
);
96 if (scrub_excessive_errors(ctx
))
100 if (map
->bmv_entries
== 0)
102 p
= map
+ map
->bmv_entries
;
103 if (p
->bmv_oflags
& BMV_OF_LAST
)
106 new_off
= p
->bmv_offset
+ p
->bmv_length
;
107 map
->bmv_length
-= new_off
- map
->bmv_offset
;
108 map
->bmv_offset
= new_off
;
114 * Pre-reflink filesystems don't know about CoW forks, so don't
115 * be too surprised if it fails.
117 if (whichfork
== XFS_COW_FORK
&& ret
== EINVAL
)