]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/filemap.c
scrub: remove xfs_ prefixes from various function
[thirdparty/xfsprogs-dev.git] / scrub / filemap.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 */
6 #include "xfs.h"
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/statvfs.h>
13 #include "libfrog/paths.h"
14 #include "xfs_scrub.h"
15 #include "common.h"
16 #include "filemap.h"
17
18 /*
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.
22 */
23
24 #define BMAP_NR 2048
25
26 /*
27 * Iterate all the extent block mappings between the key and fork end.
28 * Returns 0 or a positive error number.
29 */
30 int
31 scrub_iterate_filemaps(
32 struct scrub_ctx *ctx,
33 int fd,
34 int whichfork,
35 struct file_bmap *key,
36 scrub_bmap_iter_fn fn,
37 void *arg)
38 {
39 struct fsxattr fsx;
40 struct getbmapx *map;
41 struct getbmapx *p;
42 struct file_bmap bmap;
43 xfs_off_t new_off;
44 int getxattr_type;
45 int i;
46 int ret;
47
48 map = calloc(BMAP_NR, sizeof(struct getbmapx));
49 if (!map)
50 return errno;
51
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;
56 else
57 map->bmv_length = BTOBB(key->bm_length);
58 map->bmv_iflags = BMV_IF_NO_DMAPI_READ | BMV_IF_PREALLOC |
59 BMV_IF_NO_HOLES;
60 switch (whichfork) {
61 case XFS_ATTR_FORK:
62 getxattr_type = XFS_IOC_FSGETXATTRA;
63 map->bmv_iflags |= BMV_IF_ATTRFORK;
64 break;
65 case XFS_COW_FORK:
66 map->bmv_iflags |= BMV_IF_COWFORK;
67 getxattr_type = FS_IOC_FSGETXATTR;
68 break;
69 case XFS_DATA_FORK:
70 getxattr_type = FS_IOC_FSGETXATTR;
71 break;
72 default:
73 abort();
74 }
75
76 ret = ioctl(fd, getxattr_type, &fsx);
77 if (ret < 0) {
78 ret = errno;
79 goto out;
80 }
81
82 if (fsx.fsx_nextents == 0)
83 goto out;
84
85 map->bmv_count = min(fsx.fsx_nextents + 1, BMAP_NR);
86
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);
94 if (ret)
95 goto out;
96 if (scrub_excessive_errors(ctx))
97 goto out;
98 }
99
100 if (map->bmv_entries == 0)
101 break;
102 p = map + map->bmv_entries;
103 if (p->bmv_oflags & BMV_OF_LAST)
104 break;
105
106 new_off = p->bmv_offset + p->bmv_length;
107 map->bmv_length -= new_off - map->bmv_offset;
108 map->bmv_offset = new_off;
109 }
110 if (ret < 0)
111 ret = errno;
112
113 /*
114 * Pre-reflink filesystems don't know about CoW forks, so don't
115 * be too surprised if it fails.
116 */
117 if (whichfork == XFS_COW_FORK && ret == EINVAL)
118 ret = 0;
119 out:
120 free(map);
121 return ret;
122 }