]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - growfs/xfs_growfs.c
4d48617ad3d03452fefeba50c232964c9602f0e0
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
15 "Usage: %s [options] mountpoint\n\n\
17 -d grow data/metadata section\n\
18 -l grow log section\n\
19 -r grow realtime section\n\
20 -n don't change anything, just show geometry\n\
21 -i convert log from external to internal format\n\
22 -t alternate location for mount table (/etc/mtab)\n\
23 -x convert log from internal to external format\n\
24 -D size grow data/metadata section to size blks\n\
25 -L size grow/shrink log section to size blks\n\
26 -R size grow realtime section to size blks\n\
27 -e size set realtime extent size to size blks\n\
28 -m imaxpct set inode max percent to imaxpct\n\
29 -V print version information\n"),
35 main(int argc
, char **argv
)
37 int aflag
; /* fake flag, do all pieces */
38 int c
; /* current option character */
39 long long ddsize
; /* device size in 512-byte blocks */
40 int dflag
; /* -d flag */
41 long long dlsize
; /* device size in 512-byte blocks */
42 long long drsize
; /* device size in 512-byte blocks */
43 long long dsize
; /* new data size in fs blocks */
44 int error
; /* we have hit an error */
45 long esize
; /* new rt extent size */
46 int ffd
; /* mount point file descriptor */
47 struct xfs_fsop_geom geo
; /* current fs geometry */
48 int iflag
; /* -i flag */
49 int isint
; /* log is currently internal */
50 int lflag
; /* -l flag */
51 long long lsize
; /* new log size in fs blocks */
52 int maxpct
; /* -m flag value */
53 int mflag
; /* -m flag */
54 int nflag
; /* -n flag */
55 struct xfs_fsop_geom ngeo
; /* new fs geometry */
56 int rflag
; /* -r flag */
57 long long rsize
; /* new rt size in fs blocks */
58 int xflag
; /* -x flag */
59 char *fname
; /* mount point name */
60 char *datadev
; /* data device name */
61 char *logdev
; /* log device name */
62 char *rtdev
; /* RT device name */
63 fs_path_t
*fs
; /* mount point information */
64 libxfs_init_t xi
; /* libxfs structure */
68 progname
= basename(argv
[0]);
69 setlocale(LC_ALL
, "");
70 bindtextdomain(PACKAGE
, LOCALEDIR
);
74 dsize
= lsize
= rsize
= 0LL;
75 aflag
= dflag
= iflag
= lflag
= mflag
= nflag
= rflag
= xflag
= 0;
77 while ((c
= getopt(argc
, argv
, "dD:e:ilL:m:np:rR:t:xV")) != EOF
) {
80 dsize
= strtoll(optarg
, NULL
, 10);
93 lsize
= strtoll(optarg
, NULL
, 10);
100 maxpct
= atoi(optarg
);
109 rsize
= strtoll(optarg
, NULL
, 10);
121 printf(_("%s version %s\n"), progname
, VERSION
);
128 if (argc
- optind
!= 1)
132 if (dflag
+ lflag
+ rflag
+ mflag
== 0)
135 fs_table_initialise(0, NULL
, 0, NULL
);
137 if (!realpath(argv
[optind
], rpath
)) {
138 fprintf(stderr
, _("%s: path resolution failed for %s: %s\n"),
139 progname
, argv
[optind
], strerror(errno
));
143 fs
= fs_table_lookup_mount(rpath
);
145 fprintf(stderr
, _("%s: %s is not a mounted XFS filesystem\n"),
146 progname
, argv
[optind
]);
151 datadev
= fs
->fs_name
;
155 ffd
= open(fname
, O_RDONLY
);
161 if (!platform_test_xfs_fd(ffd
)) {
162 fprintf(stderr
, _("%s: specified file "
163 "[\"%s\"] is not on an XFS filesystem\n"),
168 /* get the current filesystem size & geometry */
169 ret
= xfrog_geometry(ffd
, &geo
);
172 _("%s: cannot determine geometry of filesystem mounted at %s: %s\n"),
173 progname
, fname
, strerror(ret
));
177 isint
= geo
.logstart
> 0;
180 * Need root access from here on (using raw devices)...
183 memset(&xi
, 0, sizeof(xi
));
187 xi
.isreadonly
= LIBXFS_ISREADONLY
;
189 if (!libxfs_init(&xi
))
192 /* check we got the info for all the sections we are trying to modify */
194 fprintf(stderr
, _("%s: failed to access data device for %s\n"),
198 if (lflag
&& !isint
&& !xi
.logdev
) {
199 fprintf(stderr
, _("%s: failed to access external log for %s\n"),
203 if (rflag
&& !xi
.rtdev
) {
205 _("%s: failed to access realtime device for %s\n"),
210 xfs_report_geom(&geo
, datadev
, logdev
, rtdev
);
213 dlsize
= ( xi
.logBBsize
? xi
.logBBsize
:
214 geo
.logblocks
* (geo
.blocksize
/ BBSIZE
) );
218 * Ok, Linux only has a 1024-byte resolution on device _size_,
219 * and the sizes below are in basic 512-byte blocks,
220 * so if we have (size % 2), on any partition, we can't get
221 * to the last 512 bytes. Just chop it down by a block.
224 ddsize
-= (ddsize
% 2);
225 dlsize
-= (dlsize
% 2);
226 drsize
-= (drsize
% 2);
230 if (dflag
| mflag
| aflag
) {
231 xfs_growfs_data_t in
;
234 maxpct
= geo
.imaxpct
;
235 if (!dflag
&& !aflag
) /* Only mflag, no data size change */
236 dsize
= geo
.datablocks
;
238 dsize
= ddsize
/ (geo
.blocksize
/ BBSIZE
);
239 else if (dsize
> ddsize
/ (geo
.blocksize
/ BBSIZE
)) {
241 "data size %lld too large, maximum is %lld\n"),
243 (long long)(ddsize
/(geo
.blocksize
/BBSIZE
)));
247 if (!error
&& dsize
< geo
.datablocks
) {
248 fprintf(stderr
, _("data size %lld too small,"
249 " old size is %lld\n"),
250 (long long)dsize
, (long long)geo
.datablocks
);
253 dsize
== geo
.datablocks
&& maxpct
== geo
.imaxpct
) {
256 "data size unchanged, skipping\n"));
259 "inode max pct unchanged, skipping\n"));
260 } else if (!error
&& !nflag
) {
261 in
.newblocks
= (__u64
)dsize
;
262 in
.imaxpct
= (__u32
)maxpct
;
263 if (xfsctl(fname
, ffd
, XFS_IOC_FSGROWFSDATA
, &in
) < 0) {
264 if (errno
== EWOULDBLOCK
)
266 "%s: growfs operation in progress already\n"),
270 "%s: XFS_IOC_FSGROWFSDATA xfsctl failed: %s\n"),
271 progname
, strerror(errno
));
277 if (!error
&& (rflag
| aflag
)) {
281 esize
= (__u32
)geo
.rtextsize
;
283 rsize
= drsize
/ (geo
.blocksize
/ BBSIZE
);
284 else if (rsize
> drsize
/ (geo
.blocksize
/ BBSIZE
)) {
286 "realtime size %lld too large, maximum is %lld\n"),
287 rsize
, drsize
/ (geo
.blocksize
/ BBSIZE
));
290 if (!error
&& rsize
< geo
.rtblocks
) {
292 "realtime size %lld too small, old size is %lld\n"),
293 (long long)rsize
, (long long)geo
.rtblocks
);
295 } else if (!error
&& rsize
== geo
.rtblocks
) {
298 "realtime size unchanged, skipping\n"));
299 } else if (!error
&& !nflag
) {
300 in
.newblocks
= (__u64
)rsize
;
301 in
.extsize
= (__u32
)esize
;
302 if (xfsctl(fname
, ffd
, XFS_IOC_FSGROWFSRT
, &in
) < 0) {
303 if (errno
== EWOULDBLOCK
)
305 "%s: growfs operation in progress already\n"),
307 else if (errno
== ENOSYS
)
309 "%s: realtime growth not implemented\n"),
313 "%s: XFS_IOC_FSGROWFSRT xfsctl failed: %s\n"),
314 progname
, strerror(errno
));
320 if (!error
&& (lflag
| aflag
)) {
324 lsize
= dlsize
/ (geo
.blocksize
/ BBSIZE
);
330 in
.isint
= xi
.logBBsize
== 0;
331 if (lsize
== geo
.logblocks
&& (in
.isint
== isint
)) {
334 _("log size unchanged, skipping\n"));
336 in
.newblocks
= (__u32
)lsize
;
337 if (xfsctl(fname
, ffd
, XFS_IOC_FSGROWFSLOG
, &in
) < 0) {
338 if (errno
== EWOULDBLOCK
)
340 _("%s: growfs operation in progress already\n"),
342 else if (errno
== ENOSYS
)
344 _("%s: log growth not supported yet\n"),
348 _("%s: XFS_IOC_FSGROWFSLOG xfsctl failed: %s\n"),
349 progname
, strerror(errno
));
355 ret
= xfrog_geometry(ffd
, &ngeo
);
357 fprintf(stderr
, _("%s: XFS_IOC_FSGEOMETRY xfsctl failed: %s\n"),
358 progname
, strerror(ret
));
361 if (geo
.datablocks
!= ngeo
.datablocks
)
362 printf(_("data blocks changed from %lld to %lld\n"),
363 (long long)geo
.datablocks
, (long long)ngeo
.datablocks
);
364 if (geo
.imaxpct
!= ngeo
.imaxpct
)
365 printf(_("inode max percent changed from %d to %d\n"),
366 geo
.imaxpct
, ngeo
.imaxpct
);
367 if (geo
.logblocks
!= ngeo
.logblocks
)
368 printf(_("log blocks changed from %d to %d\n"),
369 geo
.logblocks
, ngeo
.logblocks
);
370 if ((geo
.logstart
== 0) != (ngeo
.logstart
== 0))
371 printf(_("log changed from %s to %s\n"),
372 geo
.logstart
? _("internal") : _("external"),
373 ngeo
.logstart
? _("internal") : _("external"));
374 if (geo
.rtblocks
!= ngeo
.rtblocks
)
375 printf(_("realtime blocks changed from %lld to %lld\n"),
376 (long long)geo
.rtblocks
, (long long)ngeo
.rtblocks
);
377 if (geo
.rtextsize
!= ngeo
.rtextsize
)
378 printf(_("realtime extent size changed from %d to %d\n"),
379 geo
.rtextsize
, ngeo
.rtextsize
);