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/
35 #include <sys/ioctl.h>
37 static char *fname
; /* mount point name */
38 static char *datadev
; /* data device name */
39 static char *logdev
; /* log device name */
40 static char *rtdev
; /* RT device name */
46 "Usage: %s [options] mountpoint\n\n\
48 -d grow data/metadata section\n\
49 -l grow log section\n\
50 -r grow realtime section\n\
51 -n don't change anything, just show geometry\n\
52 -i convert log from external to internal format\n\
53 -t alternate location for mount table (/etc/mtab)\n\
54 -x convert log from internal to external format\n\
55 -D size grow data/metadata section to size blks\n\
56 -L size grow/shrink log section to size blks\n\
57 -R size grow realtime section to size blks\n\
58 -e size set realtime extent size to size blks\n\
59 -m imaxpct set inode max percent to imaxpct\n\
60 -V print version information\n",
73 printf("meta-data=%-22s isize=%-6d agcount=%d, agsize=%d blks\n"
74 "data =%-22s bsize=%-6d blocks=%lld, imaxpct=%d\n"
75 " =%-22s sunit=%-6d swidth=%d blks, unwritten=%d\n"
76 "naming =version %-14d bsize=%-6d\n"
77 "log =%-22s bsize=%-6d blocks=%d\n"
78 "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n",
79 mntpoint
, geo
.inodesize
, geo
.agcount
, geo
.agblocks
,
80 "", geo
.blocksize
, (long long)geo
.datablocks
, geo
.imaxpct
,
81 "", geo
.sunit
, geo
.swidth
, unwritten
,
82 dirversion
, geo
.dirblocksize
,
83 isint
? "internal" : "external", geo
.blocksize
, geo
.logblocks
,
84 geo
.rtblocks
? "external" : "none",
85 geo
.rtextsize
* geo
.blocksize
,
86 (long long)geo
.rtblocks
, (long long)geo
.rtextents
);
90 explore_mtab(char *mtab
, char *mntpoint
)
93 struct stat64 statuser
;
94 struct stat64 statmtab
;
99 if ((mtp
= setmntent(mtab
, "r")) == NULL
) {
100 fprintf(stderr
, "%s: cannot access mount list %s: %s\n",
101 progname
, MOUNTED
, strerror(errno
));
104 if (stat64(mntpoint
, &statuser
) < 0) {
105 fprintf(stderr
, "%s: cannot access mount point %s: %s\n",
106 progname
, mntpoint
, strerror(errno
));
110 while ((mnt
= getmntent(mtp
)) != NULL
) {
111 if (stat64(mnt
->mnt_dir
, &statmtab
) < 0) {
112 fprintf(stderr
, "%s: ignoring entry %s in %s: %s\n",
113 progname
, mnt
->mnt_dir
, mtab
, strerror(errno
));
116 if (statuser
.st_ino
!= statmtab
.st_ino
||
117 statuser
.st_dev
!= statmtab
.st_dev
)
119 else if (strcmp(mnt
->mnt_type
, "xfs") != 0) {
120 fprintf(stderr
, "%s: %s is not an XFS filesystem\n",
124 break; /* we've found it */
129 "%s: %s is not a filesystem mount point, according to %s\n",
130 progname
, mntpoint
, MOUNTED
);
134 /* find the data, log (logdev=), and realtime (rtdev=) devices */
135 rtend
= logend
= NULL
;
136 fname
= mnt
->mnt_dir
;
137 datadev
= mnt
->mnt_fsname
;
138 if ((logdev
= hasmntopt(mnt
, "logdev="))) {
140 logend
= strtok(logdev
, " ,");
142 if ((rtdev
= hasmntopt(mnt
, "rtdev="))) {
144 rtend
= strtok(rtdev
, " ,");
147 /* Do this only after we've finished processing mount options */
148 if (logdev
&& logend
!= logdev
)
149 *logend
= '\0'; /* terminate end of log device name */
150 if (rtdev
&& rtend
!= rtdev
)
151 *rtend
= '\0'; /* terminate end of rt device name */
157 main(int argc
, char **argv
)
159 int aflag
; /* fake flag, do all pieces */
160 int c
; /* current option character */
161 long long ddsize
; /* device size in 512-byte blocks */
162 int dflag
; /* -d flag */
163 int dirversion
; /* directory version number */
164 long long dlsize
; /* device size in 512-byte blocks */
165 long long drsize
; /* device size in 512-byte blocks */
166 long long dsize
; /* new data size in fs blocks */
167 int error
; /* we have hit an error */
168 long esize
; /* new rt extent size */
169 int ffd
; /* mount point file descriptor */
170 xfs_fsop_geom_t geo
; /* current fs geometry */
171 int iflag
; /* -i flag */
172 int isint
; /* log is currently internal */
173 int lflag
; /* -l flag */
174 long long lsize
; /* new log size in fs blocks */
175 int maxpct
; /* -m flag value */
176 int mflag
; /* -m flag */
177 char *mtab
; /* mount table file (/etc/mtab) */
178 int nflag
; /* -n flag */
179 xfs_fsop_geom_t ngeo
; /* new fs geometry */
180 int rflag
; /* -r flag */
181 long long rsize
; /* new rt size in fs blocks */
182 int unwritten
; /* unwritten extent flag */
183 int xflag
; /* -x flag */
184 libxfs_init_t xi
; /* libxfs structure */
187 progname
= basename(argv
[0]);
188 aflag
= dflag
= iflag
= lflag
= mflag
= nflag
= rflag
= xflag
= 0;
190 dsize
= lsize
= rsize
= 0LL;
191 while ((c
= getopt(argc
, argv
, "dD:e:ilL:m:np:rR:t:xV")) != EOF
) {
194 dsize
= atoll(optarg
);
200 esize
= atol(optarg
);
207 lsize
= atoll(optarg
);
214 maxpct
= atoi(optarg
);
223 rsize
= atoll(optarg
);
235 printf("%s version %s\n", progname
, VERSION
);
242 if (argc
- optind
!= 1)
246 if (dflag
+ lflag
+ rflag
== 0)
249 explore_mtab(mtab
, argv
[optind
]);
251 ffd
= open(fname
, O_RDONLY
);
257 /* get the current filesystem size & geometry */
258 if (ioctl(ffd
, XFS_IOC_FSGEOMETRY
, &geo
) < 0) {
259 fprintf(stderr
, "%s: cannot determine geometry of filesystem"
260 " mounted at %s: %s\n",
261 progname
, fname
, strerror(errno
));
264 isint
= geo
.logstart
> 0;
265 unwritten
= geo
.flags
& XFS_FSOP_GEOM_FLAGS_EXTFLG
? 1 : 0;
266 dirversion
= geo
.flags
& XFS_FSOP_GEOM_FLAGS_DIRV2
? 2 : 1;
269 report_info(geo
, fname
, unwritten
, dirversion
, isint
);
274 * Need root access from here on (using raw devices)...
277 bzero(&xi
, sizeof(xi
));
282 xi
.isreadonly
= LIBXFS_ISREADONLY
;
284 if (!libxfs_init(&xi
))
287 /* check we got the info for all the sections we are trying to modify */
289 fprintf(stderr
, "%s: failed to access data device for %s\n",
293 if (lflag
&& !isint
&& !xi
.logdev
) {
294 fprintf(stderr
, "%s: failed to access external log for %s\n",
298 if (rflag
&& !xi
.rtdev
) {
299 fprintf(stderr
, "%s: failed to access realtime device for %s\n",
304 report_info(geo
, fname
, unwritten
, dirversion
, isint
);
307 dlsize
= ( xi
.logBBsize
? xi
.logBBsize
:
308 geo
.logblocks
* (geo
.blocksize
/ BBSIZE
) );
313 xfs_growfs_data_t in
;
316 maxpct
= geo
.imaxpct
;
318 dsize
= ddsize
/ (geo
.blocksize
/ BBSIZE
);
319 else if (dsize
> ddsize
/ (geo
.blocksize
/ BBSIZE
)) {
321 "data size %lld too large, maximum is %lld\n",
323 (long long)(ddsize
/(geo
.blocksize
/BBSIZE
)));
326 if (!error
&& dsize
< geo
.datablocks
) {
327 fprintf(stderr
, "data size %lld too small,"
328 " old size is %lld\n",
329 (long long)dsize
, (long long)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 (long long)rsize
, (long long)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 (long long)geo
.datablocks
, (long long)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 (long long)geo
.rtblocks
, (long long)ngeo
.rtblocks
);
454 if (geo
.rtextsize
!= ngeo
.rtextsize
)
455 printf("realtime extent size changed from %d to %d\n",
456 geo
.rtextsize
, ngeo
.rtextsize
);