]>
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.
26 /* Iterate all the extent block mappings between the key and fork end. */
29 struct scrub_ctx
*ctx
,
41 char bmap_descr
[DESCR_BUFSZ
];
50 snprintf(bmap_descr
, DESCR_BUFSZ
, _("%s attr"), descr
);
53 snprintf(bmap_descr
, DESCR_BUFSZ
, _("%s CoW"), descr
);
56 snprintf(bmap_descr
, DESCR_BUFSZ
, _("%s data"), descr
);
62 map
= calloc(BMAP_NR
, sizeof(struct getbmapx
));
64 str_errno(ctx
, bmap_descr
);
68 map
->bmv_offset
= BTOBB(key
->bm_offset
);
69 map
->bmv_block
= BTOBB(key
->bm_physical
);
70 if (key
->bm_length
== 0)
71 map
->bmv_length
= ULLONG_MAX
;
73 map
->bmv_length
= BTOBB(key
->bm_length
);
74 map
->bmv_iflags
= BMV_IF_NO_DMAPI_READ
| BMV_IF_PREALLOC
|
78 getxattr_type
= XFS_IOC_FSGETXATTRA
;
79 map
->bmv_iflags
|= BMV_IF_ATTRFORK
;
82 map
->bmv_iflags
|= BMV_IF_COWFORK
;
83 getxattr_type
= FS_IOC_FSGETXATTR
;
86 getxattr_type
= FS_IOC_FSGETXATTR
;
92 error
= ioctl(fd
, getxattr_type
, &fsx
);
94 str_errno(ctx
, bmap_descr
);
99 if (fsx
.fsx_nextents
== 0) {
104 map
->bmv_count
= min(fsx
.fsx_nextents
+ 1, BMAP_NR
);
106 while ((error
= ioctl(fd
, XFS_IOC_GETBMAPX
, map
)) == 0) {
107 for (i
= 0, p
= &map
[i
+ 1]; i
< map
->bmv_entries
; i
++, p
++) {
108 bmap
.bm_offset
= BBTOB(p
->bmv_offset
);
109 bmap
.bm_physical
= BBTOB(p
->bmv_block
);
110 bmap
.bm_length
= BBTOB(p
->bmv_length
);
111 bmap
.bm_flags
= p
->bmv_oflags
;
112 moveon
= fn(ctx
, bmap_descr
, fd
, whichfork
, &fsx
,
116 if (xfs_scrub_excessive_errors(ctx
)) {
122 if (map
->bmv_entries
== 0)
124 p
= map
+ map
->bmv_entries
;
125 if (p
->bmv_oflags
& BMV_OF_LAST
)
128 new_off
= p
->bmv_offset
+ p
->bmv_length
;
129 map
->bmv_length
-= new_off
- map
->bmv_offset
;
130 map
->bmv_offset
= new_off
;
134 * Pre-reflink filesystems don't know about CoW forks, so don't
135 * be too surprised if it fails.
137 if (whichfork
== XFS_COW_FORK
&& error
&& errno
== EINVAL
)
141 str_errno(ctx
, bmap_descr
);