#
PKG_MAJOR=1
PKG_MINOR=3
-PKG_REVISION=5
+PKG_REVISION=6
PKG_BUILD=0
-xfsprogs-current
+xfsprogs-1.3.6 (31 August 2001)
+ - make mkfs.xfs aware of geometries that might cause
+ inode numbers to exceed 32 significant bits.
+ - make xfs_growfs warn if new filesystem will have
+ inode numbers that exceed 32 significant bits.
- fix logprint bug in reporting extended attributes
(thanks to Tang Lingbo <tanglb@sina.com> for fixing this)
- fix mkfs.xfs core dump when attemping to run on devices
#include <mntent.h>
#include <sys/ioctl.h>
+/*
+ * When growing a filesystem, this is the most significant
+ * bits we'll accept in the resulting inode numbers
+ * without warning the user.
+ */
+
+#define XFS_MAX_INODE_SIG_BITS 32
+
static char *fname; /* mount point name */
static char *datadev; /* data device name */
static char *logdev; /* log device name */
-l grow log section\n\
-r grow realtime section\n\
-n don't change anything, just show geometry\n\
+ -I allow inode numbers to exceed %d significant bits\n\
-i convert log from external to internal format\n\
-t alternate location for mount table (/etc/mtab)\n\
-x convert log from internal to external format\n\
-e size set realtime extent size to size blks\n\
-m imaxpct set inode max percent to imaxpct\n\
-V print version information\n",
- progname);
+ progname, XFS_MAX_INODE_SIG_BITS);
exit(2);
}
int dirversion,
int isint)
{
+
+ int inodebits;
+
+ inodebits = (libxfs_highbit32(geo.blocksize/geo.inodesize - 1) + 1)
+ + (libxfs_highbit64(geo.agblocks - 1) + 1)
+ + (libxfs_highbit64(geo.agcount - 1) + 1);
+
printf("meta-data=%-22s isize=%-6d agcount=%d, agsize=%d blks\n"
"data =%-22s bsize=%-6d blocks=%lld, imaxpct=%d\n"
" =%-22s sunit=%-6d swidth=%d blks, unwritten=%d\n"
+ " =%-22s imaxbits=%-6d\n"
"naming =version %-14d bsize=%-6d\n"
"log =%-22s bsize=%-6d blocks=%d\n"
"realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n",
mntpoint, geo.inodesize, geo.agcount, geo.agblocks,
"", geo.blocksize, (long long)geo.datablocks, geo.imaxpct,
"", geo.sunit, geo.swidth, unwritten,
+ "", inodebits,
dirversion, geo.dirblocksize,
isint ? "internal" : "external", geo.blocksize, geo.logblocks,
geo.rtblocks ? "external" : "none",
long esize; /* new rt extent size */
int ffd; /* mount point file descriptor */
xfs_fsop_geom_t geo; /* current fs geometry */
+ int Iflag; /* force flag for big inode numbers */
int iflag; /* -i flag */
int isint; /* log is currently internal */
int lflag; /* -l flag */
mtab = MOUNTED;
progname = basename(argv[0]);
- aflag = dflag = iflag = lflag = mflag = nflag = rflag = xflag = 0;
+ aflag = dflag = Iflag = iflag = lflag = mflag = nflag = rflag = xflag = 0;
maxpct = esize = 0;
dsize = lsize = rsize = 0LL;
- while ((c = getopt(argc, argv, "dD:e:ilL:m:np:rR:t:xV")) != EOF) {
+ while ((c = getopt(argc, argv, "dD:e:IilL:m:np:rR:t:xV")) != EOF) {
switch (c) {
case 'D':
dsize = atoll(optarg);
esize = atol(optarg);
rflag = 1;
break;
+ case 'I':
+ Iflag = 1;
+ break;
case 'i':
lflag = iflag = 1;
break;
error = 0;
if (dflag | aflag) {
xfs_growfs_data_t in;
-
+ int inodebits;
+ __uint64_t new_agcount;
+
if (!mflag)
maxpct = geo.imaxpct;
if (!dsize)
(long long)(ddsize/(geo.blocksize/BBSIZE)));
error = 1;
}
+
+ new_agcount = dsize / geo.agblocks
+ + (dsize % geo.agblocks != 0);
+
+ inodebits = (libxfs_highbit32(geo.blocksize/geo.inodesize - 1) + 1)
+ + (libxfs_highbit64(geo.agblocks - 1) + 1)
+ + (libxfs_highbit64(new_agcount - 1) + 1);
+
if (!error && dsize < geo.datablocks) {
fprintf(stderr, "data size %lld too small,"
" old size is %lld\n",
if (mflag)
fprintf(stderr,
"inode max pct unchanged, skipping\n");
+ } else if (!error && !Iflag
+ && inodebits > XFS_MAX_INODE_SIG_BITS) {
+ fprintf(stderr,
+ "warning: inode numbers would exceed %d "
+ "significant bits (%d)\n"
+ " Use -I option to allow this\n",
+ XFS_MAX_INODE_SIG_BITS, inodebits);
+ error = 1;
} else if (!error && !nflag) {
in.newblocks = (__u64)dsize;
in.imaxpct = (__u32)maxpct;
progname, strerror(errno));
error = 1;
}
+ if (inodebits > XFS_MAX_INODE_SIG_BITS) {
+ fprintf(stderr,
+ "inode numbers exceed %d "
+ "significant bits (%d)\n",
+ XFS_MAX_INODE_SIG_BITS, inodebits);
+ }
}
}
The maximum value is 2048 (2 KB) subject to the restriction that
the inode size cannot exceed one half of the filesystem block size.
.IP
+XFS uses 64-bit inode numbers internally; however, the number of
+significant bits in an inode number
+is affected by filesystem geometry. In
+practice, filesystem size and inode size are the predominant factors.
+The Linux kernel and most applications cannot currently handle
+inode numbers greater than 32 significant bits, so if no
+inode size is given on the command line,
+.I mkfs.xfs
+will attempt to choose a size
+such that inode numbers will be < 32 bits. If an inode size
+is specified, or if a filesystem is sufficently large,
+.I mkfs.xfs
+will warn if this will create inode numbers > 32 significant
+bits.
+.IP
The option \f3maxpct=\f1\f2value\f1 specifies the maximum percentage
of space in the filesystem that can be allocated to inodes.
The default value is 25%.
xfs_growfs, xfs_info \- expand an XFS filesystem
.SH SYNOPSIS
.nf
-\f3xfs_growfs\f1 [ \f3\-dilnrxV\f1 ] [ \f3\-D\f1 size ] [ \f3\-e\f1 rtextsize ]
+\f3xfs_growfs\f1 [ \f3\-dIilnrxV\f1 ] [ \f3\-D\f1 size ] [ \f3\-e\f1 rtextsize ]
[ \f3\-L\f1 size ] [ \f3\-m\f1 maxpct ] [ \f3-t\f1 mtab ]
[ \f3\-R\f1 size ] mount-point
\f3xfs_info\f1 [ \f3-t\f1 mtab ] mount-point
.B \-r
.BI extsize= nnnn.
.TP
+.B \-I
+Allow new inode numbers to exceed 32 significant bits.
+(See CONSIDERATIONS below.)
+.TP
.B \-i
The new log is an internal log
(inside the data section).
disk partition available.
Adding the space is done through the mechanism of
logical volumes.
+.SH CONSIDERATIONS
+XFS uses 64-bit inode numbers internally; however, the number of
+significant bits in an inode number is
+affected by filesystem geometry. In
+practice, filesystem size and inode size are the predominant factors.
+The Linux kernel and most applications cannot currently handle
+inode numbers greater than 32 significant bits, so
+.I xfs_growfs
+will issue a warning and fail if growing the filesystem will
+cause the significant bits in inode numbers to exceed 32 bits.
+This can be overwritten with the
+.B \-I
+option.
+.PP
+If you anticipate significantly growing filesystems after using
+.I mkfs.xfs
+you should take into consideration this inode number growth
+as well,
+and keep the number of significant digits sufficiently small
+to allow for future growth. On average, doubling the size
+of the inode will reduce significant bits by one, and doubling
+the size of the filesystem will increase significant bits
+by one.
.SH SEE ALSO
mkfs.xfs(8),
lvm(8),
int imaxpct;
int imflag;
int inodelog;
+ int inodebits;
int inopblock;
int ipflag;
int isflag;
}
}
+ /*
+ * Check to see if inode number will be > 32 significant bits
+ * Note that libxfs_highbitXX returns 0 -> XX-1,
+ * so to get the bit count, add one to what we get.
+ */
+
+ inodebits = (libxfs_highbit32(blocksize/isize - 1) + 1)
+ + (libxfs_highbit64(agsize - 1) + 1)
+ + (libxfs_highbit64(agcount - 1) + 1);
+
+ if (inodebits > XFS_MAX_INODE_SIG_BITS) {
+
+ int new_isize;
+ int new_isize_ok;
+
+ new_isize = isize << (inodebits - XFS_MAX_INODE_SIG_BITS);
+
+ new_isize_ok = (new_isize <= blocksize / XFS_MIN_INODE_PERBLOCK
+ && new_isize <= XFS_DINODE_MAX_SIZE);
+
+ if (ilflag + ipflag + isflag == 0) {
+ /*
+ * If we didn't specify inode size, just bump it up
+ * unless we can't go far enough.
+ */
+
+ if (new_isize_ok) {
+ isize = new_isize;
+ /* re-calc inodebits */
+ inodebits = (libxfs_highbit32(blocksize/isize - 1) + 1)
+ + (libxfs_highbit64(agsize - 1) + 1)
+ + (libxfs_highbit64(agcount - 1) + 1);
+ /* Let's not get too chatty, no fprintf here */
+ } else {
+ /*
+ * Can't do nothin' for ya, man!
+ * Don't bother changing isize at all,
+ * one bit over is as bad as 20.
+ */
+ fprintf(stderr,
+ "warning: inode numbers exceed %d "
+ " significant bits (%d)\n",
+ XFS_MAX_INODE_SIG_BITS, inodebits);
+ }
+ } else {
+ /* if isize specified, just warn the user */
+ fprintf(stderr,
+ "warning: inode numbers exceed %d "
+ "significant bits (%d)\n",
+ XFS_MAX_INODE_SIG_BITS, inodebits);
+ if (new_isize_ok) {
+ fprintf(stderr,
+ " increase inode size to %d to "
+ "avoid this\n", new_isize);
+ }
+ }
+ }
+
protostring = setup_proto(protofile);
bsize = 1 << (blocklog - BBSHIFT);
buf = libxfs_getbuf(xi.ddev, XFS_SB_DADDR, 1);
"meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
"data =%-22s bsize=%-6d blocks=%lld, imaxpct=%d\n"
" =%-22s sunit=%-6d swidth=%d blks, unwritten=%d\n"
+ " =%-22s imaxbits=%-6d\n"
"naming =version %-14d bsize=%-6d\n"
"log =%-22s bsize=%-6d blocks=%lld\n"
"realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n",
dfile, isize, (long long)agcount, (long long)agsize,
"", blocksize, (long long)dblocks, sbp->sb_imax_pct,
"", dsunit, dswidth, extent_flagging,
+ "", inodebits,
dirversion, dirversion == 1 ? blocksize : dirblocksize,
logfile, 1 << blocklog, (long long)logblocks,
rtfile, rtextblocks << blocklog,
#define XFS_MIN_LOG_FACTOR 3 /* min log size factor */
#define XFS_DFL_LOG_FACTOR 16 /* default log size, factor */
/* with max trans reservation */
+#define XFS_MAX_INODE_SIG_BITS 32 /* most significant bits in an
+ * inode number that we'll
+ * accept w/o warnings
+ */
extern void usage (void);
extern long long cvtnum (int blocksize, char *s);