2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
37 #include <sys/ioctl.h>
39 static char *fname
; /* mount point name */
40 static char *datadev
; /* data device name */
41 static char *logdev
; /* log device name */
42 static char *rtdev
; /* RT device name */
48 "Usage: %s [options] mountpoint\n\n\
50 -d grow data/metadata section\n\
51 -l grow log section\n\
52 -r grow realtime section\n\
53 -n don't change anything, just show geometry\n\
54 -i convert log from external to internal format\n\
55 -t alternate location for mount table (/etc/mtab)\n\
56 -x convert log from internal to external format\n\
57 -D size grow data/metadata section to size blks\n\
58 -L size grow/shrink log section to size blks\n\
59 -R size grow realtime section to size blks\n\
60 -e size set realtime extent size to size blks\n\
61 -m imaxpct set inode max percent to imaxpct\n\
62 -V print version information\n",
75 printf("meta-data=%-22s isize=%-6d agcount=%d, agsize=%d blks\n"
76 "data =%-22s bsize=%-6d blocks=%lld, imaxpct=%d\n"
77 " =%-22s sunit=%-6d swidth=%d blks, unwritten=%d\n"
78 "naming =version %-14d bsize=%-6d\n"
79 "log =%-22s bsize=%-6d blocks=%d\n"
80 "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n",
81 mntpoint
, geo
.inodesize
, geo
.agcount
, geo
.agblocks
,
82 "", geo
.blocksize
, geo
.datablocks
, geo
.imaxpct
,
83 "", geo
.sunit
, geo
.swidth
, unwritten
,
84 dirversion
, geo
.dirblocksize
,
85 isint
? "internal" : "external", geo
.blocksize
, geo
.logblocks
,
86 geo
.rtblocks
? "external" : "none",
87 geo
.rtextsize
* geo
.blocksize
, geo
.rtblocks
, geo
.rtextents
);
91 explore_mtab(char *mtab
, char *mntpoint
)
94 struct stat64 statuser
;
95 struct stat64 statmtab
;
100 if ((mtp
= setmntent(mtab
, "r")) == NULL
) {
101 fprintf(stderr
, "%s: cannot access mount list %s: %s\n",
102 progname
, MOUNTED
, strerror(errno
));
105 if (stat64(mntpoint
, &statuser
) < 0) {
106 fprintf(stderr
, "%s: cannot access mount point %s: %s\n",
107 progname
, mntpoint
, strerror(errno
));
111 while ((mnt
= getmntent(mtp
)) != NULL
) {
112 if (stat64(mnt
->mnt_dir
, &statmtab
) < 0) {
113 fprintf(stderr
, "%s: ignoring entry %s in %s: %s\n",
114 progname
, mnt
->mnt_dir
, mtab
, strerror(errno
));
117 if (statuser
.st_ino
!= statmtab
.st_ino
||
118 statuser
.st_dev
!= statmtab
.st_dev
)
120 else if (strcmp(mnt
->mnt_type
, "xfs") != 0) {
121 fprintf(stderr
, "%s: %s is not an XFS filesystem\n",
125 break; /* we've found it */
130 "%s: %s is not a filesystem mount point, according to %s\n",
131 progname
, mntpoint
, MOUNTED
);
135 /* find the data, log (logdev=), and realtime (rtdev=) devices */
136 rtend
= logend
= NULL
;
137 fname
= mnt
->mnt_dir
;
138 datadev
= mnt
->mnt_fsname
;
139 if (logdev
= hasmntopt(mnt
, "logdev=")) {
141 logend
= strtok(logdev
, " ");
143 if (rtdev
= hasmntopt(mnt
, "rtdev=")) {
145 rtend
= strtok(rtdev
, " ");
148 /* Do this only after we've finished processing mount options */
149 if (logdev
&& logend
!= logdev
)
150 *logend
= '\0'; /* terminate end of log device name */
151 if (rtdev
&& rtend
!= rtdev
)
152 *rtend
= '\0'; /* terminate end of rt device name */
158 main(int argc
, char **argv
)
160 int aflag
; /* fake flag, do all pieces */
161 int c
; /* current option character */
162 long long ddsize
; /* device size in 512-byte blocks */
163 int dflag
; /* -d flag */
164 int dirversion
; /* directory version number */
165 long long dlsize
; /* device size in 512-byte blocks */
166 long long drsize
; /* device size in 512-byte blocks */
167 long long dsize
; /* new data size in fs blocks */
168 int error
; /* we have hit an error */
169 long esize
; /* new rt extent size */
170 int ffd
; /* mount point file descriptor */
171 xfs_fsop_geom_t geo
; /* current fs geometry */
172 int iflag
; /* -i flag */
173 int isint
; /* log is currently internal */
174 int lflag
; /* -l flag */
175 long long lsize
; /* new log size in fs blocks */
176 int maxpct
; /* -m flag value */
177 int mflag
; /* -m flag */
178 char *mtab
; /* mount table file (/etc/mtab) */
179 int nflag
; /* -n flag */
180 xfs_fsop_geom_t ngeo
; /* new fs geometry */
181 int rflag
; /* -r flag */
182 long long rsize
; /* new rt size in fs blocks */
183 int unwritten
; /* unwritten extent flag */
184 int xflag
; /* -x flag */
185 libxfs_init_t xi
; /* libxfs structure */
188 progname
= basename(argv
[0]);
189 aflag
= dflag
= iflag
= lflag
= mflag
= nflag
= rflag
= xflag
= 0;
191 dsize
= lsize
= rsize
= 0LL;
192 while ((c
= getopt(argc
, argv
, "dD:e:ilL:m:np:rR:t:xV")) != EOF
) {
195 dsize
= atoll(optarg
);
201 esize
= atol(optarg
);
208 lsize
= atoll(optarg
);
215 maxpct
= atoi(optarg
);
224 rsize
= atoll(optarg
);
236 printf("%s version %s\n", progname
, VERSION
);
243 if (argc
- optind
!= 1)
247 if (dflag
+ lflag
+ rflag
== 0)
250 explore_mtab(mtab
, argv
[optind
]);
252 ffd
= open(fname
, O_RDONLY
);
258 /* get the current filesystem size & geometry */
259 if (ioctl(ffd
, XFS_IOC_FSGEOMETRY
, &geo
) < 0) {
260 fprintf(stderr
, "%s: cannot determine geometry of filesystem"
261 " mounted at %s: %s\n",
262 progname
, fname
, strerror(errno
));
265 isint
= geo
.logstart
> 0;
266 unwritten
= geo
.flags
& XFS_FSOP_GEOM_FLAGS_EXTFLG
? 1 : 0;
267 dirversion
= geo
.flags
& XFS_FSOP_GEOM_FLAGS_DIRV2
? 2 : 1;
270 report_info(geo
, fname
, unwritten
, dirversion
, isint
);
275 * Need root access from here on (using raw devices)...
278 bzero(&xi
, sizeof(xi
));
283 xi
.isreadonly
= LIBXFS_ISREADONLY
;
285 if (!libxfs_init(&xi
))
288 /* check we got the info for all the sections we are trying to modify */
290 fprintf(stderr
, "%s: failed to access data device for %s\n",
294 if (lflag
&& !isint
&& !xi
.logdev
) {
295 fprintf(stderr
, "%s: failed to access external log for %s\n",
299 if (rflag
&& !xi
.rtdev
) {
300 fprintf(stderr
, "%s: failed to access realtime device for %s\n",
305 report_info(geo
, fname
, unwritten
, dirversion
, isint
);
308 dlsize
= ( xi
.logBBsize
? xi
.logBBsize
:
309 geo
.logblocks
* (geo
.blocksize
/ BBSIZE
) );
314 xfs_growfs_data_t in
;
317 maxpct
= geo
.imaxpct
;
319 dsize
= ddsize
/ (geo
.blocksize
/ BBSIZE
);
320 else if (dsize
> ddsize
/ (geo
.blocksize
/ BBSIZE
)) {
322 "data size %llu too large, maximum is %lld\n",
323 (__u64
)dsize
, ddsize
/(geo
.blocksize
/BBSIZE
));
326 if (!error
&& dsize
< geo
.datablocks
) {
327 fprintf(stderr
, "data size %llu too small,"
328 " old size is %lld\n",
329 (__u64
)dsize
, geo
.datablocks
);
332 dsize
== geo
.datablocks
&& maxpct
== geo
.imaxpct
) {
335 "data size unchanged, skipping\n");
338 "inode max pct unchanged, skipping\n");
339 } else if (!error
&& !nflag
) {
340 in
.newblocks
= (__u64
)dsize
;
341 in
.imaxpct
= (__u32
)maxpct
;
342 if (ioctl(ffd
, XFS_IOC_FSGROWFSDATA
, &in
) < 0) {
343 if (errno
== EWOULDBLOCK
)
345 "%s: growfs operation in progress already\n",
349 "%s: ioctl failed - XFS_IOC_FSGROWFSDATA: %s\n",
350 progname
, strerror(errno
));
356 if (!error
&& (rflag
| aflag
)) {
360 esize
= (__u32
)geo
.rtextsize
;
362 rsize
= drsize
/ (geo
.blocksize
/ BBSIZE
);
363 else if (rsize
> drsize
/ (geo
.blocksize
/ BBSIZE
)) {
365 "realtime size %lld too large, maximum is %lld\n",
366 rsize
, drsize
/ (geo
.blocksize
/ BBSIZE
));
369 if (!error
&& rsize
< geo
.rtblocks
) {
371 "realtime size %lld too small, old size is %lld\n",
372 rsize
, geo
.rtblocks
);
374 } else if (!error
&& rsize
== geo
.rtblocks
) {
377 "realtime size unchanged, skipping\n");
378 } else if (!error
&& !nflag
) {
379 in
.newblocks
= (__u64
)rsize
;
380 in
.extsize
= (__u32
)esize
;
381 if (ioctl(ffd
, XFS_IOC_FSGROWFSRT
, &in
) < 0) {
382 if (errno
== EWOULDBLOCK
)
384 "%s: growfs operation in progress already\n",
386 else if (errno
== ENOSYS
)
388 "%s: realtime growth not implemented\n",
392 "%s: ioctl failed - XFS_IOC_FSGROWFSRT: %s\n",
393 progname
, strerror(errno
));
399 if (!error
&& (lflag
| aflag
)) {
403 lsize
= dlsize
/ (geo
.blocksize
/ BBSIZE
);
409 in
.isint
= xi
.logBBsize
== 0;
410 if (lsize
== geo
.logblocks
&& (in
.isint
== isint
)) {
413 "log size unchanged, skipping\n");
415 in
.newblocks
= (__u32
)lsize
;
416 if (ioctl(ffd
, XFS_IOC_FSGROWFSLOG
, &in
) < 0) {
417 if (errno
== EWOULDBLOCK
)
419 "%s: growfs operation in progress already\n",
421 else if (errno
== ENOSYS
)
423 "%s: log growth not supported yet\n", progname
);
426 "%s: ioctl failed - XFS_IOC_FSGROWFSLOG: %s\n",
427 progname
, strerror(errno
));
433 if (ioctl(ffd
, XFS_IOC_FSGEOMETRY
, &ngeo
) < 0) {
434 fprintf(stderr
, "%s: ioctl failed - XFS_IOC_FSGEOMETRY: %s\n",
435 progname
, strerror(errno
));
438 if (geo
.datablocks
!= ngeo
.datablocks
)
439 printf("data blocks changed from %lld to %lld\n",
440 geo
.datablocks
, ngeo
.datablocks
);
441 if (geo
.imaxpct
!= ngeo
.imaxpct
)
442 printf("inode max percent changed from %d to %d\n",
443 geo
.imaxpct
, ngeo
.imaxpct
);
444 if (geo
.logblocks
!= ngeo
.logblocks
)
445 printf("log blocks changed from %d to %d\n",
446 geo
.logblocks
, ngeo
.logblocks
);
447 if ((geo
.logstart
== 0) != (ngeo
.logstart
== 0))
448 printf("log changed from %s to %s\n",
449 geo
.logstart
? "internal" : "external",
450 ngeo
.logstart
? "internal" : "external");
451 if (geo
.rtblocks
!= ngeo
.rtblocks
)
452 printf("realtime blocks changed from %lld to %lld\n",
453 geo
.rtblocks
, ngeo
.rtblocks
);
454 if (geo
.rtextsize
!= ngeo
.rtextsize
)
455 printf("realtime extent size changed from %d to %d\n",
456 geo
.rtextsize
, ngeo
.rtextsize
);