Merge of master-melb:xfs-cmds:31229a by kenmcd.
Bump to 2.10.0
# This file is used by configure to get version information
#
PKG_MAJOR=2
-PKG_MINOR=9
-PKG_REVISION=8
+PKG_MINOR=10
+PKG_REVISION=0
PKG_BUILD=1
tag_err += INT_GET(*tagp, ARCH_CONVERT) != (char *)dep - (char *)data;
addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, db,
(char *)dep - (char *)data);
- hash = libxfs_da_hashname((uchar_t *)dep->name, dep->namelen);
+ hash = mp->m_dirnameops->hashname((uchar_t *)dep->name, dep->namelen);
dir_hash_add(hash, addr);
ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
count++;
strcat(s, ",EXTFLG");
if (XFS_SB_VERSION_HASSECTOR(sbp))
strcat(s, ",SECTOR");
+ if (xfs_sb_version_hasasciici(sbp))
+ strcat(s, ",ASCII_CI");
if (XFS_SB_VERSION_HASMOREBITS(sbp))
strcat(s, ",MOREBITS");
if (XFS_SB_VERSION_HASATTR2(sbp))
+xfsprogs-2.10.0 (26 May 2008)
+ - Add ASCII case-insensitive support to xfsprogs.
+
xfsprogs-2.9.8 (21 April 2008)
- Add support for sb_features2 in wrong location in mkfs.xfs,
xfs_repair and xfs_db.
int lazycount,
int dirversion,
int logversion,
- int attrversion)
+ int attrversion,
+ int cimode)
{
printf(_(
"meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n"
" =%-22s sectsz=%-5u attr=%u\n"
"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
" =%-22s sunit=%-6u swidth=%u blks\n"
- "naming =version %-14u bsize=%-6u\n"
+ "naming =version %-14u bsize=%-6u mixed-case=%c\n"
"log =%-22s bsize=%-6u blocks=%u, version=%u\n"
" =%-22s sectsz=%-5u sunit=%u blks, lazy-count=%u\n"
"realtime =%-22s extsz=%-6u blocks=%llu, rtextents=%llu\n"),
"", geo.blocksize, (unsigned long long)geo.datablocks,
geo.imaxpct,
"", geo.sunit, geo.swidth,
- dirversion, geo.dirblocksize,
+ dirversion, geo.dirblocksize, cimode ? 'N' : 'Y',
isint ? _("internal") : logname ? logname : _("external"),
geo.blocksize, geo.logblocks, logversion,
"", geo.logsectsize, geo.logsunit / geo.blocksize, lazycount,
xfs_fsop_geom_t ngeo; /* new fs geometry */
int rflag; /* -r flag */
long long rsize; /* new rt size in fs blocks */
+ int ci; /* ASCII case-insensitive fs */
int lazycount; /* lazy superblock counters */
int xflag; /* -x flag */
char *fname; /* mount point name */
maxpct = esize = 0;
dsize = lsize = rsize = 0LL;
aflag = dflag = iflag = lflag = mflag = nflag = rflag = xflag = 0;
+ ci = 0;
while ((c = getopt(argc, argv, "dD:e:ilL:m:np:rR:t:xV")) != EOF) {
switch (c) {
logversion = geo.flags & XFS_FSOP_GEOM_FLAGS_LOGV2 ? 2 : 1;
attrversion = geo.flags & XFS_FSOP_GEOM_FLAGS_ATTR2 ? 2 : \
(geo.flags & XFS_FSOP_GEOM_FLAGS_ATTR ? 1 : 0);
-
+ ci = geo.flags & XFS_FSOP_GEOM_FLAGS_DIRV2CI ? 1 : 0;
if (nflag) {
report_info(geo, datadev, isint, logdev, rtdev,
lazycount, dirversion, logversion,
- attrversion);
+ attrversion, ci);
exit(0);
}
report_info(geo, datadev, isint, logdev, rtdev,
lazycount, dirversion, logversion,
- attrversion);
+ attrversion, ci);
ddsize = xi.dsize;
dlsize = ( xi.logBBsize? xi.logBBsize :
int m_attr_magicpct;/* 37% of the blocksize */
int m_dir_magicpct; /* 37% of the dir blocksize */
__uint8_t m_dirversion; /* 1 or 2 */
+ const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */
int m_dirblksize; /* directory block sz--bytes */
int m_dirblkfsbs; /* directory block sz--fsbs */
xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */
* Btree searching and modification structure definitions.
*========================================================================*/
+/*
+ * Search comparison results
+ */
+enum xfs_dacmp {
+ XFS_CMP_DIFFERENT, /* names are completely different */
+ XFS_CMP_EXACT, /* names are exactly the same */
+ XFS_CMP_CASE /* names are same but differ in case */
+};
+
/*
* Structure to ease passing around component names.
*/
unsigned char rename; /* T/F: this is an atomic rename op */
unsigned char addname; /* T/F: this is an add operation */
unsigned char oknoent; /* T/F: ok to return ENOENT, else die */
+ enum xfs_dacmp cmpresult; /* name compare result for lookups */
} xfs_da_args_t;
/*
(uint)(XFS_DA_LOGOFF(BASE, ADDR)), \
(uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1)
+/*
+ * Name ops for directory and/or attr name operations
+ */
+struct xfs_nameops {
+ xfs_dahash_t (*hashname)(const uchar_t *, int);
+ enum xfs_dacmp (*compname)(const uchar_t *, int, const uchar_t *, int);
+};
+
#ifdef __KERNEL__
/*========================================================================
xfs_dabuf_t *dead_buf);
uint xfs_da_hashname(const uchar_t *name_string, int name_length);
+enum xfs_dacmp xfs_da_compname(const uchar_t *name1, int len1,
+ const uchar_t *name2, int len2);
+
uint xfs_da_log2_roundup(uint i);
xfs_da_state_t *xfs_da_state_alloc(void);
void xfs_da_state_free(xfs_da_state_t *state);
#define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */
#define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */
#define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */
+#define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */
#define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */
#define XFS_SB_VERSION_SECTORBIT 0x0800
#define XFS_SB_VERSION_EXTFLGBIT 0x1000
#define XFS_SB_VERSION_DIRV2BIT 0x2000
+#define XFS_SB_VERSION_BORGBIT 0x4000
#define XFS_SB_VERSION_MOREBITSBIT 0x8000
#define XFS_SB_VERSION_OKSASHFBITS \
(XFS_SB_VERSION_EXTFLGBIT | \
- XFS_SB_VERSION_DIRV2BIT)
+ XFS_SB_VERSION_DIRV2BIT | \
+ XFS_SB_VERSION_BORGBIT)
#define XFS_SB_VERSION_OKREALFBITS \
(XFS_SB_VERSION_ATTRBIT | \
XFS_SB_VERSION_NLINKBIT | \
((sbp)->sb_versionnum & XFS_SB_VERSION_SECTORBIT);
}
+static inline int xfs_sb_version_hasasciici(xfs_sb_t *sbp)
+{
+ return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
+ (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT);
+}
+
#define XFS_SB_VERSION_HASMOREBITS(sbp) xfs_sb_version_hasmorebits(sbp)
static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)
{
}
}
+enum xfs_dacmp
+xfs_da_compname(const uchar_t *name1, int len1, const uchar_t *name2, int len2)
+{
+ return (len1 == len2 && memcmp(name1, name2, len1) == 0) ?
+ XFS_CMP_EXACT : XFS_CMP_DIFFERENT;
+}
+
+const struct xfs_nameops xfs_default_nameops = {
+ .hashname = xfs_da_hashname,
+ .compname = xfs_da_compname
+};
+
/*
* Add a block to the btree ahead of the file.
* Return the new block number to the caller.
#include <xfs.h>
+extern const struct xfs_nameops xfs_default_nameops;
+
+/*
+ * V1/OLDCI case-insensitive support for directories that was used in IRIX.
+ *
+ * This is ASCII only case support, ie. A-Z.
+ */
+static xfs_dahash_t
+xfs_ascii_ci_hashname(
+ const uchar_t *name,
+ int len)
+{
+ xfs_dahash_t hash;
+ int i;
+
+ for (i = 0, hash = 0; i < len; i++)
+ hash = tolower(name[i]) ^ rol32(hash, 7);
+
+ return hash;
+}
+
+static enum xfs_dacmp
+xfs_ascii_ci_compname(
+ const uchar_t *name1,
+ int len1,
+ const uchar_t *name2,
+ int len2)
+{
+ enum xfs_dacmp result;
+ int i;
+
+ if (len1 != len2)
+ return XFS_CMP_DIFFERENT;
+
+ result = XFS_CMP_EXACT;
+ for (i = 0; i < len1; i++) {
+ if (name1[i] == name2[i])
+ continue;
+ if (tolower(name1[i]) != tolower(name2[i]))
+ return XFS_CMP_DIFFERENT;
+ result = XFS_CMP_CASE;
+ }
+
+ return result;
+}
+
+static const struct xfs_nameops xfs_ascii_ci_nameops = {
+ .hashname = xfs_ascii_ci_hashname,
+ .compname = xfs_ascii_ci_compname,
+};
+
/*
* Initialize directory-related fields in the mount structure.
(mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) /
(uint)sizeof(xfs_da_node_entry_t);
mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
+ if (xfs_sb_version_hasasciici(&mp->m_sb))
+ mp->m_dirnameops = &xfs_ascii_ci_nameops;
+ else
+ mp->m_dirnameops = &xfs_default_nameops;
}
/*
*/
args.name = name;
args.namelen = namelen;
- args.hashval = xfs_da_hashname(name, namelen);
+ args.hashval = dp->i_mount->m_dirnameops->hashname(name, namelen);
args.inumber = inum;
args.dp = dp;
args.firstblock = first;
*/
args.name = name;
args.namelen = namelen;
- args.hashval = xfs_da_hashname(name, namelen);
+ args.hashval = dp->i_mount->m_dirnameops->hashname(name, namelen);
args.inumber = 0;
args.dp = dp;
args.firstblock = NULL;
*/
args.name = name;
args.namelen = namelen;
- args.hashval = xfs_da_hashname(name, namelen);
+ args.hashval = dp->i_mount->m_dirnameops->hashname(name, namelen);
args.inumber = ino;
args.dp = dp;
args.firstblock = first;
*/
args.name = name;
args.namelen = namelen;
- args.hashval = xfs_da_hashname(name, namelen);
+ args.hashval = dp->i_mount->m_dirnameops->hashname(name, namelen);
args.inumber = inum;
args.dp = dp;
args.firstblock = first;
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
INT_SET(*tagp, ARCH_CONVERT, (xfs_dir2_data_off_t)((char *)dep - (char *)block));
xfs_dir2_data_log_entry(tp, bp, dep);
- INT_SET(blp[2 + i].hashval, ARCH_CONVERT, xfs_da_hashname((const uchar_t *)sfep->name, sfep->namelen));
- INT_SET(blp[2 + i].address, ARCH_CONVERT, XFS_DIR2_BYTE_TO_DATAPTR(mp,
+ blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->hashname(
+ sfep->name, sfep->namelen));
+ blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
(char *)dep - (char *)block));
offset = (int)((char *)(tagp + 1) - (char *)block);
if (++i == INT_GET(sfp->hdr.count, ARCH_CONVERT))
addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
(xfs_dir2_data_aoff_t)
((char *)dep - (char *)d));
- hash = xfs_da_hashname((char *)dep->name, dep->namelen);
+ hash = mp->m_dirnameops->hashname(dep->name, dep->namelen);
for (i = 0; i < INT_GET(btp->count, ARCH_CONVERT); i++) {
if (INT_GET(lep[i].address, ARCH_CONVERT) == addr &&
INT_GET(lep[i].hashval, ARCH_CONVERT) == hash)
.TP
.BI maxpct= value
This specifies the maximum percentage of space in the filesystem that
-can be allocated to inodes. The default
-.I value
+can be allocated to inodes. The default
+.I value
is 25% for filesystems under 1TB, 5% for filesystems under 50TB and 1%
for filesystems over 50TB.
.IP
maxpct, so a high value may result in a filesystem with nothing but
inodes in a significant portion of the lower blocks of the filesystem.
(This restriction is not present when the filesystem is mounted with
-the
-.I "inode64"
+the
+.I "inode64"
option on 64-bit platforms).
.IP
Setting the value to 0 means that essentially all of the filesystem
can become inode blocks, subject to inode32 restrictions.
.IP
-This value can be modified with
+This value can be modified with
.Ixfs_growfs(8)
.
.TP
that does not have the inode alignment feature
(any release of IRIX before 6.2, and IRIX 6.2 without XFS patches).
.TP
-.BI attr= value
+.BI attr= value
This is used to specify the version of extended attribute inline
allocation policy to be used. By default, this is 2, which uses an
efficient algorithm for managing the available inline inode space
.BI version= value
The naming (directory) version
.I value
-can be either 1 or 2, defaulting to 2 if unspecified.
-With version 2 directories,
-the directory block size can be any power of 2 size
-from the filesystem block size up to 65536.
+can be either 2 or 'ci', defaulting to 2 if unspecified.
+With version 2 directories, the directory block size can be
+any power of 2 size from the filesystem block size up to 65536.
+.IP
+The
+.B version=ci
+option enables ASCII only case-insensitive filename lookup and version
+2 directories. Filenames are case-preserving, that is, the names
+are stored in directories using the case they were created with.
+.IP
+Note: Version 1 directories are not supported.
.RE
.TP
.BI \-p " protofile"
xfs_alloc_rec_t *nrec;
int nsflag;
int nvflag;
+ int nci;
int Nflag;
char *p;
char *protofile;
loginternal = 1;
logversion = 2;
logagno = logblocks = rtblocks = rtextblocks = 0;
- Nflag = nlflag = nsflag = nvflag = 0;
- dirblocklog = dirblocksize = dirversion = 0;
+ Nflag = nlflag = nsflag = nvflag = nci = 0;
+ dirblocklog = dirblocksize = 0;
+ dirversion = XFS_DFL_DIR_VERSION;
qflag = 0;
imaxpct = inodelog = inopblock = isize = 0;
iaflag = XFS_IFLAG_ALIGN;
reqval('n', nopts, N_VERSION);
if (nvflag)
respec('n', nopts, N_VERSION);
- dirversion = atoi(value);
- if (dirversion < 1 || dirversion > 2)
- illegal(value, "n version");
+ if (!strcasecmp(value, "ci")) {
+ nci = 1; /* ASCII CI mode */
+ } else {
+ dirversion = atoi(value);
+ if (dirversion != 2)
+ illegal(value,
+ "n version");
+ }
nvflag = 1;
break;
default:
logversion = 2;
}
- if (!nvflag)
- dirversion = (nsflag || nlflag) ? 2 : XFS_DFL_DIR_VERSION;
- switch (dirversion) {
- case 1:
- if ((nsflag || nlflag) && dirblocklog != blocklog) {
+ if (nsflag || nlflag) {
+ if (dirblocksize < blocksize ||
+ dirblocksize > XFS_MAX_BLOCKSIZE) {
fprintf(stderr, _("illegal directory block size %d\n"),
dirblocksize);
usage();
}
- break;
- case 2:
- if (nsflag || nlflag) {
- if (dirblocksize < blocksize ||
- dirblocksize > XFS_MAX_BLOCKSIZE) {
- fprintf(stderr,
- _("illegal directory block size %d\n"),
- dirblocksize);
- usage();
- }
- } else {
- if (blocksize < (1 << XFS_MIN_REC_DIRSIZE))
- dirblocklog = XFS_MIN_REC_DIRSIZE;
- else
- dirblocklog = blocklog;
- dirblocksize = 1 << dirblocklog;
- }
- break;
+ } else {
+ if (blocksize < (1 << XFS_MIN_REC_DIRSIZE))
+ dirblocklog = XFS_MIN_REC_DIRSIZE;
+ else
+ dirblocklog = blocklog;
+ dirblocksize = 1 << dirblocklog;
}
if (daflag && dasize) {
" =%-22s sectsz=%-5u attr=%u\n"
"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
" =%-22s sunit=%-6u swidth=%u blks\n"
- "naming =version %-14u bsize=%-6u\n"
+ "naming =version %-14u bsize=%-6u mixed-case=%c\n"
"log =%-22s bsize=%-6d blocks=%lld, version=%d\n"
" =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n"
"realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
"", blocksize, (long long)dblocks,
calc_default_imaxpct(blocklog, dblocks),
"", dsunit, dswidth,
- dirversion, dirversion == 1 ? blocksize : dirblocksize,
+ dirversion, dirblocksize, nci ? 'N' : 'Y',
logfile, 1 << blocklog, (long long)logblocks,
logversion, "", lsectorsize, lsunit, lazy_sb_counters,
rtfile, rtextblocks << blocklog,
sbp->sb_qflags = 0;
sbp->sb_unit = dsunit;
sbp->sb_width = dswidth;
- if (dirversion == 2)
- sbp->sb_dirblklog = dirblocklog - blocklog;
+ sbp->sb_dirblklog = dirblocklog - blocklog;
if (logversion == 2) { /* This is stored in bytes */
lsunit = (lsunit == 0) ? 1 : XFS_FSB_TO_B(mp, lsunit);
sbp->sb_logsunit = lsunit;
sbp->sb_logsectlog = 0;
sbp->sb_logsectsize = 0;
}
- sbp->sb_features2 = XFS_SB_VERSION2_MKFS(lazy_sb_counters, attrversion == 2, 0);
- sbp->sb_versionnum = XFS_SB_VERSION_MKFS(
- iaflag, dsunit != 0,
- dirversion == 2, logversion == 2, attrversion == 1,
- (sectorsize != BBSIZE || lsectorsize != BBSIZE),
- sbp->sb_features2 != 0);
+ sbp->sb_features2 = XFS_SB_VERSION2_MKFS(lazy_sb_counters,
+ attrversion == 2, 0);
+ sbp->sb_versionnum = XFS_SB_VERSION_MKFS(iaflag, dsunit != 0,
+ logversion == 2, attrversion == 1,
+ (sectorsize != BBSIZE ||
+ lsectorsize != BBSIZE),
+ nci, sbp->sb_features2 != 0);
/*
* Due to a structure alignment issue, sb_features2 ended up in one
* of two locations, the second "incorrect" location represented by
#define XFS_DFL_SB_VERSION_BITS \
(XFS_SB_VERSION_NLINKBIT | \
- XFS_SB_VERSION_EXTFLGBIT)
+ XFS_SB_VERSION_EXTFLGBIT | \
+ XFS_SB_VERSION_DIRV2BIT)
-#define XFS_SB_VERSION_MKFS(ia,dia,dir2,log2,attr1,sflag,more) (\
- ((ia)||(dia)||(dir2)||(log2)||(attr1)||(sflag)||(more)) ? \
+#define XFS_SB_VERSION_MKFS(ia,dia,log2,attr1,sflag,ci,more) (\
+ ((ia)||(dia)||(log2)||(attr1)||(sflag)||(ci)||(more)) ? \
( XFS_SB_VERSION_4 | \
((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) | \
((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) | \
- ((dir2) ? XFS_SB_VERSION_DIRV2BIT : 0) | \
((log2) ? XFS_SB_VERSION_LOGV2BIT : 0) | \
((attr1) ? XFS_SB_VERSION_ATTRBIT : 0) | \
((sflag) ? XFS_SB_VERSION_SECTORBIT : 0) | \
+ ((ci) ? XFS_SB_VERSION_BORGBIT : 0) | \
((more) ? XFS_SB_VERSION_MOREBITSBIT : 0) | \
XFS_DFL_SB_VERSION_BITS | \
0 ) : XFS_SB_VERSION_1 )
*/
static int
dir_hash_add(
+ xfs_mount_t *mp,
dir_hash_tab_t *hashtab,
__uint32_t addr,
xfs_ino_t inum,
dup = 0;
if (!junk) {
- hash = libxfs_da_hashname(name, namelen);
+ hash = mp->m_dirnameops->hashname(name, namelen);
byhash = DIR_HASH_FUNC(hashtab, hash);
/*
/*
* check for duplicate names in directory.
*/
- if (!dir_hash_add(hashtab, (da_bno << mp->m_sb.sb_blocklog) +
+ if (!dir_hash_add(mp, hashtab, (da_bno << mp->m_sb.sb_blocklog) +
entry->nameidx, lino, entry->namelen,
namest->name)) {
nbad++;
/*
* check for duplicate names in directory.
*/
- if (!dir_hash_add(hashtab, addr, inum, dep->namelen,
+ if (!dir_hash_add(mp, hashtab, addr, inum, dep->namelen,
dep->name)) {
nbad++;
if (entry_junked(_("entry \"%s\" (ino %llu) in dir "
/*
* check for duplicate names in directory.
*/
- if (!dir_hash_add(hashtab,
+ if (!dir_hash_add(mp, hashtab,
(xfs_dir2_dataptr_t)(sf_entry - &sf->list[0]),
lino, sf_entry->namelen, sf_entry->name)) {
do_warn(_("entry \"%s\" (ino %llu) in dir %llu is a "
/*
* check for duplicate names in directory.
*/
- if (!dir_hash_add(hashtab, (xfs_dir2_dataptr_t)
+ if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t)
(sfep - XFS_DIR2_SF_FIRSTENTRY(sfp)),
lino, sfep->namelen, sfep->name)) {
do_warn(_("entry \"%s\" (ino %llu) in dir %llu is a "