]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/cowextsize.c
xfs_io: wire up repair ioctl stuff
[thirdparty/xfsprogs-dev.git] / io / cowextsize.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2016 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 */
6 /*
7 * If configure didn't find a struct fsxattr with fsx_cowextsize,
8 * disable the only other source (so far) of struct fsxattr. Thus,
9 * build with the internal definition of struct fsxattr, which has
10 * fsx_cowextsize.
11 */
12 #include "platform_defs.h"
13 #include "command.h"
14 #include "init.h"
15 #include "io.h"
16 #include "input.h"
17 #include "path.h"
18
19 static cmdinfo_t cowextsize_cmd;
20 static long cowextsize;
21
22 static void
23 cowextsize_help(void)
24 {
25 printf(_(
26 "\n"
27 " report or modify preferred CoW extent size (in bytes) for the current path\n"
28 "\n"
29 " -R -- recursively descend (useful when current path is a directory)\n"
30 " -D -- recursively descend, only modifying cowextsize on directories\n"
31 "\n"));
32 }
33
34 static int
35 get_cowextsize(const char *path, int fd)
36 {
37 struct fsxattr fsx;
38
39 if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
40 printf("%s: XFS_IOC_FSGETXATTR %s: %s\n",
41 progname, path, strerror(errno));
42 return 0;
43 }
44 printf("[%u] %s\n", fsx.fsx_cowextsize, path);
45 return 0;
46 }
47
48 static int
49 set_cowextsize(const char *path, int fd, long extsz)
50 {
51 struct fsxattr fsx;
52 struct stat64 stat;
53
54 if (fstat64(fd, &stat) < 0) {
55 perror("fstat64");
56 return 0;
57 }
58 if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
59 printf("%s: XFS_IOC_FSGETXATTR %s: %s\n",
60 progname, path, strerror(errno));
61 return 0;
62 }
63
64 if (S_ISREG(stat.st_mode) || S_ISDIR(stat.st_mode)) {
65 fsx.fsx_xflags |= FS_XFLAG_COWEXTSIZE;
66 } else {
67 printf(_("invalid target file type - file %s\n"), path);
68 return 0;
69 }
70 fsx.fsx_cowextsize = extsz;
71
72 if ((xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx)) < 0) {
73 printf("%s: XFS_IOC_FSSETXATTR %s: %s\n",
74 progname, path, strerror(errno));
75 return 0;
76 }
77
78 return 0;
79 }
80
81 static int
82 get_cowextsize_callback(
83 const char *path,
84 const struct stat *stat,
85 int status,
86 struct FTW *data)
87 {
88 int fd;
89
90 if (recurse_dir && !S_ISDIR(stat->st_mode))
91 return 0;
92
93 fd = open(path, O_RDONLY);
94 if (fd < 0) {
95 fprintf(stderr, _("%s: cannot open %s: %s\n"),
96 progname, path, strerror(errno));
97 } else {
98 get_cowextsize(path, fd);
99 close(fd);
100 }
101 return 0;
102 }
103
104 static int
105 set_cowextsize_callback(
106 const char *path,
107 const struct stat *stat,
108 int status,
109 struct FTW *data)
110 {
111 int fd;
112
113 if (recurse_dir && !S_ISDIR(stat->st_mode))
114 return 0;
115
116 fd = open(path, O_RDONLY);
117 if (fd < 0) {
118 fprintf(stderr, _("%s: cannot open %s: %s\n"),
119 progname, path, strerror(errno));
120 } else {
121 set_cowextsize(path, fd, cowextsize);
122 close(fd);
123 }
124 return 0;
125 }
126
127 static int
128 cowextsize_f(
129 int argc,
130 char **argv)
131 {
132 size_t blocksize, sectsize;
133 int c;
134
135 recurse_all = recurse_dir = 0;
136 init_cvtnum(&blocksize, &sectsize);
137 while ((c = getopt(argc, argv, "DR")) != EOF) {
138 switch (c) {
139 case 'D':
140 recurse_all = 0;
141 recurse_dir = 1;
142 break;
143 case 'R':
144 recurse_all = 1;
145 recurse_dir = 0;
146 break;
147 default:
148 return command_usage(&cowextsize_cmd);
149 }
150 }
151
152 if (optind < argc) {
153 cowextsize = (long)cvtnum(blocksize, sectsize, argv[optind]);
154 if (cowextsize < 0) {
155 printf(_("non-numeric cowextsize argument -- %s\n"),
156 argv[optind]);
157 return 0;
158 }
159 } else {
160 cowextsize = -1;
161 }
162
163 if (recurse_all || recurse_dir)
164 nftw(file->name, (cowextsize >= 0) ?
165 set_cowextsize_callback : get_cowextsize_callback,
166 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
167 else if (cowextsize >= 0)
168 set_cowextsize(file->name, file->fd, cowextsize);
169 else
170 get_cowextsize(file->name, file->fd);
171 return 0;
172 }
173
174 void
175 cowextsize_init(void)
176 {
177 cowextsize_cmd.name = "cowextsize";
178 cowextsize_cmd.cfunc = cowextsize_f;
179 cowextsize_cmd.args = _("[-D | -R] [cowextsize]");
180 cowextsize_cmd.argmin = 0;
181 cowextsize_cmd.argmax = -1;
182 cowextsize_cmd.flags = CMD_NOMAP_OK;
183 cowextsize_cmd.oneline =
184 _("get/set preferred CoW extent size (in bytes) for the open file");
185 cowextsize_cmd.help = cowextsize_help;
186
187 add_command(&cowextsize_cmd);
188 }