]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
1e51132f DW |
2 | /* |
3 | * Copyright (C) 2016 Oracle. All Rights Reserved. | |
1e51132f | 4 | * Author: Darrick J. Wong <darrick.wong@oracle.com> |
1e51132f DW |
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" | |
42b4c8e8 | 17 | #include "libfrog/paths.h" |
1e51132f DW |
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 | ||
ce24180d | 39 | if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { |
1e51132f DW |
40 | printf("%s: XFS_IOC_FSGETXATTR %s: %s\n", |
41 | progname, path, strerror(errno)); | |
9e1595e6 | 42 | exitcode = 1; |
1e51132f DW |
43 | return 0; |
44 | } | |
45 | printf("[%u] %s\n", fsx.fsx_cowextsize, path); | |
46 | return 0; | |
47 | } | |
48 | ||
49 | static int | |
50 | set_cowextsize(const char *path, int fd, long extsz) | |
51 | { | |
52 | struct fsxattr fsx; | |
53 | struct stat64 stat; | |
54 | ||
55 | if (fstat64(fd, &stat) < 0) { | |
56 | perror("fstat64"); | |
9e1595e6 | 57 | exitcode = 1; |
1e51132f DW |
58 | return 0; |
59 | } | |
ce24180d | 60 | if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { |
1e51132f DW |
61 | printf("%s: XFS_IOC_FSGETXATTR %s: %s\n", |
62 | progname, path, strerror(errno)); | |
9e1595e6 | 63 | exitcode = 1; |
1e51132f DW |
64 | return 0; |
65 | } | |
66 | ||
67 | if (S_ISREG(stat.st_mode) || S_ISDIR(stat.st_mode)) { | |
68 | fsx.fsx_xflags |= FS_XFLAG_COWEXTSIZE; | |
69 | } else { | |
70 | printf(_("invalid target file type - file %s\n"), path); | |
71 | return 0; | |
72 | } | |
73 | fsx.fsx_cowextsize = extsz; | |
74 | ||
ce24180d | 75 | if ((xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx)) < 0) { |
1e51132f DW |
76 | printf("%s: XFS_IOC_FSSETXATTR %s: %s\n", |
77 | progname, path, strerror(errno)); | |
9e1595e6 | 78 | exitcode = 1; |
1e51132f DW |
79 | return 0; |
80 | } | |
81 | ||
82 | return 0; | |
83 | } | |
84 | ||
85 | static int | |
86 | get_cowextsize_callback( | |
87 | const char *path, | |
88 | const struct stat *stat, | |
89 | int status, | |
90 | struct FTW *data) | |
91 | { | |
92 | int fd; | |
93 | ||
94 | if (recurse_dir && !S_ISDIR(stat->st_mode)) | |
95 | return 0; | |
96 | ||
97 | fd = open(path, O_RDONLY); | |
98 | if (fd < 0) { | |
99 | fprintf(stderr, _("%s: cannot open %s: %s\n"), | |
100 | progname, path, strerror(errno)); | |
101 | } else { | |
102 | get_cowextsize(path, fd); | |
103 | close(fd); | |
104 | } | |
105 | return 0; | |
106 | } | |
107 | ||
108 | static int | |
109 | set_cowextsize_callback( | |
110 | const char *path, | |
111 | const struct stat *stat, | |
112 | int status, | |
113 | struct FTW *data) | |
114 | { | |
115 | int fd; | |
116 | ||
117 | if (recurse_dir && !S_ISDIR(stat->st_mode)) | |
118 | return 0; | |
119 | ||
120 | fd = open(path, O_RDONLY); | |
121 | if (fd < 0) { | |
122 | fprintf(stderr, _("%s: cannot open %s: %s\n"), | |
123 | progname, path, strerror(errno)); | |
124 | } else { | |
125 | set_cowextsize(path, fd, cowextsize); | |
126 | close(fd); | |
127 | } | |
128 | return 0; | |
129 | } | |
130 | ||
131 | static int | |
132 | cowextsize_f( | |
133 | int argc, | |
134 | char **argv) | |
135 | { | |
136 | size_t blocksize, sectsize; | |
137 | int c; | |
138 | ||
139 | recurse_all = recurse_dir = 0; | |
140 | init_cvtnum(&blocksize, §size); | |
141 | while ((c = getopt(argc, argv, "DR")) != EOF) { | |
142 | switch (c) { | |
143 | case 'D': | |
1e51132f DW |
144 | recurse_dir = 1; |
145 | break; | |
146 | case 'R': | |
147 | recurse_all = 1; | |
1e51132f DW |
148 | break; |
149 | default: | |
150 | return command_usage(&cowextsize_cmd); | |
151 | } | |
152 | } | |
153 | ||
154 | if (optind < argc) { | |
155 | cowextsize = (long)cvtnum(blocksize, sectsize, argv[optind]); | |
156 | if (cowextsize < 0) { | |
157 | printf(_("non-numeric cowextsize argument -- %s\n"), | |
158 | argv[optind]); | |
9e1595e6 | 159 | exitcode = 1; |
1e51132f DW |
160 | return 0; |
161 | } | |
162 | } else { | |
163 | cowextsize = -1; | |
164 | } | |
165 | ||
5fd7257c XY |
166 | if (recurse_all && recurse_dir) { |
167 | fprintf(stderr, _("%s: -R and -D options are mutually exclusive\n"), | |
168 | progname); | |
169 | exitcode = 1; | |
170 | return 0; | |
171 | } | |
172 | ||
1e51132f DW |
173 | if (recurse_all || recurse_dir) |
174 | nftw(file->name, (cowextsize >= 0) ? | |
175 | set_cowextsize_callback : get_cowextsize_callback, | |
176 | 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); | |
177 | else if (cowextsize >= 0) | |
178 | set_cowextsize(file->name, file->fd, cowextsize); | |
179 | else | |
180 | get_cowextsize(file->name, file->fd); | |
181 | return 0; | |
182 | } | |
183 | ||
184 | void | |
185 | cowextsize_init(void) | |
186 | { | |
187 | cowextsize_cmd.name = "cowextsize"; | |
188 | cowextsize_cmd.cfunc = cowextsize_f; | |
189 | cowextsize_cmd.args = _("[-D | -R] [cowextsize]"); | |
190 | cowextsize_cmd.argmin = 0; | |
191 | cowextsize_cmd.argmax = -1; | |
192 | cowextsize_cmd.flags = CMD_NOMAP_OK; | |
193 | cowextsize_cmd.oneline = | |
194 | _("get/set preferred CoW extent size (in bytes) for the open file"); | |
195 | cowextsize_cmd.help = cowextsize_help; | |
196 | ||
197 | add_command(&cowextsize_cmd); | |
198 | } |