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